]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge current mainline tree into linux-omap tree
authorTony Lindgren <tony@atomide.com>
Thu, 14 Aug 2008 09:57:16 +0000 (12:57 +0300)
committerTony Lindgren <tony@atomide.com>
Thu, 14 Aug 2008 09:57:16 +0000 (12:57 +0300)
Merge branches 'master' and 'linus'

Conflicts:

arch/arm/Makefile
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/memory.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/sleep.S
arch/arm/plat-omap/devices.c
drivers/i2c/chips/menelaus.c
drivers/input/keyboard/omap-keypad.c
drivers/watchdog/omap_wdt.c
include/asm-arm/arch-omap/board-2430sdp.h
include/asm-arm/arch-omap/board-apollon.h
include/asm-arm/arch-omap/board-h4.h
include/asm-arm/arch-omap/board-nokia.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/clock.h
include/asm-arm/arch-omap/common.h
include/asm-arm/arch-omap/control.h
include/asm-arm/arch-omap/cpu.h
include/asm-arm/arch-omap/debug-macro.S
include/asm-arm/arch-omap/dsp_common.h
include/asm-arm/arch-omap/entry-macro.S
include/asm-arm/arch-omap/gpio-switch.h
include/asm-arm/arch-omap/gpio.h
include/asm-arm/arch-omap/gpmc.h
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/mailbox.h
include/asm-arm/arch-omap/mcbsp.h
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-omap/mmc.h
include/asm-arm/arch-omap/mux.h
include/asm-arm/arch-omap/omap-alsa.h
include/asm-arm/arch-omap/omap1510.h
include/asm-arm/arch-omap/omap16xx.h
include/asm-arm/arch-omap/omap24xx.h
include/asm-arm/arch-omap/omap34xx.h
include/asm-arm/arch-omap/omapfb.h
include/asm-arm/arch-omap/onenand.h
include/asm-arm/arch-omap/pm.h
include/asm-arm/arch-omap/prcm.h
include/asm-arm/arch-omap/sdrc.h
include/asm-arm/arch-omap/serial.h
include/asm-arm/arch-omap/sram.h
include/asm-arm/arch-omap/system.h
include/asm-arm/arch-omap/timex.h
include/asm-arm/arch-omap/usb.h
include/asm-arm/arch-omap/vmalloc.h

254 files changed:
1  2 
MAINTAINERS
Makefile
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/include/asm/pgtable.h
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap1/mmu.c
arch/arm/mach-omap1/mmu.h
arch/arm/mach-omap2/bci.c
arch/arm/mach-omap2/board-2430sdp-flash.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp-flash.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-apollon-keys.c
arch/arm/mach-omap2/board-apollon-mmc.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4-mmc.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-n800-audio.c
arch/arm/mach-omap2/board-n800-bt.c
arch/arm/mach-omap2/board-n800-camera.c
arch/arm/mach-omap2/board-n800-dsp.c
arch/arm/mach-omap2/board-n800-flash.c
arch/arm/mach-omap2/board-n800-mmc.c
arch/arm/mach-omap2/board-n800-usb.c
arch/arm/mach-omap2/board-n800.c
arch/arm/mach-omap2/board-n810.c
arch/arm/mach-omap2/board-omap2evm.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm-flash.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.h
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/clockdomains.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/mmu.c
arch/arm/mach-omap2/mmu.h
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomains.h
arch/arm/mach-omap2/powerdomains24xx.h
arch/arm/mach-omap2/powerdomains34xx.h
arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
arch/arm/mach-omap2/sdrc.c
arch/arm/mach-omap2/sdrc2xxx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sleep242x.S
arch/arm/mach-omap2/sleep243x.S
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/sram242x.S
arch/arm/mach-omap2/sram243x.S
arch/arm/mach-omap2/sram34xx.S
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-omap2/usb-ehci.c
arch/arm/mach-omap2/usb-musb.c
arch/arm/mach-omap2/usb-tusb6010.c
arch/arm/plat-omap/bootreason.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/component-version.c
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio-switch.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/mach/aic23.h
arch/arm/plat-omap/include/mach/bci.h
arch/arm/plat-omap/include/mach/board-2430sdp.h
arch/arm/plat-omap/include/mach/board-3430sdp.h
arch/arm/plat-omap/include/mach/board-apollon.h
arch/arm/plat-omap/include/mach/board-h4.h
arch/arm/plat-omap/include/mach/board-ldp.h
arch/arm/plat-omap/include/mach/board-nokia.h
arch/arm/plat-omap/include/mach/board-omap2evm.h
arch/arm/plat-omap/include/mach/board-omap3beagle.h
arch/arm/plat-omap/include/mach/board-omap3evm.h
arch/arm/plat-omap/include/mach/board.h
arch/arm/plat-omap/include/mach/clock.h
arch/arm/plat-omap/include/mach/clockdomain.h
arch/arm/plat-omap/include/mach/common.h
arch/arm/plat-omap/include/mach/control.h
arch/arm/plat-omap/include/mach/cpu.h
arch/arm/plat-omap/include/mach/debug-macro.S
arch/arm/plat-omap/include/mach/dsp.h
arch/arm/plat-omap/include/mach/dsp_common.h
arch/arm/plat-omap/include/mach/entry-macro.S
arch/arm/plat-omap/include/mach/gpio-switch.h
arch/arm/plat-omap/include/mach/gpio.h
arch/arm/plat-omap/include/mach/gpmc.h
arch/arm/plat-omap/include/mach/hardware.h
arch/arm/plat-omap/include/mach/hdrc_cnf.h
arch/arm/plat-omap/include/mach/hsmmc.h
arch/arm/plat-omap/include/mach/io.h
arch/arm/plat-omap/include/mach/irqs.h
arch/arm/plat-omap/include/mach/mailbox.h
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/include/mach/memory.h
arch/arm/plat-omap/include/mach/mmc.h
arch/arm/plat-omap/include/mach/mmu.h
arch/arm/plat-omap/include/mach/mux.h
arch/arm/plat-omap/include/mach/omap-alsa.h
arch/arm/plat-omap/include/mach/omap1510.h
arch/arm/plat-omap/include/mach/omap16xx.h
arch/arm/plat-omap/include/mach/omap24xx.h
arch/arm/plat-omap/include/mach/omap34xx.h
arch/arm/plat-omap/include/mach/omapfb.h
arch/arm/plat-omap/include/mach/onenand.h
arch/arm/plat-omap/include/mach/pm.h
arch/arm/plat-omap/include/mach/powerdomain.h
arch/arm/plat-omap/include/mach/prcm.h
arch/arm/plat-omap/include/mach/sdrc.h
arch/arm/plat-omap/include/mach/serial.h
arch/arm/plat-omap/include/mach/sram.h
arch/arm/plat-omap/include/mach/sti.h
arch/arm/plat-omap/include/mach/system.h
arch/arm/plat-omap/include/mach/timex.h
arch/arm/plat-omap/include/mach/usb-ehci.h
arch/arm/plat-omap/include/mach/usb-musb.h
arch/arm/plat-omap/include/mach/usb.h
arch/arm/plat-omap/include/mach/vmalloc.h
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/mmu.c
arch/arm/plat-omap/sram.c
drivers/bluetooth/brf6150.c
drivers/bluetooth/brf6150.h
drivers/cbus/cbus.c
drivers/cbus/retu.c
drivers/cbus/tahvo-usb.c
drivers/cbus/tahvo.c
drivers/dsp/dspgateway/dsp.h
drivers/dsp/dspgateway/dsp_common.c
drivers/dsp/dspgateway/dsp_core.c
drivers/dsp/dspgateway/dsp_ctl.c
drivers/dsp/dspgateway/dsp_mem.c
drivers/dsp/dspgateway/error.c
drivers/dsp/dspgateway/ipbuf.c
drivers/dsp/dspgateway/mblog.c
drivers/dsp/dspgateway/omap2_dsp.h
drivers/dsp/dspgateway/task.c
drivers/dsp/dspgateway/taskwatch.c
drivers/dsp/dspgateway/uaccess_dsp.h
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/omap34xx_temp.c
drivers/i2c/Kconfig
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/lp5521.c
drivers/i2c/chips/menelaus.c
drivers/i2c/chips/tlv320aic23.c
drivers/i2c/chips/tsl2563.c
drivers/i2c/chips/twl4030-core.c
drivers/i2c/chips/twl4030-gpio.c
drivers/i2c/chips/twl4030-usb.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/omap-twl4030keypad.c
drivers/input/touchscreen/tsc2005.c
drivers/leds/leds-omap-pwm.c
drivers/leds/leds-omap.c
drivers/media/video/Kconfig
drivers/media/video/omap/omap16xxcam.c
drivers/misc/Kconfig
drivers/misc/sti/sdti.c
drivers/misc/sti/sti-console.c
drivers/misc/sti/sti-fifo.c
drivers/misc/sti/sti-netlink.c
drivers/misc/sti/sti.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/omap_hsmmc.c
drivers/mtd/maps/omap-toto-flash.c
drivers/mtd/maps/omap_nor.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/omap-hw.c
drivers/mtd/nand/omap-nand-flash.c
drivers/mtd/nand/omap2.c
drivers/mtd/onenand/omap2.c
drivers/net/Kconfig
drivers/net/irda/omap-ir.c
drivers/net/smc911x.h
drivers/rtc/rtc-twl4030.c
drivers/spi/tsc2301-core.c
drivers/usb/gadget/omap_udc.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-omap.h
drivers/usb/host/ohci-omap.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_procfs.c
drivers/usb/musb/omap2430.c
drivers/usb/musb/omap2430.h
drivers/usb/musb/tusb6010_omap.c
drivers/video/backlight/omap_bl.c
drivers/video/omap/blizzard.c
drivers/video/omap/dispc.c
drivers/video/omap/lcd_2430sdp.c
drivers/video/omap/lcd_ams_delta.c
drivers/video/omap/lcd_apollon.c
drivers/video/omap/lcd_h2.c
drivers/video/omap/lcd_mipid.c
drivers/video/omap/lcd_omap2evm.c
drivers/video/omap/lcd_omap3beagle.c
drivers/video/omap/lcd_omap3evm.c
drivers/video/omap/lcd_p2.c
drivers/video/omap/omapfb_main.c
drivers/video/omap/rfbi.c
drivers/video/omap/sossi.c
drivers/w1/masters/omap_hdq.c
drivers/watchdog/Kconfig
drivers/watchdog/omap_wdt.c
include/linux/i2c-id.h
include/linux/i2c/twl4030.h
sound/arm/omap/eac.c
sound/arm/omap/omap-alsa-aic23-mixer.c
sound/arm/omap/omap-alsa-aic23.c
sound/arm/omap/omap-alsa-aic23.h
sound/arm/omap/omap-alsa-dma.c
sound/arm/omap/omap-alsa-dma.h
sound/arm/omap/omap-alsa-sx1.c
sound/arm/omap/omap-alsa-tsc2101.c
sound/arm/omap/omap-alsa-tsc2102-mixer.c
sound/arm/omap/omap-alsa-tsc2102.c
sound/arm/omap/omap-alsa.c
sound/oss/omap-audio-aic23.c
sound/oss/omap-audio-dma-intfc.c
sound/oss/omap-audio-tsc2101.c
sound/oss/omap-audio.c
sound/oss/omap-audio.h

diff --cc MAINTAINERS
Simple merge
diff --cc Makefile
Simple merge
index c595df316365d4f23c88ac5278a1c1b63ee5f0af,703a44fa0f9b7c70814c17ab21e613eafcf4655a..552ea6d71ea26a553f75fdffbc0cfceeccb921fd
@@@ -119,9 -118,9 +118,10 @@@ endi
   machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
   machine-$(CONFIG_ARCH_OMAP1)    := omap1
   machine-$(CONFIG_ARCH_OMAP2)    := omap2
-  machine-$(CONFIG_ARCH_OMAP3)         := omap2
-   incdir-$(CONFIG_ARCH_OMAP)     := omap
-  machine-$(CONFIG_ARCH_S3C2410)          := s3c2410
++ machine-$(CONFIG_ARCH_OMAP3)    := omap2
+     plat-$(CONFIG_ARCH_OMAP)     := omap
+  machine-$(CONFIG_ARCH_S3C2410)          := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
+     plat-$(CONFIG_PLAT_S3C24XX)          := s3c24xx
   machine-$(CONFIG_ARCH_LH7A40X)          := lh7a40x
   machine-$(CONFIG_ARCH_VERSATILE)  := versatile
   machine-$(CONFIG_ARCH_IMX)      := imx
Simple merge
Simple merge
index c9e627df6ff11b7e0ca3d8044f10b049bdb193e1,3b65914b9141c79b3dab4d5936537a265dab7adc..1055de1ae4d1890a4c43e0b865635065659900f7
  #include <linux/mtd/partitions.h>
  #include <linux/input.h>
  #include <linux/i2c/tps65010.h>
 +#include <linux/workqueue.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc2101.h>
 +#include <linux/clk.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/gpio.h>
  
  #include <asm/mach-types.h>
  #include <asm/mach/flash.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/gpio-switch.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/tc.h>
- #include <asm/arch/nand.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
++#include <mach/gpio.h>
+ #include <mach/gpio-switch.h>
+ #include <mach/mux.h>
+ #include <mach/tc.h>
+ #include <mach/nand.h>
+ #include <mach/irda.h>
+ #include <mach/usb.h>
+ #include <mach/keypad.h>
+ #include <mach/common.h>
+ #include <mach/mcbsp.h>
+ #include <mach/omap-alsa.h>
  
  static int h2_keymap[] = {
        KEY(0, 0, KEY_LEFT),
index b2a12864007fa58e29460cd354c5fca775c63a44,2ced6d9984d27802844a448aa37720f54889d62a..7516d21af86c28c9ef1b5c9de4c24f0654337fce
  #include <asm/mach/flash.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/gpio-switch.h>
- #include <asm/arch/gpioexpander.h>
- #include <asm/arch/irqs.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/tc.h>
- #include <asm/arch/nand.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
 +#include <media/v4l2-int-device.h>
 +
++#include <mach/gpio.h>
++#include <mach/gpio-switch.h>
+ #include <mach/gpioexpander.h>
+ #include <mach/irqs.h>
+ #include <mach/mux.h>
+ #include <mach/tc.h>
+ #include <mach/nand.h>
+ #include <mach/irda.h>
+ #include <mach/usb.h>
+ #include <mach/keypad.h>
+ #include <mach/dma.h>
+ #include <mach/common.h>
+ #include <mach/mcbsp.h>
+ #include <mach/omap-alsa.h>
  
 +#include <../drivers/media/video/ov9640.h>
 +
  #define H3_TS_GPIO    48
  
  static int h3_keymap[] = {
index 33a987739b44dd244dccb94a94ec75c5c1e0b434,38d9783ac6d6fe420972df38f2b3fb4993ec8440..0e297f3de01aa0a7286f41699ba50f25b9ea54ff
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/board.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/common.h>
- #include <asm/arch/dsp_common.h>
- #include <asm/arch/aic23.h>
- #include <asm/arch/omapfb.h>
- #include <asm/arch/hwa742.h>
- #include <asm/arch/lcd_mipid.h>
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/board.h>
+ #include <mach/keypad.h>
+ #include <mach/common.h>
+ #include <mach/dsp_common.h>
+ #include <mach/aic23.h>
+ #include <mach/omapfb.h>
++#include <mach/hwa742.h>
+ #include <mach/lcd_mipid.h>
  
  #define ADS7846_PENDOWN_GPIO  15
  
index 2a467657588957b1a099a203331e7531856611ff,b58043644a6f55681ba5c66cb1d3a47f03687116..4b2c62b3853d3137d8e86b0affacc6e412bb1445
  #include <asm/mach/map.h>
  #include <asm/mach/flash.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/tc.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/board.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
- #include <asm/arch/gpio-switch.h>
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/tc.h>
+ #include <mach/dma.h>
+ #include <mach/board.h>
+ #include <mach/irda.h>
+ #include <mach/keypad.h>
+ #include <mach/common.h>
+ #include <mach/mcbsp.h>
+ #include <mach/omap-alsa.h>
++#include <mach/gpio-switch.h>
  
  static void __init omap_palmte_init_irq(void)
  {
index 566f970f8c18262755f7908ee83493a7818a808a,130bcc6fd082b4a7fa5745e3bb0d3c27b059f68b..d3156b8451daabc5c63a28298a31cb93b437b12a
  #include <asm/mach/flash.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/gpio-switch.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/tc.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
- #include <asm/arch/keypad.h>
+ #include <mach/gpio.h>
++#include <mach/gpio-switch.h>
+ #include <mach/mux.h>
+ #include <mach/irda.h>
+ #include <mach/usb.h>
+ #include <mach/tc.h>
+ #include <mach/board.h>
+ #include <mach/common.h>
+ #include <mach/mcbsp.h>
+ #include <mach/omap-alsa.h>
+ #include <mach/keypad.h>
  
  /* Write to I2C device */
  int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
Simple merge
Simple merge
Simple merge
index a894ca2da247b280f2ecec33dc31a49dab1c52b4,0000000000000000000000000000000000000000..75dd310a9073921264659e6e8f34cac93718d661
mode 100644,000000..100644
--- /dev/null
@@@ -1,351 -1,0 +1,351 @@@
- #include <asm/arch/dsp_common.h>
 +/*
 + * linux/arch/arm/mach-omap1/mmu.c
 + *
 + * Support for non-MPU OMAP1 MMUs.
 + *
 + * Copyright (C) 2002-2005 Nokia Corporation
 + *
 + * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *        and Paul Mundt <paul.mundt@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#include <linux/types.h>
 +#include <linux/init.h>
 +#include <linux/rwsem.h>
 +#include <linux/device.h>
 +#include <linux/kernel.h>
 +#include <linux/mm.h>
 +#include <linux/interrupt.h>
 +#include <linux/err.h>
 +#include "mmu.h"
 +#include <asm/tlbflush.h>
++#include <mach/dsp_common.h>
 +
 +static void *dspvect_page;
 +#define DSP_INIT_PAGE 0xfff000
 +
 +#define MMUFAULT_MASK (OMAP_MMU_FAULT_ST_PERM |\
 +                     OMAP_MMU_FAULT_ST_TLB_MISS |\
 +                     OMAP_MMU_FAULT_ST_TRANS)
 +
 +static unsigned int get_cam_l_va_mask(u16 pgsz)
 +{
 +      switch (pgsz) {
 +      case OMAP_MMU_CAM_PAGESIZE_1MB:
 +              return OMAP_MMU_CAM_L_VA_TAG_L1_MASK |
 +                     OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1MB;
 +      case OMAP_MMU_CAM_PAGESIZE_64KB:
 +              return OMAP_MMU_CAM_L_VA_TAG_L1_MASK |
 +                     OMAP_MMU_CAM_L_VA_TAG_L2_MASK_64KB;
 +      case OMAP_MMU_CAM_PAGESIZE_4KB:
 +              return OMAP_MMU_CAM_L_VA_TAG_L1_MASK |
 +                     OMAP_MMU_CAM_L_VA_TAG_L2_MASK_4KB;
 +      case OMAP_MMU_CAM_PAGESIZE_1KB:
 +              return OMAP_MMU_CAM_L_VA_TAG_L1_MASK |
 +                     OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1KB;
 +      }
 +      return 0;
 +}
 +
 +#define get_cam_va_mask(pgsz) \
 +      ((u32)OMAP_MMU_CAM_H_VA_TAG_H_MASK << 22 | \
 +       (u32)get_cam_l_va_mask(pgsz) << 6)
 +
 +static int intmem_usecount;
 +
 +/* for safety */
 +void dsp_mem_usecount_clear(void)
 +{
 +      if (intmem_usecount != 0) {
 +              printk(KERN_WARNING
 +                     "MMU: unbalanced memory request/release detected.\n"
 +                     "         intmem_usecount is not zero at where "
 +                     "it should be! ... fixed to be zero.\n");
 +              intmem_usecount = 0;
 +              omap_dsp_release_mem();
 +      }
 +}
 +EXPORT_SYMBOL_GPL(dsp_mem_usecount_clear);
 +
 +void omap_mmu_itack(struct omap_mmu *mmu)
 +{
 +      omap_mmu_write_reg(mmu, OMAP_MMU_IT_ACK_IT_ACK, OMAP_MMU_IT_ACK);
 +}
 +EXPORT_SYMBOL(omap_mmu_itack);
 +
 +static int omap1_mmu_mem_enable(struct omap_mmu *mmu, void *addr)
 +{
 +      int ret = 0;
 +
 +      if (omap_mmu_internal_memory(mmu, addr)) {
 +              if (intmem_usecount++ == 0)
 +                      ret = omap_dsp_request_mem();
 +      }
 +
 +      return ret;
 +}
 +
 +static int omap1_mmu_mem_disable(struct omap_mmu *mmu, void *addr)
 +{
 +      int ret = 0;
 +
 +      if (omap_mmu_internal_memory(mmu, addr)) {
 +              if (--intmem_usecount == 0)
 +                      omap_dsp_release_mem();
 +      } else
 +              ret = -EIO;
 +
 +      return ret;
 +}
 +
 +static inline void
 +omap1_mmu_read_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      /* read a TLB entry */
 +      omap_mmu_write_reg(mmu, OMAP_MMU_LD_TLB_RD, OMAP_MMU_LD_TLB);
 +
 +      cr->cam_h = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM_H);
 +      cr->cam_l = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM_L);
 +      cr->ram_h = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM_H);
 +      cr->ram_l = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM_L);
 +}
 +
 +static inline void
 +omap1_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      /* Set the CAM and RAM entries */
 +      omap_mmu_write_reg(mmu, cr->cam_h, OMAP_MMU_CAM_H);
 +      omap_mmu_write_reg(mmu, cr->cam_l, OMAP_MMU_CAM_L);
 +      omap_mmu_write_reg(mmu, cr->ram_h, OMAP_MMU_RAM_H);
 +      omap_mmu_write_reg(mmu, cr->ram_l, OMAP_MMU_RAM_L);
 +}
 +
 +static ssize_t omap1_mmu_show(struct omap_mmu *mmu, char *buf,
 +                            struct omap_mmu_tlb_lock *tlb_lock)
 +{
 +      int i, len;
 +
 +      len = sprintf(buf, "P: preserved, V: valid\n"
 +                         "ety P V size   cam_va     ram_pa ap\n");
 +                       /* 00: P V  4KB 0x300000 0x10171800 FA */
 +
 +      for (i = 0; i < mmu->nr_tlb_entries; i++) {
 +              struct omap_mmu_tlb_entry ent;
 +              struct cam_ram_regset cr;
 +              struct omap_mmu_tlb_lock entry_lock;
 +              char *pgsz_str, *ap_str;
 +
 +              /* read a TLB entry */
 +              entry_lock.base   = tlb_lock->base;
 +              entry_lock.victim = i;
 +              omap_mmu_read_tlb(mmu, &entry_lock, &cr);
 +
 +              ent.pgsz  = cr.cam_l & OMAP_MMU_CAM_PAGESIZE_MASK;
 +              ent.prsvd = cr.cam_l & OMAP_MMU_CAM_P;
 +              ent.valid = cr.cam_l & OMAP_MMU_CAM_V;
 +              ent.ap    = cr.ram_l & OMAP_MMU_RAM_L_AP_MASK;
 +              ent.va = (u32)(cr.cam_h & OMAP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
 +                       (u32)(cr.cam_l & get_cam_l_va_mask(ent.pgsz)) << 6;
 +              ent.pa = (unsigned long)cr.ram_h << 16 |
 +                       (cr.ram_l & OMAP_MMU_RAM_L_RAM_LSB_MASK);
 +
 +              pgsz_str = (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1MB)  ? " 1MB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_4KB)  ? " 4KB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1KB)  ? " 1KB":
 +                                                                   " ???";
 +              ap_str = (ent.ap == OMAP_MMU_RAM_L_AP_RO) ? "RO":
 +                       (ent.ap == OMAP_MMU_RAM_L_AP_FA) ? "FA":
 +                       (ent.ap == OMAP_MMU_RAM_L_AP_NA) ? "NA":
 +                                                         "??";
 +
 +              if (i == tlb_lock->base)
 +                      len += sprintf(buf + len, "lock base = %d\n",
 +                                     tlb_lock->base);
 +              if (i == tlb_lock->victim)
 +                      len += sprintf(buf + len, "victim    = %d\n",
 +                                     tlb_lock->victim);
 +              len += sprintf(buf + len,
 +                             /* 00: P V  4KB 0x300000 0x10171800 FA */
 +                             "%02d: %c %c %s 0x%06lx 0x%08lx %s\n",
 +                             i,
 +                             ent.prsvd ? 'P' : ' ',
 +                             ent.valid ? 'V' : ' ',
 +                             pgsz_str, ent.va, ent.pa, ap_str);
 +      }
 +
 +      return len;
 +}
 +
 +static int exmap_setup_preserved_entries(struct omap_mmu *mmu)
 +{
 +      int n = 0;
 +
 +      exmap_setup_preserved_mem_page(mmu, dspvect_page, DSP_INIT_PAGE, n++);
 +
 +      return n;
 +}
 +
 +static void exmap_clear_preserved_entries(struct omap_mmu *mmu)
 +{
 +      exmap_clear_mem_page(mmu, DSP_INIT_PAGE);
 +}
 +
 +static int omap1_mmu_startup(struct omap_mmu *mmu)
 +{
 +      dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
 +      if (dspvect_page == NULL) {
 +              dev_err(mmu->dev, "MMU %s: failed to allocate memory "
 +                      "for vector table\n", mmu->name);
 +              return -ENOMEM;
 +      }
 +
 +      mmu->nr_exmap_preserved = exmap_setup_preserved_entries(mmu);
 +
 +      return 0;
 +}
 +
 +static void omap1_mmu_shutdown(struct omap_mmu *mmu)
 +{
 +      exmap_clear_preserved_entries(mmu);
 +
 +      if (dspvect_page != NULL) {
 +              unsigned long virt;
 +
 +              down_read(&mmu->exmap_sem);
 +
 +              virt = (unsigned long)omap_mmu_to_virt(mmu, DSP_INIT_PAGE);
 +              flush_tlb_kernel_range(virt, virt + PAGE_SIZE);
 +              free_page((unsigned long)dspvect_page);
 +              dspvect_page = NULL;
 +
 +              up_read(&mmu->exmap_sem);
 +      }
 +}
 +
 +static inline unsigned long omap1_mmu_cam_va(struct cam_ram_regset *cr)
 +{
 +      unsigned int page_size = cr->cam_l & OMAP_MMU_CAM_PAGESIZE_MASK;
 +
 +      return (u32)(cr->cam_h & OMAP_MMU_CAM_H_VA_TAG_H_MASK)  << 22 |
 +             (u32)(cr->cam_l & get_cam_l_va_mask(page_size)) << 6;
 +}
 +
 +static struct cam_ram_regset *
 +omap1_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry)
 +{
 +      struct cam_ram_regset *cr;
 +
 +      if (entry->va & ~(get_cam_va_mask(entry->pgsz))) {
 +              dev_err(mmu->dev, "MMU %s: mapping vadr (0x%06lx) is not on"
 +                      " an aligned boundary\n", mmu->name, entry->va);
 +              return ERR_PTR(-EINVAL);
 +      }
 +
 +      cr = kmalloc(sizeof(struct cam_ram_regset), GFP_KERNEL);
 +
 +      cr->cam_h = entry->va >> 22;
 +      cr->cam_l = (entry->va >> 6 & get_cam_l_va_mask(entry->pgsz)) |
 +                 entry->prsvd | entry->pgsz;
 +      cr->ram_h = entry->pa >> 16;
 +      cr->ram_l = (entry->pa & OMAP_MMU_RAM_L_RAM_LSB_MASK) | entry->ap;
 +
 +      return cr;
 +}
 +
 +static inline int omap1_mmu_cam_ram_valid(struct cam_ram_regset *cr)
 +{
 +      return cr->cam_l & OMAP_MMU_CAM_V;
 +}
 +
 +static void omap1_mmu_interrupt(struct omap_mmu *mmu)
 +{
 +      unsigned long status;
 +      unsigned long adh, adl;
 +      unsigned long dp;
 +      unsigned long va;
 +
 +      status = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_ST);
 +      adh = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD_H);
 +      adl = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD_L);
 +      dp = adh & OMAP_MMU_FAULT_AD_H_DP;
 +      va = (((adh & OMAP_MMU_FAULT_AD_H_ADR_MASK) << 16) | adl);
 +
 +      /* if the fault is masked, nothing to do */
 +      if ((status & MMUFAULT_MASK) == 0) {
 +              pr_debug("MMU interrupt, but ignoring.\n");
 +              /*
 +               * note: in OMAP1710,
 +               * when CACHE + DMA domain gets out of idle in DSP,
 +               * MMU interrupt occurs but MMU_FAULT_ST is not set.
 +               * in this case, we just ignore the interrupt.
 +               */
 +              if (status) {
 +                      pr_debug("%s%s%s%s\n",
 +                               (status & OMAP_MMU_FAULT_ST_PREF)?
 +                               "  (prefetch err)" : "",
 +                               (status & OMAP_MMU_FAULT_ST_PERM)?
 +                               "  (permission fault)" : "",
 +                               (status & OMAP_MMU_FAULT_ST_TLB_MISS)?
 +                               "  (TLB miss)" : "",
 +                               (status & OMAP_MMU_FAULT_ST_TRANS) ?
 +                               "  (translation fault)": "");
 +                      pr_debug("fault address = %#08lx\n", va);
 +              }
 +              enable_irq(mmu->irq);
 +              return;
 +      }
 +
 +      pr_info("%s%s%s%s\n",
 +              (status & OMAP_MMU_FAULT_ST_PREF)?
 +              (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_PREF)?
 +              "  prefetch err":
 +              "  (prefetch err)":
 +              "",
 +              (status & OMAP_MMU_FAULT_ST_PERM)?
 +              (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_PERM)?
 +              "  permission fault":
 +              "  (permission fault)":
 +              "",
 +              (status & OMAP_MMU_FAULT_ST_TLB_MISS)?
 +              (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_TLB_MISS)?
 +              "  TLB miss":
 +              "  (TLB miss)":
 +              "",
 +              (status & OMAP_MMU_FAULT_ST_TRANS)?
 +              (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_TRANS)?
 +              "  translation fault":
 +              "  (translation fault)":
 +              "");
 +      pr_info("fault address = %#08lx\n", va);
 +
 +      mmu->fault_address = va;
 +      schedule_work(&mmu->irq_work);
 +}
 +
 +static pgprot_t omap1_mmu_pte_get_attr(struct omap_mmu_tlb_entry *entry)
 +{
 +      /* 4KB AP position as default */
 +      u32 attr = entry->ap >> 4;
 +      attr <<= ((entry->pgsz == OMAP_MMU_CAM_PAGESIZE_1MB) ? 6:0);
 +      return attr;
 +}
 +
 +struct omap_mmu_ops omap1_mmu_ops = {
 +      .startup        = omap1_mmu_startup,
 +      .shutdown       = omap1_mmu_shutdown,
 +      .mem_enable     = omap1_mmu_mem_enable,
 +      .mem_disable    = omap1_mmu_mem_disable,
 +      .read_tlb       = omap1_mmu_read_tlb,
 +      .load_tlb       = omap1_mmu_load_tlb,
 +      .show           = omap1_mmu_show,
 +      .cam_va         = omap1_mmu_cam_va,
 +      .cam_ram_alloc  = omap1_mmu_cam_ram_alloc,
 +      .cam_ram_valid  = omap1_mmu_cam_ram_valid,
 +      .interrupt      = omap1_mmu_interrupt,
 +      .pte_get_attr   = omap1_mmu_pte_get_attr,
 +};
 +EXPORT_SYMBOL_GPL(omap1_mmu_ops);
index 9d9d9bc9dc683c0efcbc119517c7e8b52e47ff5f,0000000000000000000000000000000000000000..b0255af2b1d38d161a0603ff660a02e261ffb9b6
mode 100644,000000..100644
--- /dev/null
@@@ -1,119 -1,0 +1,119 @@@
- #include <asm/arch/mmu.h>
 +#ifndef __MACH_OMAP1_MMU_H
 +#define __MACH_OMAP1_MMU_H
 +
 +#include <linux/io.h>
++#include <mach/mmu.h>
 +
 +#define MMU_LOCK_BASE_MASK            (0x3f << 10)
 +#define MMU_LOCK_VICTIM_MASK          (0x3f << 4)
 +
 +#define OMAP_MMU_PREFETCH             0x00
 +#define OMAP_MMU_WALKING_ST           0x04
 +#define OMAP_MMU_CNTL                 0x08
 +#define OMAP_MMU_FAULT_AD_H           0x0c
 +#define OMAP_MMU_FAULT_AD_L           0x10
 +#define OMAP_MMU_FAULT_ST             0x14
 +#define OMAP_MMU_IT_ACK                       0x18
 +#define OMAP_MMU_TTB_H                        0x1c
 +#define OMAP_MMU_TTB_L                        0x20
 +#define OMAP_MMU_LOCK                 0x24
 +#define OMAP_MMU_LD_TLB                       0x28
 +#define OMAP_MMU_CAM_H                        0x2c
 +#define OMAP_MMU_CAM_L                        0x30
 +#define OMAP_MMU_RAM_H                        0x34
 +#define OMAP_MMU_RAM_L                        0x38
 +#define OMAP_MMU_GFLUSH                       0x3c
 +#define OMAP_MMU_FLUSH_ENTRY          0x40
 +#define OMAP_MMU_READ_CAM_H           0x44
 +#define OMAP_MMU_READ_CAM_L           0x48
 +#define OMAP_MMU_READ_RAM_H           0x4c
 +#define OMAP_MMU_READ_RAM_L           0x50
 +
 +#define OMAP_MMU_CNTL_BURST_16MNGT_EN 0x0020
 +#define OMAP_MMU_CNTL_WTL_EN          0x0004
 +#define OMAP_MMU_CNTL_MMU_EN          0x0002
 +#define OMAP_MMU_CNTL_RESET_SW                0x0001
 +
 +#define OMAP_MMU_FAULT_AD_H_DP                0x0100
 +#define OMAP_MMU_FAULT_AD_H_ADR_MASK  0x00ff
 +
 +#define OMAP_MMU_FAULT_ST_PREF                0x0008
 +#define OMAP_MMU_FAULT_ST_PERM                0x0004
 +#define OMAP_MMU_FAULT_ST_TLB_MISS    0x0002
 +#define OMAP_MMU_FAULT_ST_TRANS               0x0001
 +
 +#define OMAP_MMU_IT_ACK_IT_ACK                0x0001
 +
 +#define OMAP_MMU_CAM_H_VA_TAG_H_MASK          0x0003
 +
 +#define OMAP_MMU_CAM_L_VA_TAG_L1_MASK         0xc000
 +#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1MB     0x0000
 +#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_64KB    0x3c00
 +#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_4KB     0x3fc0
 +#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1KB     0x3ff0
 +#define OMAP_MMU_CAM_L_P                      0x0008
 +#define OMAP_MMU_CAM_L_V                      0x0004
 +#define OMAP_MMU_CAM_L_PAGESIZE_MASK          0x0003
 +#define OMAP_MMU_CAM_L_PAGESIZE_1MB           0x0000
 +#define OMAP_MMU_CAM_L_PAGESIZE_64KB          0x0001
 +#define OMAP_MMU_CAM_L_PAGESIZE_4KB           0x0002
 +#define OMAP_MMU_CAM_L_PAGESIZE_1KB           0x0003
 +
 +#define OMAP_MMU_CAM_P                        OMAP_MMU_CAM_L_P
 +#define OMAP_MMU_CAM_V                        OMAP_MMU_CAM_L_V
 +#define OMAP_MMU_CAM_PAGESIZE_MASK    OMAP_MMU_CAM_L_PAGESIZE_MASK
 +#define OMAP_MMU_CAM_PAGESIZE_1MB     OMAP_MMU_CAM_L_PAGESIZE_1MB
 +#define OMAP_MMU_CAM_PAGESIZE_64KB    OMAP_MMU_CAM_L_PAGESIZE_64KB
 +#define OMAP_MMU_CAM_PAGESIZE_4KB     OMAP_MMU_CAM_L_PAGESIZE_4KB
 +#define OMAP_MMU_CAM_PAGESIZE_1KB     OMAP_MMU_CAM_L_PAGESIZE_1KB
 +#define OMAP_MMU_CAM_PAGESIZE_16MB    -1 /* unused in omap1 */
 +
 +#define OMAP_MMU_RAM_L_RAM_LSB_MASK   0xfc00
 +#define OMAP_MMU_RAM_L_AP_MASK                0x0300
 +#define OMAP_MMU_RAM_L_AP_NA          0x0000
 +#define OMAP_MMU_RAM_L_AP_RO          0x0200
 +#define OMAP_MMU_RAM_L_AP_FA          0x0300
 +
 +#define OMAP_MMU_LD_TLB_RD            0x0002
 +
 +#define INIT_TLB_ENTRY(ent, v, p, ps)                 \
 +do {                                                  \
 +      (ent)->va       = (v);                          \
 +      (ent)->pa       = (p);                          \
 +      (ent)->pgsz     = (ps);                         \
 +      (ent)->prsvd    = 0;                            \
 +      (ent)->ap       = OMAP_MMU_RAM_L_AP_FA;         \
 +      (ent)->tlb      = 1;                            \
 +} while (0)
 +
 +#define INIT_TLB_ENTRY_4KB_PRESERVED(ent, v, p)       \
 +do {                                                  \
 +      (ent)->va       = (v);                          \
 +      (ent)->pa       = (p);                          \
 +      (ent)->pgsz     = OMAP_MMU_CAM_PAGESIZE_4KB;    \
 +      (ent)->prsvd    = OMAP_MMU_CAM_P;               \
 +      (ent)->ap       = OMAP_MMU_RAM_L_AP_FA;         \
 +} while (0)
 +
 +struct omap_mmu_tlb_entry {
 +      unsigned long va;
 +      unsigned long pa;
 +      unsigned int pgsz, prsvd, valid;
 +
 +      u16 ap;
 +      unsigned int tlb;
 +};
 +
 +static inline unsigned short
 +omap_mmu_read_reg(struct omap_mmu *mmu, unsigned long reg)
 +{
 +      return __raw_readw(mmu->base + reg);
 +}
 +
 +static inline void omap_mmu_write_reg(struct omap_mmu *mmu,
 +                             unsigned short val, unsigned long reg)
 +{
 +      __raw_writew(val, mmu->base + reg);
 +}
 +
 +#endif /* __MACH_OMAP1_MMU_H */
index 2bd71d525ad686fe8bb80210f8680df790c76d97,0000000000000000000000000000000000000000..9b9f9d20412e860727395cf198b7ea6101e6176e
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,57 @@@
- #include <asm/arch/bci.h>
 +/*
 + * linux/arch/arm/mach-omap2/bci.c
 + *
 + * TWL4030 BCI platform device setup/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.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
++#include <mach/bci.h>
 +
 +#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
 +      defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
 +/*
 + * Thermistor Calibration for Current Source and MADC
 + * Tolerance (for THS05-3H103F)
 + */
 +static int sdp3430_batt_table[] = {
 +/* 0 C*/
 +30800, 29500, 28300, 27100,
 +26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
 +17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
 +11600, 11200, 10800, 10400, 10000, 9630,   9280,   8950,   8620,   8310,
 +8020,   7730,   7460,   7200,   6950,   6710,   6470,   6250,   6040,   5830,
 +5640,   5450,   5260,   5090,   4920,   4760,   4600,   4450,   4310,   4170,
 +4040,   3910,   3790,   3670,   3550
 +};
 +
 +static struct twl4030_bci_platform_data sdp3430_bci_data = {
 +      .battery_tmp_tbl = sdp3430_batt_table,
 +      .tblsize = ARRAY_SIZE(sdp3430_batt_table),
 +};
 +
 +static struct platform_device twl4030_bci_battery_device = {
 +      .name           = "twl4030-bci-battery",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data  = &sdp3430_bci_data,
 +      },
 +      .num_resources  = 0,
 +};
 +
 +void __init twl4030_bci_battery_init(void)
 +{
 +      (void) platform_device_register(&twl4030_bci_battery_device);
 +}
 +#else
 +void __init twl4030_bci_battery_init(void)
 +{
 +}
 +#endif
index aaa8db46e3c630e15ecac1a23295acef22142ccd,0000000000000000000000000000000000000000..57d3b553715bcc07dfacce7f8cd00b5d07e12572
mode 100644,000000..100644
--- /dev/null
@@@ -1,185 -1,0 +1,185 @@@
- #include <asm/arch/onenand.h>
- #include <asm/arch/board.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/nand.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-2430sdp-flash.c
 + *
 + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
 + * Author: Kevin Hilman
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/platform_device.h>
 +#include <asm/mach/flash.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/mtd/onenand_regs.h>
 +
 +#include <asm/io.h>
++#include <mach/onenand.h>
++#include <mach/board.h>
++#include <mach/gpmc.h>
++#include <mach/nand.h>
 +
 +#define ONENAND_MAP 0x20000000
 +#define GPMC_OFF_CONFIG1_0 0x60
 +
 +enum fstype {
 +      NAND = 0,
 +      NOR,
 +      ONENAND,
 +      UNKNOWN = -1
 +};
 +
 +static enum fstype flash_type = NAND;
 +
 +static struct mtd_partition nand_partitions[] = {
 +      {
 +              .name           = "X-Loader",
 +              .offset         = 0,
 +              .size           = 4*(64*2048),  /* 0-3 blks reserved.
 +                                                 Mandated by ROM code */
 +              .mask_flags     = MTD_WRITEABLE /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           =  4*(64*2048),
 +              .mask_flags     = MTD_WRITEABLE /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot Environment",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 2*(64*2048),
 +      },
 +      {
 +              .name           = "Kernel",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 32*(64*2048),         /* 4*1M */
 +      },
 +      {
 +              .name           = "File System",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = MTDPART_SIZ_FULL,
 +      },
 +};
 +static struct omap_nand_platform_data sdp_nand_data = {
 +      .parts          = nand_partitions,
 +      .nr_parts       = ARRAY_SIZE(nand_partitions),
 +      .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
 +};
 +
 +static struct platform_device sdp_nand_device = {
 +      .name           = "omap2-nand",
 +      .id             = -1,
 +      .dev = {
 +              .platform_data = &sdp_nand_data,
 +      },
 +};
 +
 +static struct mtd_partition onenand_partitions[] = {
 +      {
 +              .name           = "(OneNAND)X-Loader",
 +              .offset         = 0,
 +              .size           = 4*(64*2048),  /* 0-3 blks reserved.
 +                                                 Mandated by ROM code */
 +              .mask_flags     = MTD_WRITEABLE /* force read-only */
 +      },
 +      {
 +              .name           = "(OneNAND)U-Boot",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           =  2*(64*2048),
 +              .mask_flags     = MTD_WRITEABLE /* force read-only */
 +      },
 +      {
 +              .name           = "(OneNAND)U-Boot Environment",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 1*(64*2048),
 +      },
 +      {
 +              .name           = "(OneNAND)Kernel",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 4*(64*2048),
 +      },
 +      {
 +              .name           = "(OneNAND)File System",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = MTDPART_SIZ_FULL,
 +      },
 +};
 +
 +static struct omap_onenand_platform_data sdp_onenand_data = {
 +      .parts          = onenand_partitions,
 +      .nr_parts       = ARRAY_SIZE(onenand_partitions),
 +      .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
 +};
 +
 +static struct platform_device sdp_onenand_device = {
 +      .name           = "omap2-onenand",
 +      .id             = -1,
 +      .dev = {
 +              .platform_data = &sdp_onenand_data,
 +      },
 +};
 +
 +void __init sdp2430_flash_init(void)
 +{
 +      void __iomem *gpmc_base_add, *gpmc_cs_base_add;
 +      unsigned char cs = 0;
 +
 +      gpmc_base_add = (__force void __iomem *)OMAP243X_GPMC_VIRT;
 +      while (cs < GPMC_CS_NUM) {
 +              int ret = 0;
 +
 +              /* Each GPMC set for a single CS is at offset 0x30 */
 +              gpmc_cs_base_add = (gpmc_base_add + GPMC_OFF_CONFIG1_0 +
 +                                  (cs*0x30));
 +
 +              /* xloader/Uboot would have programmed the NAND/oneNAND
 +               * base address for us This is a ugly hack. The proper
 +               * way of doing this is to pass the setup of u-boot up
 +               * to kernel using kernel params - something on the
 +               * lines of machineID. Check if Nand/oneNAND is
 +               * configured */
 +              ret = __raw_readl(gpmc_cs_base_add + GPMC_CS_CONFIG1);
 +              if ((ret & 0xC00) == (0x800)) {
 +                      /* Found it!! */
 +                      printk(KERN_INFO "NAND: Found NAND on CS %d \n", cs);
 +                      flash_type = NAND;
 +                      break;
 +              }
 +              ret = __raw_readl(gpmc_cs_base_add + GPMC_CS_CONFIG7);
 +              if ((ret & 0x3F) == (ONENAND_MAP >> 24)) {
 +                      /* Found it!! */
 +                      flash_type = ONENAND;
 +                      break;
 +              }
 +              cs++;
 +      }
 +      if (cs >= GPMC_CS_NUM) {
 +              printk(KERN_INFO "MTD: Unable to find MTD configuration in "
 +                               "GPMC   - not registering.\n");
 +              return;
 +      }
 +
 +      if (flash_type == NAND) {
 +              sdp_nand_data.cs               = cs;
 +              sdp_nand_data.gpmc_cs_baseaddr = gpmc_cs_base_add;
 +              sdp_nand_data.gpmc_baseaddr    = gpmc_base_add;
 +
 +              if (platform_device_register(&sdp_nand_device) < 0) {
 +                      printk(KERN_ERR "Unable to register NAND device\n");
 +                      return;
 +              }
 +      }
 +
 +      if (flash_type == ONENAND) {
 +              sdp_onenand_data.cs = cs;
 +
 +              if (platform_device_register(&sdp_onenand_device) < 0) {
 +                      printk(KERN_ERR "Unable to register OneNAND device\n");
 +                      return;
 +              }
 +      }
 +}
index b2f8b9ccd75f0ad46e28209b07c114e13fc75c75,d4d6385cad7c7e3275370f8f67138c1a9398b1a5..cb38fc236b5298064648784c33194b924d33d687
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/partitions.h>
  #include <linux/delay.h>
 +#include <linux/input.h>
  #include <linux/err.h>
  #include <linux/clk.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/ads7846.h>
 +#include <linux/i2c/twl4030-rtc.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/mach-types.h>
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  #include <asm/mach/flash.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/board.h>
- #include <asm/arch/usb-musb.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/common.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/mcspi.h>
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+ #include <mach/board.h>
++#include <mach/usb-musb.h>
++#include <mach/hsmmc.h>
+ #include <mach/common.h>
++#include <mach/keypad.h>
+ #include <mach/gpmc.h>
++#include <mach/mcspi.h>
  
  #include <asm/io.h>
  
index 1fddcd67b57750feab6e889efb93c811a2e59cc4,0000000000000000000000000000000000000000..945a2ae520b60ccfc179d3b2a84b31b8291be323
mode 100644,000000..100644
--- /dev/null
@@@ -1,190 -1,0 +1,190 @@@
- #include <asm/arch/onenand.h>
- #include <asm/arch/board.h>
- #include <asm/arch/gpmc.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-3430sdp-flash.c
 + *
 + * Copyright (c) 2007 Texas Instruments
 + *
 + * Modified from mach-omap2/board-2430sdp-flash.c
 + * Author: Rohit Choraria <rohitkc@ti.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/platform_device.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/mtd/nand.h>
 +#include <linux/mtd/onenand_regs.h>
 +#include <linux/types.h>
 +#include <linux/io.h>
 +
 +#include <asm/mach/flash.h>
++#include <mach/onenand.h>
++#include <mach/board.h>
++#include <mach/gpmc.h>
 +
 +static struct mtd_partition sdp_nor_partitions[] = {
 +      /* bootloader (U-Boot, etc) in first sector */
 +      {
 +              .name           = "Bootloader-NOR",
 +              .offset         = 0,
 +              .size           = SZ_256K,
 +              .mask_flags     = MTD_WRITEABLE, /* force read-only */
 +      },
 +      /* bootloader params in the next sector */
 +      {
 +              .name           = "Params-NOR",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = SZ_256K,
 +              .mask_flags     = 0,
 +      },
 +      /* kernel */
 +      {
 +              .name           = "Kernel-NOR",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = SZ_2M,
 +              .mask_flags     = 0
 +      },
 +      /* file system */
 +      {
 +              .name           = "Filesystem-NOR",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = MTDPART_SIZ_FULL,
 +              .mask_flags     = 0
 +      }
 +};
 +
 +static struct flash_platform_data sdp_nor_data = {
 +      .map_name       = "cfi_probe",
 +      .width          = 2,
 +      .parts          = sdp_nor_partitions,
 +      .nr_parts       = ARRAY_SIZE(sdp_nor_partitions),
 +};
 +
 +static struct resource sdp_nor_resource = {
 +      .start          = 0,
 +      .end            = 0,
 +      .flags          = IORESOURCE_MEM,
 +};
 +
 +static struct platform_device sdp_nor_device = {
 +      .name           = "omapflash",
 +      .id             = 0,
 +      .dev            = {
 +                      .platform_data = &sdp_nor_data,
 +      },
 +      .num_resources  = 1,
 +      .resource       = &sdp_nor_resource,
 +};
 +
 +static int sdp_onenand_setup(void __iomem *, int freq);
 +
 +static struct mtd_partition sdp_onenand_partitions[] = {
 +      {
 +              .name           = "X-Loader-OneNAND",
 +              .offset         = 0,
 +              .size           = 4 * (64 * 2048),
 +              .mask_flags     = MTD_WRITEABLE  /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot-OneNAND",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 2 * (64 * 2048),
 +              .mask_flags     = MTD_WRITEABLE  /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot Environment-OneNAND",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 1 * (64 * 2048),
 +      },
 +      {
 +              .name           = "Kernel-OneNAND",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 16 * (64 * 2048),
 +      },
 +      {
 +              .name           = "File System-OneNAND",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = MTDPART_SIZ_FULL,
 +      },
 +};
 +
 +static struct omap_onenand_platform_data sdp_onenand_data = {
 +      .parts          = sdp_onenand_partitions,
 +      .nr_parts       = ARRAY_SIZE(sdp_onenand_partitions),
 +      .onenand_setup  = sdp_onenand_setup,
 +      .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
 +};
 +
 +static struct platform_device sdp_onenand_device = {
 +      .name           = "omap2-onenand",
 +      .id             = -1,
 +      .dev = {
 +              .platform_data = &sdp_onenand_data,
 +      },
 +};
 +
 +/*
 + * sdp_onenand_setup - The function configures the onenand flash.
 + * @onenand_base: Onenand base address
 + *
 + * @return int:       Currently always returning zero.
 + */
 +static int sdp_onenand_setup(void __iomem *onenand_base, int freq)
 +{
 +      /* Onenand setup does nothing at present */
 +      return 0;
 +}
 +/**
 + * sdp3430_flash_init - Identify devices connected to GPMC and register.
 + *
 + * @return - void.
 + */
 +void __init sdp3430_flash_init(void)
 +{
 +      u8              cs = 0;
 +      u8              onenandcs = GPMC_CS_NUM + 1;
 +
 +      /* Configure start address and size of NOR device */
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
 +              sdp_nor_resource.start  = FLASH_BASE_SDPV2;
 +              sdp_nor_resource.end    = FLASH_BASE_SDPV2
 +                                              + FLASH_SIZE_SDPV2 - 1;
 +      } else {
 +              sdp_nor_resource.start  = FLASH_BASE_SDPV1;
 +              sdp_nor_resource.end    = FLASH_BASE_SDPV1
 +                                              + FLASH_SIZE_SDPV1 - 1;
 +      }
 +
 +      if (platform_device_register(&sdp_nor_device) < 0)
 +              printk(KERN_ERR "Unable to register NOR device\n");
 +
 +      while (cs < GPMC_CS_NUM) {
 +              u32 ret = 0;
 +              ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
 +
 +              /*
 +              * xloader/Uboot would have programmed the oneNAND
 +              * base address for us This is a ugly hack. The proper
 +              * way of doing this is to pass the setup of u-boot up
 +              * to kernel using kernel params - something on the
 +              * lines of machineID. Check if oneNAND is configured
 +              */
 +              if ((ret & 0x3F) == (ONENAND_MAP >> 24))
 +                      onenandcs = cs;
 +              cs++;
 +      }
 +      if (onenandcs > GPMC_CS_NUM) {
 +              printk(KERN_INFO "OneNAND: Unable to find configuration "
 +                              " in GPMC\n ");
 +              return;
 +      }
 +
 +      if (onenandcs < GPMC_CS_NUM) {
 +              sdp_onenand_data.cs = onenandcs;
 +              if (platform_device_register(&sdp_onenand_device) < 0)
 +                      printk(KERN_ERR "Unable to register OneNAND device\n");
 +      }
 +}
index ee4ec18f375b1e2273e3e8cc3219052fa368a0dc,0000000000000000000000000000000000000000..637f1c8e04b7d31d1aead0f46f8c923b06b61813
mode 100644,000000..100644
--- /dev/null
@@@ -1,391 -1,0 +1,391 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-3430sdp.c
 + *
 + * Copyright (C) 2007 Texas Instruments
 + *
 + * Modified from mach-omap2/board-generic.c
 + *
 + * Initial code: Syed Mohammed Khasim
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/input.h>
 +#include <linux/workqueue.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/ads7846.h>
 +
- #include <asm/arch/mcspi.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/board.h>
- #include <asm/arch/usb-musb.h>
- #include <asm/arch/usb-ehci.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/common.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/gpmc.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +
- #include <asm/arch/control.h>
++#include <mach/mcspi.h>
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/board.h>
++#include <mach/usb-musb.h>
++#include <mach/usb-ehci.h>
++#include <mach/hsmmc.h>
++#include <mach/common.h>
++#include <mach/keypad.h>
++#include <mach/dma.h>
++#include <mach/gpmc.h>
 +#include <linux/i2c/twl4030-rtc.h>
 +
 +#include <asm/io.h>
 +#include <asm/delay.h>
++#include <mach/control.h>
 +
 +#include "sdram-qimonda-hyb18m512160af-6.h"
 +
 +#define       SDP3430_SMC91X_CS       3
 +
 +#define ENABLE_VAUX3_DEDICATED        0x03
 +#define ENABLE_VAUX3_DEV_GRP  0x20
 +
 +
 +#define TWL4030_MSECURE_GPIO 22
 +
 +static struct resource sdp3430_smc91x_resources[] = {
 +      [0] = {
 +              .start  = OMAP34XX_ETHR_START,
 +              .end    = OMAP34XX_ETHR_START + SZ_4K,
 +              .flags  = IORESOURCE_MEM,
 +      },
 +      [1] = {
 +              .start  = 0,
 +              .end    = 0,
 +              .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 +      },
 +};
 +
 +static struct platform_device sdp3430_smc91x_device = {
 +      .name           = "smc91x",
 +      .id             = -1,
 +      .num_resources  = ARRAY_SIZE(sdp3430_smc91x_resources),
 +      .resource       = sdp3430_smc91x_resources,
 +};
 +
 +static int sdp3430_keymap[] = {
 +      KEY(0, 0, KEY_LEFT),
 +      KEY(0, 1, KEY_RIGHT),
 +      KEY(0, 2, KEY_A),
 +      KEY(0, 3, KEY_B),
 +      KEY(0, 4, KEY_C),
 +      KEY(1, 0, KEY_DOWN),
 +      KEY(1, 1, KEY_UP),
 +      KEY(1, 2, KEY_E),
 +      KEY(1, 3, KEY_F),
 +      KEY(1, 4, KEY_G),
 +      KEY(2, 0, KEY_ENTER),
 +      KEY(2, 1, KEY_I),
 +      KEY(2, 2, KEY_J),
 +      KEY(2, 3, KEY_K),
 +      KEY(2, 4, KEY_3),
 +      KEY(3, 0, KEY_M),
 +      KEY(3, 1, KEY_N),
 +      KEY(3, 2, KEY_O),
 +      KEY(3, 3, KEY_P),
 +      KEY(3, 4, KEY_Q),
 +      KEY(4, 0, KEY_R),
 +      KEY(4, 1, KEY_4),
 +      KEY(4, 2, KEY_T),
 +      KEY(4, 3, KEY_U),
 +      KEY(4, 4, KEY_D),
 +      KEY(5, 0, KEY_V),
 +      KEY(5, 1, KEY_W),
 +      KEY(5, 2, KEY_L),
 +      KEY(5, 3, KEY_S),
 +      KEY(5, 4, KEY_H),
 +      0
 +};
 +
 +static struct omap_kp_platform_data sdp3430_kp_data = {
 +      .rows           = 5,
 +      .cols           = 6,
 +      .keymap         = sdp3430_keymap,
 +      .keymapsize     = ARRAY_SIZE(sdp3430_keymap),
 +      .rep            = 1,
 +};
 +
 +static struct platform_device sdp3430_kp_device = {
 +      .name           = "omap_twl4030keypad",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data  = &sdp3430_kp_data,
 +      },
 +};
 +
 +static int ts_gpio;
 +
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +static int twl4030_rtc_init(void)
 +{
 +      int ret = 0;
 +
 +      /* 3430ES2.0 doesn't have msecure/gpio-22 line connected to T2 */
 +      if (is_device_type_gp() && is_sil_rev_less_than(OMAP3430_REV_ES2_0)) {
 +              u32 msecure_pad_config_reg = omap_ctrl_base_get() + 0xA3C;
 +              int mux_mask = 0x04;
 +              u16 tmp;
 +
 +              ret = omap_request_gpio(TWL4030_MSECURE_GPIO);
 +              if (ret < 0) {
 +                      printk(KERN_ERR "twl4030_rtc_init: can't"
 +                              "reserve GPIO:%d !\n", TWL4030_MSECURE_GPIO);
 +                      goto out;
 +              }
 +              /*
 +               * TWL4030 will be in secure mode if msecure line from OMAP
 +               * is low. Make msecure line high in order to change the
 +               * TWL4030 RTC time and calender registers.
 +               */
 +              omap_set_gpio_direction(TWL4030_MSECURE_GPIO, 0);
 +
 +              tmp = omap_readw(msecure_pad_config_reg);
 +              tmp &= 0xF8; /* To enable mux mode 03/04 = GPIO_RTC */
 +              tmp |= mux_mask;/* To enable mux mode 03/04 = GPIO_RTC */
 +              omap_writew(tmp, msecure_pad_config_reg);
 +
 +              omap_set_gpio_dataout(TWL4030_MSECURE_GPIO, 1);
 +      }
 +out:
 +      return ret;
 +}
 +
 +static void twl4030_rtc_exit(void)
 +{
 +      if (is_device_type_gp() &&
 +                      is_sil_rev_less_than(OMAP3430_REV_ES2_0)) {
 +              omap_free_gpio(TWL4030_MSECURE_GPIO);
 +      }
 +}
 +
 +static struct twl4030rtc_platform_data sdp3430_twl4030rtc_data = {
 +      .init = &twl4030_rtc_init,
 +      .exit = &twl4030_rtc_exit,
 +};
 +
 +static struct platform_device sdp3430_twl4030rtc_device = {
 +      .name = "twl4030_rtc",
 +      .id = -1,
 +      .dev = {
 +      .platform_data = &sdp3430_twl4030rtc_data,
 +      },
 +};
 +#endif
 +
 +/**
 + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq
 + *
 + * @return - void. If request gpio fails then Flag KERN_ERR.
 + */
 +static void ads7846_dev_init(void)
 +{
 +      if (omap_request_gpio(ts_gpio) < 0) {
 +              printk(KERN_ERR "can't get ads746 pen down GPIO\n");
 +              return;
 +      }
 +
 +      omap_set_gpio_direction(ts_gpio, 1);
 +
 +      omap_set_gpio_debounce(ts_gpio, 1);
 +      omap_set_gpio_debounce_time(ts_gpio, 0xa);
 +}
 +
 +static int ads7846_get_pendown_state(void)
 +{
 +      return !omap_get_gpio_datain(ts_gpio);
 +}
 +
 +/*
 + * This enable(1)/disable(0) the voltage for TS: uses twl4030 calls
 + */
 +static int ads7846_vaux_control(int vaux_cntrl)
 +{
 +      int ret = 0;
 +
 +#ifdef CONFIG_TWL4030_CORE
 +      /* check for return value of ldo_use: if success it returns 0 */
 +      if (vaux_cntrl == VAUX_ENABLE) {
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      ENABLE_VAUX3_DEDICATED, TWL4030_VAUX3_DEDICATED))
 +                      return -EIO;
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      ENABLE_VAUX3_DEV_GRP, TWL4030_VAUX3_DEV_GRP))
 +                      return -EIO;
 +      } else if (vaux_cntrl == VAUX_DISABLE) {
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      0x00, TWL4030_VAUX3_DEDICATED))
 +                      return -EIO;
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      0x00, TWL4030_VAUX3_DEV_GRP))
 +                      return -EIO;
 +      }
 +#else
 +      ret = -EIO;
 +#endif
 +      return ret;
 +}
 +
 +static struct ads7846_platform_data tsc2046_config __initdata = {
 +      .get_pendown_state      = ads7846_get_pendown_state,
 +      .keep_vref_on           = 1,
 +      .vaux_control           = ads7846_vaux_control,
 +};
 +
 +
 +static struct omap2_mcspi_device_config tsc2046_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,  /* 0: slave, 1: master */
 +};
 +
 +static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
 +      [0] = {
 +              /*
 +               * TSC2046 operates at a max freqency of 2MHz, so
 +               * operate slightly below at 1.5MHz
 +               */
 +              .modalias               = "ads7846",
 +              .bus_num                = 1,
 +              .chip_select            = 0,
 +              .max_speed_hz           = 1500000,
 +              .controller_data        = &tsc2046_mcspi_config,
 +              .irq                    = 0,
 +              .platform_data          = &tsc2046_config,
 +      },
 +};
 +
 +static struct platform_device sdp3430_lcd_device = {
 +      .name           = "sdp2430_lcd",
 +      .id             = -1,
 +};
 +
 +static struct platform_device *sdp3430_devices[] __initdata = {
 +      &sdp3430_smc91x_device,
 +      &sdp3430_kp_device,
 +      &sdp3430_lcd_device,
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +      &sdp3430_twl4030rtc_device,
 +#endif
 +};
 +
 +static inline void __init sdp3430_init_smc91x(void)
 +{
 +      int eth_cs;
 +      unsigned long cs_mem_base;
 +      int eth_gpio = 0;
 +
 +      eth_cs = SDP3430_SMC91X_CS;
 +
 +      if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
 +              printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
 +              return;
 +      }
 +
 +      sdp3430_smc91x_resources[0].start = cs_mem_base + 0x0;
 +      sdp3430_smc91x_resources[0].end   = cs_mem_base + 0xf;
 +      udelay(100);
 +
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0))
 +              eth_gpio = OMAP34XX_ETHR_GPIO_IRQ_SDPV2;
 +      else
 +              eth_gpio = OMAP34XX_ETHR_GPIO_IRQ_SDPV1;
 +
 +      sdp3430_smc91x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio);
 +
 +      if (omap_request_gpio(eth_gpio) < 0) {
 +              printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
 +                      eth_gpio);
 +              return;
 +      }
 +      omap_set_gpio_direction(eth_gpio, 1);
 +}
 +
 +static void __init omap_3430sdp_init_irq(void)
 +{
 +      omap2_init_common_hw(hyb18m512160af6_sdrc_params);
 +      omap_init_irq();
 +      omap_gpio_init();
 +      sdp3430_init_smc91x();
 +}
 +
 +static struct omap_uart_config sdp3430_uart_config __initdata = {
 +      .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
 +};
 +
 +static struct omap_lcd_config sdp3430_lcd_config __initdata = {
 +      .ctrl_name      = "internal",
 +};
 +
 +static struct omap_mmc_config sdp3430_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled        = 1,
 +              .wire4          = 1,
 +      },
 +};
 +
 +static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 +      { OMAP_TAG_UART,        &sdp3430_uart_config },
 +      {OMAP_TAG_LCD,          &sdp3430_lcd_config},
 +      {OMAP_TAG_MMC,          &sdp3430_mmc_config },
 +};
 +
 +static int __init omap3430_i2c_init(void)
 +{
 +      omap_register_i2c_bus(1, 2600, NULL, 0);
 +      omap_register_i2c_bus(2, 400, NULL, 0);
 +      omap_register_i2c_bus(3, 400, NULL, 0);
 +      return 0;
 +}
 +
 +extern void __init sdp3430_flash_init(void);
 +
 +static void __init omap_3430sdp_init(void)
 +{
 +      platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices));
 +      omap_board_config = sdp3430_config;
 +      omap_board_config_size = ARRAY_SIZE(sdp3430_config);
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0))
 +              ts_gpio = OMAP34XX_TS_GPIO_IRQ_SDPV2;
 +      else
 +              ts_gpio = OMAP34XX_TS_GPIO_IRQ_SDPV1;
 +      sdp3430_spi_board_info[0].irq = OMAP_GPIO_IRQ(ts_gpio);
 +      spi_register_board_info(sdp3430_spi_board_info,
 +                              ARRAY_SIZE(sdp3430_spi_board_info));
 +      ads7846_dev_init();
 +      sdp3430_flash_init();
 +      twl4030_bci_battery_init();
 +      omap_serial_init();
 +      usb_musb_init();
 +      usb_ehci_init();
 +      hsmmc_init();
 +}
 +
 +static void __init omap_3430sdp_map_io(void)
 +{
 +      omap2_set_globals_343x();
 +      omap2_map_common_io();
 +}
 +arch_initcall(omap3430_i2c_init);
 +
 +MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 +      /* Maintainer: Syed Khasim - Texas Instruments Inc */
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = omap_3430sdp_map_io,
 +      .init_irq       = omap_3430sdp_init_irq,
 +      .init_machine   = omap_3430sdp_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index adc4ee649fde0a84fdc116a9cf597d109f8d5485,0000000000000000000000000000000000000000..e3f74e62a78873bddf286762e9d8df138683ab01
mode 100644,000000..100644
--- /dev/null
@@@ -1,101 -1,0 +1,101 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-apollon-keys.c
 + *
 + * Copyright (C) 2007 Samsung Electronics
 + * Author: Kyungmin Park <kyungmin.park@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/input.h>
 +#include <linux/gpio_keys.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
 +
 +#define SW_ENTER_GPIO16               16
 +#define SW_UP_GPIO17          17
 +#define SW_DOWN_GPIO58                58
 +#define SW_LEFT_GPIO95                95
 +#define SW_RIGHT_GPIO96               96
 +#define SW_ESC_GPIO97         97
 +
 +static struct gpio_keys_button apollon_gpio_keys_buttons[] = {
 +      [0] = {
 +              .code           = KEY_ENTER,
 +              .gpio           = SW_ENTER_GPIO16,
 +              .desc           = "enter sw",
 +      },
 +      [1] = {
 +              .code           = KEY_UP,
 +              .gpio           = SW_UP_GPIO17,
 +              .desc           = "up sw",
 +      },
 +      [2] = {
 +              .code           = KEY_DOWN,
 +              .gpio           = SW_DOWN_GPIO58,
 +              .desc           = "down sw",
 +      },
 +      [3] = {
 +              .code           = KEY_LEFT,
 +              .gpio           = SW_LEFT_GPIO95,
 +              .desc           = "left sw",
 +      },
 +      [4] = {
 +              .code           = KEY_RIGHT,
 +              .gpio           = SW_RIGHT_GPIO96,
 +              .desc           = "right sw",
 +      },
 +      [5] = {
 +              .code           = KEY_ESC,
 +              .gpio           = SW_ESC_GPIO97,
 +              .desc           = "esc sw",
 +      },
 +};
 +
 +static struct gpio_keys_platform_data apollon_gpio_keys = {
 +      .buttons                = apollon_gpio_keys_buttons,
 +      .nbuttons               = ARRAY_SIZE(apollon_gpio_keys_buttons),
 +};
 +
 +static struct platform_device apollon_gpio_keys_device = {
 +      .name                   = "gpio-keys",
 +      .id                     = -1,
 +      .dev                    = {
 +              .platform_data  = &apollon_gpio_keys,
 +      },
 +};
 +
 +static void __init apollon_sw_init(void)
 +{
 +      /* Enter SW - Y11 */
 +      omap_cfg_reg(Y11_242X_GPIO16);
 +      /* Up SW - AA12 */
 +      omap_cfg_reg(AA12_242X_GPIO17);
 +      /* Down SW - AA8 */
 +      omap_cfg_reg(AA8_242X_GPIO58);
 +
 +      if (apollon_plus()) {
 +              /* Left SW - P18 */
 +              omap_cfg_reg(P18_24XX_GPIO95);
 +              /* Right SW - M18 */
 +              omap_cfg_reg(M18_24XX_GPIO96);
 +              /* Esc SW - L14 */
 +              omap_cfg_reg(L14_24XX_GPIO97);
 +      } else
 +              apollon_gpio_keys.nbuttons = 3;
 +}
 +
 +static int __init omap_apollon_keys_init(void)
 +{
 +      apollon_sw_init();
 +
 +      return platform_device_register(&apollon_gpio_keys_device);
 +}
 +
 +arch_initcall(omap_apollon_keys_init);
index f77167e1af004440e74e524120c331c7f4420ea0,0000000000000000000000000000000000000000..71fccd9b3f3539bb6cfbcc1fea59affc2f75900c
mode 100644,000000..100644
--- /dev/null
@@@ -1,88 -1,0 +1,88 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mmc.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-apollon-mmc.c
 + *
 + * Copyright (C) 2005-2007 Samsung Electronics
 + * Author: Kyungmin Park <kyungmin.park@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +
++#include <mach/gpio.h>
++#include <mach/mmc.h>
 +
 +#ifdef CONFIG_MMC_OMAP
 +
 +static struct device *mmc_device;
 +
 +static int apollon_mmc_set_power(struct device *dev, int slot, int power_on,
 +                                      int vdd)
 +{
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
 +              power_on ? "on" : "off", vdd);
 +#endif
 +      if (slot != 0) {
 +              dev_err(dev, "No such slot %d\n", slot + 1);
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +static int apollon_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
 +{
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
 +              bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
 +#endif
 +      if (slot != 0) {
 +              dev_err(dev, "No such slot %d\n", slot + 1);
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +static int apollon_mmc_late_init(struct device *dev)
 +{
 +      mmc_device = dev;
 +
 +      return 0;
 +}
 +
 +static void apollon_mmc_cleanup(struct device *dev)
 +{
 +}
 +
 +static struct omap_mmc_platform_data apollon_mmc_data = {
 +      .nr_slots                       = 1,
 +      .switch_slot                    = NULL,
 +      .init                           = apollon_mmc_late_init,
 +      .cleanup                        = apollon_mmc_cleanup,
 +      .slots[0]       = {
 +              .set_power              = apollon_mmc_set_power,
 +              .set_bus_mode           = apollon_mmc_set_bus_mode,
 +              .get_ro                 = NULL,
 +              .get_cover_state        = NULL,
 +              .ocr_mask               = MMC_VDD_30_31 | MMC_VDD_31_32 |
 +                                        MMC_VDD_32_33 | MMC_VDD_33_34,
 +              .name                   = "mmcblk",
 +      },
 +};
 +
 +void __init apollon_mmc_init(void)
 +{
 +      omap_set_mmc_info(1, &apollon_mmc_data);
 +}
 +
 +#else /* !CONFIG_MMC_OMAP */
 +
 +void __init apollon_mmc_init(void)
 +{
 +}
 +
 +#endif        /* CONFIG_MMC_OMAP */
index 41542a034a26a1ac8682a631bb2213f48ce48b55,989ad152d7f87105c6b02a1ea4bf0c7fdbc3cd00..e76328062c0d2e754dabbaec73e0d2f537340e0e
  #include <linux/leds.h>
  #include <linux/err.h>
  #include <linux/clk.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc210x.h>
  
- #include <asm/hardware.h>
 +#include <asm/io.h>
+ #include <mach/hardware.h>
  #include <asm/mach-types.h>
  #include <asm/mach/arch.h>
  #include <asm/mach/flash.h>
  
- #include <asm/arch/gpio.h>
- #include <asm/arch/led.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/gpmc.h>
+ #include <mach/gpio.h>
+ #include <mach/led.h>
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/board.h>
+ #include <mach/common.h>
+ #include <mach/gpmc.h>
 -#include <mach/control.h>
  
  /* LED & Switch macros */
  #define LED0_GPIO13           13
Simple merge
index 84b3f4e9e7f601c8ea9550414216e2679fd92afa,0000000000000000000000000000000000000000..0916a3ca5df3d6a8cabcb08a46417a4b6e2ad188
mode 100644,000000..100644
--- /dev/null
@@@ -1,266 -1,0 +1,266 @@@
- #include <asm/arch/mmc.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-h4-mmc.c
 + *
 + * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
 + * Authors: David Cohen <david.cohen@indt.org.br>
 + *          Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
 + *
 + * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Juha Yrjola
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
++#include <mach/mmc.h>
 +
 +#include <asm/mach-types.h>
 +#include <linux/delay.h>
 +#include <linux/i2c/menelaus.h>
 +
 +#ifdef CONFIG_MMC_OMAP
 +
 +/* Bit mask for slots detection interrupts */
 +#define SD1_CD_ST     (1 << 0)
 +#define SD2_CD_ST     (1 << 1)
 +
 +static int slot1_cover_open;
 +static int slot2_cover_open;
 +static struct device *mmc_device;
 +
 +/*
 + * VMMC --> slot 1
 + * VDCDC3_APE, VMCS2_APE --> slot 2
 + */
 +
 +static int h4_mmc_switch_slot(struct device *dev, int slot)
 +{
 +      int r = 0;
 +
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Choose slot %d\n", slot + 1);
 +#endif
 +      if (slot == 0) {
 +              r = menelaus_enable_slot(2, 0);
 +              r |= menelaus_enable_slot(1, 1);
 +      } else {
 +              r = menelaus_enable_slot(1, 0);
 +              r |= menelaus_enable_slot(2, 1);
 +      }
 +
 +      return r ? -ENODEV : 0;
 +}
 +
 +static int h4_mmc_set_power(struct device *dev, int slot, int power_on,
 +                              int vdd)
 +{
 +      int mV = 0;
 +
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
 +              power_on ? "on" : "off", vdd);
 +#endif
 +      if (slot == 0) {
 +              if (!power_on)
 +                      return menelaus_set_vmmc(3000);
 +              switch (1 << vdd) {
 +                      case MMC_VDD_33_34:
 +                      case MMC_VDD_32_33:
 +                      case MMC_VDD_31_32:
 +                              mV = 3100;
 +                              break;
 +                      case MMC_VDD_30_31:
 +                              mV = 3000;
 +                              break;
 +                      case MMC_VDD_28_29:
 +                              mV = 2800;
 +                              break;
 +                      case MMC_VDD_165_195:
 +                              mV = 1850;
 +                              break;
 +                      default:
 +                              BUG();
 +              }
 +              return menelaus_set_vmmc(mV);
 +      } else {
 +              if (!power_on)
 +                      return menelaus_set_vdcdc(3, 3000);
 +              switch (1 << vdd) {
 +                      case MMC_VDD_33_34:
 +                      case MMC_VDD_32_33:
 +                              mV = 3300;
 +                              break;
 +                      case MMC_VDD_30_31:
 +                      case MMC_VDD_29_30:
 +                              mV = 3000;
 +                              break;
 +                      case MMC_VDD_28_29:
 +                      case MMC_VDD_27_28:
 +                              mV = 2800;
 +                              break;
 +                      case MMC_VDD_24_25:
 +                      case MMC_VDD_23_24:
 +                              mV = 2400;
 +                              break;
 +                      case MMC_VDD_22_23:
 +                      case MMC_VDD_21_22:
 +                              mV = 2200;
 +                              break;
 +                      case MMC_VDD_20_21:
 +                              mV = 2000;
 +                              break;
 +                      case MMC_VDD_165_195:
 +                              mV = 1800;
 +                              break;
 +                      default:
 +                              BUG();
 +              }
 +              return menelaus_set_vdcdc(3, mV);
 +      }
 +      return 0;
 +}
 +
 +static int h4_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
 +{
 +      int r = 0;
 +
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1,
 +              bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
 +#endif
 +      BUG_ON(slot != 0 && slot != 1);
 +      slot++;
 +      switch (bus_mode) {
 +      case MMC_BUSMODE_OPENDRAIN:
 +              r = menelaus_set_mmc_opendrain(slot, 1);
 +              break;
 +      case MMC_BUSMODE_PUSHPULL:
 +              r = menelaus_set_mmc_opendrain(slot, 0);
 +              break;
 +      default:
 +              BUG();
 +      }
 +      if (r != 0 && printk_ratelimit()) {
 +              dev_err(dev, "MMC: unable to set bus mode for slot %d\n",
 +                      slot);
 +      }
 +      return r;
 +}
 +
 +static int h4_mmc_slot1_cover_state(struct device *dev, int slot)
 +{
 +      BUG_ON(slot != 0);
 +      return slot1_cover_open;
 +}
 +
 +static int h4_mmc_slot2_cover_state(struct device *dev, int slot)
 +{
 +      BUG_ON(slot != 1);
 +      return slot2_cover_open;
 +}
 +
 +static void h4_mmc_slot_callback(void *data, u8 card_mask)
 +{
 +      int cover_open;
 +
 +      cover_open = (card_mask & SD1_CD_ST) ? 0 : 1;
 +      if (cover_open != slot1_cover_open) {
 +              slot1_cover_open = cover_open;
 +              omap_mmc_notify_cover_event(mmc_device, 0, slot1_cover_open);
 +      }
 +
 +      cover_open = (card_mask & SD2_CD_ST) ? 0 : 1;
 +      if (cover_open != slot2_cover_open) {
 +              slot2_cover_open = cover_open;
 +              omap_mmc_notify_cover_event(mmc_device, 1, slot2_cover_open);
 +      }
 +}
 +
 +static int h4_mmc_late_init(struct device *dev)
 +{
 +      int r;
 +
 +      mmc_device = dev;
 +
 +      r = menelaus_set_mmc_slot(1, 0, 0, 1);
 +      if (r < 0)
 +              goto out;
 +      r = menelaus_set_mmc_slot(2, 0, 0, 1);
 +      if (r < 0)
 +              goto out;
 +
 +      r = menelaus_get_slot_pin_states();
 +      if (r < 0)
 +              goto out;
 +
 +      if (r & SD1_CD_ST)
 +              slot1_cover_open = 1;
 +      else
 +              slot1_cover_open = 0;
 +
 +      /* Slot pin bits seem to be inversed until first swith change,
 +       * but just for slot 2
 +       */
 +      if ((r == 0xf) || (r == (0xf & ~SD2_CD_ST)))
 +              r = ~r;
 +
 +      if (r & SD2_CD_ST)
 +              slot2_cover_open = 1;
 +      else
 +              slot2_cover_open = 0;
 +
 +      r = menelaus_register_mmc_callback(h4_mmc_slot_callback, NULL);
 +
 +out:
 +      return r;
 +}
 +
 +static void h4_mmc_cleanup(struct device *dev)
 +{
 +      menelaus_unregister_mmc_callback();
 +}
 +
 +static struct omap_mmc_platform_data h4_mmc_data = {
 +      .nr_slots               = 2,
 +      .switch_slot            = h4_mmc_switch_slot,
 +      .init                   = h4_mmc_late_init,
 +      .cleanup                = h4_mmc_cleanup,
 +      .slots[0] = {
 +              .set_power      = h4_mmc_set_power,
 +              .set_bus_mode   = h4_mmc_set_bus_mode,
 +              .get_ro         = NULL,
 +              .get_cover_state= h4_mmc_slot1_cover_state,
 +              .ocr_mask       = MMC_VDD_165_195 |
 +                                MMC_VDD_28_29 | MMC_VDD_30_31 |
 +                                MMC_VDD_32_33 | MMC_VDD_33_34,
 +              .name           = "slot1",
 +      },
 +      .slots[1] = {
 +              .set_power      = h4_mmc_set_power,
 +              .set_bus_mode   = h4_mmc_set_bus_mode,
 +              .get_ro         = NULL,
 +              .get_cover_state= h4_mmc_slot2_cover_state,
 +              .ocr_mask       = MMC_VDD_165_195 | MMC_VDD_20_21 |
 +                                MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 |
 +                                MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 |
 +                                MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 |
 +                                MMC_VDD_33_34,
 +              .name           = "slot2",
 +      },
 +};
 +
 +void __init h4_mmc_init(void)
 +{
 +      omap_set_mmc_info(1, &h4_mmc_data);
 +}
 +
 +#else
 +
 +void __init h4_mmc_init(void)
 +{
 +}
 +
 +#endif
 +
index 5d3088cddf111a85d880cc77b4500c2d16d1ef91,9e2624ca70a2493cb0320d0373d446e91d1526da..54ecab9ed5a8e62f551eace3baa7cea495359503
  #include <linux/input.h>
  #include <linux/err.h>
  #include <linux/clk.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c/menelaus.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc210x.h>
 +
 +#include <media/v4l2-int-device.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/mach-types.h>
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  #include <asm/mach/flash.h>
  
- #include <asm/arch/control.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/gpioexpander.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/irda.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/gpmc.h>
+ #include <mach/control.h>
+ #include <mach/gpio.h>
+ #include <mach/gpioexpander.h>
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/irda.h>
+ #include <mach/board.h>
+ #include <mach/common.h>
+ #include <mach/keypad.h>
 -#include <mach/menelaus.h>
+ #include <mach/dma.h>
+ #include <mach/gpmc.h>
  
  #include <asm/io.h>
  
index 1998d62c46c14b2bd5ad8123a49d53ab42455bcb,0000000000000000000000000000000000000000..7f672c6b0b55e30b997598f904e30ab0cfb486b5
mode 100644,000000..100644
--- /dev/null
@@@ -1,253 -1,0 +1,253 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-ldp.c
 + *
 + * Copyright (C) 2008 Texas Instruments Inc.
 + * Nishant Kamat <nskamat@ti.com>
 + *
 + * Modified from mach-omap2/board-3430sdp.c
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/input.h>
 +#include <linux/workqueue.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/ads7846.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/i2c/twl4030-rtc.h>
 +
- #include <asm/arch/mcspi.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/usb-musb.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +
- #include <asm/arch/control.h>
++#include <mach/mcspi.h>
++#include <mach/gpio.h>
++#include <mach/board.h>
++#include <mach/common.h>
++#include <mach/gpmc.h>
++#include <mach/hsmmc.h>
++#include <mach/usb-musb.h>
 +
 +#include <asm/io.h>
 +#include <asm/delay.h>
++#include <mach/control.h>
 +
 +#define ENABLE_VAUX1_DEDICATED        0x03
 +#define ENABLE_VAUX1_DEV_GRP  0x20
 +
 +#define TWL4030_MSECURE_GPIO  22
 +
 +static int ts_gpio;
 +
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +static int twl4030_rtc_init(void)
 +{
 +      int ret = 0;
 +
 +      /* 3430ES2.0 doesn't have msecure/gpio-22 line connected to T2 */
 +      if (is_device_type_gp() && is_sil_rev_less_than(OMAP3430_REV_ES2_0)) {
 +              u32 msecure_pad_config_reg = omap_ctrl_base_get() + 0xA3C;
 +              int mux_mask = 0x04;
 +              u16 tmp;
 +
 +              ret = omap_request_gpio(TWL4030_MSECURE_GPIO);
 +              if (ret < 0) {
 +                      printk(KERN_ERR "twl4030_rtc_init: can't"
 +                              "reserve GPIO:%d !\n", TWL4030_MSECURE_GPIO);
 +                      goto out;
 +              }
 +              /*
 +               * TWL4030 will be in secure mode if msecure line from OMAP
 +               * is low. Make msecure line high in order to change the
 +               * TWL4030 RTC time and calender registers.
 +               */
 +              omap_set_gpio_direction(TWL4030_MSECURE_GPIO, 0);
 +
 +              tmp = omap_readw(msecure_pad_config_reg);
 +              tmp &= 0xF8;    /* To enable mux mode 03/04 = GPIO_RTC */
 +              tmp |= mux_mask;/* To enable mux mode 03/04 = GPIO_RTC */
 +              omap_writew(tmp, msecure_pad_config_reg);
 +
 +              omap_set_gpio_dataout(TWL4030_MSECURE_GPIO, 1);
 +      }
 +out:
 +      return ret;
 +}
 +
 +static void twl4030_rtc_exit(void)
 +{
 +      omap_free_gpio(TWL4030_MSECURE_GPIO);
 +}
 +
 +static struct twl4030rtc_platform_data ldp_twl4030rtc_data = {
 +      .init = &twl4030_rtc_init,
 +      .exit = &twl4030_rtc_exit,
 +};
 +
 +static struct platform_device ldp_twl4030rtc_device = {
 +      .name           = "twl4030_rtc",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data  = &ldp_twl4030rtc_data,
 +      },
 +};
 +#endif
 +
 +/**
 + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq
 + *
 + * @return - void. If request gpio fails then Flag KERN_ERR.
 + */
 +static void ads7846_dev_init(void)
 +{
 +      if (omap_request_gpio(ts_gpio) < 0) {
 +              printk(KERN_ERR "can't get ads746 pen down GPIO\n");
 +              return;
 +      }
 +
 +      omap_set_gpio_direction(ts_gpio, 1);
 +
 +      omap_set_gpio_debounce(ts_gpio, 1);
 +      omap_set_gpio_debounce_time(ts_gpio, 0xa);
 +}
 +
 +static int ads7846_get_pendown_state(void)
 +{
 +      return !omap_get_gpio_datain(ts_gpio);
 +}
 +
 +/*
 + * This enable(1)/disable(0) the voltage for TS: uses twl4030 calls
 + */
 +static int ads7846_vaux_control(int vaux_cntrl)
 +{
 +      int ret = 0;
 +
 +#ifdef CONFIG_TWL4030_CORE
 +      /* check for return value of ldo_use: if success it returns 0 */
 +      if (vaux_cntrl == VAUX_ENABLE) {
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      ENABLE_VAUX1_DEDICATED, TWL4030_VAUX1_DEDICATED))
 +                      return -EIO;
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      ENABLE_VAUX1_DEV_GRP, TWL4030_VAUX1_DEV_GRP))
 +                      return -EIO;
 +      } else if (vaux_cntrl == VAUX_DISABLE) {
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      0x00, TWL4030_VAUX1_DEDICATED))
 +                      return -EIO;
 +              if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                      0x00, TWL4030_VAUX1_DEV_GRP))
 +                      return -EIO;
 +      }
 +#else
 +      ret = -EIO;
 +#endif
 +      return ret;
 +}
 +
 +static struct ads7846_platform_data tsc2046_config __initdata = {
 +      .get_pendown_state      = ads7846_get_pendown_state,
 +      .keep_vref_on           = 1,
 +      .vaux_control           = ads7846_vaux_control,
 +};
 +
 +
 +static struct omap2_mcspi_device_config tsc2046_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,  /* 0: slave, 1: master */
 +};
 +
 +static struct spi_board_info ldp_spi_board_info[] __initdata = {
 +      [0] = {
 +              /*
 +               * TSC2046 operates at a max freqency of 2MHz, so
 +               * operate slightly below at 1.5MHz
 +               */
 +              .modalias               = "ads7846",
 +              .bus_num                = 1,
 +              .chip_select            = 0,
 +              .max_speed_hz           = 1500000,
 +              .controller_data        = &tsc2046_mcspi_config,
 +              .irq                    = 0,
 +              .platform_data          = &tsc2046_config,
 +      },
 +};
 +
 +static struct platform_device *ldp_devices[] __initdata = {
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +      &ldp_twl4030rtc_device,
 +#endif
 +};
 +
 +static void __init omap_ldp_init_irq(void)
 +{
 +      omap2_init_common_hw(NULL);
 +      omap_init_irq();
 +      omap_gpio_init();
 +}
 +
 +static struct omap_uart_config ldp_uart_config __initdata = {
 +      .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
 +};
 +
 +static struct omap_mmc_config ldp_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled        = 1,
 +              .wire4          = 1,
 +      },
 +};
 +
 +static struct omap_board_config_kernel ldp_config[] __initdata = {
 +      { OMAP_TAG_UART,        &ldp_uart_config },
 +      { OMAP_TAG_MMC,         &ldp_mmc_config },
 +};
 +
 +static int __init omap_i2c_init(void)
 +{
 +      omap_register_i2c_bus(1, 2600, NULL, 0);
 +      omap_register_i2c_bus(2, 400, NULL, 0);
 +      omap_register_i2c_bus(3, 400, NULL, 0);
 +      return 0;
 +}
 +
 +static void __init omap_ldp_init(void)
 +{
 +      platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
 +      omap_board_config = ldp_config;
 +      omap_board_config_size = ARRAY_SIZE(ldp_config);
 +      ts_gpio = 54;
 +      ldp_spi_board_info[0].irq = OMAP_GPIO_IRQ(ts_gpio);
 +      spi_register_board_info(ldp_spi_board_info,
 +                              ARRAY_SIZE(ldp_spi_board_info));
 +      ads7846_dev_init();
 +      omap_serial_init();
 +      usb_musb_init();
 +      hsmmc_init();
 +}
 +
 +static void __init omap_ldp_map_io(void)
 +{
 +      omap2_set_globals_343x();
 +      omap2_map_common_io();
 +}
 +arch_initcall(omap_i2c_init);
 +
 +MACHINE_START(OMAP_LDP, "OMAP LDP board")
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = omap_ldp_map_io,
 +      .init_irq       = omap_ldp_init_irq,
 +      .init_machine   = omap_ldp_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 233198edbd577ca0db8c577442132fe8177d4caf,0000000000000000000000000000000000000000..ebaf21f689f0688c031573a9d4f32e32c4fc4277
mode 100644,000000..100644
--- /dev/null
@@@ -1,377 -1,0 +1,377 @@@
- #include <asm/arch/eac.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800-audio.c
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Contact: Juha Yrjola
 + *          Jarkko Nikula <jarkko.nikula@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/platform_device.h>
 +#include <linux/spi/tsc2301.h>
 +
 +#include <asm/io.h>
- #include <asm/arch/dsp_common.h>
++#include <mach/eac.h>
 +
++#include <mach/dsp_common.h>
 +
 +#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC)
 +#define AUDIO_ENABLED
 +
 +static struct clk *sys_clkout2;
 +static struct clk *sys_clkout2_src;
 +static struct clk *func96m_clk;
 +static struct device *eac_device;
 +static struct device *tsc2301_device;
 +
 +static int enable_audio;
 +static int audio_ok;
 +static spinlock_t audio_lock;
 +
 +/*
 + * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results
 + * in about 2 mA extra current leak when audios are powered down. The
 + * workaround is to multiplex them to protected mode (with pull-ups enabled)
 + * whenever audio is not being used.
 + */
 +static int eac_mux_disabled = 0;
 +static int clkout2_mux_disabled = 0;
 +static u32 saved_mux[2];
 +
 +#define MUX_EAC_IOP2V(x)              (__force void __iomem *)io_p2v(x)
 +
 +static void n800_enable_eac_mux(void)
 +{
 +      if (!eac_mux_disabled)
 +              return;
 +      __raw_writel(saved_mux[1], MUX_EAC_IOP2V(0x48000124));
 +      eac_mux_disabled = 0;
 +}
 +
 +static void n800_disable_eac_mux(void)
 +{
 +      if (eac_mux_disabled) {
 +              WARN_ON(eac_mux_disabled);
 +              return;
 +      }
 +      saved_mux[1] = __raw_readl(MUX_EAC_IOP2V(0x48000124));
 +      __raw_writel(0x1f1f1f1f, MUX_EAC_IOP2V(0x48000124));
 +      eac_mux_disabled = 1;
 +}
 +
 +static void n800_enable_clkout2_mux(void)
 +{
 +      if (!clkout2_mux_disabled)
 +              return;
 +      __raw_writel(saved_mux[0], MUX_EAC_IOP2V(0x480000e8));
 +      clkout2_mux_disabled = 0;
 +}
 +
 +static void n800_disable_clkout2_mux(void)
 +{
 +      u32 l;
 +
 +      if (clkout2_mux_disabled) {
 +              WARN_ON(clkout2_mux_disabled);
 +              return;
 +      }
 +      saved_mux[0] = __raw_readl(MUX_EAC_IOP2V(0x480000e8));
 +      l = saved_mux[0] & ~0xff;
 +      l |= 0x1f;
 +      __raw_writel(l, MUX_EAC_IOP2V(0x480000e8));
 +      clkout2_mux_disabled = 1;
 +}
 +
 +static int n800_eac_enable_ext_clocks(struct device *dev)
 +{
 +      BUG_ON(tsc2301_device == NULL);
 +      n800_enable_eac_mux();
 +      tsc2301_mixer_enable_mclk(tsc2301_device);
 +
 +      return 0;
 +}
 +
 +static void n800_eac_disable_ext_clocks(struct device *dev)
 +{
 +      BUG_ON(tsc2301_device == NULL);
 +      tsc2301_mixer_disable_mclk(tsc2301_device);
 +      n800_disable_eac_mux();
 +}
 +
 +static int n800_audio_set_power(void *pdata, int dac, int adc)
 +{
 +      BUG_ON(pdata != tsc2301_device);
 +      tsc2301_mixer_set_power(tsc2301_device, dac, adc);
 +
 +      return 0;
 +}
 +
 +static int n800_audio_register_controls(void *pdata, struct snd_card *card)
 +{
 +      BUG_ON(pdata != tsc2301_device);
 +      return tsc2301_mixer_register_controls(tsc2301_device, card);
 +}
 +
 +static struct eac_codec n800_eac_codec = {
 +      .mclk_src = EAC_MCLK_EXT_2x12288000,
 +      .codec_mode = EAC_CODEC_I2S_MASTER,
 +      .codec_conf.i2s.polarity_changed_mode = 0,
 +      .codec_conf.i2s.sync_delay_enable = 0,
 +      .default_rate = 48000,
 +      .set_power = n800_audio_set_power,
 +      .register_controls = n800_audio_register_controls,
 +      .short_name = "TSC2301",
 +};
 +
 +static int n800_register_codec(void)
 +{
 +      int r, do_enable = 0;
 +      unsigned long flags;
 +
 +      n800_eac_codec.private_data = tsc2301_device;
 +      r = eac_register_codec(eac_device, &n800_eac_codec);
 +      if (r < 0)
 +              return r;
 +      spin_lock_irqsave(&audio_lock, flags);
 +      audio_ok = 1;
 +      if (enable_audio)
 +              do_enable = 1;
 +      spin_unlock_irqrestore(&audio_lock, flags);
 +      if (do_enable)
 +              eac_set_mode(eac_device, 1, 1);
 +      return 0;
 +}
 +
 +static void n800_unregister_codec(void)
 +{
 +      audio_ok = 0;
 +      eac_unregister_codec(eac_device);
 +      eac_set_mode(eac_device, 0, 0);
 +}
 +
 +static int n800_eac_init(struct device *dev)
 +{
 +      int r;
 +
 +      BUG_ON(eac_device != NULL);
 +      eac_device = dev;
 +      if (tsc2301_device != NULL) {
 +              r = n800_register_codec();
 +              if (r < 0)
 +                      return r;
 +      }
 +
 +      return 0;
 +}
 +
 +static void n800_eac_cleanup(struct device *dev)
 +{
 +      eac_device = NULL;
 +      if (tsc2301_device != NULL)
 +              n800_unregister_codec();
 +}
 +
 +static int n800_codec_get_clocks(struct device *dev)
 +{
 +      sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
 +      if (IS_ERR(sys_clkout2_src)) {
 +              dev_err(dev, "Could not get sys_clkout2_src clock\n");
 +              return -ENODEV;
 +      }
 +      sys_clkout2 = clk_get(dev, "sys_clkout2");
 +      if (IS_ERR(sys_clkout2)) {
 +              dev_err(dev, "Could not get sys_clkout2 clock\n");
 +              clk_put(sys_clkout2_src);
 +              return -ENODEV;
 +      }
 +      /* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
 +       * 96 MHz as its parent in order to get 12 MHz */
 +      func96m_clk = clk_get(dev, "func_96m_ck");
 +      if (IS_ERR(func96m_clk)) {
 +              dev_err(dev, "Could not get func 96M clock\n");
 +              clk_put(sys_clkout2);
 +              clk_put(sys_clkout2_src);
 +              return -ENODEV;
 +      }
 +
 +      clk_set_parent(sys_clkout2_src, func96m_clk);
 +      clk_set_rate(sys_clkout2, 12000000);
 +
 +      return 0;
 +}
 +
 +static void n800_codec_put_clocks(struct device *dev)
 +{
 +      clk_put(func96m_clk);
 +      clk_put(sys_clkout2);
 +      clk_put(sys_clkout2_src);
 +}
 +
 +static int n800_codec_enable_clock(struct device *dev)
 +{
 +      n800_enable_clkout2_mux();
 +      return clk_enable(sys_clkout2);
 +}
 +
 +static void n800_codec_disable_clock(struct device *dev)
 +{
 +      clk_disable(sys_clkout2);
 +      n800_disable_clkout2_mux();
 +}
 +
 +static int n800_codec_init(struct device *dev)
 +{
 +      int r;
 +
 +      BUG_ON(tsc2301_device != NULL);
 +      tsc2301_device = dev;
 +      if ((r = n800_codec_get_clocks(dev)) < 0)
 +              return r;
 +      if (eac_device != NULL) {
 +              r = n800_register_codec();
 +              if (r < 0) {
 +                      n800_codec_put_clocks(dev);
 +                      return r;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static void n800_codec_cleanup(struct device *dev)
 +{
 +      tsc2301_device = NULL;
 +      if (eac_device != NULL)
 +              n800_unregister_codec();
 +      n800_codec_put_clocks(dev);
 +}
 +
 +static struct eac_platform_data n800_eac_data = {
 +      .init = n800_eac_init,
 +      .cleanup = n800_eac_cleanup,
 +      .enable_ext_clocks = n800_eac_enable_ext_clocks,
 +      .disable_ext_clocks = n800_eac_disable_ext_clocks,
 +};
 +
 +static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = {
 +      {
 +              .name                   = "Headset Amplifier",
 +              .gpio                   = 1,
 +              .deactivate_on_pd       = 1,
 +      }, {
 +              .name                   = "Speaker Amplifier",
 +              .gpio                   = 2,
 +              .def_enable             = 1,
 +              .deactivate_on_pd       = 1,
 +      }, {
 +              .name                   = "Headset Mic Select",
 +              .gpio                   = 3,
 +      }
 +};
 +
 +static struct platform_device retu_headset_device = {
 +      .name           = "retu-headset",
 +      .id             = -1,
 +      .dev            = {
 +              .release        = NULL,
 +      },
 +};
 +
 +void __init n800_audio_init(struct tsc2301_platform_data *tc)
 +{
 +      spin_lock_init(&audio_lock);
 +
 +      if (platform_device_register(&retu_headset_device) < 0)
 +              return;
 +      omap_init_eac(&n800_eac_data);
 +
 +      tc->pll_pdc = 7;
 +      tc->pll_a = 7;
 +      tc->pll_n = 9;
 +      tc->pll_output = 1;
 +      tc->mclk_ratio = TSC2301_MCLK_256xFS;
 +      tc->i2s_sample_rate = TSC2301_I2S_SR_48000;
 +      tc->i2s_format = TSC2301_I2S_FORMAT0;
 +      tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD;
 +      tc->mixer_gpios = n800_mixer_gpios;
 +      tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios);
 +      tc->codec_init = n800_codec_init;
 +      tc->codec_cleanup = n800_codec_cleanup;
 +      tc->enable_clock = n800_codec_enable_clock;
 +      tc->disable_clock = n800_codec_disable_clock;
 +}
 +
 +#else
 +
 +void __init n800_audio_init(struct tsc2301_platform_data *tc)
 +{
 +}
 +
 +#endif
 +
 +#ifdef CONFIG_OMAP_DSP
 +
 +int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage)
 +{
 +#ifdef AUDIO_ENABLED
 +      unsigned long flags;
 +      int do_enable = 0;
 +
 +      spin_lock_irqsave(&audio_lock, flags);
 +
 +      pr_debug("DSP power up request (audio codec %sinitialized)\n",
 +               audio_ok ? "" : "not ");
 +
 +      if (enable_audio)
 +              goto out;
 +      enable_audio = 1;
 +      if (audio_ok)
 +              do_enable = 1;
 +out:
 +      spin_unlock_irqrestore(&audio_lock, flags);
 +      if (do_enable)
 +              eac_set_mode(eac_device, 1, 1);
 +#endif
 +      return 0;
 +}
 +
 +int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage)
 +{
 +#ifdef AUDIO_ENABLED
 +      unsigned long flags;
 +      int do_disable = 0;
 +
 +      spin_lock_irqsave(&audio_lock, flags);
 +
 +      pr_debug("DSP power down request (audio codec %sinitialized)\n",
 +              audio_ok ? "" : "not ");
 +
 +      if (!enable_audio)
 +              goto out;
 +      enable_audio = 0;
 +      if (audio_ok)
 +              do_disable = 1;
 +out:
 +      spin_unlock_irqrestore(&audio_lock, flags);
 +      if (do_disable)
 +              eac_set_mode(eac_device, 0, 0);
 +#endif
 +      return 0;
 +}
 +
 +#endif /* CONFIG_OMAP_DSP */
index 4ea19cca83f991a654d92bd8a003f8baab86cc50,0000000000000000000000000000000000000000..61afd2b2878e8b13dd1f443aad3d1f7de222f63b
mode 100644,000000..100644
--- /dev/null
@@@ -1,42 -1,0 +1,42 @@@
- #include <asm/arch/board.h>
 +/*
 + * Nokia N800 platform-specific data for Bluetooth
 + *
 + * Copyright (C) 2005, 2006 Nokia Corporation
 + * Contact: Ville Tervo <ville.tervo@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/platform_device.h>
++#include <mach/board.h>
 +
 +static struct platform_device n800_bt_device = {
 +      .name           = "hci_h4p",
 +      .id             = -1,
 +      .num_resources  = 0,
 +};
 +
 +void __init n800_bt_init(void)
 +{
 +      const struct omap_bluetooth_config *bt_config;
 +
 +      bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT,
 +                                           struct omap_bluetooth_config);
 +      n800_bt_device.dev.platform_data = (void *) bt_config;
 +      if (platform_device_register(&n800_bt_device) < 0)
 +              BUG();
 +}
 +
index 701dedaa2583335b23e0ab2d0f7203172759674a,0000000000000000000000000000000000000000..6272263e39867dac0a8aaf4cf986a52e60a72961
mode 100644,000000..100644
--- /dev/null
@@@ -1,377 -1,0 +1,377 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
 +/*
 + * arch/arm/mach-omap2/board-n800-camera.c
 + *
 + * Copyright (C) 2007 Nokia Corporation
 + *
 + * Contact: Sakari Ailus <sakari.ailus@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/clk.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/videodev2.h>
 +#include <linux/i2c/menelaus.h>
 +
 +#include <media/v4l2-int-device.h>
 +
 +#include <asm/mach-types.h>
 +
++#include <mach/gpio.h>
++#include <mach/board.h>
 +
 +#include <../drivers/cbus/retu.h>
 +#include <../drivers/media/video/tcm825x.h>
 +
 +#include "board-n800.h"
 +
 +#if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 +
 +#define OMAP24XX_CAMERA_JAM_HACK
 +
 +#ifdef OMAP24XX_CAMERA_JAM_HACK
 +/*
 + * We don't need to check every pixel to assume that the frame is
 + * corrupt and the sensor is jammed. CHECK_X and CHECK_Y are the
 + * number of u32s to check per line / row, plus there are two lines in
 + * the bottom of the frame.
 + */
 +#define CHECK_X 8
 +#define CHECK_Y 6
 +/*
 + * Start checking after this many frames since resetting the sensor.
 + * Sometimes the first frame(s) is(/are) black which could trigger
 + * unwanted reset(s).
 + */
 +#define JAM_CHECK_AFTER 3
 +/*
 + * If the sensor is quickly brought into bright conditions from dark,
 + * it may temporarily be saturated, leaving out the normal background
 + * noise. This many saturated frames may go through before the sensor
 + * is considered jammed.
 + */
 +#define SATURATED_MAX 30
 +#endif
 +
 +#define N800_CAM_SENSOR_RESET_GPIO    53
 +
 +static int sensor_okay;
 +#ifdef OMAP24XX_CAMERA_JAM_HACK
 +static int frames_after_reset;
 +static int saturated_count;
 +#endif
 +
 +const static struct tcm825x_reg tcm825x_regs_n800[] = {
 +      /* initial settings for 2.5 V */
 +      {0x00, 0x03}, {0x03, 0x29}, {0xaa, 0x2a}, {0xc0, 0x2b},
 +      {0x10, 0x2c}, {0x4c, 0x2d}, {0x9c, 0x3f},
 +
 +      /* main settings */
 +      {0x00, 0x00}, {0x30, 0x01}, {0x0e, 0x02}, /* initial */
 +      {0x0f, 0x04}, {0x02, 0x05}, {0x0d, 0x06}, {0xc0, 0x07},
 +      {0x38, 0x08}, {0x50, 0x09}, {0x80, 0x0a}, {0x40, 0x0b},
 +      {0x40, 0x0c}, {0x00, 0x0d}, {0x04, 0x0e}, {0x04, 0x0f},
 +      {0x22, 0x10}, {0x96, 0x11}, {0xf0, 0x12}, {0x08, 0x13},
 +      {0x08, 0x14}, {0x30, 0x15}, {0x30, 0x16}, {0x01, 0x17},
 +      {0x40, 0x18}, {0x87, 0x19}, {0x2b, 0x1a}, {0x84, 0x1b},
 +      {0x52, 0x1c}, {0x44, 0x1d}, {0x68, 0x1e}, {0x00, 0x1f},
 +      {0x00, 0x20}, {0x01, 0x21}, {0x27, 0x22}, {0x40, 0x23},
 +      {0x27, 0x24}, {0x5f, 0x25}, {0x00, 0x26}, {0x16, 0x27},
 +      {0x23, 0x28}, /* initial */ /* initial */ /* initial */
 +      /* initial */ /* initial */ {0x00, 0x2e}, {0x00, 0x2f},
 +      {0x00, 0x30}, {0x00, 0x31}, {0x00, 0x32}, {0x00, 0x33},
 +      {0x00, 0x34}, {0x00, 0x35}, {0x00, 0x36}, {0x00, 0x37},
 +      {0x00, 0x38}, {0x8c, 0x39}, {0xc8, 0x3A}, {0x80, 0x3b},
 +      {0x00, 0x3c}, {0x17, 0x3d}, {0x85, 0x3e}, /* initial */
 +      {0xa0, 0x40}, {0x00, 0x41}, {0x00, 0x42}, {0x00, 0x43},
 +      {0x08, 0x44}, {0x12, 0x45}, {0x00, 0x46}, {0x20, 0x47},
 +      {0x30, 0x48}, {0x18, 0x49}, {0x20, 0x4a}, {0x4d, 0x4b},
 +      {0x0c, 0x4c}, {0xe0, 0x4d}, {0x20, 0x4e}, {0x89, 0x4f},
 +      {0x21, 0x50}, {0x80, 0x51}, {0x02, 0x52}, {0x00, 0x53},
 +      {0x30, 0x54}, {0x90, 0x55}, {0x40, 0x56}, {0x06, 0x57},
 +      {0x0f, 0x58}, {0x23, 0x59}, {0x08, 0x5A}, {0x04, 0x5b},
 +      {0x08, 0x5c}, {0x08, 0x5d}, {0x08, 0x5e}, {0x08, 0x5f},
 +      {TCM825X_VAL_TERM, TCM825X_REG_TERM}
 +};
 +
 +const static struct tcm825x_reg tcm825x_regs_n810[] = {
 +      /* initial settings for 2.5 V */
 +      {0x00, 0x03}, {0x03, 0x29}, {0xaa, 0x2a}, {0xc0, 0x2b},
 +      {0x10, 0x2c}, {0x4c, 0x2d}, {0x9c, 0x3f},
 +
 +      /* main settings */
 +      {0x00, 0x00}, {0x30, 0x01}, {0x0e, 0x02}, /* initial */
 +      {0xcf, 0x04}, {0x02, 0x05}, {0x0d, 0x06}, {0xc0, 0x07},
 +      {0x38, 0x08}, {0x50, 0x09}, {0x80, 0x0a}, {0x40, 0x0b},
 +      {0x40, 0x0c}, {0x00, 0x0d}, {0x04, 0x0e}, {0x04, 0x0f},
 +      {0x22, 0x10}, {0x96, 0x11}, {0xf0, 0x12}, {0x08, 0x13},
 +      {0x08, 0x14}, {0x30, 0x15}, {0x30, 0x16}, {0x01, 0x17},
 +      {0x40, 0x18}, {0x87, 0x19}, {0x2b, 0x1a}, {0x84, 0x1b},
 +      {0x52, 0x1c}, {0x44, 0x1d}, {0x68, 0x1e}, {0x00, 0x1f},
 +      {0x00, 0x20}, {0x01, 0x21}, {0x27, 0x22}, {0x40, 0x23},
 +      {0x27, 0x24}, {0x5f, 0x25}, {0x00, 0x26}, {0x16, 0x27},
 +      {0x23, 0x28}, /* initial */ /* initial */ /* initial */
 +      /* initial */ /* initial */ {0x00, 0x2e}, {0x00, 0x2f},
 +      {0x00, 0x30}, {0x00, 0x31}, {0x00, 0x32}, {0x00, 0x33},
 +      {0x00, 0x34}, {0x00, 0x35}, {0x00, 0x36}, {0x00, 0x37},
 +      {0x00, 0x38}, {0x8c, 0x39}, {0xc8, 0x3A}, {0x80, 0x3b},
 +      {0x00, 0x3c}, {0x17, 0x3d}, {0x85, 0x3e}, /* initial */
 +      {0xa0, 0x40}, {0x00, 0x41}, {0x00, 0x42}, {0x00, 0x43},
 +      {0x08, 0x44}, {0x12, 0x45}, {0x00, 0x46}, {0x20, 0x47},
 +      {0x30, 0x48}, {0x18, 0x49}, {0x20, 0x4a}, {0x4d, 0x4b},
 +      {0x0c, 0x4c}, {0xe0, 0x4d}, {0x20, 0x4e}, {0x89, 0x4f},
 +      {0x21, 0x50}, {0x80, 0x51}, {0x02, 0x52}, {0x00, 0x53},
 +      {0x30, 0x54}, {0x90, 0x55}, {0x40, 0x56}, {0x06, 0x57},
 +      {0x0f, 0x58}, {0x23, 0x59}, {0x08, 0x5A}, {0x04, 0x5b},
 +      {0x08, 0x5c}, {0x08, 0x5d}, {0x08, 0x5e}, {0x08, 0x5f},
 +      {TCM825X_VAL_TERM, TCM825X_REG_TERM}
 +};
 +
 +static int tcm825x_is_okay(void)
 +{
 +      return sensor_okay;
 +}
 +
 +/*
 + * VSIM1      --> CAM_IOVDD   --> IOVDD (1.8 V)
 + */
 +static int tcm825x_power_on(void)
 +{
 +      int ret;
 +
 +      /* Set VMEM to 1.5V and VIO to 2.5V */
 +      ret = menelaus_set_vmem(1500);
 +      if (ret < 0) {
 +              /* Try once more, it seems the sensor power up causes
 +               * some problems on the I2C bus. */
 +              ret = menelaus_set_vmem(1500);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +      msleep(1);
 +
 +      ret = menelaus_set_vio(2500);
 +      if (ret < 0)
 +              return ret;
 +
 +      /* Set VSim1 on */
 +      retu_write_reg(RETU_REG_CTRL_SET, 0x0080);
 +      msleep(1);
 +
 +      omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 1);
 +      msleep(1);
 +
 +      saturated_count = 0;
 +      frames_after_reset = 0;
 +
 +      return 0;
 +}
 +
 +static int tcm825x_power_off(void)
 +{
 +      int ret;
 +
 +      omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0);
 +      msleep(1);
 +
 +      /* Set VSim1 off */
 +      retu_write_reg(RETU_REG_CTRL_CLR, 0x0080);
 +      msleep(1);
 +
 +      /* Set VIO_MODE to off */
 +      ret = menelaus_set_vio(0);
 +      if (ret < 0)
 +              return ret;
 +      msleep(1);
 +
 +      /* Set VMEM_MODE to off */
 +      ret = menelaus_set_vmem(0);
 +      if (ret < 0)
 +              return ret;
 +      msleep(1);
 +
 +      return 0;
 +}
 +
 +static int tcm825x_power_set(int power)
 +{
 +      BUG_ON(!sensor_okay);
 +
 +      if (power)
 +              return tcm825x_power_on();
 +      else
 +              return tcm825x_power_off();
 +}
 +
 +static const struct tcm825x_reg *tcm825x_default_regs(void)
 +{
 +      if (machine_is_nokia_n810())
 +              return tcm825x_regs_n810;
 +
 +      return tcm825x_regs_n800;
 +}
 +
 +#ifdef OMAP24XX_CAMERA_JAM_HACK
 +/*
 + * Check for jammed sensor, in which case all horizontal lines are
 + * equal. Handle also case where sensor could be saturated awhile in
 + * case of rapid increase of brightness.
 + */
 +static int tcm825x_needs_reset(struct v4l2_int_device *s, void *buf,
 +                             struct v4l2_pix_format *pix)
 +{
 +      int i, j;
 +      uint32_t xor, xor2;
 +      uint32_t offset;
 +      uint32_t dx_offset;
 +      uint32_t saturated_pattern;
 +      int is_saturated = 1;
 +
 +      switch (pix->pixelformat) {
 +      default:
 +      case V4L2_PIX_FMT_RGB565:
 +              saturated_pattern = 0xffffffff; /* guess */
 +              break;
 +      case V4L2_PIX_FMT_UYVY:
 +              saturated_pattern = 0xe080e080;
 +              break;
 +      }
 +
 +      /* This won't work for height under 2 at all. */
 +      if (pix->height < 2)
 +              return 0;
 +      /* Check that there is enough image data. */
 +      if (pix->width * TCM825X_BYTES_PER_PIXEL < sizeof(uint32_t))
 +              return 0;
 +      /*
 +       * Don't check for jamming immediately. Sometimes frames
 +       * immediately after reset are black.
 +       */
 +      if (frames_after_reset < JAM_CHECK_AFTER) {
 +              frames_after_reset++;
 +              return 0;
 +      }
 +
 +      dx_offset = ((pix->width - sizeof(uint32_t) / TCM825X_BYTES_PER_PIXEL)
 +                   * TCM825X_BYTES_PER_PIXEL) / (CHECK_X - 1);
 +      dx_offset = dx_offset - dx_offset % TCM825X_BYTES_PER_PIXEL;
 +      /*
 +       * Check two lines in the bottom first. They're unlikely to be
 +       * saturated and quick to check.
 +       */
 +      offset = (pix->height - 2) * pix->bytesperline;
 +      xor = xor2 = 0;
 +      for (j = 0; j < CHECK_X; j++) {
 +              uint32_t *val = buf + offset;
 +              uint32_t *val2 = buf + offset + pix->bytesperline;
 +              xor ^= *val;
 +              if (*val != saturated_pattern)
 +                      is_saturated = 0;
 +              xor2 ^= *val2;
 +              if (xor2 != xor) {
 +                      saturated_count = 0;
 +                      return 0;
 +              }
 +              offset += dx_offset;
 +      }
 +      /* Check the rest of the picture. */
 +      offset = 0;
 +      for (i = 0; i < CHECK_Y; i++) {
 +              uint32_t offset2 = offset;
 +              xor2 = 0;
 +              for (j = 0; j < CHECK_X; j++) {
 +                      uint32_t *val = buf + offset2;
 +                      xor2 ^= *val;
 +                      offset2 += dx_offset;
 +              }
 +              if (xor2 != xor) {
 +                      saturated_count = 0;
 +                      return 0;
 +              }
 +              offset += pix->bytesperline * ((pix->height - 2) / CHECK_Y);
 +      }
 +
 +      if (is_saturated && saturated_count++ < SATURATED_MAX)
 +              return 0;
 +
 +      return -EIO;
 +}
 +#else
 +static int tcm825x_needs_reset(struct v4l2_int_device *s, void *buf,
 +                             struct v4l2_pix_format *pix)
 +{
 +      return 0;
 +}
 +#endif
 +
 +static const struct v4l2_ifparm ifparm = {
 +      .if_type = V4L2_IF_TYPE_BT656,
 +      .u = {
 +              .bt656 = {
 +                       .frame_start_on_rising_vs = 1,
 +                       .latch_clk_inv = 1,
 +                       .mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT,
 +                       .clock_min = TCM825X_XCLK_MIN,
 +                       .clock_max = TCM825X_XCLK_MAX,
 +               },
 +      },
 +};
 +
 +static int tcm825x_ifparm(struct v4l2_ifparm *p)
 +{
 +      *p = ifparm;
 +
 +      return 0;
 +}
 +
 +static int tcm825x_is_upside_down(void)
 +{
 +      return machine_is_nokia_n810();
 +}
 +
 +const struct tcm825x_platform_data n800_tcm825x_platform_data = {
 +      .is_okay        = tcm825x_is_okay,
 +      .power_set      = tcm825x_power_set,
 +      .default_regs   = tcm825x_default_regs,
 +      .needs_reset    = tcm825x_needs_reset,
 +      .ifparm         = tcm825x_ifparm,
 +      .is_upside_down = tcm825x_is_upside_down,
 +};
 +
 +void __init n800_cam_init(void)
 +{
 +      int r;
 +
 +      r = omap_request_gpio(N800_CAM_SENSOR_RESET_GPIO);
 +      if (r < 0) {
 +              printk(KERN_WARNING "%s: failed to request gpio\n",
 +                      __func__);
 +              return;
 +      }
 +
 +      omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0);
 +      omap_set_gpio_direction(N800_CAM_SENSOR_RESET_GPIO, 0);
 +
 +      sensor_okay = 1;
 +}
 +
 +#else
 +void __init n800_cam_init(void)
 +{
 +}
 +
 +#endif
index d524b620571d89630f3c1d946d8b8604c9f50011,0000000000000000000000000000000000000000..5f3f0d6e954fc56ea46d098b765c05f32b68415e
mode 100644,000000..100644
--- /dev/null
@@@ -1,155 -1,0 +1,155 @@@
- #include <asm/arch/clock.h>
- #include <asm/arch/board.h>
- #include <asm/arch/dsp_common.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800-dsp.c
 + *
 + * Copyright (C) 2006 Nokia Corporation.
 + *
 + * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/device.h>
 +#include <linux/list.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +
 +#include <asm/io.h>
++#include <mach/clock.h>
++#include <mach/board.h>
++#include <mach/dsp_common.h>
 +
 +#if   defined(CONFIG_OMAP_DSP)
 +
 +/*
 + * dsp peripheral device: AUDIO
 + */
 +static struct dsp_kfunc_device n800_audio_device = {
 +      .name    = "audio",
 +      .type    = DSP_KFUNC_DEV_TYPE_AUDIO,
 +      .enable  = n800_audio_enable,
 +      .disable = n800_audio_disable,
 +};
 +
 +/*
 + * dsp peripheral device: TIMER
 + */
 +static int dsp_timer_probe(struct dsp_kfunc_device *kdev, int stage)
 +{
 +      char clockname[20];
 +
 +      strcpy(clockname, kdev->name);
 +      strcat(clockname, "_fck");
 +
 +      kdev->fck = clk_get(NULL, clockname);
 +      if (IS_ERR(kdev->fck)) {
 +              printk(KERN_ERR "couldn't acquire %s\n", clockname);
 +              return PTR_ERR(kdev->fck);
 +      }
 +      pr_debug("%s probed successfully\n", clockname);
 +
 +      strcpy(clockname, kdev->name);
 +      strcat(clockname, "_ick");
 +      kdev->ick = clk_get(NULL, clockname);
 +      if (IS_ERR(kdev->ick)) {
 +              printk(KERN_ERR "couldn't acquire %s\n", clockname);
 +              goto fail;
 +      }
 +      pr_debug("%s probed successfully\n", clockname);
 +
 +      return 0;
 + fail:
 +      clk_put(kdev->fck);
 +
 +      return PTR_ERR(kdev->ick);
 +}
 +
 +static int dsp_timer_remove(struct dsp_kfunc_device *kdev, int stage)
 +{
 +      clk_put(kdev->ick);
 +      clk_put(kdev->fck);
 +      pr_debug("%s removed successfully\n", kdev->name);
 +      return 0;
 +}
 +
 +static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage)
 +{
 +      pr_debug("%s enabled(%d)\n", kdev->name, stage);
 +
 +      spin_lock(&kdev->lock);
 +
 +      if (kdev->enabled)
 +              goto out;
 +      kdev->enabled = 1;
 +
 +      clk_enable(kdev->fck);
 +      clk_enable(kdev->ick);
 + out:
 +      spin_unlock(&kdev->lock);
 +
 +      return 0;
 +}
 +
 +static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage)
 +{
 +      pr_debug("%s disabled(%d)\n", kdev->name, stage);
 +
 +      spin_lock(&kdev->lock);
 +
 +      if (kdev->enabled == 0)
 +              goto out;
 +      kdev->enabled = 0;
 +
 +      clk_disable(kdev->ick);
 +      clk_disable(kdev->fck);
 + out:
 +      spin_unlock(&kdev->lock);
 +
 +      return 0;
 +}
 +
 +static struct dsp_kfunc_device n800_timer_device = {
 +      .name    = "gpt5",
 +      .type    = DSP_KFUNC_DEV_TYPE_COMMON,
 +      .probe   = dsp_timer_probe,
 +      .remove  = dsp_timer_remove,
 +      .enable  = dsp_timer_enable,
 +      .disable = dsp_timer_disable,
 +};
 +
 +static struct dsp_kfunc_device *n800_kfunc_dev[] = {
 +      &n800_audio_device,
 +      &n800_timer_device,
 +};
 +
 +void __init n800_dsp_init(void)
 +{
 +      int i, ret;
 +      struct dsp_kfunc_device **p = n800_kfunc_dev;
 +
 +      for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) {
 +              ret = dsp_kfunc_device_register(p[i]);
 +              if (ret) {
 +                      printk(KERN_ERR
 +                             "KFUNC device registration failed: %s\n",
 +                             p[i]->name);
 +              }
 +      }
 +}
 +
 +#else
 +void __init n800_dsp_init(void) { }
 +#endif        /* CONFIG_OMAP_DSP */
index fbf83b3b0eba5e02a67bc9f5f8059613e48df3d6,0000000000000000000000000000000000000000..52aaf76417e36f48a1890f8995debd53b5ca8202
mode 100644,000000..100644
--- /dev/null
@@@ -1,349 -1,0 +1,349 @@@
- #include <asm/arch/onenand.h>
- #include <asm/arch/board.h>
- #include <asm/arch/gpmc.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800-flash.c
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Juha Yrjola
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/platform_device.h>
 +#include <asm/mach/flash.h>
 +#include <linux/mtd/onenand_regs.h>
 +
 +#include <asm/io.h>
++#include <mach/onenand.h>
++#include <mach/board.h>
++#include <mach/gpmc.h>
 +
 +struct mtd_partition n800_partitions[ONENAND_MAX_PARTITIONS];
 +
 +int n800_onenand_setup(void __iomem *, int freq);
 +
 +static struct omap_onenand_platform_data n800_onenand_data = {
 +      .cs = 0,
 +      .parts = n800_partitions,
 +      .nr_parts = 0, /* filled later */
 +      .onenand_setup = n800_onenand_setup,
 +};
 +
 +static struct platform_device n800_onenand_device = {
 +      .name           = "omap2-onenand",
 +      .id             = -1,
 +      .dev = {
 +              .platform_data = &n800_onenand_data,
 +      },
 +};
 +
 +static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 +{
 +      struct gpmc_timings t;
 +
 +      const int t_cer = 15;
 +      const int t_avdp = 12;
 +      const int t_aavdh = 7;
 +      const int t_ce = 76;
 +      const int t_aa = 76;
 +      const int t_oe = 20;
 +      const int t_cez = 20; /* max of t_cez, t_oez */
 +      const int t_ds = 30;
 +      const int t_wpl = 40;
 +      const int t_wph = 30;
 +
 +      memset(&t, 0, sizeof(t));
 +      t.sync_clk = 0;
 +      t.cs_on = 0;
 +      t.adv_on = 0;
 +
 +      /* Read */
 +      t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
 +      t.oe_on  = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
 +      t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
 +      t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
 +      t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
 +      t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
 +      t.cs_rd_off = t.oe_off;
 +      t.rd_cycle  = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
 +
 +      /* Write */
 +      t.adv_wr_off = t.adv_rd_off;
 +      t.we_on  = t.oe_on;
 +      if (cpu_is_omap34xx()) {
 +              t.wr_data_mux_bus = t.we_on;
 +              t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
 +      }
 +      t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
 +      t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
 +      t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 +
 +      /* Configure GPMC for asynchronous read */
 +      gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
 +                        GPMC_CONFIG1_DEVICESIZE_16 |
 +                        GPMC_CONFIG1_MUXADDDATA);
 +
 +      return gpmc_cs_set_timings(cs, &t);
 +}
 +
 +static unsigned short omap2_onenand_readw(void __iomem *addr)
 +{
 +      return readw(addr);
 +}
 +
 +static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
 +{
 +      writew(value, addr);
 +}
 +
 +static void set_onenand_cfg(void __iomem *onenand_base, int latency,
 +                          int sync_write, int hf)
 +{
 +      u32 reg;
 +
 +      reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
 +      reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
 +      reg |=  (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
 +              ONENAND_SYS_CFG1_SYNC_READ |
 +              ONENAND_SYS_CFG1_BL_16;
 +      if (sync_write)
 +              reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
 +      else
 +              reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
 +      if (hf)
 +              reg |= ONENAND_SYS_CFG1_HF;
 +      else
 +              reg &= ~ONENAND_SYS_CFG1_HF;
 +      omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 +}
 +
 +static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base,
 +                                     int freq)
 +{
 +      struct gpmc_timings t;
 +      const int t_cer  = 15;
 +      const int t_avdp = 12;
 +      const int t_cez  = 20; /* max of t_cez, t_oez */
 +      const int t_ds   = 30;
 +      const int t_wpl  = 40;
 +      const int t_wph  = 30;
 +      int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
 +      int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
 +      int err, ticks_cez, sync_write = 0, first_time = 0, hf = 0;
 +      u32 reg;
 +
 +      if (!freq) {
 +              /* Very first call freq is not known */
 +              err = omap2_onenand_set_async_mode(cs, onenand_base);
 +              if (err)
 +                      return err;
 +              reg = omap2_onenand_readw(onenand_base +
 +                                        ONENAND_REG_VERSION_ID);
 +              switch ((reg >> 4) & 0xf) {
 +              case 0:
 +                      freq = 40;
 +                      break;
 +              case 1:
 +                      freq = 54;
 +                      break;
 +              case 2:
 +                      freq = 66;
 +                      break;
 +              case 3:
 +                      freq = 83;
 +                      break;
 +              case 4:
 +                      freq = 104;
 +                      break;
 +              default:
 +                      freq = 54;
 +                      break;
 +              }
 +              first_time = 1;
 +      }
 +
 +      switch (freq) {
 +      case 83:
 +              min_gpmc_clk_period = 12; /* 83 MHz */
 +              t_ces   = 5;
 +              t_avds  = 4;
 +              t_avdh  = 2;
 +              t_ach   = 6;
 +              t_aavdh = 6;
 +              t_rdyo  = 9;
 +              if (cpu_is_omap34xx())
 +                      sync_write = 1;
 +              break;
 +      case 66:
 +              min_gpmc_clk_period = 15; /* 66 MHz */
 +              t_ces   = 6;
 +              t_avds  = 5;
 +              t_avdh  = 2;
 +              t_ach   = 6;
 +              t_aavdh = 6;
 +              t_rdyo  = 11;
 +              if (cpu_is_omap34xx())
 +                      sync_write = 1;
 +              break;
 +      default:
 +              min_gpmc_clk_period = 18; /* 54 MHz */
 +              t_ces   = 7;
 +              t_avds  = 7;
 +              t_avdh  = 7;
 +              t_ach   = 9;
 +              t_aavdh = 7;
 +              t_rdyo  = 15;
 +              break;
 +      }
 +
 +      tick_ns = gpmc_ticks_to_ns(1);
 +      div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
 +      gpmc_clk_ns = gpmc_ticks_to_ns(div);
 +      if (gpmc_clk_ns < 15) /* >66Mhz */
 +              hf = 1;
 +      if (hf)
 +              latency = 6;
 +      else if (gpmc_clk_ns >= 25) /* 40 MHz*/
 +              latency = 3;
 +      else
 +              latency = 4;
 +
 +      if (first_time)
 +              set_onenand_cfg(onenand_base, latency, sync_write, hf);
 +
 +      if (div == 1) {
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
 +              reg |= (1 << 7);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
 +              reg |= (1 << 7);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
 +              reg |= (1 << 7);
 +              reg |= (1 << 23);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
 +      } else {
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
 +              reg &= ~(1 << 7);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
 +              reg &= ~(1 << 7);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
 +              reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
 +              reg &= ~(1 << 7);
 +              reg &= ~(1 << 23);
 +              gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
 +      }
 +
 +      /* Set synchronous read timings */
 +      memset(&t, 0, sizeof(t));
 +      t.sync_clk = min_gpmc_clk_period;
 +      t.cs_on = 0;
 +      t.adv_on = 0;
 +      fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
 +      fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
 +      t.page_burst_access = gpmc_clk_ns;
 +
 +      /* Read */
 +      t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
 +      t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
 +      t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
 +      t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
 +      t.cs_rd_off = t.oe_off;
 +      ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
 +      t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
 +                   ticks_cez);
 +
 +      /* Write */
 +      if (sync_write) {
 +              t.adv_wr_off = t.adv_rd_off;
 +              t.we_on  = 0;
 +              t.we_off = t.cs_rd_off;
 +              t.cs_wr_off = t.cs_rd_off;
 +              t.wr_cycle  = t.rd_cycle;
 +              if (cpu_is_omap34xx()) {
 +                      t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
 +                                      gpmc_ns_to_ticks(min_gpmc_clk_period +
 +                                      t_rdyo));
 +                      t.wr_access = t.access;
 +              }
 +      } else {
 +              t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
 +              t.we_on  = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
 +              t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
 +              t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
 +              t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 +              if (cpu_is_omap34xx()) {
 +                      t.wr_data_mux_bus = t.we_on;
 +                      t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
 +              }
 +      }
 +
 +      /* Configure GPMC for synchronous read */
 +      gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
 +                        GPMC_CONFIG1_WRAPBURST_SUPP |
 +                        GPMC_CONFIG1_READMULTIPLE_SUPP |
 +                        GPMC_CONFIG1_READTYPE_SYNC |
 +                        (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
 +                        (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
 +                        GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
 +                        GPMC_CONFIG1_PAGE_LEN(2) |
 +                        (cpu_is_omap34xx() ? 0 :
 +                              (GPMC_CONFIG1_WAIT_READ_MON |
 +                               GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
 +                        GPMC_CONFIG1_DEVICESIZE_16 |
 +                        GPMC_CONFIG1_DEVICETYPE_NOR |
 +                        GPMC_CONFIG1_MUXADDDATA);
 +
 +      err = gpmc_cs_set_timings(cs, &t);
 +      if (err)
 +              return err;
 +
 +      set_onenand_cfg(onenand_base, latency, sync_write, hf);
 +
 +      return 0;
 +}
 +
 +int n800_onenand_setup(void __iomem *onenand_base, int freq)
 +{
 +      struct omap_onenand_platform_data *datap = &n800_onenand_data;
 +      struct device *dev = &n800_onenand_device.dev;
 +
 +      /* Set sync timings in GPMC */
 +      if (omap2_onenand_set_sync_mode(datap->cs, onenand_base, freq) < 0) {
 +              dev_err(dev, "Unable to set synchronous mode\n");
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +void __init n800_flash_init(void)
 +{
 +      const struct omap_partition_config *part;
 +      int i = 0;
 +
 +      n800_onenand_data.gpio_irq = cpu_is_omap34xx() ? 65 : 26;
 +
 +      while ((part = omap_get_nr_config(OMAP_TAG_PARTITION,
 +                              struct omap_partition_config, i)) != NULL) {
 +              struct mtd_partition *mpart;
 +
 +              mpart = n800_partitions + i;
 +              mpart->name = (char *) part->name;
 +              mpart->size = part->size;
 +              mpart->offset = part->offset;
 +              mpart->mask_flags = part->mask_flags;
 +              i++;
 +              if (i == ARRAY_SIZE(n800_partitions)) {
 +                      printk(KERN_ERR "Too many partitions supplied\n");
 +                      return;
 +              }
 +      }
 +      n800_onenand_data.nr_parts = i;
 +      if (platform_device_register(&n800_onenand_device) < 0) {
 +              printk(KERN_ERR "Unable to register OneNAND device\n");
 +              return;
 +      }
 +}
index 2028710c8fed8dde3c1bbcd429b2a51ce3c56be7,0000000000000000000000000000000000000000..dac159f2f9a46d28d0cbd7f292f2c861d5a97ad4
mode 100644,000000..100644
--- /dev/null
@@@ -1,370 -1,0 +1,370 @@@
- #include <asm/arch/mmc.h>
- #include <asm/arch/gpio.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800-mmc.c
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Juha Yrjola
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
++#include <mach/mmc.h>
++#include <mach/gpio.h>
 +
 +#include <asm/mach-types.h>
 +#include <linux/delay.h>
 +#include <linux/i2c/menelaus.h>
 +
 +#ifdef CONFIG_MMC_OMAP
 +
 +static const int slot_switch_gpio = 96;
 +
 +static const int n810_slot2_pw_vddf = 23;
 +static const int n810_slot2_pw_vdd = 9;
 +
 +static int slot1_cover_open;
 +static int slot2_cover_open;
 +static struct device *mmc_device;
 +
 +/*
 + * VMMC   --> slot 1 (N800 & N810)
 + * VDCDC3_APE, VMCS2_APE --> slot 2 on N800
 + * GPIO96 --> Menelaus GPIO2
 + * GPIO23 --> controls slot2 VSD    (N810 only)
 + * GPIO9  --> controls slot2 VIO_SD (N810 only)
 + */
 +
 +static int n800_mmc_switch_slot(struct device *dev, int slot)
 +{
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Choose slot %d\n", slot + 1);
 +#endif
 +      if (slot == 0)
 +              omap_set_gpio_dataout(slot_switch_gpio, 0);
 +      else
 +              omap_set_gpio_dataout(slot_switch_gpio, 1);
 +      return 0;
 +}
 +
 +static int n800_mmc_set_power_menelaus(struct device *dev, int slot,
 +                                      int power_on, int vdd)
 +{
 +      int mV;
 +
 +#ifdef CONFIG_MMC_DEBUG
 +      dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
 +              power_on ? "on" : "off", vdd);
 +#endif
 +      if (slot == 0) {
 +              if (!power_on)
 +                      return menelaus_set_vmmc(0);
 +              switch (1 << vdd) {
 +              case MMC_VDD_33_34:
 +              case MMC_VDD_32_33:
 +              case MMC_VDD_31_32:
 +                      mV = 3100;
 +                      break;
 +              case MMC_VDD_30_31:
 +                      mV = 3000;
 +                      break;
 +              case MMC_VDD_28_29:
 +                      mV = 2800;
 +                      break;
 +              case MMC_VDD_165_195:
 +                      mV = 1850;
 +                      break;
 +              default:
 +                      BUG();
 +              }
 +              return menelaus_set_vmmc(mV);
 +      } else {
 +              if (!power_on)
 +                      return menelaus_set_vdcdc(3, 0);
 +              switch (1 << vdd) {
 +              case MMC_VDD_33_34:
 +              case MMC_VDD_32_33:
 +                      mV = 3300;
 +                      break;
 +              case MMC_VDD_30_31:
 +              case MMC_VDD_29_30:
 +                      mV = 3000;
 +                      break;
 +              case MMC_VDD_28_29:
 +              case MMC_VDD_27_28:
 +                      mV = 2800;
 +                      break;
 +              case MMC_VDD_24_25:
 +              case MMC_VDD_23_24:
 +                      mV = 2400;
 +                      break;
 +              case MMC_VDD_22_23:
 +              case MMC_VDD_21_22:
 +                      mV = 2200;
 +                      break;
 +              case MMC_VDD_20_21:
 +                      mV = 2000;
 +                      break;
 +              case MMC_VDD_165_195:
 +                      mV = 1800;
 +                      break;
 +              default:
 +                      BUG();
 +              }
 +              return menelaus_set_vdcdc(3, mV);
 +      }
 +      return 0;
 +}
 +
 +static void nokia_mmc_set_power_internal(struct device *dev,
 +                                       int power_on)
 +{
 +      dev_dbg(dev, "Set internal slot power %s\n",
 +              power_on ? "on" : "off");
 +
 +      if (power_on) {
 +              omap_set_gpio_dataout(n810_slot2_pw_vddf, 1);
 +              udelay(30);
 +              omap_set_gpio_dataout(n810_slot2_pw_vdd, 1);
 +              udelay(100);
 +      } else {
 +              omap_set_gpio_dataout(n810_slot2_pw_vdd, 0);
 +              msleep(50);
 +              omap_set_gpio_dataout(n810_slot2_pw_vddf, 0);
 +              msleep(50);
 +      }
 +}
 +
 +static int n800_mmc_set_power(struct device *dev, int slot, int power_on,
 +                            int vdd)
 +{
 +      if (machine_is_nokia_n800() || slot == 0)
 +              return n800_mmc_set_power_menelaus(dev, slot, power_on, vdd);
 +
 +      nokia_mmc_set_power_internal(dev, power_on);
 +
 +      return 0;
 +}
 +
 +static int n800_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
 +{
 +      int r;
 +
 +      dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1,
 +              bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
 +      BUG_ON(slot != 0 && slot != 1);
 +      slot++;
 +      switch (bus_mode) {
 +      case MMC_BUSMODE_OPENDRAIN:
 +              r = menelaus_set_mmc_opendrain(slot, 1);
 +              break;
 +      case MMC_BUSMODE_PUSHPULL:
 +              r = menelaus_set_mmc_opendrain(slot, 0);
 +              break;
 +      default:
 +              BUG();
 +      }
 +      if (r != 0 && printk_ratelimit())
 +              dev_err(dev, "MMC: unable to set bus mode for slot %d\n",
 +                      slot);
 +      return r;
 +}
 +
 +static int n800_mmc_get_cover_state(struct device *dev, int slot)
 +{
 +      slot++;
 +      BUG_ON(slot != 1 && slot != 2);
 +      if (slot == 1)
 +              return slot1_cover_open;
 +      else
 +              return slot2_cover_open;
 +}
 +
 +static void n800_mmc_callback(void *data, u8 card_mask)
 +{
 +      int bit, *openp, index;
 +
 +      if (machine_is_nokia_n800()) {
 +              bit = 1 << 1;
 +              openp = &slot2_cover_open;
 +              index = 1;
 +      } else {
 +              bit = 1;
 +              openp = &slot1_cover_open;
 +              index = 0;
 +      }
 +
 +      if (card_mask & bit)
 +              *openp = 1;
 +      else
 +              *openp = 0;
 +
 +      omap_mmc_notify_cover_event(mmc_device, index, *openp);
 +}
 +
 +void n800_mmc_slot1_cover_handler(void *arg, int closed_state)
 +{
 +      if (mmc_device == NULL)
 +              return;
 +
 +      slot1_cover_open = !closed_state;
 +      omap_mmc_notify_cover_event(mmc_device, 0, closed_state);
 +}
 +
 +static int n800_mmc_late_init(struct device *dev)
 +{
 +      int r, bit, *openp;
 +      int vs2sel;
 +
 +      mmc_device = dev;
 +
 +      r = menelaus_set_slot_sel(1);
 +      if (r < 0)
 +              return r;
 +
 +      if (machine_is_nokia_n800())
 +              vs2sel = 0;
 +      else
 +              vs2sel = 2;
 +
 +      r = menelaus_set_mmc_slot(2, 0, vs2sel, 1);
 +      if (r < 0)
 +              return r;
 +
 +      n800_mmc_set_power(dev, 0, MMC_POWER_ON, 16); /* MMC_VDD_28_29 */
 +      n800_mmc_set_power(dev, 1, MMC_POWER_ON, 16);
 +
 +      r = menelaus_set_mmc_slot(1, 1, 0, 1);
 +      if (r < 0)
 +              return r;
 +      r = menelaus_set_mmc_slot(2, 1, vs2sel, 1);
 +      if (r < 0)
 +              return r;
 +
 +      r = menelaus_get_slot_pin_states();
 +      if (r < 0)
 +              return r;
 +
 +      if (machine_is_nokia_n800()) {
 +              bit = 1 << 1;
 +              openp = &slot2_cover_open;
 +      } else {
 +              bit = 1;
 +              openp = &slot1_cover_open;
 +              slot2_cover_open = 0;
 +      }
 +
 +      /* All slot pin bits seem to be inversed until first swith change */
 +      if (r == 0xf || r == (0xf & ~bit))
 +              r = ~r;
 +
 +      if (r & bit)
 +              *openp = 1;
 +      else
 +              *openp = 0;
 +
 +      r = menelaus_register_mmc_callback(n800_mmc_callback, NULL);
 +
 +      return r;
 +}
 +
 +static void n800_mmc_shutdown(struct device *dev)
 +{
 +      int vs2sel;
 +
 +      if (machine_is_nokia_n800())
 +              vs2sel = 0;
 +      else
 +              vs2sel = 2;
 +
 +      menelaus_set_mmc_slot(1, 0, 0, 0);
 +      menelaus_set_mmc_slot(2, 0, vs2sel, 0);
 +}
 +
 +static void n800_mmc_cleanup(struct device *dev)
 +{
 +      menelaus_unregister_mmc_callback();
 +
 +      omap_free_gpio(slot_switch_gpio);
 +
 +      if (machine_is_nokia_n810()) {
 +              omap_free_gpio(n810_slot2_pw_vddf);
 +              omap_free_gpio(n810_slot2_pw_vdd);
 +      }
 +}
 +
 +static struct omap_mmc_platform_data n800_mmc_data = {
 +      .nr_slots               = 2,
 +      .switch_slot            = n800_mmc_switch_slot,
 +      .init                   = n800_mmc_late_init,
 +      .cleanup                = n800_mmc_cleanup,
 +      .shutdown               = n800_mmc_shutdown,
 +      .max_freq               = 24000000,
 +      .slots[0] = {
 +              .set_power      = n800_mmc_set_power,
 +              .set_bus_mode   = n800_mmc_set_bus_mode,
 +              .get_ro         = NULL,
 +              .get_cover_state= n800_mmc_get_cover_state,
 +              .ocr_mask       = MMC_VDD_165_195 | MMC_VDD_30_31 |
 +                                MMC_VDD_32_33   | MMC_VDD_33_34,
 +              .name           = "internal",
 +      },
 +      .slots[1] = {
 +              .set_power      = n800_mmc_set_power,
 +              .set_bus_mode   = n800_mmc_set_bus_mode,
 +              .get_ro         = NULL,
 +              .get_cover_state= n800_mmc_get_cover_state,
 +              .ocr_mask       = MMC_VDD_165_195 | MMC_VDD_20_21 |
 +                                MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 |
 +                                MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 |
 +                                MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 |
 +                                MMC_VDD_33_34,
 +              .name           = "external",
 +      },
 +};
 +
 +void __init n800_mmc_init(void)
 +
 +{
 +      if (machine_is_nokia_n810()) {
 +              n800_mmc_data.slots[0].name = "external";
 +
 +              /*
 +               * Some Samsung Movinand chips do not like open-ended
 +               * multi-block reads and fall to braind-dead state
 +               * while doing so. Reducing the number of blocks in
 +               * the transfer or delays in clock disable do not help
 +               */
 +              n800_mmc_data.slots[1].name = "internal";
 +              n800_mmc_data.slots[1].ban_openended = 1;
 +      }
 +
 +      omap_set_mmc_info(1, &n800_mmc_data);
 +      if (omap_request_gpio(slot_switch_gpio) < 0)
 +              BUG();
 +      omap_set_gpio_dataout(slot_switch_gpio, 0);
 +      omap_set_gpio_direction(slot_switch_gpio, 0);
 +
 +      if (machine_is_nokia_n810()) {
 +              if (omap_request_gpio(n810_slot2_pw_vddf) < 0)
 +                      BUG();
 +              omap_set_gpio_dataout(n810_slot2_pw_vddf, 0);
 +              omap_set_gpio_direction(n810_slot2_pw_vddf, 0);
 +
 +              if (omap_request_gpio(n810_slot2_pw_vdd) < 0)
 +                      BUG();
 +              omap_set_gpio_dataout(n810_slot2_pw_vdd, 0);
 +              omap_set_gpio_direction(n810_slot2_pw_vdd, 0);
 +      }
 +}
 +#else
 +
 +void __init n800_mmc_init(void)
 +{
 +}
 +
 +void n800_mmc_slot1_cover_handler(void *arg, int state)
 +{
 +}
 +
 +#endif
index 7599f64775c508565c9d957fb627de9bf886123e,0000000000000000000000000000000000000000..66dcd0f5aabd920c3595e296b0ca27fceb216b06
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,131 @@@
- #include <asm/arch/gpmc.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/pm.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800-usb.c
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Juha Yrjola
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/types.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/err.h>
 +#include <linux/usb/musb.h>
++#include <mach/gpmc.h>
++#include <mach/gpio.h>
++#include <mach/pm.h>
 +
 +#define TUSB_ASYNC_CS         1
 +#define TUSB_SYNC_CS          4
 +#define GPIO_TUSB_INT         58
 +#define GPIO_TUSB_ENABLE      0
 +
 +static int tusb_set_power(int state);
 +static int tusb_set_clock(struct clk *osc_ck, int state);
 +
 +#if   defined(CONFIG_USB_MUSB_OTG)
 +#     define BOARD_MODE       MUSB_OTG
 +#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
 +#     define BOARD_MODE       MUSB_PERIPHERAL
 +#else /* defined(CONFIG_USB_MUSB_HOST) */
 +#     define BOARD_MODE       MUSB_HOST
 +#endif
 +
 +static struct musb_hdrc_platform_data tusb_data = {
 +      .mode           = BOARD_MODE,
 +      .multipoint     = 1,
 +      .set_power      = tusb_set_power,
 +      .set_clock      = tusb_set_clock,
 +      .min_power      = 25,   /* x2 = 50 mA drawn from VBUS as peripheral */
 +      .power          = 100,  /* Max 100 mA VBUS for host mode */
 +      .clock          = "osc_ck",
 +};
 +
 +/*
 + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
 + * 1.5 V voltage regulators of PM companion chip. Companion chip will then
 + * provide then PGOOD signal to TUSB6010 which will release it from reset.
 + */
 +static int tusb_set_power(int state)
 +{
 +      int i, retval = 0;
 +
 +      if (state) {
 +              omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 1);
 +              msleep(1);
 +
 +              /* Wait until TUSB6010 pulls INT pin down */
 +              i = 100;
 +              while (i && omap_get_gpio_datain(GPIO_TUSB_INT)) {
 +                      msleep(1);
 +                      i--;
 +              }
 +
 +              if (!i) {
 +                      printk(KERN_ERR "tusb: powerup failed\n");
 +                      retval = -ENODEV;
 +              }
 +      } else {
 +              omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 0);
 +              msleep(10);
 +      }
 +
 +      return retval;
 +}
 +
 +static int            osc_ck_on;
 +
 +static int tusb_set_clock(struct clk *osc_ck, int state)
 +{
 +      if (state) {
 +              if (osc_ck_on > 0)
 +                      return -ENODEV;
 +
 +              omap2_block_sleep();
 +              clk_enable(osc_ck);
 +              osc_ck_on = 1;
 +      } else {
 +              if (osc_ck_on == 0)
 +                      return -ENODEV;
 +
 +              clk_disable(osc_ck);
 +              osc_ck_on = 0;
 +              omap2_allow_sleep();
 +      }
 +
 +      return 0;
 +}
 +
 +void __init n800_usb_init(void)
 +{
 +      int ret = 0;
 +      static char     announce[] __initdata = KERN_INFO "TUSB 6010\n";
 +
 +      /* PM companion chip power control pin */
 +      ret = omap_request_gpio(GPIO_TUSB_ENABLE);
 +      if (ret != 0) {
 +              printk(KERN_ERR "Could not get TUSB power GPIO%i\n",
 +                     GPIO_TUSB_ENABLE);
 +              return;
 +      }
 +      omap_set_gpio_direction(GPIO_TUSB_ENABLE, 0);
 +
 +      tusb_set_power(0);
 +
 +      ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
 +                                      TUSB_ASYNC_CS, TUSB_SYNC_CS,
 +                                      GPIO_TUSB_INT, 0x3f);
 +      if (ret != 0)
 +              goto err;
 +
 +      printk(announce);
 +
 +      return;
 +
 +err:
 +      omap_free_gpio(GPIO_TUSB_ENABLE);
 +}
index 90909630b9200a131b7c5ffdcedd569dd559349e,0000000000000000000000000000000000000000..95cc84ab42c8d7a2dc4adcd08aaec38c965f6aab
mode 100644,000000..100644
--- /dev/null
@@@ -1,738 -1,0 +1,738 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n800.c
 + *
 + * Copyright (C) 2005-2007 Nokia Corporation
 + * Author: Juha Yrjola <juha.yrjola@nokia.com>
 + *
 + * Modified from mach-omap2/board-generic.c
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/clk.h>
 +#include <linux/device.h>
 +#include <linux/platform_device.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc2301.h>
 +#include <linux/spi/tsc2005.h>
 +#include <linux/input.h>
 +#include <linux/delay.h>
 +#include <linux/interrupt.h>
 +#include <linux/irq.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c/lm8323.h>
 +#include <linux/i2c/menelaus.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/usb.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcspi.h>
- #include <asm/arch/lcd_mipid.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/gpio-switch.h>
- #include <asm/arch/omapfb.h>
- #include <asm/arch/blizzard.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
++#include <mach/gpio.h>
++#include <mach/usb.h>
++#include <mach/board.h>
++#include <mach/common.h>
++#include <mach/mcspi.h>
++#include <mach/lcd_mipid.h>
++#include <mach/clock.h>
++#include <mach/gpio-switch.h>
++#include <mach/omapfb.h>
++#include <mach/blizzard.h>
 +
 +#include <../drivers/cbus/tahvo.h>
 +#include <../drivers/media/video/tcm825x.h>
 +
 +#define N800_BLIZZARD_POWERDOWN_GPIO  15
 +#define N800_STI_GPIO                 62
 +#define N800_KEYB_IRQ_GPIO            109
 +#define N800_DAV_IRQ_GPIO             103
 +#define N800_TSC2301_RESET_GPIO               118
 +
 +#ifdef CONFIG_MACH_NOKIA_N810
 +static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 +      [0x01] = KEY_Q,
 +      [0x02] = KEY_K,
 +      [0x03] = KEY_O,
 +      [0x04] = KEY_P,
 +      [0x05] = KEY_BACKSPACE,
 +      [0x06] = KEY_A,
 +      [0x07] = KEY_S,
 +      [0x08] = KEY_D,
 +      [0x09] = KEY_F,
 +      [0x0a] = KEY_G,
 +      [0x0b] = KEY_H,
 +      [0x0c] = KEY_J,
 +
 +      [0x11] = KEY_W,
 +      [0x12] = KEY_F4,
 +      [0x13] = KEY_L,
 +      [0x14] = KEY_APOSTROPHE,
 +      [0x16] = KEY_Z,
 +      [0x17] = KEY_X,
 +      [0x18] = KEY_C,
 +      [0x19] = KEY_V,
 +      [0x1a] = KEY_B,
 +      [0x1b] = KEY_N,
 +      [0x1c] = KEY_LEFTSHIFT, /* Actually, this is both shift keys */
 +      [0x1f] = KEY_F7,
 +
 +      [0x21] = KEY_E,
 +      [0x22] = KEY_SEMICOLON,
 +      [0x23] = KEY_MINUS,
 +      [0x24] = KEY_EQUAL,
 +      [0x2b] = KEY_FN,
 +      [0x2c] = KEY_M,
 +      [0x2f] = KEY_F8,
 +
 +      [0x31] = KEY_R,
 +      [0x32] = KEY_RIGHTCTRL,
 +      [0x34] = KEY_SPACE,
 +      [0x35] = KEY_COMMA,
 +      [0x37] = KEY_UP,
 +      [0x3c] = KEY_COMPOSE,
 +      [0x3f] = KEY_F6,
 +
 +      [0x41] = KEY_T,
 +      [0x44] = KEY_DOT,
 +      [0x46] = KEY_RIGHT,
 +      [0x4f] = KEY_F5,
 +      [0x51] = KEY_Y,
 +      [0x53] = KEY_DOWN,
 +      [0x55] = KEY_ENTER,
 +      [0x5f] = KEY_ESC,
 +
 +      [0x61] = KEY_U,
 +      [0x64] = KEY_LEFT,
 +
 +      [0x71] = KEY_I,
 +      [0x75] = KEY_KPENTER,
 +};
 +
 +static struct lm8323_platform_data lm8323_pdata = {
 +      .repeat = 0, /* Repeat is handled in userspace for now. */
 +      .keymap = rx44_keymap,
 +
 +      .name = "Internal keyboard",
 +      .pwm1_name = "keyboard",
 +      .pwm2_name = "cover",
 +};
 +#endif
 +
 +void __init nokia_n800_init_irq(void)
 +{
 +      omap2_init_common_hw(NULL);
 +      omap_init_irq();
 +      omap_gpio_init();
 +
 +#ifdef CONFIG_OMAP_STI
 +      if (omap_request_gpio(N800_STI_GPIO) < 0) {
 +              printk(KERN_ERR "Failed to request GPIO %d for STI\n",
 +                     N800_STI_GPIO);
 +              return;
 +      }
 +
 +      omap_set_gpio_direction(N800_STI_GPIO, 0);
 +      omap_set_gpio_dataout(N800_STI_GPIO, 0);
 +#endif
 +}
 +
 +#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105)
 +
 +static int n800_tmp105_set_power(int enable)
 +{
 +      return menelaus_set_vaux(enable ? 2800 : 0);
 +}
 +
 +#else
 +
 +#define n800_tmp105_set_power NULL
 +
 +#endif
 +
 +static struct omap_uart_config n800_uart_config __initdata = {
 +      .enabled_uarts = (1 << 0) | (1 << 2),
 +};
 +
 +#include "../../../drivers/cbus/retu.h"
 +
 +static struct omap_fbmem_config n800_fbmem0_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_fbmem_config n800_fbmem1_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_fbmem_config n800_fbmem2_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_tmp105_config n800_tmp105_config __initdata = {
 +      .tmp105_irq_pin = 125,
 +      .set_power = n800_tmp105_set_power,
 +};
 +
 +static void mipid_shutdown(struct mipid_platform_data *pdata)
 +{
 +      if (pdata->nreset_gpio != -1) {
 +              pr_info("shutdown LCD\n");
 +              omap_set_gpio_dataout(pdata->nreset_gpio, 0);
 +              msleep(120);
 +      }
 +}
 +
 +static struct mipid_platform_data n800_mipid_platform_data = {
 +      .shutdown = mipid_shutdown,
 +};
 +
 +static void __init mipid_dev_init(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +              n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
 +              n800_mipid_platform_data.data_lines = conf->data_lines;
 +      }
 +}
 +
 +static struct {
 +      struct clk *sys_ck;
 +} blizzard;
 +
 +static int blizzard_get_clocks(void)
 +{
 +      blizzard.sys_ck = clk_get(0, "osc_ck");
 +      if (IS_ERR(blizzard.sys_ck)) {
 +              printk(KERN_ERR "can't get Blizzard clock\n");
 +              return PTR_ERR(blizzard.sys_ck);
 +      }
 +      return 0;
 +}
 +
 +static unsigned long blizzard_get_clock_rate(struct device *dev)
 +{
 +      return clk_get_rate(blizzard.sys_ck);
 +}
 +
 +static void blizzard_enable_clocks(int enable)
 +{
 +      if (enable)
 +              clk_enable(blizzard.sys_ck);
 +      else
 +              clk_disable(blizzard.sys_ck);
 +}
 +
 +static void blizzard_power_up(struct device *dev)
 +{
 +      /* Vcore to 1.475V */
 +      tahvo_set_clear_reg_bits(0x07, 0, 0xf);
 +      msleep(10);
 +
 +      blizzard_enable_clocks(1);
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 +}
 +
 +static void blizzard_power_down(struct device *dev)
 +{
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 0);
 +      blizzard_enable_clocks(0);
 +
 +      /* Vcore to 1.005V */
 +      tahvo_set_clear_reg_bits(0x07, 0xf, 0);
 +}
 +
 +static struct blizzard_platform_data n800_blizzard_data = {
 +      .power_up       = blizzard_power_up,
 +      .power_down     = blizzard_power_down,
 +      .get_clock_rate = blizzard_get_clock_rate,
 +      .te_connected   = 1,
 +};
 +
 +static void __init blizzard_dev_init(void)
 +{
 +      int r;
 +
 +      r = omap_request_gpio(N800_BLIZZARD_POWERDOWN_GPIO);
 +      if (r < 0)
 +              return;
 +      omap_set_gpio_direction(N800_BLIZZARD_POWERDOWN_GPIO, 0);
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 +
 +      blizzard_get_clocks();
 +      omapfb_set_ctrl_platform_data(&n800_blizzard_data);
 +}
 +
 +static struct omap_mmc_config n800_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled                = 1,
 +              .wire4                  = 1,
 +      },
 +};
 +
 +extern struct omap_mmc_platform_data n800_mmc_data;
 +
 +static struct omap_board_config_kernel n800_config[] __initdata = {
 +      { OMAP_TAG_UART,                        &n800_uart_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem0_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem1_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem2_config },
 +      { OMAP_TAG_TMP105,                      &n800_tmp105_config },
 +      { OMAP_TAG_MMC,                         &n800_mmc_config },
 +};
 +
 +static struct tsc2301_platform_data tsc2301_config = {
 +      .reset_gpio     = N800_TSC2301_RESET_GPIO,
 +      .keymap = {
 +              -1,             /* Event for bit 0 */
 +              KEY_UP,         /* Event for bit 1 (up) */
 +              KEY_F5,         /* Event for bit 2 (home) */
 +              -1,             /* Event for bit 3 */
 +              KEY_LEFT,       /* Event for bit 4 (left) */
 +              KEY_ENTER,      /* Event for bit 5 (enter) */
 +              KEY_RIGHT,      /* Event for bit 6 (right) */
 +              -1,             /* Event for bit 7 */
 +              KEY_ESC,        /* Event for bit 8 (cycle) */
 +              KEY_DOWN,       /* Event for bit 9 (down) */
 +              KEY_F4,         /* Event for bit 10 (menu) */
 +              -1,             /* Event for bit 11 */
 +              KEY_F8,         /* Event for bit 12 (Zoom-) */
 +              KEY_F6,         /* Event for bit 13 (FS) */
 +              KEY_F7,         /* Event for bit 14 (Zoom+) */
 +              -1,             /* Event for bit 15 */
 +      },
 +      .kp_rep         = 0,
 +      .keyb_name      = "Internal keypad",
 +};
 +
 +static void tsc2301_dev_init(void)
 +{
 +      int r;
 +      int gpio = N800_KEYB_IRQ_GPIO;
 +
 +      r = gpio_request(gpio, "tsc2301 KBD IRQ");
 +      if (r >= 0) {
 +              gpio_direction_input(gpio);
 +              tsc2301_config.keyb_int = OMAP_GPIO_IRQ(gpio);
 +      } else {
 +              printk(KERN_ERR "unable to get KBD GPIO");
 +      }
 +
 +      gpio = N800_DAV_IRQ_GPIO;
 +      r = gpio_request(gpio, "tsc2301 DAV IRQ");
 +      if (r >= 0) {
 +              gpio_direction_input(gpio);
 +              tsc2301_config.dav_int = OMAP_GPIO_IRQ(gpio);
 +      } else {
 +              printk(KERN_ERR "unable to get DAV GPIO");
 +      }
 +}
 +
 +static int __init tea5761_dev_init(void)
 +{
 +      const struct omap_tea5761_config *info;
 +      int enable_gpio = 0;
 +
 +      info = omap_get_config(OMAP_TAG_TEA5761, struct omap_tea5761_config);
 +      if (info)
 +              enable_gpio = info->enable_gpio;
 +
 +      if (enable_gpio) {
 +              pr_debug("Enabling tea5761 at GPIO %d\n",
 +                       enable_gpio);
 +
 +              if (omap_request_gpio(enable_gpio) < 0) {
 +                      printk(KERN_ERR "Can't request GPIO %d\n",
 +                             enable_gpio);
 +                      return -ENODEV;
 +              }
 +
 +              omap_set_gpio_direction(enable_gpio, 0);
 +              udelay(50);
 +              omap_set_gpio_dataout(enable_gpio, 1);
 +      }
 +
 +      return 0;
 +}
 +
 +static struct omap2_mcspi_device_config tsc2301_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +static struct omap2_mcspi_device_config mipid_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +static struct omap2_mcspi_device_config cx3110x_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +#ifdef CONFIG_TOUCHSCREEN_TSC2005
 +static struct tsc2005_platform_data tsc2005_config = {
 +      .reset_gpio = 94,
 +      .dav_gpio = 106
 +};
 +
 +static struct omap2_mcspi_device_config tsc2005_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +#endif
 +
 +static struct spi_board_info n800_spi_board_info[] __initdata = {
 +      {
 +              .modalias       = "lcd_mipid",
 +              .bus_num        = 1,
 +              .chip_select    = 1,
 +              .max_speed_hz   = 4000000,
 +              .controller_data= &mipid_mcspi_config,
 +              .platform_data  = &n800_mipid_platform_data,
 +      }, {
 +              .modalias       = "cx3110x",
 +              .bus_num        = 2,
 +              .chip_select    = 0,
 +              .max_speed_hz   = 48000000,
 +              .controller_data= &cx3110x_mcspi_config,
 +      },
 +      {
 +              .modalias       = "tsc2301",
 +              .bus_num        = 1,
 +              .chip_select    = 0,
 +              .max_speed_hz   = 6000000,
 +              .controller_data= &tsc2301_mcspi_config,
 +              .platform_data  = &tsc2301_config,
 +      },
 +};
 +
 +static struct spi_board_info n810_spi_board_info[] __initdata = {
 +      {
 +              .modalias        = "lcd_mipid",
 +              .bus_num         = 1,
 +              .chip_select     = 1,
 +              .max_speed_hz    = 4000000,
 +              .controller_data = &mipid_mcspi_config,
 +              .platform_data   = &n800_mipid_platform_data,
 +      },
 +      {
 +              .modalias        = "cx3110x",
 +              .bus_num         = 2,
 +              .chip_select     = 0,
 +              .max_speed_hz    = 48000000,
 +              .controller_data = &cx3110x_mcspi_config,
 +      },
 +      {
 +              .modalias        = "tsc2005",
 +              .bus_num         = 1,
 +              .chip_select     = 0,
 +              .max_speed_hz    = 6000000,
 +              .controller_data = &tsc2005_mcspi_config,
 +              .platform_data   = &tsc2005_config,
 +      },
 +};
 +
 +static void __init tsc2005_set_config(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +#ifdef CONFIG_TOUCHSCREEN_TSC2005
 +              if (strcmp(conf->panel_name, "lph8923") == 0) {
 +                      tsc2005_config.ts_x_plate_ohm = 180;
 +                      tsc2005_config.ts_hw_avg = 0;
 +                      tsc2005_config.ts_ignore_last = 0;
 +                      tsc2005_config.ts_touch_pressure = 1500;
 +                      tsc2005_config.ts_stab_time = 100;
 +                      tsc2005_config.ts_pressure_max = 2048;
 +                      tsc2005_config.ts_pressure_fudge = 2;
 +                      tsc2005_config.ts_x_max = 4096;
 +                      tsc2005_config.ts_x_fudge = 4;
 +                      tsc2005_config.ts_y_max = 4096;
 +                      tsc2005_config.ts_y_fudge = 7;
 +              } else if (strcmp(conf->panel_name, "ls041y3") == 0) {
 +                      tsc2005_config.ts_x_plate_ohm = 280;
 +                      tsc2005_config.ts_hw_avg = 0;
 +                      tsc2005_config.ts_ignore_last = 0;
 +                      tsc2005_config.ts_touch_pressure = 1500;
 +                      tsc2005_config.ts_stab_time = 1000;
 +                      tsc2005_config.ts_pressure_max = 2048;
 +                      tsc2005_config.ts_pressure_fudge = 2;
 +                      tsc2005_config.ts_x_max = 4096;
 +                      tsc2005_config.ts_x_fudge = 4;
 +                      tsc2005_config.ts_y_max = 4096;
 +                      tsc2005_config.ts_y_fudge = 7;
 +              } else {
 +                      printk(KERN_ERR "Unknown panel type, set default "
 +                             "touchscreen configuration\n");
 +                      tsc2005_config.ts_x_plate_ohm = 200;
 +                      tsc2005_config.ts_stab_time = 100;
 +              }
 +#endif
 +      }
 +}
 +
 +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
 +
 +void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self,
 +                             int on_off)
 +{
 +      if (on_off) {
 +              retu_write_reg(RETU_REG_CTRL_SET, 1 << 6);
 +              msleep(2);
 +              retu_write_reg(RETU_REG_CTRL_SET, 1 << 3);
 +      } else {
 +              retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3));
 +      }
 +}
 +
 +static struct omap_pwm_led_platform_data n800_keypad_led_data = {
 +      .name = "keypad",
 +      .intensity_timer = 10,
 +      .blink_timer = 9,
 +      .set_power = retu_keypad_led_set_power,
 +};
 +
 +static struct platform_device n800_keypad_led_device = {
 +      .name           = "omap_pwm_led",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data = &n800_keypad_led_data,
 +      },
 +};
 +#endif
 +
 +#if defined(CONFIG_TOUCHSCREEN_TSC2301)
 +static void __init n800_ts_set_config(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +              if (strcmp(conf->panel_name, "lph8923") == 0) {
 +                      tsc2301_config.ts_x_plate_ohm   = 180;
 +                      tsc2301_config.ts_hw_avg        = 8;
 +                      tsc2301_config.ts_max_pressure  = 2048;
 +                      tsc2301_config.ts_touch_pressure = 400;
 +                      tsc2301_config.ts_stab_time     = 100;
 +                      tsc2301_config.ts_pressure_fudge = 2;
 +                      tsc2301_config.ts_x_max         = 4096;
 +                      tsc2301_config.ts_x_fudge       = 4;
 +                      tsc2301_config.ts_y_max         = 4096;
 +                      tsc2301_config.ts_y_fudge       = 7;
 +              } else if (strcmp(conf->panel_name, "ls041y3") == 0) {
 +                      tsc2301_config.ts_x_plate_ohm   = 280;
 +                      tsc2301_config.ts_hw_avg        = 8;
 +                      tsc2301_config.ts_touch_pressure = 400;
 +                      tsc2301_config.ts_max_pressure  = 2048;
 +                      tsc2301_config.ts_stab_time     = 1000;
 +                      tsc2301_config.ts_pressure_fudge = 2;
 +                      tsc2301_config.ts_x_max         = 4096;
 +                      tsc2301_config.ts_x_fudge       = 4;
 +                      tsc2301_config.ts_y_max         = 4096;
 +                      tsc2301_config.ts_y_fudge       = 7;
 +              } else {
 +                      printk(KERN_ERR "Unknown panel type, set default "
 +                             "touchscreen configuration\n");
 +                      tsc2301_config.ts_x_plate_ohm   = 200;
 +                      tsc2301_config.ts_stab_time     = 100;
 +              }
 +      }
 +}
 +#else
 +static inline void n800_ts_set_config(void)
 +{
 +}
 +#endif
 +
 +static struct omap_gpio_switch n800_gpio_switches[] __initdata = {
 +      {
 +              .name                   = "bat_cover",
 +              .gpio                   = -1,
 +              .debounce_rising        = 100,
 +              .debounce_falling       = 0,
 +              .notify                 = n800_mmc_slot1_cover_handler,
 +              .notify_data            = NULL,
 +      }, {
 +              .name                   = "headphone",
 +              .gpio                   = -1,
 +              .debounce_rising        = 200,
 +              .debounce_falling       = 200,
 +      }, {
 +              .name                   = "cam_act",
 +              .gpio                   = -1,
 +              .debounce_rising        = 200,
 +              .debounce_falling       = 200,
 +      }, {
 +              .name                   = "cam_turn",
 +              .gpio                   = -1,
 +              .debounce_rising        = 100,
 +              .debounce_falling       = 100,
 +      },
 +};
 +
 +static struct platform_device *n800_devices[] __initdata = {
 +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
 +      &n800_keypad_led_device,
 +#endif
 +};
 +
 +#ifdef CONFIG_MENELAUS
 +static int n800_auto_sleep_regulators(void)
 +{
 +      u32 val;
 +      int ret;
 +
 +      val = EN_VPLL_SLEEP | EN_VMMC_SLEEP    \
 +              | EN_VAUX_SLEEP | EN_VIO_SLEEP \
 +              | EN_VMEM_SLEEP | EN_DC3_SLEEP \
 +              | EN_VC_SLEEP | EN_DC2_SLEEP;
 +
 +      ret = menelaus_set_regulator_sleep(1, val);
 +      if (ret < 0) {
 +              printk(KERN_ERR "Could not set regulators to sleep on "
 +                      "menelaus: %u\n", ret);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +static int n800_auto_voltage_scale(void)
 +{
 +      int ret;
 +
 +      ret = menelaus_set_vcore_hw(1400, 1050);
 +      if (ret < 0) {
 +              printk(KERN_ERR "Could not set VCORE voltage on "
 +                      "menelaus: %u\n", ret);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +static int n800_menelaus_init(struct device *dev)
 +{
 +      int ret;
 +
 +      ret = n800_auto_voltage_scale();
 +      if (ret < 0)
 +              return ret;
 +      ret = n800_auto_sleep_regulators();
 +      if (ret < 0)
 +              return ret;
 +      return 0;
 +}
 +
 +static struct menelaus_platform_data n800_menelaus_platform_data = {
 +      .late_init = n800_menelaus_init,
 +};
 +#endif
 +
 +static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 +      {
 +              I2C_BOARD_INFO("menelaus", 0x72),
 +              .irq = INT_24XX_SYS_NIRQ,
 +              .platform_data = &n800_menelaus_platform_data,
 +      },
 +};
 +
 +extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 +
 +static struct i2c_board_info __initdata_or_module n8x0_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
 +#if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 +              .platform_data = &n800_tcm825x_platform_data,
 +#endif
 +      },
 +      {
 +              I2C_BOARD_INFO("tsl2563", 0x29),
 +      },
 +      {
 +              I2C_BOARD_INFO("lp5521", 0x32),
 +      },
 +};
 +
 +
 +static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO("tea5761", 0x10),
 +      },
 +};
 +
 +static struct i2c_board_info __initdata_or_module n810_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO("lm8323", 0x45),
 +              .irq            = OMAP_GPIO_IRQ(109),
 +              .platform_data  = &lm8323_pdata,
 +      },
 +};
 +
 +void __init nokia_n800_common_init(void)
 +{
 +      platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices));
 +
 +      n800_flash_init();
 +      n800_mmc_init();
 +      n800_bt_init();
 +      n800_dsp_init();
 +      n800_usb_init();
 +      n800_cam_init();
 +      if (machine_is_nokia_n800())
 +              spi_register_board_info(n800_spi_board_info,
 +                              ARRAY_SIZE(n800_spi_board_info));
 +      if (machine_is_nokia_n810()) {
 +              tsc2005_set_config();
 +              spi_register_board_info(n810_spi_board_info,
 +                              ARRAY_SIZE(n810_spi_board_info));
 +      }
 +      omap_serial_init();
 +      omap_register_i2c_bus(1, 400, n800_i2c_board_info_1,
 +                            ARRAY_SIZE(n800_i2c_board_info_1));
 +      omap_register_i2c_bus(2, 400, n8x0_i2c_board_info_2,
 +                            ARRAY_SIZE(n800_i2c_board_info_2));
 +      if (machine_is_nokia_n800())
 +              i2c_register_board_info(2, n800_i2c_board_info_2,
 +                      ARRAY_SIZE(n800_i2c_board_info_2));
 +      if (machine_is_nokia_n810())
 +              i2c_register_board_info(2, n810_i2c_board_info_2,
 +                      ARRAY_SIZE(n810_i2c_board_info_2));
 +              
 +      mipid_dev_init();
 +      blizzard_dev_init();
 +}
 +
 +static void __init nokia_n800_init(void)
 +{
 +      nokia_n800_common_init();
 +
 +      n800_audio_init(&tsc2301_config);
 +      n800_ts_set_config();
 +      tsc2301_dev_init();
 +      tea5761_dev_init();
 +      omap_register_gpio_switches(n800_gpio_switches,
 +                                  ARRAY_SIZE(n800_gpio_switches));
 +}
 +
 +void __init nokia_n800_map_io(void)
 +{
 +      omap_board_config = n800_config;
 +      omap_board_config_size = ARRAY_SIZE(n800_config);
 +
 +      omap2_set_globals_242x();
 +      omap2_map_common_io();
 +}
 +
 +MACHINE_START(NOKIA_N800, "Nokia N800")
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = nokia_n800_map_io,
 +      .init_irq       = nokia_n800_init_irq,
 +      .init_machine   = nokia_n800_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 8609a0b6591a254e7f4362dd4735e11ec1e517ff,0000000000000000000000000000000000000000..7984d43aeec9189c723306c82a0fd9e91824a00d
mode 100644,000000..100644
--- /dev/null
@@@ -1,47 -1,0 +1,47 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-n810.c
 + *
 + * Copyright (C) 2007 Nokia
 + * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/init.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c/lm8323.h>
 +
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
++#include <mach/board.h>
++#include <mach/common.h>
 +
 +#include "board-n800.h"
 +
 +static void __init nokia_n810_init(void)
 +{
 +      nokia_n800_common_init();
 +}
 +
 +MACHINE_START(NOKIA_N810, "Nokia N810")
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = nokia_n800_map_io,
 +      .init_irq       = nokia_n800_init_irq,
 +      .init_machine   = nokia_n810_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
 +
 +MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = nokia_n800_map_io,
 +      .init_irq       = nokia_n800_init_irq,
 +      .init_machine   = nokia_n810_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 9eb93b6802c91b1b8211fb9df938a0f4c96a5794,0000000000000000000000000000000000000000..9bb8fbaf824aa9ebf6c26d9e9b71beba4e6a9bde
mode 100644,000000..100644
--- /dev/null
@@@ -1,180 -1,0 +1,180 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-omap2evm.c
 + *
 + * Copyright (C) 2008 Mistral Solutions Pvt Ltd
 + *
 + * Modified from mach-omap2/board-generic.c
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <linux/input.h>
 +
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
- #include <asm/arch/common.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/keypad.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +
++#include <mach/gpio.h>
++#include <mach/board.h>
++#include <mach/common.h>
++#include <mach/hsmmc.h>
++#include <mach/keypad.h>
 +
 +static struct resource omap2evm_smc911x_resources[] = {
 +      [0] =   {
 +              .start  = OMAP2EVM_ETHR_START,
 +              .end    = (OMAP2EVM_ETHR_START + OMAP2EVM_ETHR_SIZE - 1),
 +              .flags  = IORESOURCE_MEM,
 +      },
 +      [1] =   {
 +              .start  = OMAP_GPIO_IRQ(OMAP2EVM_ETHR_GPIO_IRQ),
 +              .end    = OMAP_GPIO_IRQ(OMAP2EVM_ETHR_GPIO_IRQ),
 +              .flags  = IORESOURCE_IRQ,
 +      },
 +};
 +
 +static struct platform_device omap2evm_smc911x_device = {
 +      .name       = "smc911x",
 +      .id     = -1,
 +      .num_resources  = ARRAY_SIZE(omap2evm_smc911x_resources),
 +      .resource   = &omap2evm_smc911x_resources [0],
 +};
 +
 +static inline void __init omap2evm_init_smc911x(void)
 +{
 +      int gpio = OMAP2EVM_ETHR_GPIO_IRQ;
 +      int ret;
 +
 +      ret = gpio_request(gpio, "smc911x IRQ");
 +      if (ret < 0) {
 +              printk(KERN_ERR "Failed to request GPIO %d for smc911x IRQ\n",
 +                              gpio);
 +              return;
 +      }
 +      gpio_direction_input(gpio);
 +
 +}
 +
 +static struct platform_device omap2_evm_lcd_device = {
 +      .name           = "omap2evm_lcd",
 +      .id             = -1,
 +};
 +
 +static struct omap_lcd_config omap2_evm_lcd_config __initdata = {
 +      .ctrl_name      = "internal",
 +};
 +
 +static int omap2evm_keymap[] = {
 +      KEY(0, 0, KEY_LEFT),
 +      KEY(0, 1, KEY_RIGHT),
 +      KEY(0, 2, KEY_A),
 +      KEY(0, 3, KEY_B),
 +      KEY(1, 0, KEY_DOWN),
 +      KEY(1, 1, KEY_UP),
 +      KEY(1, 2, KEY_E),
 +      KEY(1, 3, KEY_F),
 +      KEY(2, 0, KEY_ENTER),
 +      KEY(2, 1, KEY_I),
 +      KEY(2, 2, KEY_J),
 +      KEY(2, 3, KEY_K),
 +      KEY(3, 0, KEY_M),
 +      KEY(3, 1, KEY_N),
 +      KEY(3, 2, KEY_O),
 +      KEY(3, 3, KEY_P)
 +};
 +
 +static struct omap_kp_platform_data omap2evm_kp_data = {
 +      .rows           = 4,
 +      .cols           = 4,
 +      .keymap         = omap2evm_keymap,
 +      .keymapsize     = ARRAY_SIZE(omap2evm_keymap),
 +      .rep            = 1,
 +};
 +
 +static struct platform_device omap2evm_kp_device = {
 +      .name           = "omap_twl4030keypad",
 +      .id             = -1,
 +      .dev            = {
 +                              .platform_data = &omap2evm_kp_data,
 +                      },
 +};
 +
 +static void __init omap2_evm_init_irq(void)
 +{
 +      omap2_init_common_hw(NULL);
 +      omap_init_irq();
 +      omap_gpio_init();
 +      omap2evm_init_smc911x();
 +}
 +
 +static struct omap_uart_config omap2_evm_uart_config __initdata = {
 +      .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
 +};
 +
 +static struct omap_mmc_config omap2_evm_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled        = 1,
 +              .wire4          = 1,
 +      },
 +};
 +
 +static struct omap_board_config_kernel omap2_evm_config[] __initdata = {
 +      { OMAP_TAG_UART,        &omap2_evm_uart_config },
 +      { OMAP_TAG_LCD,         &omap2_evm_lcd_config },
 +      { OMAP_TAG_MMC,         &omap2_evm_mmc_config },
 +};
 +
 +static int __init omap2_evm_i2c_init(void)
 +{
 +      /*
 +       * Registering bus 2 first to avoid twl4030 misbehaving as OMAP2EVM
 +       * has twl4030 on bus 2
 +       */
 +      omap_register_i2c_bus(2, 2600, NULL, 0);
 +      omap_register_i2c_bus(1, 400, NULL, 0);
 +      return 0;
 +}
 +
 +static struct platform_device *omap2_evm_devices[] __initdata = {
 +      &omap2_evm_lcd_device,
 +      &omap2evm_smc911x_device,
 +      &omap2evm_kp_device,
 +};
 +
 +static void __init omap2_evm_init(void)
 +{
 +      platform_add_devices(omap2_evm_devices, ARRAY_SIZE(omap2_evm_devices));
 +      omap_board_config = omap2_evm_config;
 +      omap_board_config_size = ARRAY_SIZE(omap2_evm_config);
 +      omap_serial_init();
 +      hsmmc_init();
 +}
 +
 +static void __init omap2_evm_map_io(void)
 +{
 +      omap2_set_globals_243x();
 +      omap2_map_common_io();
 +}
 +
 +arch_initcall(omap2_evm_i2c_init);
 +
 +MACHINE_START(OMAP2EVM, "OMAP2EVM Board")
 +      /* Maintainer:  Arun KS <arunks@mistralsolutions.com> */
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = omap2_evm_map_io,
 +      .init_irq       = omap2_evm_init_irq,
 +      .init_machine   = omap2_evm_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 307cbf84de4aabbe4175f836eed2cd677d84ec4e,0000000000000000000000000000000000000000..85119ce5aa1467c6782a41fa3491981edd89fa06
mode 100644,000000..100644
--- /dev/null
@@@ -1,249 -1,0 +1,249 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-omap3beagle.c
 + *
 + * Copyright (C) 2008 Texas Instruments
 + *
 + * Modified from mach-omap2/board-3430sdp.c
 + *
 + * Initial code: Syed Mohammed Khasim
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <linux/leds.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/mtd/nand.h>
 +
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
- #include <asm/arch/usb-musb.h>
- #include <asm/arch/usb-ehci.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/common.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/nand.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +#include <asm/mach/flash.h>
 +
++#include <mach/gpio.h>
++#include <mach/board.h>
++#include <mach/usb-musb.h>
++#include <mach/usb-ehci.h>
++#include <mach/hsmmc.h>
++#include <mach/common.h>
++#include <mach/gpmc.h>
++#include <mach/nand.h>
 +
 +#define GPMC_CS0_BASE  0x60
 +#define GPMC_CS_SIZE   0x30
 +
 +static struct mtd_partition omap3beagle_nand_partitions[] = {
 +      /* All the partition sizes are listed in terms of NAND block size */
 +      {
 +              .name           = "X-Loader",
 +              .offset         = 0,
 +              .size           = 4*(64 * 2048),
 +              .mask_flags     = MTD_WRITEABLE,        /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot",
 +              .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
 +              .size           = 15*(64 * 2048),
 +              .mask_flags     = MTD_WRITEABLE,        /* force read-only */
 +      },
 +      {
 +              .name           = "U-Boot Env",
 +              .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
 +              .size           = 1*(64 * 2048),
 +      },
 +      {
 +              .name           = "Kernel",
 +              .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
 +              .size           = 32*(64 * 2048),
 +      },
 +      {
 +              .name           = "File System",
 +              .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
 +              .size           = MTDPART_SIZ_FULL,
 +      },
 +};
 +
 +static struct omap_nand_platform_data omap3beagle_nand_data = {
 +      .parts          = omap3beagle_nand_partitions,
 +      .nr_parts       = ARRAY_SIZE(omap3beagle_nand_partitions),
 +      .dma_channel    = -1,           /* disable DMA in OMAP NAND driver */
 +      .nand_setup     = NULL,
 +      .dev_ready      = NULL,
 +};
 +
 +static struct resource omap3beagle_nand_resource = {
 +      .flags          = IORESOURCE_MEM,
 +};
 +
 +static struct platform_device omap3beagle_nand_device = {
 +      .name           = "omap2-nand",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data  = &omap3beagle_nand_data,
 +      },
 +      .num_resources  = 1,
 +      .resource       = &omap3beagle_nand_resource,
 +};
 +
 +#include "sdram-micron-mt46h32m32lf-6.h"
 +
 +static struct omap_uart_config omap3_beagle_uart_config __initdata = {
 +      .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
 +};
 +
 +static int __init omap3_beagle_i2c_init(void)
 +{
 +      omap_register_i2c_bus(1, 2600, NULL, 0);
 +#ifdef CONFIG_I2C2_OMAP_BEAGLE
 +      omap_register_i2c_bus(2, 400, NULL, 0);
 +#endif
 +      omap_register_i2c_bus(3, 400, NULL, 0);
 +      return 0;
 +}
 +
 +static void __init omap3_beagle_init_irq(void)
 +{
 +      omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
 +      omap_init_irq();
 +      omap_gpio_init();
 +}
 +
 +static struct omap_mmc_config omap3beagle_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled        = 1,
 +              .wire4          = 1,
 +      },
 +};
 +
 +static struct platform_device omap3_beagle_twl4030rtc_device = {
 +      .name           = "twl4030_rtc",
 +      .id             = -1,
 +};
 +
 +static struct platform_device omap3_beagle_lcd_device = {
 +      .name           = "omap3beagle_lcd",
 +      .id             = -1,
 +};
 +
 +static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
 +      .ctrl_name      = "internal",
 +};
 +
 +struct gpio_led gpio_leds[] = {
 +      {
 +              .name                   = "beagleboard::usr0",
 +              .default_trigger        = "none",
 +              .gpio                   = 150,
 +      },
 +      {
 +              .name                   = "beagleboard::usr1",
 +              .default_trigger        = "none",
 +              .gpio                   = 149,
 +      },
 +};
 +
 +static struct gpio_led_platform_data gpio_led_info = {
 +      .leds           = gpio_leds,
 +      .num_leds       = ARRAY_SIZE(gpio_leds),
 +};
 +
 +static struct platform_device leds_gpio = {
 +      .name   = "leds-gpio",
 +      .id     = -1,
 +      .dev    = {
 +              .platform_data  = &gpio_led_info,
 +      },
 +};
 +
 +static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
 +      { OMAP_TAG_UART,        &omap3_beagle_uart_config },
 +      { OMAP_TAG_MMC,         &omap3beagle_mmc_config },
 +      { OMAP_TAG_LCD,         &omap3_beagle_lcd_config },
 +};
 +
 +static struct platform_device *omap3_beagle_devices[] __initdata = {
 +      &omap3_beagle_lcd_device,
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +      &omap3_beagle_twl4030rtc_device,
 +#endif
 +      &leds_gpio,
 +};
 +
 +void __init omap3beagle_flash_init(void)
 +{
 +      u8 cs = 0;
 +      u8 nandcs = GPMC_CS_NUM + 1;
 +
 +      u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
 +
 +      /* find out the chip-select on which NAND exists */
 +      while (cs < GPMC_CS_NUM) {
 +              u32 ret = 0;
 +              ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
 +
 +              if ((ret & 0xC00) == 0x800) {
 +                      printk(KERN_INFO "Found NAND on CS%d\n", cs);
 +                      if (nandcs > GPMC_CS_NUM)
 +                              nandcs = cs;
 +              }
 +              cs++;
 +      }
 +
 +      if (nandcs > GPMC_CS_NUM) {
 +              printk(KERN_INFO "NAND: Unable to find configuration "
 +                               "in GPMC\n ");
 +              return;
 +      }
 +
 +      if (nandcs < GPMC_CS_NUM) {
 +              omap3beagle_nand_data.cs = nandcs;
 +              omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
 +                      (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
 +              omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
 +
 +              printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
 +              if (platform_device_register(&omap3beagle_nand_device) < 0)
 +                      printk(KERN_ERR "Unable to register NAND device\n");
 +      }
 +}
 +
 +static void __init omap3_beagle_init(void)
 +{
 +      platform_add_devices(omap3_beagle_devices, ARRAY_SIZE(omap3_beagle_devices));
 +      omap_board_config = omap3_beagle_config;
 +      omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
 +      omap_serial_init();
 +      hsmmc_init();
 +      usb_musb_init();
 +      usb_ehci_init();
 +      omap3beagle_flash_init();
 +}
 +
 +arch_initcall(omap3_beagle_i2c_init);
 +
 +static void __init omap3_beagle_map_io(void)
 +{
 +      omap2_set_globals_343x();
 +      omap2_map_common_io();
 +}
 +
 +MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 +      /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = omap3_beagle_map_io,
 +      .init_irq       = omap3_beagle_init_irq,
 +      .init_machine   = omap3_beagle_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 109d8f22abdb241e327cef6185784f1cd4bf34f7,0000000000000000000000000000000000000000..0aa8ef26879b8c56afcafe3ca1571afe45db8d14
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,117 @@@
- #include <asm/arch/onenand.h>
- #include <asm/arch/board.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/nand.h>
 +/*
 + * board-omap3evm-flash.c
 + *
 + * Copyright (c) 2008 Texas Instruments,
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/platform_device.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/mtd/nand.h>
 +#include <linux/mtd/onenand_regs.h>
 +#include <linux/types.h>
 +#include <linux/io.h>
 +
 +#include <asm/mach/flash.h>
++#include <mach/onenand.h>
++#include <mach/board.h>
++#include <mach/gpmc.h>
++#include <mach/nand.h>
 +
 +static int omap3evm_onenand_setup(void __iomem *);
 +
 +static struct mtd_partition omap3evm_onenand_partitions[] = {
 +      {
 +              .name           = "xloader",
 +              .offset         = 0,
 +              .size           = 4*(64*2048),
 +              .mask_flags     = MTD_WRITEABLE
 +      },
 +      {
 +              .name           = "uboot",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           =  15*(64*2048),
 +              .mask_flags     = MTD_WRITEABLE
 +      },
 +      {
 +              .name           = "params",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 1*(64*2048),
 +      },
 +      {
 +              .name           = "linux",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = 40*(64*2048),
 +      },
 +      {
 +              .name           = "jffs2",
 +              .offset         = MTDPART_OFS_APPEND,
 +              .size           = MTDPART_SIZ_FULL,
 +      },
 +};
 +
 +static struct omap_onenand_platform_data omap3evm_onenand_data = {
 +      .parts = omap3evm_onenand_partitions,
 +      .nr_parts = ARRAY_SIZE(omap3evm_onenand_partitions),
 +      .onenand_setup = omap3evm_onenand_setup,
 +      .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
 +};
 +
 +static struct platform_device omap3evm_onenand_device = {
 +      .name           = "omap2-onenand",
 +      .id             = -1,
 +      .dev = {
 +              .platform_data = &omap3evm_onenand_data,
 +      },
 +};
 +
 +/*
 + *      omap3evm_onenand_setup - Set the onenand sync mode
 + *      @onenand_base:  The onenand base address in GPMC memory map
 + *
 + */
 +
 +static int omap3evm_onenand_setup(void __iomem *onenand_base)
 +      {
 +      /* nothing is required to be setup for onenand as of now */
 +      return 0;
 +}
 +
 +void __init omap3evm_flash_init(void)
 +{
 +      u8              cs = 0;
 +      u8              onenandcs = GPMC_CS_NUM + 1;
 +
 +      while (cs < GPMC_CS_NUM) {
 +              u32 ret = 0;
 +              ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
 +
 +              /*
 +              * xloader/Uboot would have programmed the oneNAND
 +              * base address for us This is a ugly hack. The proper
 +              * way of doing this is to pass the setup of u-boot up
 +              * to kernel using kernel params - something on the
 +              * lines of machineID. Check if oneNAND is configured
 +              */
 +              if ((ret & 0x3F) == (ONENAND_MAP >> 24))
 +                      onenandcs = cs;
 +              cs++;
 +      }
 +      if (onenandcs > GPMC_CS_NUM) {
 +              printk(KERN_INFO "OneNAND: Unable to find configuration "
 +                              " in GPMC\n ");
 +              return;
 +      }
 +
 +      if (onenandcs < GPMC_CS_NUM) {
 +              omap3evm_onenand_data.cs = onenandcs;
 +              if (platform_device_register(&omap3evm_onenand_device) < 0)
 +                      printk(KERN_ERR "Unable to register OneNAND device\n");
 +      }
 +}
 +
index df81706d26856e8f9842ac66d288b9afd85012f0,0000000000000000000000000000000000000000..4963f0fad310c63c78d644b004186bc1d8da1285
mode 100644,000000..100644
--- /dev/null
@@@ -1,248 -1,0 +1,248 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-omap3evm.c
 + *
 + * Copyright (C) 2008 Texas Instruments
 + *
 + * Modified from mach-omap2/board-3430sdp.c
 + *
 + * Initial code: Syed Mohammed Khasim
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <linux/input.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/ads7846.h>
 +
- #include <asm/arch/gpio.h>
- #include <asm/arch/keypad.h>
- #include <asm/arch/board.h>
- #include <asm/arch/hsmmc.h>
- #include <asm/arch/usb-musb.h>
- #include <asm/arch/usb-ehci.h>
- #include <asm/arch/common.h>
- #include <asm/arch/mcspi.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +
++#include <mach/gpio.h>
++#include <mach/keypad.h>
++#include <mach/board.h>
++#include <mach/hsmmc.h>
++#include <mach/usb-musb.h>
++#include <mach/usb-ehci.h>
++#include <mach/common.h>
++#include <mach/mcspi.h>
 +
 +#include "sdram-micron-mt46h32m32lf-6.h"
 +
 +static struct resource omap3evm_smc911x_resources[] = {
 +      [0] =   {
 +              .start  = OMAP3EVM_ETHR_START,
 +              .end    = (OMAP3EVM_ETHR_START + OMAP3EVM_ETHR_SIZE - 1),
 +              .flags  = IORESOURCE_MEM,
 +      },
 +      [1] =   {
 +              .start  = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ),
 +              .end    = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ),
 +              .flags  = IORESOURCE_IRQ,
 +      },
 +};
 +
 +static struct platform_device omap3evm_smc911x_device = {
 +      .name           = "smc911x",
 +      .id             = -1,
 +      .num_resources  = ARRAY_SIZE(omap3evm_smc911x_resources),
 +      .resource       = &omap3evm_smc911x_resources [0],
 +};
 +
 +static inline void __init omap3evm_init_smc911x(void)
 +{
 +      int eth_cs;
 +      struct clk *l3ck;
 +      unsigned int rate;
 +
 +      eth_cs = OMAP3EVM_SMC911X_CS;
 +
 +      l3ck = clk_get(NULL, "l3_ck");
 +      if (IS_ERR(l3ck))
 +              rate = 100000000;
 +      else
 +              rate = clk_get_rate(l3ck);
 +
 +      if (omap_request_gpio(OMAP3EVM_ETHR_GPIO_IRQ) < 0) {
 +              printk(KERN_ERR "Failed to request GPIO%d for smc911x IRQ\n",
 +                      OMAP3EVM_ETHR_GPIO_IRQ);
 +              return;
 +      }
 +
 +      omap_set_gpio_direction(OMAP3EVM_ETHR_GPIO_IRQ, 1);
 +}
 +
 +static struct omap_uart_config omap3_evm_uart_config __initdata = {
 +      .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
 +};
 +
 +static int __init omap3_evm_i2c_init(void)
 +{
 +      omap_register_i2c_bus(1, 2600, NULL, 0);
 +      omap_register_i2c_bus(2, 400, NULL, 0);
 +      omap_register_i2c_bus(3, 400, NULL, 0);
 +      return 0;
 +}
 +
 +static struct omap_mmc_config omap3_evm_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled        = 1,
 +              .wire4          = 1,
 +      },
 +};
 +
 +static struct platform_device omap3_evm_lcd_device = {
 +      .name           = "omap3evm_lcd",
 +      .id             = -1,
 +};
 +
 +static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
 +      .ctrl_name      = "internal",
 +};
 +
 +static struct platform_device omap3_evm_twl4030rtc_device = {
 +      .name           = "twl4030_rtc",
 +      .id             = -1,
 +};
 +
 +static void ads7846_dev_init(void)
 +{
 +      if (omap_request_gpio(OMAP3_EVM_TS_GPIO) < 0)
 +              printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
 +
 +      omap_set_gpio_direction(OMAP3_EVM_TS_GPIO, 1);
 +
 +      omap_set_gpio_debounce(OMAP3_EVM_TS_GPIO, 1);
 +      omap_set_gpio_debounce_time(OMAP3_EVM_TS_GPIO, 0xa);
 +}
 +
 +static int ads7846_get_pendown_state(void)
 +{
 +      return !omap_get_gpio_datain(OMAP3_EVM_TS_GPIO);
 +}
 +
 +struct ads7846_platform_data ads7846_config = {
 +      .get_pendown_state      = ads7846_get_pendown_state,
 +      .keep_vref_on           = 1,
 +};
 +
 +static struct omap2_mcspi_device_config ads7846_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,  /* 0: slave, 1: master */
 +};
 +
 +struct spi_board_info omap3evm_spi_board_info[] = {
 +      [0] = {
 +              .modalias               = "ads7846",
 +              .bus_num                = 1,
 +              .chip_select            = 0,
 +              .max_speed_hz           = 1500000,
 +              .controller_data        = &ads7846_mcspi_config,
 +              .irq                    = OMAP_GPIO_IRQ(OMAP3_EVM_TS_GPIO),
 +              .platform_data          = &ads7846_config,
 +      },
 +};
 +
 +static int omap3evm_keymap[] = {
 +      KEY(0, 0, KEY_LEFT),
 +      KEY(0, 1, KEY_RIGHT),
 +      KEY(0, 2, KEY_A),
 +      KEY(0, 3, KEY_B),
 +      KEY(1, 0, KEY_DOWN),
 +      KEY(1, 1, KEY_UP),
 +      KEY(1, 2, KEY_E),
 +      KEY(1, 3, KEY_F),
 +      KEY(2, 0, KEY_ENTER),
 +      KEY(2, 1, KEY_I),
 +      KEY(2, 2, KEY_J),
 +      KEY(2, 3, KEY_K),
 +      KEY(3, 0, KEY_M),
 +      KEY(3, 1, KEY_N),
 +      KEY(3, 2, KEY_O),
 +      KEY(3, 3, KEY_P)
 +};
 +
 +static struct omap_kp_platform_data omap3evm_kp_data = {
 +      .rows           = 4,
 +      .cols           = 4,
 +      .keymap         = omap3evm_keymap,
 +      .keymapsize     = ARRAY_SIZE(omap3evm_keymap),
 +      .rep            = 1,
 +};
 +
 +static struct platform_device omap3evm_kp_device = {
 +      .name           = "omap_twl4030keypad",
 +      .id             = -1,
 +      .dev            = {
 +                              .platform_data = &omap3evm_kp_data,
 +                      },
 +};
 +
 +static void __init omap3_evm_init_irq(void)
 +{
 +      omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
 +      omap_init_irq();
 +      omap_gpio_init();
 +      omap3evm_init_smc911x();
 +}
 +
 +static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 +      { OMAP_TAG_UART,        &omap3_evm_uart_config },
 +      { OMAP_TAG_MMC,         &omap3_evm_mmc_config },
 +      { OMAP_TAG_LCD,         &omap3_evm_lcd_config },
 +};
 +
 +static struct platform_device *omap3_evm_devices[] __initdata = {
 +      &omap3_evm_lcd_device,
 +      &omap3evm_kp_device,
 +#ifdef CONFIG_RTC_DRV_TWL4030
 +      &omap3_evm_twl4030rtc_device,
 +#endif
 +      &omap3evm_smc911x_device,
 +};
 +
 +static void __init omap3_evm_init(void)
 +{
 +      platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
 +      omap_board_config = omap3_evm_config;
 +      omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 +
 +      spi_register_board_info(omap3evm_spi_board_info,
 +                              ARRAY_SIZE(omap3evm_spi_board_info));
 +
 +      omap_serial_init();
 +      hsmmc_init();
 +      usb_musb_init();
 +      usb_ehci_init();
 +      omap3evm_flash_init();
 +      ads7846_dev_init();
 +}
 +
 +arch_initcall(omap3_evm_i2c_init);
 +
 +static void __init omap3_evm_map_io(void)
 +{
 +      omap2_set_globals_343x();
 +      omap2_map_common_io();
 +}
 +
 +MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 +      /* Maintainer: Syed Mohammed Khasim - Texas Instruments */
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = omap3_evm_map_io,
 +      .init_irq       = omap3_evm_init_irq,
 +      .init_machine   = omap3_evm_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
index 3e15681cd29b2abcb02d273062e8a0fe9b6f98f6,1d891e4a69337d76aba8a75cb931e58477935161..be5c6169f4790e8e273ca73cb78b1f2c0d98e730
  #include <linux/errno.h>
  #include <linux/delay.h>
  #include <linux/clk.h>
 -#include <asm/bitops.h>
 -
 -#include <asm/io.h>
 +#include <linux/bitops.h>
 +#include <linux/io.h>
  
- #include <asm/arch/clock.h>
- #include <asm/arch/clockdomain.h>
- #include <asm/arch/sram.h>
- #include <asm/arch/cpu.h>
- #include <asm/arch/prcm.h>
+ #include <mach/clock.h>
++#include <mach/clockdomain.h>
+ #include <mach/sram.h>
+ #include <mach/cpu.h>
++#include <mach/prcm.h>
  #include <asm/div64.h>
  
- #include <asm/arch/sdrc.h>
 -#include "memory.h"
++#include <mach/sdrc.h>
  #include "sdrc.h"
  #include "clock.h"
  #include "prm.h"
Simple merge
index 0d9d91f70720821bf295165705784bb724406f22,295e671e9cfdbcb397560cac97d881960077c07c..c26d9d8e73261db0c00e11718321f0f2dc4dd35c
  #include <linux/io.h>
  #include <linux/cpufreq.h>
  
- #include <asm/arch/common.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/sram.h>
++#include <mach/common.h>
+ #include <mach/clock.h>
+ #include <mach/sram.h>
  #include <asm/div64.h>
 -#include <asm/bitops.h>
  
- #include <asm/arch/sdrc.h>
 -#include "memory.h"
++#include <mach/sdrc.h>
  #include "clock.h"
  #include "clock24xx.h"
  #include "prm.h"
index 0caa4ddb49230987682973a957ea7f038fd44e4f,3ff74952f8354658d310654fa32c894f3e6c2475..21492c2f7a2fada467b00ff96102f0ef737d2cad
@@@ -31,7 -31,7 +31,7 @@@
  #include <asm/div64.h>
  #include <asm/bitops.h>
  
- #include <asm/arch/sdrc.h>
 -#include "memory.h"
++#include <mach/sdrc.h>
  #include "clock.h"
  #include "clock34xx.h"
  #include "prm.h"
Simple merge
index 49741e8c9cd095eae4133a276e68cff430f35b62,0000000000000000000000000000000000000000..fa62f14de2a3a7f18ff51200aed3886eef877a51
mode 100644,000000..100644
--- /dev/null
@@@ -1,623 -1,0 +1,623 @@@
- #include <asm/arch/clock.h>
 +/*
 + * OMAP2/3 clockdomain framework functions
 + *
 + * Copyright (C) 2008 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley and Jouni Högander
 + *
 + * 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.
 + */
 +#ifdef CONFIG_OMAP_DEBUG_CLOCKDOMAIN
 +#  define DEBUG
 +#endif
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/device.h>
 +#include <linux/list.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/clk.h>
 +#include <linux/limits.h>
 +
 +#include <linux/io.h>
 +
 +#include <linux/bitops.h>
 +
- #include <asm/arch/powerdomain.h>
- #include <asm/arch/clockdomain.h>
++#include <mach/clock.h>
 +
 +#include "prm.h"
 +#include "prm-regbits-24xx.h"
 +#include "cm.h"
 +
++#include <mach/powerdomain.h>
++#include <mach/clockdomain.h>
 +
 +/* clkdm_list contains all registered struct clockdomains */
 +static LIST_HEAD(clkdm_list);
 +
 +/* clkdm_mutex protects clkdm_list add and del ops */
 +static DEFINE_MUTEX(clkdm_mutex);
 +
 +/* array of powerdomain deps to be added/removed when clkdm in hwsup mode */
 +static struct clkdm_pwrdm_autodep *autodeps;
 +
 +
 +/* Private functions */
 +
 +/*
 + * _autodep_lookup - resolve autodep pwrdm names to pwrdm pointers; store
 + * @autodep: struct clkdm_pwrdm_autodep * to resolve
 + *
 + * Resolve autodep powerdomain names to powerdomain pointers via
 + * pwrdm_lookup() and store the pointers in the autodep structure.  An
 + * "autodep" is a powerdomain sleep/wakeup dependency that is
 + * automatically added and removed whenever clocks in the associated
 + * clockdomain are enabled or disabled (respectively) when the
 + * clockdomain is in hardware-supervised mode.        Meant to be called
 + * once at clockdomain layer initialization, since these should remain
 + * fixed for a particular architecture.  No return value.
 + */
 +static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
 +{
 +      struct powerdomain *pwrdm;
 +
 +      if (!autodep)
 +              return;
 +
 +      if (!omap_chip_is(autodep->omap_chip))
 +              return;
 +
 +      pwrdm = pwrdm_lookup(autodep->pwrdm.name);
 +      if (!pwrdm) {
 +              pr_debug("clockdomain: _autodep_lookup: powerdomain %s "
 +                       "does not exist\n", autodep->pwrdm.name);
 +              WARN_ON(1);
 +              return;
 +      }
 +      autodep->pwrdm.ptr = pwrdm;
 +
 +      return;
 +}
 +
 +/*
 + * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
 + * @clkdm: struct clockdomain *
 + *
 + * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
 + * in hardware-supervised mode.  Meant to be called from clock framework
 + * when a clock inside clockdomain 'clkdm' is enabled.        No return value.
 + */
 +static void _clkdm_add_autodeps(struct clockdomain *clkdm)
 +{
 +      struct clkdm_pwrdm_autodep *autodep;
 +
 +      for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
 +              if (!omap_chip_is(autodep->omap_chip))
 +                      continue;
 +
 +              pr_debug("clockdomain: adding %s sleepdep/wkdep for "
 +                       "pwrdm %s\n", autodep->pwrdm.ptr->name,
 +                       clkdm->pwrdm.ptr->name);
 +
 +              pwrdm_add_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 +              pwrdm_add_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 +      }
 +}
 +
 +/*
 + * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
 + * @clkdm: struct clockdomain *
 + *
 + * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
 + * in hardware-supervised mode.  Meant to be called from clock framework
 + * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
 + */
 +static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 +{
 +      struct clkdm_pwrdm_autodep *autodep;
 +
 +      for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
 +              if (!omap_chip_is(autodep->omap_chip))
 +                      continue;
 +
 +              pr_debug("clockdomain: removing %s sleepdep/wkdep for "
 +                       "pwrdm %s\n", autodep->pwrdm.ptr->name,
 +                       clkdm->pwrdm.ptr->name);
 +
 +              pwrdm_del_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 +              pwrdm_del_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 +      }
 +}
 +
 +
 +static struct clockdomain *_clkdm_lookup(const char *name)
 +{
 +      struct clockdomain *clkdm, *temp_clkdm;
 +
 +      if (!name)
 +              return NULL;
 +
 +      clkdm = NULL;
 +
 +      list_for_each_entry(temp_clkdm, &clkdm_list, node) {
 +              if (!strcmp(name, temp_clkdm->name)) {
 +                      clkdm = temp_clkdm;
 +                      break;
 +              }
 +      }
 +
 +      return clkdm;
 +}
 +
 +
 +/* Public functions */
 +
 +/**
 + * clkdm_init - set up the clockdomain layer
 + * @clkdms: optional pointer to an array of clockdomains to register
 + * @init_autodeps: optional pointer to an array of autodeps to register
 + *
 + * Set up internal state.  If a pointer to an array of clockdomains
 + * was supplied, loop through the list of clockdomains, register all
 + * that are available on the current platform.        Similarly, if a
 + * pointer to an array of clockdomain-powerdomain autodependencies was
 + * provided, register those.  No return value.
 + */
 +void clkdm_init(struct clockdomain **clkdms,
 +              struct clkdm_pwrdm_autodep *init_autodeps)
 +{
 +      struct clockdomain **c = NULL;
 +      struct clkdm_pwrdm_autodep *autodep = NULL;
 +
 +      if (clkdms)
 +              for (c = clkdms; *c; c++)
 +                      clkdm_register(*c);
 +
 +      autodeps = init_autodeps;
 +      if (autodeps)
 +              for (autodep = autodeps; autodep->pwrdm.ptr; autodep++)
 +                      _autodep_lookup(autodep);
 +}
 +
 +/**
 + * clkdm_register - register a clockdomain
 + * @clkdm: struct clockdomain * to register
 + *
 + * Adds a clockdomain to the internal clockdomain list.
 + * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
 + * already registered by the provided name, or 0 upon success.
 + */
 +int clkdm_register(struct clockdomain *clkdm)
 +{
 +      int ret = -EINVAL;
 +      struct powerdomain *pwrdm;
 +
 +      if (!clkdm || !clkdm->name)
 +              return -EINVAL;
 +
 +      if (!omap_chip_is(clkdm->omap_chip))
 +              return -EINVAL;
 +
 +      pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
 +      if (!pwrdm) {
 +              pr_debug("clockdomain: clkdm_register %s: powerdomain %s "
 +                       "does not exist\n", clkdm->name, clkdm->pwrdm.name);
 +              return -EINVAL;
 +      }
 +      clkdm->pwrdm.ptr = pwrdm;
 +
 +      mutex_lock(&clkdm_mutex);
 +      /* Verify that the clockdomain is not already registered */
 +      if (_clkdm_lookup(clkdm->name)) {
 +              ret = -EEXIST;
 +              goto cr_unlock;
 +      };
 +
 +      list_add(&clkdm->node, &clkdm_list);
 +
 +      pwrdm_add_clkdm(pwrdm, clkdm);
 +
 +      pr_debug("clockdomain: registered %s\n", clkdm->name);
 +      ret = 0;
 +
 +cr_unlock:
 +      mutex_unlock(&clkdm_mutex);
 +
 +      return ret;
 +}
 +
 +/**
 + * clkdm_unregister - unregister a clockdomain
 + * @clkdm: struct clockdomain * to unregister
 + *
 + * Removes a clockdomain from the internal clockdomain list.  Returns
 + * -EINVAL if clkdm argument is NULL.
 + */
 +int clkdm_unregister(struct clockdomain *clkdm)
 +{
 +      if (!clkdm)
 +              return -EINVAL;
 +
 +      pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm);
 +
 +      mutex_lock(&clkdm_mutex);
 +      list_del(&clkdm->node);
 +      mutex_unlock(&clkdm_mutex);
 +
 +      pr_debug("clockdomain: unregistered %s\n", clkdm->name);
 +
 +      return 0;
 +}
 +
 +/**
 + * clkdm_lookup - look up a clockdomain by name, return a pointer
 + * @name: name of clockdomain
 + *
 + * Find a registered clockdomain by its name.  Returns a pointer to the
 + * struct clockdomain if found, or NULL otherwise.
 + */
 +struct clockdomain *clkdm_lookup(const char *name)
 +{
 +      struct clockdomain *clkdm, *temp_clkdm;
 +
 +      if (!name)
 +              return NULL;
 +
 +      clkdm = NULL;
 +
 +      mutex_lock(&clkdm_mutex);
 +      list_for_each_entry(temp_clkdm, &clkdm_list, node) {
 +              if (!strcmp(name, temp_clkdm->name)) {
 +                      clkdm = temp_clkdm;
 +                      break;
 +              }
 +      }
 +      mutex_unlock(&clkdm_mutex);
 +
 +      return clkdm;
 +}
 +
 +/**
 + * clkdm_for_each - call function on each registered clockdomain
 + * @fn: callback function *
 + *
 + * Call the supplied function for each registered clockdomain.
 + * The callback function can return anything but 0 to bail
 + * out early from the iterator.  The callback function is called with
 + * the clkdm_mutex held, so no clockdomain structure manipulation
 + * functions should be called from the callback, although hardware
 + * clockdomain control functions are fine.  Returns the last return
 + * value of the callback function, which should be 0 for success or
 + * anything else to indicate failure; or -EINVAL if the function pointer
 + * is null.
 + */
 +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm))
 +{
 +      struct clockdomain *clkdm;
 +      int ret = 0;
 +
 +      if (!fn)
 +              return -EINVAL;
 +
 +      mutex_lock(&clkdm_mutex);
 +      list_for_each_entry(clkdm, &clkdm_list, node) {
 +              ret = (*fn)(clkdm);
 +              if (ret)
 +                      break;
 +      }
 +      mutex_unlock(&clkdm_mutex);
 +
 +      return ret;
 +}
 +
 +
 +/**
 + * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in
 + * @clkdm: struct clockdomain *
 + *
 + * Return a pointer to the struct powerdomain that the specified clockdomain
 + * 'clkdm' exists in, or returns NULL if clkdm argument is NULL.
 + */
 +struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
 +{
 +      if (!clkdm)
 +              return NULL;
 +
 +      return clkdm->pwrdm.ptr;
 +}
 +
 +
 +/* Hardware clockdomain control */
 +
 +/**
 + * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
 + * @clk: struct clk * of a clockdomain
 + *
 + * Return the clockdomain's current state transition mode from the
 + * corresponding domain CM_CLKSTCTRL register.        Returns -EINVAL if clk
 + * is NULL or the current mode upon success.
 + */
 +static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
 +{
 +      u32 v;
 +
 +      if (!clkdm)
 +              return -EINVAL;
 +
 +      v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 +      v &= clkdm->clktrctrl_mask;
 +      v >>= __ffs(clkdm->clktrctrl_mask);
 +
 +      return v;
 +}
 +
 +/**
 + * omap2_clkdm_sleep - force clockdomain sleep transition
 + * @clkdm: struct clockdomain *
 + *
 + * Instruct the CM to force a sleep transition on the specified
 + * clockdomain 'clkdm'.  Returns -EINVAL if clk is NULL or if
 + * clockdomain does not support software-initiated sleep; 0 upon
 + * success.
 + */
 +int omap2_clkdm_sleep(struct clockdomain *clkdm)
 +{
 +      if (!clkdm)
 +              return -EINVAL;
 +
 +      if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
 +              pr_debug("clockdomain: %s does not support forcing "
 +                       "sleep via software\n", clkdm->name);
 +              return -EINVAL;
 +      }
 +
 +      pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 +
 +      if (cpu_is_omap24xx()) {
 +
 +              cm_set_mod_reg_bits(OMAP24XX_FORCESTATE,
 +                                  clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
 +
 +      } else if (cpu_is_omap34xx()) {
 +
 +              u32 v = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
 +                       __ffs(clkdm->clktrctrl_mask));
 +
 +              cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
 +                                  clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 +
 +      } else {
 +              BUG();
 +      };
 +
 +      return 0;
 +}
 +
 +/**
 + * omap2_clkdm_wakeup - force clockdomain wakeup transition
 + * @clkdm: struct clockdomain *
 + *
 + * Instruct the CM to force a wakeup transition on the specified
 + * clockdomain 'clkdm'.  Returns -EINVAL if clkdm is NULL or if the
 + * clockdomain does not support software-controlled wakeup; 0 upon
 + * success.
 + */
 +int omap2_clkdm_wakeup(struct clockdomain *clkdm)
 +{
 +      if (!clkdm)
 +              return -EINVAL;
 +
 +      if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
 +              pr_debug("clockdomain: %s does not support forcing "
 +                       "wakeup via software\n", clkdm->name);
 +              return -EINVAL;
 +      }
 +
 +      pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 +
 +      if (cpu_is_omap24xx()) {
 +
 +              cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE,
 +                                    clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
 +
 +      } else if (cpu_is_omap34xx()) {
 +
 +              u32 v = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
 +                       __ffs(clkdm->clktrctrl_mask));
 +
 +              cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
 +                                  clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 +
 +      } else {
 +              BUG();
 +      };
 +
 +      return 0;
 +}
 +
 +/**
 + * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
 + * @clkdm: struct clockdomain *
 + *
 + * Allow the hardware to automatically switch the clockdomain into
 + * active or idle states, as needed by downstream clocks.  If the
 + * clockdomain has any downstream clocks enabled in the clock
 + * framework, wkdep/sleepdep autodependencies are added; this is so
 + * device drivers can read and write to the device.  No return value.
 + */
 +void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
 +{
 +      u32 v;
 +
 +      if (!clkdm)
 +              return;
 +
 +      if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
 +              pr_debug("clock: automatic idle transitions cannot be enabled "
 +                       "on clockdomain %s\n", clkdm->name);
 +              return;
 +      }
 +
 +      pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 +               clkdm->name);
 +
 +      if (atomic_read(&clkdm->usecount) > 0)
 +              _clkdm_add_autodeps(clkdm);
 +
 +      if (cpu_is_omap24xx())
 +              v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
 +      else if (cpu_is_omap34xx())
 +              v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
 +      else
 +              BUG();
 +
 +
 +      cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
 +                          v << __ffs(clkdm->clktrctrl_mask),
 +                          clkdm->pwrdm.ptr->prcm_offs,
 +                          CM_CLKSTCTRL);
 +}
 +
 +/**
 + * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
 + * @clkdm: struct clockdomain *
 + *
 + * Prevent the hardware from automatically switching the clockdomain
 + * into inactive or idle states.  If the clockdomain has downstream
 + * clocks enabled in the clock framework, wkdep/sleepdep
 + * autodependencies are removed.  No return value.
 + */
 +void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
 +{
 +      u32 v;
 +
 +      if (!clkdm)
 +              return;
 +
 +      if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
 +              pr_debug("clockdomain: automatic idle transitions cannot be "
 +                       "disabled on %s\n", clkdm->name);
 +              return;
 +      }
 +
 +      pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 +               clkdm->name);
 +
 +      if (cpu_is_omap24xx())
 +              v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
 +      else if (cpu_is_omap34xx())
 +              v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
 +      else
 +              BUG();
 +
 +      cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
 +                          v << __ffs(clkdm->clktrctrl_mask),
 +                          clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 +
 +      if (atomic_read(&clkdm->usecount) > 0)
 +              _clkdm_del_autodeps(clkdm);
 +}
 +
 +
 +/* Clockdomain-to-clock framework interface code */
 +
 +/**
 + * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
 + * @clkdm: struct clockdomain *
 + * @clk: struct clk * of the enabled downstream clock
 + *
 + * Increment the usecount of this clockdomain 'clkdm' and ensure that
 + * it is awake.  Intended to be called by clk_enable() code.  If the
 + * clockdomain is in software-supervised idle mode, force the
 + * clockdomain to wake.  If the clockdomain is in hardware-supervised
 + * idle mode, add clkdm-pwrdm autodependencies, to ensure that devices
 + * in the clockdomain can be read from/written to by on-chip processors.
 + * Returns -EINVAL if passed null pointers; returns 0 upon success or
 + * if the clockdomain is in hwsup idle mode.
 + */
 +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 +{
 +      int v;
 +
 +      /*
 +       * XXX Rewrite this code to maintain a list of enabled
 +       * downstream clocks for debugging purposes?
 +       */
 +
 +      if (!clkdm || !clk)
 +              return -EINVAL;
 +
 +      if (atomic_inc_return(&clkdm->usecount) > 1)
 +              return 0;
 +
 +      /* Clockdomain now has one enabled downstream clock */
 +
 +      pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
 +               clk->name);
 +
 +      v = omap2_clkdm_clktrctrl_read(clkdm);
 +
 +      if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
 +          (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
 +              _clkdm_add_autodeps(clkdm);
 +      else
 +              omap2_clkdm_wakeup(clkdm);
 +
 +      return 0;
 +}
 +
 +/**
 + * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
 + * @clkdm: struct clockdomain *
 + * @clk: struct clk * of the disabled downstream clock
 + *
 + * Decrement the usecount of this clockdomain 'clkdm'. Intended to be
 + * called by clk_disable() code.  If the usecount goes to 0, put the
 + * clockdomain to sleep (software-supervised mode) or remove the
 + * clkdm-pwrdm autodependencies (hardware-supervised mode).  Returns
 + * -EINVAL if passed null pointers; -ERANGE if the clkdm usecount
 + * underflows and debugging is enabled; or returns 0 upon success or
 + * if the clockdomain is in hwsup idle mode.
 + */
 +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 +{
 +      int v;
 +
 +      /*
 +       * XXX Rewrite this code to maintain a list of enabled
 +       * downstream clocks for debugging purposes?
 +       */
 +
 +      if (!clkdm || !clk)
 +              return -EINVAL;
 +
 +#ifdef DEBUG
 +      if (atomic_read(&clkdm->usecount) == 0) {
 +              WARN_ON(1); /* underflow */
 +              return -ERANGE;
 +      }
 +#endif
 +
 +      if (atomic_dec_return(&clkdm->usecount) > 0)
 +              return 0;
 +
 +      /* All downstream clocks of this clockdomain are now disabled */
 +
 +      pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
 +               clk->name);
 +
 +      v = omap2_clkdm_clktrctrl_read(clkdm);
 +
 +      if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
 +          (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
 +              _clkdm_del_autodeps(clkdm);
 +      else
 +              omap2_clkdm_sleep(clkdm);
 +
 +      return 0;
 +}
 +
index 85590809ab2993cc27b1c764d2f6ea2a65702f8c,0000000000000000000000000000000000000000..e17c3693542cec8cdeafd41a1bd79778990e3c4a
mode 100644,000000..100644
--- /dev/null
@@@ -1,307 -1,0 +1,307 @@@
- #include <asm/arch/clockdomain.h>
 +/*
 + * OMAP2/3 clockdomains
 + *
 + * Copyright (C) 2008 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + */
 +
 +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
 +#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
 +
++#include <mach/clockdomain.h>
 +
 +/*
 + * OMAP2/3-common clockdomains
 + */
 +
 +/* This is an implicit clockdomain - it is never defined as such in TRM */
 +static struct clockdomain wkup_clkdm = {
 +      .name           = "wkup_clkdm",
 +      .pwrdm          = { .name = "wkup_pwrdm" },
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 +};
 +
 +/*
 + * 2420-only clockdomains
 + */
 +
 +#if defined(CONFIG_ARCH_OMAP2420)
 +
 +static struct clockdomain mpu_2420_clkdm = {
 +      .name           = "mpu_clkdm",
 +      .pwrdm          = { .name = "mpu_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 +};
 +
 +static struct clockdomain iva1_2420_clkdm = {
 +      .name           = "iva1_clkdm",
 +      .pwrdm          = { .name = "dsp_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 +};
 +
 +#endif  /* CONFIG_ARCH_OMAP2420 */
 +
 +
 +/*
 + * 2430-only clockdomains
 + */
 +
 +#if defined(CONFIG_ARCH_OMAP2430)
 +
 +static struct clockdomain mpu_2430_clkdm = {
 +      .name           = "mpu_clkdm",
 +      .pwrdm          = { .name = "mpu_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 +};
 +
 +static struct clockdomain mdm_clkdm = {
 +      .name           = "mdm_clkdm",
 +      .pwrdm          = { .name = "mdm_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 +};
 +
 +#endif    /* CONFIG_ARCH_OMAP2430 */
 +
 +
 +/*
 + * 24XX-only clockdomains
 + */
 +
 +#if defined(CONFIG_ARCH_OMAP24XX)
 +
 +static struct clockdomain dsp_clkdm = {
 +      .name           = "dsp_clkdm",
 +      .pwrdm          = { .name = "dsp_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +};
 +
 +static struct clockdomain gfx_24xx_clkdm = {
 +      .name           = "gfx_clkdm",
 +      .pwrdm          = { .name = "gfx_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +};
 +
 +static struct clockdomain core_l3_24xx_clkdm = {
 +      .name           = "core_l3_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +};
 +
 +static struct clockdomain core_l4_24xx_clkdm = {
 +      .name           = "core_l4_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +};
 +
 +static struct clockdomain dss_24xx_clkdm = {
 +      .name           = "dss_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +};
 +
 +#endif   /* CONFIG_ARCH_OMAP24XX */
 +
 +
 +/*
 + * 34xx clockdomains
 + */
 +
 +#if defined(CONFIG_ARCH_OMAP34XX)
 +
 +static struct clockdomain mpu_34xx_clkdm = {
 +      .name           = "mpu_clkdm",
 +      .pwrdm          = { .name = "mpu_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain neon_clkdm = {
 +      .name           = "neon_clkdm",
 +      .pwrdm          = { .name = "neon_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain iva2_clkdm = {
 +      .name           = "iva2_clkdm",
 +      .pwrdm          = { .name = "iva2_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain gfx_3430es1_clkdm = {
 +      .name           = "gfx_clkdm",
 +      .pwrdm          = { .name = "gfx_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
 +};
 +
 +static struct clockdomain sgx_clkdm = {
 +      .name           = "sgx_clkdm",
 +      .pwrdm          = { .name = "sgx_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
 +};
 +
 +/*
 + * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
 + * then that information was removed from the 34xx ES2+ TRM.  It is
 + * unclear whether the core is still there, but the clockdomain logic
 + * is there, and must be programmed to an appropriate state if the
 + * CORE clockdomain is to become inactive.
 + */
 +static struct clockdomain d2d_clkdm = {
 +      .name           = "d2d_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain core_l3_34xx_clkdm = {
 +      .name           = "core_l3_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain core_l4_34xx_clkdm = {
 +      .name           = "core_l4_clkdm",
 +      .pwrdm          = { .name = "core_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain dss_34xx_clkdm = {
 +      .name           = "dss_clkdm",
 +      .pwrdm          = { .name = "dss_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain cam_clkdm = {
 +      .name           = "cam_clkdm",
 +      .pwrdm          = { .name = "cam_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain usbhost_clkdm = {
 +      .name           = "usbhost_clkdm",
 +      .pwrdm          = { .name = "usbhost_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
 +};
 +
 +static struct clockdomain per_clkdm = {
 +      .name           = "per_clkdm",
 +      .pwrdm          = { .name = "per_pwrdm" },
 +      .flags          = CLKDM_CAN_HWSUP_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct clockdomain emu_clkdm = {
 +      .name           = "emu_clkdm",
 +      .pwrdm          = { .name = "emu_pwrdm" },
 +      .flags          = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP,
 +      .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +#endif   /* CONFIG_ARCH_OMAP34XX */
 +
 +/*
 + * Clockdomain-powerdomain hwsup dependencies (34XX only)
 + */
 +
 +static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
 +      {
 +              .pwrdm     = { .name = "mpu_pwrdm" },
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm     = { .name = "iva2_pwrdm" },
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm     = { .name = NULL },
 +      }
 +};
 +
 +/*
 + *
 + */
 +
 +static struct clockdomain *clockdomains_omap[] = {
 +
 +      &wkup_clkdm,
 +
 +#ifdef CONFIG_ARCH_OMAP2420
 +      &mpu_2420_clkdm,
 +      &iva1_2420_clkdm,
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP2430
 +      &mpu_2430_clkdm,
 +      &mdm_clkdm,
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP24XX
 +      &dsp_clkdm,
 +      &gfx_24xx_clkdm,
 +      &core_l3_24xx_clkdm,
 +      &core_l4_24xx_clkdm,
 +      &dss_24xx_clkdm,
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP34XX
 +      &mpu_34xx_clkdm,
 +      &neon_clkdm,
 +      &iva2_clkdm,
 +      &gfx_3430es1_clkdm,
 +      &sgx_clkdm,
 +      &d2d_clkdm,
 +      &core_l3_34xx_clkdm,
 +      &core_l4_34xx_clkdm,
 +      &dss_34xx_clkdm,
 +      &cam_clkdm,
 +      &usbhost_clkdm,
 +      &per_clkdm,
 +      &emu_clkdm,
 +#endif
 +
 +      NULL,
 +};
 +
 +#endif
index d8fb3f888c5b7fb30a40cee62abbad30f9a331db,7a7f02559075fc9ce8538c5f64d26c538ef03bc3..cc5c294b9dc13b8ea39a7c8c70316a7b64f79468
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/platform_device.h>
 +#include <linux/io.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
 -#include <asm/io.h>
  #include <asm/mach-types.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/tc.h>
- #include <asm/arch/board.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/eac.h>
+ #include <mach/tc.h>
+ #include <mach/board.h>
+ #include <mach/mux.h>
+ #include <mach/gpio.h>
++#include <mach/eac.h>
  
 -#if   defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 +#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
  
 -#define OMAP2_I2C_BASE2               0x48072000
 -#define OMAP2_I2C_INT2                57
 -
 -static struct resource i2c_resources2[] = {
 +static struct resource cam_resources[] = {
        {
 -              .start          = OMAP2_I2C_BASE2,
 -              .end            = OMAP2_I2C_BASE2 + 0x3f,
 +              .start          = OMAP24XX_CAMERA_BASE,
 +              .end            = OMAP24XX_CAMERA_BASE + 0xfff,
                .flags          = IORESOURCE_MEM,
        },
        {
@@@ -149,9 -140,9 +149,9 @@@ static inline void omap_init_sti(void
  static inline void omap_init_sti(void) {}
  #endif
  
 -#if defined(CONFIG_SPI_OMAP24XX)
 +#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
  
- #include <asm/arch/mcspi.h>
+ #include <mach/mcspi.h>
  
  #define OMAP2_MCSPI1_BASE             0x48098000
  #define OMAP2_MCSPI2_BASE             0x4809a000
index 11f19ff7225beb4525ef2ff2ef4e476547785f97,f51d69bc457dac2be97ff36c81ed4e037155c67c..9d6c916ae3ea66997b4600632ff2a938004f5eef
  #include <linux/clk.h>
  #include <linux/ioport.h>
  #include <linux/spinlock.h>
 +#include <linux/module.h>
 +#include <linux/io.h>
  
 -#include <asm/io.h>
  #include <asm/mach-types.h>
- #include <asm/arch/gpmc.h>
+ #include <mach/gpmc.h>
  
- #include <asm/arch/sdrc.h>
 -#undef DEBUG
 -
 -#ifdef CONFIG_ARCH_OMAP2420
 -#define GPMC_BASE             0x6800a000
 -#endif
 -
 -#ifdef CONFIG_ARCH_OMAP2430
 -#define GPMC_BASE             0x6E000000
 -#endif
++#include <mach/sdrc.h>
  
 +/* GPMC register offsets */
  #define GPMC_REVISION         0x00
  #define GPMC_SYSCONFIG                0x10
  #define GPMC_SYSSTATUS                0x14
index e16d6c0504ff35910dc3ccfaf5d4f8a57943de7a,0000000000000000000000000000000000000000..3805b930e0a85d35b85ef8febe71185b198a092d
mode 100644,000000..100644
--- /dev/null
@@@ -1,293 -1,0 +1,293 @@@
- #include <asm/hardware.h>
- #include <asm/arch/mmc.h>
- #include <asm/arch/board.h>
 +/*
 + * linux/arch/arm/mach-omap2/board-sdp-hsmmc.c
 + *
 + * Copyright (C) 2007-2008 Texas Instruments
 + * Copyright (C) 2008 Nokia Corporation
 + * Author: Texas Instruments
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#include <linux/err.h>
 +#include <linux/io.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/i2c/twl4030.h>
++#include <mach/hardware.h>
++#include <mach/mmc.h>
++#include <mach/board.h>
 +
 +#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 +
 +#define VMMC1_DEV_GRP         0x27
 +#define P1_DEV_GRP            0x20
 +#define VMMC1_DEDICATED               0x2A
 +#define VSEL_3V                       0x02
 +#define VSEL_18V              0x00
 +#define TWL_GPIO_PUPDCTR1     0x13
 +#define TWL_GPIO_IMR1A                0x1C
 +#define TWL_GPIO_ISR1A                0x19
 +#define LDO_CLR                       0x00
 +#define VSEL_S2_CLR           0x40
 +#define GPIO_0_BIT_POS                (1 << 0)
 +#define MMC1_CD_IRQ           0
 +#define MMC2_CD_IRQ           1
 +
 +#define OMAP2_CONTROL_DEVCONF0        0x48002274
 +#define OMAP2_CONTROL_DEVCONF1        0x490022E8
 +
 +#define OMAP2_CONTROL_DEVCONF0_LBCLK  (1 << 24)
 +#define OMAP2_CONTROL_DEVCONF1_ACTOV  (1 << 31)
 +
 +#define OMAP2_CONTROL_PBIAS_VMODE     (1 << 0)
 +#define OMAP2_CONTROL_PBIAS_PWRDNZ    (1 << 1)
 +#define OMAP2_CONTROL_PBIAS_SCTRL     (1 << 2)
 +
 +static int hsmmc_card_detect(int irq)
 +{
 +      return twl4030_get_gpio_datain(irq - TWL4030_GPIO_IRQ_BASE);
 +}
 +
 +/*
 + * MMC Slot Initialization.
 + */
 +static int hsmmc_late_init(struct device *dev)
 +{
 +      int ret = 0;
 +
 +      /*
 +       * Configure TWL4030 GPIO parameters for MMC hotplug irq
 +       */
 +      ret = twl4030_request_gpio(MMC1_CD_IRQ);
 +      if (ret)
 +              goto err;
 +
 +      ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
 +                      TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
 +      if (ret)
 +              goto err;
 +
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
 +                                              TWL_GPIO_PUPDCTR1);
 +      if (ret)
 +              goto err;
 +
 +      ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE);
 +      if (ret)
 +              goto err;
 +
 +      return ret;
 +
 +err:
 +      dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
 +      return ret;
 +}
 +
 +static void hsmmc_cleanup(struct device *dev)
 +{
 +      int ret = 0;
 +
 +      ret = twl4030_free_gpio(MMC1_CD_IRQ);
 +      if (ret)
 +              dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
 +}
 +
 +#ifdef CONFIG_PM
 +
 +/*
 + * To mask and unmask MMC Card Detect Interrupt
 + * mask : 1
 + * unmask : 0
 + */
 +static int mask_cd_interrupt(int mask)
 +{
 +      u8 reg = 0, ret = 0;
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_IMR1A);
 +      if (ret)
 +              goto err;
 +
 +      reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
 +
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
 +      if (ret)
 +              goto err;
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_ISR1A);
 +      if (ret)
 +              goto err;
 +
 +      reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
 +
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
 +      if (ret)
 +              goto err;
 +
 +err:
 +      return ret;
 +}
 +
 +static int hsmmc_suspend(struct device *dev, int slot)
 +{
 +      int ret = 0;
 +
 +      disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
 +      ret = mask_cd_interrupt(1);
 +
 +      return ret;
 +}
 +
 +static int hsmmc_resume(struct device *dev, int slot)
 +{
 +      int ret = 0;
 +
 +      enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
 +      ret = mask_cd_interrupt(0);
 +
 +      return ret;
 +}
 +
 +#endif
 +
 +static int hsmmc_set_power(struct device *dev, int slot, int power_on,
 +                              int vdd)
 +{
 +      u32 vdd_sel = 0, devconf = 0, reg = 0;
 +      int ret = 0;
 +
 +      /* REVISIT: Using address directly till the control.h defines
 +       * are settled.
 +       */
 +#if defined(CONFIG_ARCH_OMAP2430)
 +      #define OMAP2_CONTROL_PBIAS 0x490024A0
 +#else
 +      #define OMAP2_CONTROL_PBIAS 0x48002520
 +#endif
 +
 +      if (power_on) {
 +              if (cpu_is_omap24xx())
 +                      devconf = omap_readl(OMAP2_CONTROL_DEVCONF1);
 +              else
 +                      devconf = omap_readl(OMAP2_CONTROL_DEVCONF0);
 +
 +              switch (1 << vdd) {
 +              case MMC_VDD_33_34:
 +              case MMC_VDD_32_33:
 +                      vdd_sel = VSEL_3V;
 +                      if (cpu_is_omap24xx())
 +                              devconf |= OMAP2_CONTROL_DEVCONF1_ACTOV;
 +                      break;
 +              case MMC_VDD_165_195:
 +                      vdd_sel = VSEL_18V;
 +                      if (cpu_is_omap24xx())
 +                              devconf &= ~OMAP2_CONTROL_DEVCONF1_ACTOV;
 +              }
 +
 +              if (cpu_is_omap24xx())
 +                      omap_writel(devconf, OMAP2_CONTROL_DEVCONF1);
 +              else
 +                      omap_writel(devconf | OMAP2_CONTROL_DEVCONF0_LBCLK,
 +                                  OMAP2_CONTROL_DEVCONF0);
 +
 +              reg = omap_readl(OMAP2_CONTROL_PBIAS);
 +              reg |= OMAP2_CONTROL_PBIAS_SCTRL;
 +              omap_writel(reg, OMAP2_CONTROL_PBIAS);
 +
 +              reg = omap_readl(OMAP2_CONTROL_PBIAS);
 +              reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ;
 +              omap_writel(reg, OMAP2_CONTROL_PBIAS);
 +
 +              ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                                              P1_DEV_GRP, VMMC1_DEV_GRP);
 +              if (ret)
 +                      goto err;
 +
 +              ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                                              vdd_sel, VMMC1_DEDICATED);
 +              if (ret)
 +                      goto err;
 +
 +              msleep(100);
 +              reg = omap_readl(OMAP2_CONTROL_PBIAS);
 +              reg |= (OMAP2_CONTROL_PBIAS_SCTRL |
 +                      OMAP2_CONTROL_PBIAS_PWRDNZ);
 +              if (vdd_sel == VSEL_18V)
 +                      reg &= ~OMAP2_CONTROL_PBIAS_VMODE;
 +              else
 +                      reg |= OMAP2_CONTROL_PBIAS_VMODE;
 +              omap_writel(reg, OMAP2_CONTROL_PBIAS);
 +
 +              return ret;
 +
 +      } else {
 +              /* Power OFF */
 +
 +              /* For MMC1, Toggle PBIAS before every power up sequence */
 +              reg = omap_readl(OMAP2_CONTROL_PBIAS);
 +              reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ;
 +              omap_writel(reg, OMAP2_CONTROL_PBIAS);
 +
 +              ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                                              LDO_CLR, VMMC1_DEV_GRP);
 +              if (ret)
 +                      goto err;
 +
 +              ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 +                                              VSEL_S2_CLR, VMMC1_DEDICATED);
 +              if (ret)
 +                      goto err;
 +
 +              /* 100ms delay required for PBIAS configuration */
 +              msleep(100);
 +              reg = omap_readl(OMAP2_CONTROL_PBIAS);
 +              reg |= (OMAP2_CONTROL_PBIAS_VMODE |
 +                      OMAP2_CONTROL_PBIAS_PWRDNZ |
 +                      OMAP2_CONTROL_PBIAS_SCTRL);
 +              omap_writel(reg, OMAP2_CONTROL_PBIAS);
 +      }
 +
 +      return 0;
 +
 +err:
 +      return 1;
 +}
 +
 +static struct omap_mmc_platform_data hsmmc_data = {
 +      .nr_slots                       = 1,
 +      .switch_slot                    = NULL,
 +      .init                           = hsmmc_late_init,
 +      .cleanup                        = hsmmc_cleanup,
 +#ifdef CONFIG_PM
 +      .suspend                        = hsmmc_suspend,
 +      .resume                         = hsmmc_resume,
 +#endif
 +      .slots[0] = {
 +              .set_power              = hsmmc_set_power,
 +              .set_bus_mode           = NULL,
 +              .get_ro                 = NULL,
 +              .get_cover_state        = NULL,
 +              .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34 |
 +                                              MMC_VDD_165_195,
 +              .name                   = "first slot",
 +
 +              .card_detect_irq        = TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ),
 +              .card_detect            = hsmmc_card_detect,
 +      },
 +};
 +
 +void __init hsmmc_init(void)
 +{
 +      omap_set_mmc_info(1, &hsmmc_data);
 +}
 +
 +#else
 +
 +void __init hsmmc_init(void)
 +{
 +
 +}
 +
 +#endif
index c7f9ab7efdca01bbb3d35dfa7b825bc4c069469e,a5d4526ac4d6debdb1f0a0e0393bc37443e00bac..a526c0fc628d94553dfef5d23ce0773be9127aa2
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
 +#include <linux/io.h>
  
- #include <asm/arch/common.h>
- #include <asm/arch/control.h>
- #include <asm/arch/cpu.h>
 -#include <asm/io.h>
 -
++#include <mach/common.h>
+ #include <mach/control.h>
+ #include <mach/cpu.h>
  
 -#if defined(CONFIG_ARCH_OMAP2420)
 -#define TAP_BASE      io_p2v(0x48014000)
 -#elif defined(CONFIG_ARCH_OMAP2430)
 -#define TAP_BASE      io_p2v(0x4900A000)
 -#elif defined(CONFIG_ARCH_OMAP34XX)
 -#define TAP_BASE      io_p2v(0x4830A000)
 -#endif
 +static u32 class;
 +static void __iomem *tap_base;
 +static u16 tap_prod_id;
  
  #define OMAP_TAP_IDCODE               0x0204
 -#if defined(CONFIG_ARCH_OMAP34XX)
 -#define OMAP_TAP_PROD_ID      0x0210
 -#else
 -#define OMAP_TAP_PROD_ID      0x0208
 -#endif
 -
  #define OMAP_TAP_DIE_ID_0     0x0218
  #define OMAP_TAP_DIE_ID_1     0x021C
  #define OMAP_TAP_DIE_ID_2     0x0220
index e0191aa3a144c683d0d080ac475f016280965558,987351f07d7b618bb0a10ea12a2d18001a9415e4..adbe21fcd68408c30b712d06aff6daf671afed38
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
 +#include <linux/io.h>
  
  #include <asm/tlb.h>
 -#include <asm/io.h>
  
  #include <asm/mach/map.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
- #include <asm/arch/sram.h>
- #include <asm/arch/sdrc.h>
- #include <asm/arch/gpmc.h>
 -
+ #include <mach/mux.h>
+ #include <mach/omapfb.h>
++#include <mach/sram.h>
++#include <mach/sdrc.h>
++#include <mach/gpmc.h>
 +
 +#include "clock.h"
 +
- #include <asm/arch/powerdomain.h>
++#include <mach/powerdomain.h>
 +
 +#include "powerdomains.h"
  
- #include <asm/arch/clockdomain.h>
 -extern void omap_sram_init(void);
 -extern int omap2_clk_init(void);
 -extern void omap2_check_revision(void);
 -extern void omap2_init_memory(void);
 -extern void gpmc_init(void);
 -extern void omapfb_reserve_sdram(void);
++#include <mach/clockdomain.h>
 +#include "clockdomains.h"
  
  /*
   * The machine specific code may provide the extra mapping besides the
index 441463e16e2419ab0aa662e0f629476486720420,9ef15b31d8fcc4f8c0b62167ef889685905fcbd1..82e954a72218e235a7f1cc43ddbdec10d10302ad
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/mach/irq.h>
 -#include <asm/irq.h>
 -#include <asm/io.h>
 +#include <linux/irq.h>
 +#include <linux/io.h>
  
 -#define INTC_REVISION 0x0000
 -#define INTC_SYSCONFIG        0x0010
 -#define INTC_SYSSTATUS        0x0014
 -#define INTC_CONTROL  0x0048
 -#define INTC_MIR_CLEAR0       0x0088
 -#define INTC_MIR_SET0 0x008c
 +/* selected INTC register offsets */
 +
 +#define INTC_REVISION         0x0000
 +#define INTC_SYSCONFIG                0x0010
 +#define INTC_SYSSTATUS                0x0014
 +#define INTC_CONTROL          0x0048
 +#define INTC_MIR_CLEAR0               0x0088
 +#define INTC_MIR_SET0         0x008c
 +#define INTC_PENDING_IRQ0     0x0098
 +
 +/* Number of IRQ state bits in each MIR register */
 +#define IRQ_BITS_PER_REG      32
  
  /*
   * OMAP2 has a number of different interrupt controllers, each interrupt
Simple merge
Simple merge
index 11718ce5afbc4765cc52c5adea8730de3e1df9c9,0000000000000000000000000000000000000000..6fc3303af515adaee06797612611c02778e6c221
mode 100644,000000..100644
--- /dev/null
@@@ -1,330 -1,0 +1,330 @@@
- #include <asm/arch/mmu.h>
 +/*
 + * linux/arch/arm/mach-omap2/mmu.c
 + *
 + * Support for non-MPU OMAP2 MMUs.
 + *
 + * Copyright (C) 2002-2007 Nokia Corporation
 + *
 + * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *        and Paul Mundt <paul.mundt@nokia.com>
 + *
 + * TWL support: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#include <linux/types.h>
 +#include <linux/init.h>
 +#include <linux/rwsem.h>
 +#include <linux/device.h>
 +#include <linux/mm.h>
 +#include <linux/interrupt.h>
 +#include <linux/err.h>
 +#include <linux/io.h>
 +#include "mmu.h"
++#include <mach/mmu.h>
 +#include <asm/tlbflush.h>
 +#include <asm/sizes.h>
 +
 +static void *dspvect_page;
 +#define DSP_INIT_PAGE 0xfff000
 +
 +static inline void
 +omap2_mmu_read_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      cr->cam = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM);
 +      cr->ram = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM);
 +}
 +
 +static inline void
 +omap2_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      /* Set the CAM and RAM entries */
 +      omap_mmu_write_reg(mmu, cr->cam | OMAP_MMU_CAM_V, OMAP_MMU_CAM);
 +      omap_mmu_write_reg(mmu, cr->ram, OMAP_MMU_RAM);
 +}
 +
 +static void exmap_setup_iomap_page(struct omap_mmu *mmu, unsigned long phys,
 +                                 unsigned long dsp_io_adr, int index)
 +{
 +      unsigned long dspadr;
 +      void *virt;
 +      struct omap_mmu_tlb_entry tlb_ent;
 +
 +      dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
 +      virt = omap_mmu_to_virt(mmu, dspadr);
 +      exmap_set_armmmu(mmu, (unsigned long)virt, phys, PAGE_SIZE);
 +      INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(mmu->exmap_tbl + index, NULL, virt);
 +      INIT_TLB_ENTRY_4KB_ES32_PRESERVED(&tlb_ent, dspadr, phys);
 +      omap_mmu_load_pte_entry(mmu, &tlb_ent);
 +}
 +
 +static void exmap_clear_iomap_page(struct omap_mmu *mmu,
 +                                 unsigned long dsp_io_adr)
 +{
 +      unsigned long dspadr;
 +      void *virt;
 +
 +      dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
 +      virt = omap_mmu_to_virt(mmu, dspadr);
 +      exmap_clear_armmmu(mmu, (unsigned long)virt, PAGE_SIZE);
 +      /* DSP MMU is shutting down. not handled here. */
 +}
 +
 +#define OMAP24XX_MAILBOX_BASE (L4_24XX_BASE + 0x94000)
 +#define OMAP2420_GPT5_BASE    (L4_24XX_BASE + 0x7c000)
 +#define OMAP2420_GPT6_BASE    (L4_24XX_BASE + 0x7e000)
 +#define OMAP2420_GPT7_BASE    (L4_24XX_BASE + 0x80000)
 +#define OMAP2420_GPT8_BASE    (L4_24XX_BASE + 0x82000)
 +#define OMAP24XX_EAC_BASE     (L4_24XX_BASE + 0x90000)
 +#define OMAP24XX_STI_BASE     (L4_24XX_BASE + 0x68000)
 +#define OMAP24XX_STI_CH_BASE  (L4_24XX_BASE + 0x0c000000)
 +
 +static int exmap_setup_preserved_entries(struct omap_mmu *mmu)
 +{
 +      int i, n = 0;
 +
 +      exmap_setup_preserved_mem_page(mmu, dspvect_page, DSP_INIT_PAGE, n++);
 +
 +      /* REVISIT: This will need to be revisited for 3430 */
 +      exmap_setup_iomap_page(mmu, OMAP2_PRCM_BASE, 0x7000, n++);
 +      exmap_setup_iomap_page(mmu, OMAP24XX_MAILBOX_BASE, 0x11000, n++);
 +
 +      if (cpu_is_omap2420()) {
 +              exmap_setup_iomap_page(mmu, OMAP2420_GPT5_BASE, 0xe000, n++);
 +              exmap_setup_iomap_page(mmu, OMAP2420_GPT6_BASE, 0xe800, n++);
 +              exmap_setup_iomap_page(mmu, OMAP2420_GPT7_BASE, 0xf000, n++);
 +              exmap_setup_iomap_page(mmu, OMAP2420_GPT8_BASE, 0xf800, n++);
 +              exmap_setup_iomap_page(mmu, OMAP24XX_EAC_BASE,  0x10000, n++);
 +              exmap_setup_iomap_page(mmu, OMAP24XX_STI_BASE, 0xc800, n++);
 +              for (i = 0; i < 5; i++)
 +                      exmap_setup_preserved_mem_page(mmu,
 +                              __va(OMAP24XX_STI_CH_BASE + i*SZ_4K),
 +                              0xfb0000 + i*SZ_4K, n++);
 +      }
 +
 +      return n;
 +}
 +
 +static void exmap_clear_preserved_entries(struct omap_mmu *mmu)
 +{
 +      int i;
 +
 +      exmap_clear_iomap_page(mmu, 0x7000);    /* PRCM registers */
 +      exmap_clear_iomap_page(mmu, 0x11000);   /* MAILBOX registers */
 +
 +      if (cpu_is_omap2420()) {
 +              exmap_clear_iomap_page(mmu, 0xe000);    /* GPT5 */
 +              exmap_clear_iomap_page(mmu, 0xe800);    /* GPT6 */
 +              exmap_clear_iomap_page(mmu, 0xf000);    /* GPT7 */
 +              exmap_clear_iomap_page(mmu, 0xf800);    /* GPT8 */
 +              exmap_clear_iomap_page(mmu, 0x10000);   /* EAC */
 +              exmap_clear_iomap_page(mmu, 0xc800);    /* STI */
 +              for (i = 0; i < 5; i++)                 /* STI CH */
 +                      exmap_clear_mem_page(mmu, 0xfb0000 + i*SZ_4K);
 +      }
 +
 +      exmap_clear_mem_page(mmu, DSP_INIT_PAGE);
 +}
 +
 +#define MMU_IRQ_MASK \
 +      (OMAP_MMU_IRQ_MULTIHITFAULT | \
 +       OMAP_MMU_IRQ_TABLEWALKFAULT | \
 +       OMAP_MMU_IRQ_EMUMISS | \
 +       OMAP_MMU_IRQ_TRANSLATIONFAULT)
 +
 +static int omap2_mmu_startup(struct omap_mmu *mmu)
 +{
 +      u32 rev = omap_mmu_read_reg(mmu, OMAP_MMU_REVISION);
 +
 +      pr_info("MMU: OMAP %s MMU initialized (HW v%d.%d)\n", mmu->name,
 +              (rev >> 4) & 0xf, rev & 0xf);
 +
 +      dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
 +      if (dspvect_page == NULL) {
 +              dev_err(mmu->dev, "MMU %s: failed to allocate memory "
 +                      "for vector table\n", mmu->name);
 +              return -ENOMEM;
 +      }
 +
 +      mmu->nr_exmap_preserved = exmap_setup_preserved_entries(mmu);
 +
 +      omap_mmu_write_reg(mmu, MMU_IRQ_MASK, OMAP_MMU_IRQENABLE);
 +
 +      return 0;
 +}
 +
 +static void omap2_mmu_shutdown(struct omap_mmu *mmu)
 +{
 +      exmap_clear_preserved_entries(mmu);
 +
 +      if (dspvect_page != NULL) {
 +              unsigned long virt;
 +
 +              down_read(&mmu->exmap_sem);
 +
 +              virt = (unsigned long)omap_mmu_to_virt(mmu, DSP_INIT_PAGE);
 +              flush_tlb_kernel_range(virt, virt + PAGE_SIZE);
 +              free_page((unsigned long)dspvect_page);
 +              dspvect_page = NULL;
 +
 +              up_read(&mmu->exmap_sem);
 +      }
 +}
 +
 +static ssize_t omap2_mmu_show(struct omap_mmu *mmu, char *buf,
 +                            struct omap_mmu_tlb_lock *tlb_lock)
 +{
 +      int i, len;
 +
 +      len = sprintf(buf, "P: preserved, V: valid\n"
 +                         "B: big endian, L:little endian, "
 +                         "M: mixed page attribute\n"
 +                         "ety P V size   cam_va     ram_pa E ES M\n");
 +                       /* 00: P V  4KB 0x300000 0x10171800 B 16 M */
 +
 +      for (i = 0; i < mmu->nr_tlb_entries; i++) {
 +              struct omap_mmu_tlb_entry ent;
 +              struct cam_ram_regset cr;
 +              struct omap_mmu_tlb_lock entry_lock;
 +              char *pgsz_str, *elsz_str;
 +
 +              /* read a TLB entry */
 +              entry_lock.base   = tlb_lock->base;
 +              entry_lock.victim = i;
 +              omap_mmu_read_tlb(mmu, &entry_lock, &cr);
 +
 +              ent.pgsz   = cr.cam & OMAP_MMU_CAM_PAGESIZE_MASK;
 +              ent.prsvd  = cr.cam & OMAP_MMU_CAM_P;
 +              ent.valid  = cr.cam & OMAP_MMU_CAM_V;
 +              ent.va     = cr.cam & OMAP_MMU_CAM_VATAG_MASK;
 +              ent.endian = cr.ram & OMAP_MMU_RAM_ENDIANNESS;
 +              ent.elsz   = cr.ram & OMAP_MMU_RAM_ELEMENTSIZE_MASK;
 +              ent.pa     = cr.ram & OMAP_MMU_RAM_PADDR_MASK;
 +              ent.mixed  = cr.ram & OMAP_MMU_RAM_MIXED;
 +
 +              pgsz_str = (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_16MB) ? "64MB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1MB)  ? " 1MB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
 +                         (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_4KB)  ? " 4KB":
 +                                                                   " ???";
 +              elsz_str = (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_8)  ? " 8":
 +                         (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_16) ? "16":
 +                         (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_32) ? "32":
 +                                                                    "??";
 +
 +              if (i == tlb_lock->base)
 +                      len += sprintf(buf + len, "lock base = %d\n",
 +                                     tlb_lock->base);
 +              if (i == tlb_lock->victim)
 +                      len += sprintf(buf + len, "victim    = %d\n",
 +                                     tlb_lock->victim);
 +
 +              len += sprintf(buf + len,
 +                             /* 00: P V  4KB 0x300000 0x10171800 B 16 M */
 +                             "%02d: %c %c %s 0x%06lx 0x%08lx %c %s %c\n",
 +                             i,
 +                             ent.prsvd ? 'P' : ' ',
 +                             ent.valid ? 'V' : ' ',
 +                             pgsz_str, ent.va, ent.pa,
 +                             ent.endian ? 'B' : 'L',
 +                             elsz_str,
 +                             ent.mixed ? 'M' : ' ');
 +      }
 +
 +      return len;
 +}
 +
 +#define get_cam_va_mask(pgsz) \
 +      (((pgsz) == OMAP_MMU_CAM_PAGESIZE_16MB) ? 0xff000000 : \
 +       ((pgsz) == OMAP_MMU_CAM_PAGESIZE_1MB)  ? 0xfff00000 : \
 +       ((pgsz) == OMAP_MMU_CAM_PAGESIZE_64KB) ? 0xffff0000 : \
 +       ((pgsz) == OMAP_MMU_CAM_PAGESIZE_4KB)  ? 0xfffff000 : 0)
 +
 +static inline unsigned long omap2_mmu_cam_va(struct cam_ram_regset *cr)
 +{
 +      unsigned int page_size = cr->cam & OMAP_MMU_CAM_PAGESIZE_MASK;
 +      unsigned int mask = get_cam_va_mask(cr->cam & page_size);
 +
 +      return cr->cam & mask;
 +}
 +
 +static struct cam_ram_regset *
 +omap2_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry)
 +{
 +      struct cam_ram_regset *cr;
 +
 +      if (entry->va & ~(get_cam_va_mask(entry->pgsz))) {
 +              dev_err(mmu->dev, "MMU %s: mapping vadr (0x%06lx) is not on"
 +                      " an aligned boundary\n", mmu->name, entry->va);
 +              return ERR_PTR(-EINVAL);
 +      }
 +
 +      cr = kmalloc(sizeof(struct cam_ram_regset), GFP_KERNEL);
 +
 +      cr->cam = (entry->va & OMAP_MMU_CAM_VATAG_MASK) |
 +                entry->prsvd | entry->pgsz;
 +      cr->ram = entry->pa | entry->endian | entry->elsz;
 +
 +      return cr;
 +}
 +
 +static inline int omap2_mmu_cam_ram_valid(struct cam_ram_regset *cr)
 +{
 +      return cr->cam & OMAP_MMU_CAM_V;
 +}
 +
 +static void omap2_mmu_interrupt(struct omap_mmu *mmu)
 +{
 +      unsigned long status, va;
 +
 +      status = MMU_IRQ_MASK & omap_mmu_read_reg(mmu, OMAP_MMU_IRQSTATUS);
 +      va = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD);
 +
 +      pr_info("%s\n", (status & OMAP_MMU_IRQ_MULTIHITFAULT)?
 +              "multi hit":"");
 +      pr_info("%s\n", (status & OMAP_MMU_IRQ_TABLEWALKFAULT)?
 +              "table walk fault":"");
 +      pr_info("%s\n", (status & OMAP_MMU_IRQ_EMUMISS)?
 +              "EMU miss":"");
 +      pr_info("%s\n", (status & OMAP_MMU_IRQ_TRANSLATIONFAULT)?
 +              "translation fault":"");
 +      pr_info("%s\n", (status & OMAP_MMU_IRQ_TLBMISS)?
 +              "TLB miss":"");
 +      pr_info("fault address = %#08lx\n", va);
 +
 +      omap_mmu_disable(mmu);
 +      omap_mmu_write_reg(mmu, status, OMAP_MMU_IRQSTATUS);
 +
 +      mmu->fault_address = va;
 +      schedule_work(&mmu->irq_work);
 +}
 +
 +static pgprot_t omap2_mmu_pte_get_attr(struct omap_mmu_tlb_entry *entry)
 +{
 +      u32 attr;
 +
 +      attr = entry->mixed << 5;
 +      attr |= entry->endian;
 +      attr |= entry->elsz >> 3;
 +      attr <<= ((entry->pgsz & OMAP_MMU_CAM_PAGESIZE_4KB) ? 0:6);
 +
 +      return attr;
 +}
 +
 +struct omap_mmu_ops omap2_mmu_ops = {
 +      .startup        = omap2_mmu_startup,
 +      .shutdown       = omap2_mmu_shutdown,
 +      .read_tlb       = omap2_mmu_read_tlb,
 +      .load_tlb       = omap2_mmu_load_tlb,
 +      .show           = omap2_mmu_show,
 +      .cam_va         = omap2_mmu_cam_va,
 +      .cam_ram_alloc  = omap2_mmu_cam_ram_alloc,
 +      .cam_ram_valid  = omap2_mmu_cam_ram_valid,
 +      .interrupt      = omap2_mmu_interrupt,
 +      .pte_get_attr   = omap2_mmu_pte_get_attr,
 +};
 +EXPORT_SYMBOL_GPL(omap2_mmu_ops);
 +
 +MODULE_LICENSE("GPL");
index 363eaa1e9cb6da8d00957a59169333a0b3947c9f,0000000000000000000000000000000000000000..c9eabf0993fde5a6d1ae32c835b6c1b3f6b4606c
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,117 @@@
- #include <asm/arch/mmu.h>
 +#ifndef __MACH_OMAP2_MMU_H
 +#define __MACH_OMAP2_MMU_H
 +
 +#include <linux/io.h>
++#include <mach/mmu.h>
 +
 +#define MMU_LOCK_BASE_MASK            (0x1f << 10)
 +#define MMU_LOCK_VICTIM_MASK          (0x1f << 4)
 +
 +#define OMAP_MMU_REVISION             0x00
 +#define OMAP_MMU_SYSCONFIG            0x10
 +#define OMAP_MMU_SYSSTATUS            0x14
 +#define OMAP_MMU_IRQSTATUS            0x18
 +#define OMAP_MMU_IRQENABLE            0x1c
 +#define OMAP_MMU_WALKING_ST           0x40
 +#define OMAP_MMU_CNTL                 0x44
 +#define OMAP_MMU_FAULT_AD             0x48
 +#define OMAP_MMU_TTB                  0x4c
 +#define OMAP_MMU_LOCK                 0x50
 +#define OMAP_MMU_LD_TLB                       0x54
 +#define OMAP_MMU_CAM                  0x58
 +#define OMAP_MMU_RAM                  0x5c
 +#define OMAP_MMU_GFLUSH                       0x60
 +#define OMAP_MMU_FLUSH_ENTRY          0x64
 +#define OMAP_MMU_READ_CAM             0x68
 +#define OMAP_MMU_READ_RAM             0x6c
 +#define OMAP_MMU_EMU_FAULT_AD         0x70
 +
 +#define OMAP_MMU_CNTL_BURST_16MNGT_EN   0x0020
 +#define OMAP_MMU_CNTL_WTL_EN            0x0004
 +#define OMAP_MMU_CNTL_MMU_EN            0x0002
 +#define OMAP_MMU_CNTL_RESET_SW          0x0001
 +
 +#define OMAP_MMU_IRQ_MULTIHITFAULT    0x00000010
 +#define OMAP_MMU_IRQ_TABLEWALKFAULT   0x00000008
 +#define OMAP_MMU_IRQ_EMUMISS          0x00000004
 +#define OMAP_MMU_IRQ_TRANSLATIONFAULT 0x00000002
 +#define OMAP_MMU_IRQ_TLBMISS          0x00000001
 +
 +#define OMAP_MMU_CAM_VATAG_MASK               0xfffff000
 +#define OMAP_MMU_CAM_P                        0x00000008
 +#define OMAP_MMU_CAM_V                        0x00000004
 +#define OMAP_MMU_CAM_PAGESIZE_MASK    0x00000003
 +#define OMAP_MMU_CAM_PAGESIZE_1MB     0x00000000
 +#define OMAP_MMU_CAM_PAGESIZE_64KB    0x00000001
 +#define OMAP_MMU_CAM_PAGESIZE_4KB     0x00000002
 +#define OMAP_MMU_CAM_PAGESIZE_16MB    0x00000003
 +
 +#define OMAP_MMU_RAM_PADDR_MASK               0xfffff000
 +#define OMAP_MMU_RAM_ENDIANNESS               0x00000200
 +#define OMAP_MMU_RAM_ENDIANNESS_BIG   0x00000200
 +#define OMAP_MMU_RAM_ENDIANNESS_LITTLE        0x00000000
 +#define OMAP_MMU_RAM_ELEMENTSIZE_MASK 0x00000180
 +#define OMAP_MMU_RAM_ELEMENTSIZE_8    0x00000000
 +#define OMAP_MMU_RAM_ELEMENTSIZE_16   0x00000080
 +#define OMAP_MMU_RAM_ELEMENTSIZE_32   0x00000100
 +#define OMAP_MMU_RAM_ELEMENTSIZE_NONE 0x00000180
 +#define OMAP_MMU_RAM_MIXED            0x00000040
 +
 +#define IOMAP_VAL     0x3f
 +
 +#define INIT_TLB_ENTRY(ent, v, p, ps)                         \
 +do {                                                          \
 +      (ent)->va       = (v);                                  \
 +      (ent)->pa       = (p);                                  \
 +      (ent)->pgsz     = (ps);                                 \
 +      (ent)->prsvd    = 0;                                    \
 +      (ent)->endian   = OMAP_MMU_RAM_ENDIANNESS_LITTLE;       \
 +      (ent)->elsz     = OMAP_MMU_RAM_ELEMENTSIZE_16;          \
 +      (ent)->mixed    = 0;                                    \
 +      (ent)->tlb      = 1;                                    \
 +} while (0)
 +
 +#define INIT_TLB_ENTRY_4KB_PRESERVED(ent, v, p)               \
 +do {                                                          \
 +      (ent)->va       = (v);                                  \
 +      (ent)->pa       = (p);                                  \
 +      (ent)->pgsz     = OMAP_MMU_CAM_PAGESIZE_4KB;            \
 +      (ent)->prsvd    = OMAP_MMU_CAM_P;                       \
 +      (ent)->endian   = OMAP_MMU_RAM_ENDIANNESS_LITTLE;       \
 +      (ent)->elsz     = OMAP_MMU_RAM_ELEMENTSIZE_16;          \
 +      (ent)->mixed    = 0;                                    \
 +} while (0)
 +
 +#define INIT_TLB_ENTRY_4KB_ES32_PRESERVED(ent, v, p)          \
 +do {                                                          \
 +      (ent)->va       = (v);                                  \
 +      (ent)->pa       = (p);                                  \
 +      (ent)->pgsz     = OMAP_MMU_CAM_PAGESIZE_4KB;            \
 +      (ent)->prsvd    = OMAP_MMU_CAM_P;                       \
 +      (ent)->endian   = OMAP_MMU_RAM_ENDIANNESS_LITTLE;       \
 +      (ent)->elsz     = OMAP_MMU_RAM_ELEMENTSIZE_32;          \
 +      (ent)->mixed    = 0;                                    \
 +} while (0)
 +
 +struct omap_mmu_tlb_entry {
 +      unsigned long va;
 +      unsigned long pa;
 +      unsigned int pgsz, prsvd, valid;
 +
 +      u32 endian, elsz, mixed;
 +      unsigned int tlb;
 +};
 +
 +static inline unsigned long
 +omap_mmu_read_reg(struct omap_mmu *mmu, unsigned long reg)
 +{
 +      return __raw_readl((void __iomem *)(mmu->base + reg));
 +}
 +
 +static inline void omap_mmu_write_reg(struct omap_mmu *mmu,
 +                             unsigned long val, unsigned long reg)
 +{
 +      __raw_writel(val, (void __iomem *)(mmu->base + reg));
 +}
 +
 +#endif /* __MACH_OMAP2_MMU_H */
index 545e0924ba58ab93b9e94f530b23271c26ab6cd0,443d07fef7f3155ee06b9e877d17d7286cd3b43c..741ab189fc41223f790248bddf9fb1798a9f3026
  #include <linux/module.h>
  #include <linux/init.h>
  #include <asm/system.h>
 -#include <asm/io.h>
 +#include <linux/io.h>
  #include <linux/spinlock.h>
  
- #include <asm/arch/control.h>
- #include <asm/arch/mux.h>
+ #include <mach/control.h>
+ #include <mach/mux.h>
  
  #ifdef CONFIG_OMAP_MUX
  
index a32f11f4adb0d5f8efa88874bfe3da1f30a61d4f,0000000000000000000000000000000000000000..1b14bcf6cb811d97b18f06e135cc3489fa5715df
mode 100644,000000..100644
--- /dev/null
@@@ -1,288 -1,0 +1,288 @@@
- #include <asm/arch/clock.h>
- #include <asm/arch/board.h>
 +/*
 + * linux/arch/arm/mach-omap2/pm_debug.c
 + *
 + * OMAP Power Management debug routines
 + *
 + * Copyright (C) 2005 Texas Instruments, Inc.
 + * Copyright (C) 2006-2008 Nokia Corporation
 + *
 + * Written by:
 + * Richard Woodruff <r-woodruff2@ti.com>
 + * Tony Lindgren
 + * Juha Yrjola
 + * Amit Kucheria <amit.kucheria@nokia.com>
 + * Igor Stoppa <igor.stoppa@nokia.com>
 + * Jouni Hogander
 + *
 + * Based on pm.c for omap2
 + *
 + * 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/timer.h>
 +#include <linux/clk.h>
 +#include <linux/err.h>
 +#include <linux/io.h>
 +
++#include <mach/clock.h>
++#include <mach/board.h>
 +
 +#include "prm.h"
 +#include "cm.h"
 +#include "pm.h"
 +
 +#ifdef CONFIG_PM_DEBUG
 +int omap2_pm_debug = 0;
 +
 +static int serial_console_clock_disabled;
 +static int serial_console_uart;
 +static unsigned int serial_console_next_disable;
 +
 +static struct clk *console_iclk, *console_fclk;
 +
 +static void serial_console_kick(void)
 +{
 +      serial_console_next_disable = omap2_read_32k_sync_counter();
 +      /* Keep the clocks on for 4 secs */
 +      serial_console_next_disable += 4 * 32768;
 +}
 +
 +static void serial_wait_tx(void)
 +{
 +      static const unsigned long uart_bases[3] = {
 +              0x4806a000, 0x4806c000, 0x4806e000
 +      };
 +      unsigned long lsr_reg;
 +      int looped = 0;
 +
 +      /* Wait for TX FIFO and THR to get empty */
 +      lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5 << 2));
 +      while ((__raw_readb(lsr_reg) & 0x60) != 0x60)
 +              looped = 1;
 +      if (looped)
 +              serial_console_kick();
 +}
 +
 +u32 omap2_read_32k_sync_counter(void)
 +{
 +        return omap_readl(OMAP2_32KSYNCT_BASE + 0x0010);
 +}
 +
 +void serial_console_fclk_mask(u32 *f1, u32 *f2)
 +{
 +      switch (serial_console_uart)  {
 +      case 1:
 +              *f1 &= ~(1 << 21);
 +              break;
 +      case 2:
 +              *f1 &= ~(1 << 22);
 +              break;
 +      case 3:
 +              *f2 &= ~(1 << 2);
 +              break;
 +      }
 +}
 +
 +void serial_console_sleep(int enable)
 +{
 +      if (console_iclk == NULL || console_fclk == NULL)
 +              return;
 +
 +      if (enable) {
 +              BUG_ON(serial_console_clock_disabled);
 +              if (clk_get_usecount(console_fclk) == 0)
 +                      return;
 +              if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
 +                      return;
 +              serial_wait_tx();
 +              clk_disable(console_iclk);
 +              clk_disable(console_fclk);
 +              serial_console_clock_disabled = 1;
 +      } else {
 +              int serial_wakeup = 0;
 +              u32 l;
 +
 +              switch (serial_console_uart)  {
 +              case 1:
 +                      l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
 +                      if (l & OMAP24XX_ST_UART1)
 +                              serial_wakeup = 1;
 +                      break;
 +              case 2:
 +                      l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
 +                      if (l & OMAP24XX_ST_UART2)
 +                              serial_wakeup = 1;
 +                      break;
 +              case 3:
 +                      l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
 +                      if (l & OMAP24XX_ST_UART3)
 +                              serial_wakeup = 1;
 +                      break;
 +              }
 +              if (serial_wakeup)
 +                      serial_console_kick();
 +              if (!serial_console_clock_disabled)
 +                      return;
 +              clk_enable(console_iclk);
 +              clk_enable(console_fclk);
 +              serial_console_clock_disabled = 0;
 +      }
 +}
 +
 +void pm_init_serial_console(void)
 +{
 +      const struct omap_serial_console_config *conf;
 +      char name[16];
 +
 +      conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
 +                             struct omap_serial_console_config);
 +      if (conf == NULL)
 +              return;
 +      if (conf->console_uart > 3 || conf->console_uart < 1)
 +              return;
 +      serial_console_uart = conf->console_uart;
 +      sprintf(name, "uart%d_fck", conf->console_uart);
 +      console_fclk = clk_get(NULL, name);
 +      if (IS_ERR(console_fclk))
 +              console_fclk = NULL;
 +      name[6] = 'i';
 +      console_iclk = clk_get(NULL, name);
 +      if (IS_ERR(console_fclk))
 +              console_iclk = NULL;
 +      if (console_fclk == NULL || console_iclk == NULL) {
 +              serial_console_uart = 0;
 +              return;
 +      }
 +      switch (serial_console_uart) {
 +      case 1:
 +              prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
 +              break;
 +      case 2:
 +              prm_set_mod_reg_bits(OMAP24XX_ST_UART2, CORE_MOD, PM_WKEN1);
 +              break;
 +      case 3:
 +              prm_set_mod_reg_bits(OMAP24XX_ST_UART3, CORE_MOD, OMAP24XX_PM_WKEN2);
 +              break;
 +      }
 +}
 +
 +#define DUMP_PRM_MOD_REG(mod, reg)    \
 +      regs[reg_count].name = #mod "." #reg; \
 +      regs[reg_count++].val = prm_read_mod_reg(mod, reg)
 +#define DUMP_CM_MOD_REG(mod, reg)     \
 +      regs[reg_count].name = #mod "." #reg; \
 +      regs[reg_count++].val = cm_read_mod_reg(mod, reg)
 +#define DUMP_PRM_REG(reg) \
 +      regs[reg_count].name = #reg; \
 +      regs[reg_count++].val = __raw_readl(reg)
 +#define DUMP_CM_REG(reg) \
 +      regs[reg_count].name = #reg; \
 +      regs[reg_count++].val = __raw_readl(reg)
 +#define DUMP_INTC_REG(reg, off) \
 +      regs[reg_count].name = #reg; \
 +      regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
 +
 +void omap2_pm_dump(int mode, int resume, unsigned int us)
 +{
 +      struct reg {
 +              const char *name;
 +              u32 val;
 +      } regs[32];
 +      int reg_count = 0, i;
 +      const char *s1 = NULL, *s2 = NULL;
 +
 +      if (!resume) {
 +#if 0
 +              /* MPU */
 +              DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
 +              DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
 +              DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
 +              DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
 +              DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
 +#endif
 +#if 0
 +              /* INTC */
 +              DUMP_INTC_REG(INTC_MIR0, 0x0084);
 +              DUMP_INTC_REG(INTC_MIR1, 0x00a4);
 +              DUMP_INTC_REG(INTC_MIR2, 0x00c4);
 +#endif
 +#if 0
 +              DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
 +              if (cpu_is_omap24xx()) {
 +                      DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
 +                                      OMAP24XX_PRCM_CLKEMUL_CTRL_OFFSET);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
 +                                      OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
 +              }
 +              DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
 +              DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
 +              DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
 +              DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
 +              DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
 +              DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
 +              DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
 +#endif
 +#if 0
 +              /* DSP */
 +              if (cpu_is_omap24xx()) {
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
 +                      DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
 +                      DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
 +              }
 +#endif
 +      } else {
 +              DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
 +              if (cpu_is_omap24xx())
 +                      DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
 +              DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
 +              DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +#if 1
 +              DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
 +              DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
 +              DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
 +#endif
 +      }
 +
 +      switch (mode) {
 +      case 0:
 +              s1 = "full";
 +              s2 = "retention";
 +              break;
 +      case 1:
 +              s1 = "MPU";
 +              s2 = "retention";
 +              break;
 +      case 2:
 +              s1 = "MPU";
 +              s2 = "idle";
 +              break;
 +      }
 +
 +      if (!resume)
 +#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
 +              printk("--- Going to %s %s (next timer after %u ms)\n", s1, s2,
 +                     jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
 +                                      jiffies));
 +#else
 +              printk("--- Going to %s %s\n", s1, s2);
 +#endif
 +      else
 +              printk("--- Woke up (slept for %u.%03u ms)\n",
 +                      us / 1000, us % 1000);
 +
 +      for (i = 0; i < reg_count; i++)
 +              printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val);
 +}
 +
 +#endif
index 524b4db06dca699bd774606b369fed592808f41c,8671e1079ab54c7764adfe729294e793e9504d17..4652136de15f7150b61496d0bd190bb0e785cd1b
   */
  
  #include <linux/suspend.h>
 -#include <linux/sched.h>
 -#include <linux/proc_fs.h>
 -#include <linux/interrupt.h>
 -#include <linux/sysfs.h>
 -#include <linux/module.h>
 -#include <linux/delay.h>
 -#include <linux/clk.h>
 -
 -#include <asm/io.h>
 -#include <asm/irq.h>
 -#include <asm/atomic.h>
 +#include <linux/time.h>
 +
- #include <asm/arch/cpu.h>
++#include <mach/cpu.h>
  #include <asm/mach/time.h>
 -#include <asm/mach/irq.h>
 +#include <asm/atomic.h>
  
- #include <asm/arch/pm.h>
 -#include <mach/irqs.h>
 -#include <mach/clock.h>
 -#include <mach/sram.h>
+ #include <mach/pm.h>
 +#include "pm.h"
  
 -static struct clk *vclk;
 -static void (*omap2_sram_idle)(void);
 -static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
 -static void (*saved_idle)(void);
 +unsigned short enable_dyn_sleep;
 +unsigned short clocks_off_while_idle;
 +atomic_t sleep_block = ATOMIC_INIT(0);
  
 -extern void __init pmdomain_init(void);
 -extern void pmdomain_set_autoidle(void);
 +static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *);
 +static ssize_t idle_store(struct kobject *k, struct kobj_attribute *,
 +                        const char *buf, size_t n);
  
 -static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
 +static struct kobj_attribute sleep_while_idle_attr =
 +      __ATTR(sleep_while_idle, 0644, idle_show, idle_store);
  
 -void omap2_pm_idle(void)
 -{
 -      local_irq_disable();
 -      local_fiq_disable();
 -      if (need_resched()) {
 -              local_fiq_enable();
 -              local_irq_enable();
 -              return;
 -      }
 -
 -      omap2_sram_idle();
 -      local_fiq_enable();
 -      local_irq_enable();
 -}
 +static struct kobj_attribute clocks_off_while_idle_attr =
 +      __ATTR(clocks_off_while_idle, 0644, idle_show, idle_store);
  
 -static int omap2_pm_prepare(void)
 +static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
 +                       char *buf)
  {
 -      /* We cannot sleep in idle until we have resumed */
 -      saved_idle = pm_idle;
 -      pm_idle = NULL;
 -      return 0;
 +      if (attr == &sleep_while_idle_attr)
 +              return sprintf(buf, "%hu\n", enable_dyn_sleep);
 +      else if (attr == &clocks_off_while_idle_attr)
 +              return sprintf(buf, "%hu\n", clocks_off_while_idle);
 +      else
 +              return -EINVAL;
  }
  
 -static int omap2_pm_suspend(void)
 +static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
 +                        const char *buf, size_t n)
  {
 -      return 0;
 -}
 +      unsigned short value;
  
 -static int omap2_pm_enter(suspend_state_t state)
 -{
 -      int ret = 0;
 -
 -      switch (state)
 -      {
 -      case PM_SUSPEND_STANDBY:
 -      case PM_SUSPEND_MEM:
 -              ret = omap2_pm_suspend();
 -              break;
 -      default:
 -              ret = -EINVAL;
 +      if (sscanf(buf, "%hu", &value) != 1 ||
 +          (value != 0 && value != 1)) {
 +              printk(KERN_ERR "idle_store: Invalid value\n");
 +              return -EINVAL;
        }
  
 -      return ret;
 +      if (attr == &sleep_while_idle_attr)
 +              enable_dyn_sleep = value;
 +      else if (attr == &clocks_off_while_idle_attr)
 +              clocks_off_while_idle = value;
 +      else
 +              return -EINVAL;
 +
 +      return n;
  }
  
 -static void omap2_pm_finish(void)
 +void omap2_block_sleep(void)
  {
 -      pm_idle = saved_idle;
 +      atomic_inc(&sleep_block);
  }
  
 -static struct platform_suspend_ops omap_pm_ops = {
 -      .prepare        = omap2_pm_prepare,
 -      .enter          = omap2_pm_enter,
 -      .finish         = omap2_pm_finish,
 -      .valid          = suspend_valid_only_mem,
 -};
 +void omap2_allow_sleep(void)
 +{
 +      int i;
 +
 +      i = atomic_dec_return(&sleep_block);
 +      BUG_ON(i < 0);
 +}
  
 -int __init omap2_pm_init(void)
 +static int __init omap_pm_init(void)
  {
 -      return 0;
 +      int error = -1;
 +
 +      if (cpu_is_omap24xx())
 +              error = omap2_pm_init();
 +      if (cpu_is_omap34xx())
 +              error = omap3_pm_init();
 +      if (error) {
 +              printk(KERN_ERR "omap2|3_pm_init failed: %d\n", error);
 +              return error;
 +      }
 +
 +      /* disabled till drivers are fixed */
 +      enable_dyn_sleep = 0;
 +      error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
 +      if (error)
 +              printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
 +      error = sysfs_create_file(power_kobj,
 +                                &clocks_off_while_idle_attr.attr);
 +      if (error)
 +              printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
 +
 +      return error;
  }
  
 -__initcall(omap2_pm_init);
 +late_initcall(omap_pm_init);
index 69972a2f988af795b2034412611823711a3d138f,0000000000000000000000000000000000000000..5c7612069d35a19647918ac6b2cc7ae5db883f89
mode 100644,000000..100644
--- /dev/null
@@@ -1,555 -1,0 +1,555 @@@
- #include <asm/arch/irqs.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/sram.h>
- #include <asm/arch/control.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/pm.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/board.h>
 +/*
 + * linux/arch/arm/mach-omap2/pm.c
 + *
 + * OMAP2 Power Management Routines
 + *
 + * Copyright (C) 2005 Texas Instruments, Inc.
 + * Copyright (C) 2006-2008 Nokia Corporation
 + *
 + * Written by:
 + * Richard Woodruff <r-woodruff2@ti.com>
 + * Tony Lindgren
 + * Juha Yrjola
 + * Amit Kucheria <amit.kucheria@nokia.com>
 + * Igor Stoppa <igor.stoppa@nokia.com>
 + *
 + * Based on pm.c for omap1
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/suspend.h>
 +#include <linux/sched.h>
 +#include <linux/proc_fs.h>
 +#include <linux/interrupt.h>
 +#include <linux/sysfs.h>
 +#include <linux/module.h>
 +#include <linux/delay.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <linux/irq.h>
 +
 +#include <asm/mach/time.h>
 +#include <asm/mach/irq.h>
 +#include <asm/mach-types.h>
 +
- #include <asm/arch/powerdomain.h>
- #include <asm/arch/clockdomain.h>
++#include <mach/irqs.h>
++#include <mach/clock.h>
++#include <mach/sram.h>
++#include <mach/control.h>
++#include <mach/gpio.h>
++#include <mach/pm.h>
++#include <mach/mux.h>
++#include <mach/dma.h>
++#include <mach/board.h>
 +
 +#include "prm.h"
 +#include "prm-regbits-24xx.h"
 +#include "cm.h"
 +#include "cm-regbits-24xx.h"
 +#include "sdrc.h"
 +#include "pm.h"
 +
++#include <mach/powerdomain.h>
++#include <mach/clockdomain.h>
 +
 +static void (*omap2_sram_idle)(void);
 +static void (*omap2_sram_suspend)(void __iomem *dllctrl);
 +static void (*saved_idle)(void);
 +
 +static struct powerdomain *mpu_pwrdm;
 +static struct powerdomain *core_pwrdm;
 +
 +static struct clockdomain *dsp_clkdm;
 +static struct clockdomain *gfx_clkdm;
 +
 +static struct clk *osc_ck, *emul_ck;
 +
 +static int omap2_fclks_active(void)
 +{
 +      u32 f1, f2;
 +
 +      f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 +      f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 +      serial_console_fclk_mask(&f1, &f2);
 +      if (f1 | f2)
 +              return 1;
 +      return 0;
 +}
 +
 +static void omap2_enter_full_retention(void)
 +{
 +      u32 l, sleep_time = 0;
 +
 +      /* There is 1 reference hold for all children of the oscillator
 +       * clock, the following will remove it. If no one else uses the
 +       * oscillator itself it will be disabled if/when we enter retention
 +       * mode.
 +       */
 +      clk_disable(osc_ck);
 +
 +      /* Clear old wake-up events */
 +      /* REVISIT: These write to reserved bits? */
 +      prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
 +      prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 +      prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 +
 +      /*
 +       * Set MPU powerdomain's next power state to RETENTION;
 +       * preserve logic state during retention
 +       */
 +      pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 +      pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 +
 +      /* Workaround to kill USB */
 +      l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
 +      omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
 +
 +      omap2_gpio_prepare_for_retention();
 +
 +      if (omap2_pm_debug) {
 +              omap2_pm_dump(0, 0, 0);
 +              sleep_time = omap2_read_32k_sync_counter();
 +      }
 +
 +      /* One last check for pending IRQs to avoid extra latency due
 +       * to sleeping unnecessarily. */
 +      if (omap_irq_pending())
 +              goto no_sleep;
 +
 +      serial_console_sleep(1);
 +      /* Jump to SRAM suspend code */
 +      omap2_sram_suspend(OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL));
 +no_sleep:
 +      serial_console_sleep(0);
 +
 +      if (omap2_pm_debug) {
 +              unsigned long long tmp;
 +              u32 resume_time;
 +
 +              resume_time = omap2_read_32k_sync_counter();
 +              tmp = resume_time - sleep_time;
 +              tmp *= 1000000;
 +              omap2_pm_dump(0, 1, tmp / 32768);
 +      }
 +      omap2_gpio_resume_after_retention();
 +
 +      clk_enable(osc_ck);
 +
 +      /* clear CORE wake-up events */
 +      prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
 +      prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 +
 +      /* wakeup domain events - bit 1: GPT1, bit5 GPIO */
 +      prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
 +
 +      /* MPU domain wake events */
 +      l = prm_read_mod_reg(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +      if (l & 0x01)
 +              prm_write_mod_reg(0x01, OCP_MOD,
 +                              OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +      if (l & 0x20)
 +              prm_write_mod_reg(0x20, OCP_MOD,
 +                              OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +
 +      /* Mask future PRCM-to-MPU interrupts */
 +      prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +}
 +
 +static int omap2_i2c_active(void)
 +{
 +      u32 l;
 +
 +      l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 +      return l & (OMAP2420_EN_I2C2 | OMAP2420_EN_I2C1);
 +}
 +
 +static int sti_console_enabled;
 +
 +static int omap2_allow_mpu_retention(void)
 +{
 +      u32 l;
 +
 +      if (atomic_read(&sleep_block))
 +              return 0;
 +
 +      /* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
 +      l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 +      if (l & (OMAP2420_EN_MMC | OMAP24XX_EN_UART2 |
 +               OMAP24XX_EN_UART1 | OMAP24XX_EN_MCSPI2 |
 +               OMAP24XX_EN_MCSPI1 | OMAP24XX_EN_DSS1))
 +              return 0;
 +      /* Check for UART3. */
 +      l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
 +      if (l & OMAP24XX_EN_UART3)
 +              return 0;
 +      if (sti_console_enabled)
 +              return 0;
 +
 +      return 1;
 +}
 +
 +static void omap2_enter_mpu_retention(void)
 +{
 +      u32 sleep_time = 0;
 +      int only_idle = 0;
 +
 +      /* Putting MPU into the WFI state while a transfer is active
 +       * seems to cause the I2C block to timeout. Why? Good question. */
 +      if (omap2_i2c_active())
 +              return;
 +
 +      /* The peripherals seem not to be able to wake up the MPU when
 +       * it is in retention mode. */
 +      if (omap2_allow_mpu_retention()) {
 +              /* REVISIT: These write to reserved bits? */
 +              prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
 +              prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 +              prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 +
 +              /* Try to enter MPU retention */
 +              prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
 +                                OMAP_LOGICRETSTATE,
 +                                MPU_MOD, PM_PWSTCTRL);
 +      } else {
 +              /* Block MPU retention */
 +
 +              prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
 +              only_idle = 1;
 +      }
 +
 +      if (omap2_pm_debug) {
 +              omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
 +              sleep_time = omap2_read_32k_sync_counter();
 +      }
 +
 +      omap2_sram_idle();
 +
 +      if (omap2_pm_debug) {
 +              unsigned long long tmp;
 +              u32 resume_time;
 +
 +              resume_time = omap2_read_32k_sync_counter();
 +              tmp = resume_time - sleep_time;
 +              tmp *= 1000000;
 +              omap2_pm_dump(only_idle ? 2 : 1, 1, tmp / 32768);
 +      }
 +}
 +
 +static int omap2_can_sleep(void)
 +{
 +      if (!enable_dyn_sleep)
 +              return 0;
 +      if (omap2_fclks_active())
 +              return 0;
 +      if (atomic_read(&sleep_block) > 0)
 +              return 0;
 +      if (clk_get_usecount(osc_ck) > 1)
 +              return 0;
 +      if (omap_dma_running())
 +              return 0;
 +
 +      return 1;
 +}
 +
 +/*
 + * Note that you can use clock_event_device->min_delta_ns if you want to
 + * avoid reprogramming timer too often when using CONFIG_NO_HZ.
 + */
 +static void omap2_pm_idle(void)
 +{
 +      local_irq_disable();
 +      local_fiq_disable();
 +
 +      if (!omap2_can_sleep()) {
 +              if (!atomic_read(&sleep_block) && omap_irq_pending())
 +                      goto out;
 +              omap2_enter_mpu_retention();
 +              goto out;
 +      }
 +
 +      if (omap_irq_pending())
 +              goto out;
 +
 +      omap2_enter_full_retention();
 +
 +out:
 +      local_fiq_enable();
 +      local_irq_enable();
 +}
 +
 +static int omap2_pm_prepare(void)
 +{
 +      /* We cannot sleep in idle until we have resumed */
 +      saved_idle = pm_idle;
 +      pm_idle = NULL;
 +
 +      return 0;
 +}
 +
 +static int omap2_pm_suspend(void)
 +{
 +      u32 wken_wkup, mir1;
 +
 +      wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 +      prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN);
 +
 +      /* Mask GPT1 */
 +      mir1 = omap_readl(0x480fe0a4);
 +      omap_writel(1 << 5, 0x480fe0ac);
 +
 +      omap2_enter_full_retention();
 +
 +      omap_writel(mir1, 0x480fe0a4);
 +      prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
 +
 +      return 0;
 +}
 +
 +static int omap2_pm_enter(suspend_state_t state)
 +{
 +      int ret = 0;
 +
 +      switch (state) {
 +      case PM_SUSPEND_STANDBY:
 +      case PM_SUSPEND_MEM:
 +              ret = omap2_pm_suspend();
 +              break;
 +      default:
 +              ret = -EINVAL;
 +      }
 +
 +      return ret;
 +}
 +
 +static void omap2_pm_finish(void)
 +{
 +      pm_idle = saved_idle;
 +}
 +
 +static struct platform_suspend_ops omap_pm_ops = {
 +      .prepare        = omap2_pm_prepare,
 +      .enter          = omap2_pm_enter,
 +      .finish         = omap2_pm_finish,
 +      .valid          = suspend_valid_only_mem,
 +};
 +
 +static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
 +{
 +      omap2_clkdm_allow_idle(clkdm);
 +      return 0;
 +}
 +
 +static void __init prcm_setup_regs(void)
 +{
 +      int i, num_mem_banks;
 +      struct powerdomain *pwrdm;
 +
 +      /* Enable autoidle */
 +      prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
 +                              OMAP24XX_PRM_SYSCONFIG_OFFSET);
 +
 +      /* Set all domain wakeup dependencies */
 +      prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
 +      if (cpu_is_omap2430())
 +              prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
 +
 +      /*
 +       * Set CORE powerdomain memory banks to retain their contents
 +       * during RETENTION
 +       */
 +      num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
 +      for (i = 0; i < num_mem_banks; i++)
 +              pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
 +
 +      /* Set CORE powerdomain's next power state to RETENTION */
 +      pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
 +
 +      /*
 +       * Set MPU powerdomain's next power state to RETENTION;
 +       * preserve logic state during retention
 +       */
 +      pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 +      pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 +
 +      /* Force-power down DSP, GFX powerdomains */
 +
 +      pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 +      pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
 +      omap2_clkdm_sleep(dsp_clkdm);
 +
 +      pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 +      pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
 +      omap2_clkdm_sleep(gfx_clkdm);
 +
 +      /* Enable clockdomain hardware-supervised control for all clkdms */
 +      clkdm_for_each(_pm_clkdm_enable_hwsup);
 +
 +      /* Enable clock autoidle for all domains */
 +      cm_write_mod_reg(OMAP24XX_AUTO_CAM |
 +                       OMAP24XX_AUTO_MAILBOXES |
 +                       OMAP24XX_AUTO_WDT4 |
 +                       OMAP2420_AUTO_WDT3 |
 +                       OMAP24XX_AUTO_MSPRO |
 +                       OMAP2420_AUTO_MMC |
 +                       OMAP24XX_AUTO_FAC |
 +                       OMAP2420_AUTO_EAC |
 +                       OMAP24XX_AUTO_HDQ |
 +                       OMAP24XX_AUTO_UART2 |
 +                       OMAP24XX_AUTO_UART1 |
 +                       OMAP24XX_AUTO_I2C2 |
 +                       OMAP24XX_AUTO_I2C1 |
 +                       OMAP24XX_AUTO_MCSPI2 |
 +                       OMAP24XX_AUTO_MCSPI1 |
 +                       OMAP24XX_AUTO_MCBSP2 |
 +                       OMAP24XX_AUTO_MCBSP1 |
 +                       OMAP24XX_AUTO_GPT12 |
 +                       OMAP24XX_AUTO_GPT11 |
 +                       OMAP24XX_AUTO_GPT10 |
 +                       OMAP24XX_AUTO_GPT9 |
 +                       OMAP24XX_AUTO_GPT8 |
 +                       OMAP24XX_AUTO_GPT7 |
 +                       OMAP24XX_AUTO_GPT6 |
 +                       OMAP24XX_AUTO_GPT5 |
 +                       OMAP24XX_AUTO_GPT4 |
 +                       OMAP24XX_AUTO_GPT3 |
 +                       OMAP24XX_AUTO_GPT2 |
 +                       OMAP2420_AUTO_VLYNQ |
 +                       OMAP24XX_AUTO_DSS,
 +                       CORE_MOD, CM_AUTOIDLE1);
 +      cm_write_mod_reg(OMAP24XX_AUTO_UART3 |
 +                       OMAP24XX_AUTO_SSI |
 +                       OMAP24XX_AUTO_USB,
 +                       CORE_MOD, CM_AUTOIDLE2);
 +      cm_write_mod_reg(OMAP24XX_AUTO_SDRC |
 +                       OMAP24XX_AUTO_GPMC |
 +                       OMAP24XX_AUTO_SDMA,
 +                       CORE_MOD, CM_AUTOIDLE3);
 +      cm_write_mod_reg(OMAP24XX_AUTO_PKA |
 +                       OMAP24XX_AUTO_AES |
 +                       OMAP24XX_AUTO_RNG |
 +                       OMAP24XX_AUTO_SHA |
 +                       OMAP24XX_AUTO_DES,
 +                       CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
 +
 +      cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
 +
 +      /* Put DPLL and both APLLs into autoidle mode */
 +      cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
 +                       (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
 +                       (0x03 << OMAP24XX_AUTO_54M_SHIFT),
 +                       PLL_MOD, CM_AUTOIDLE);
 +
 +      cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL |
 +                       OMAP24XX_AUTO_WDT1 |
 +                       OMAP24XX_AUTO_MPU_WDT |
 +                       OMAP24XX_AUTO_GPIOS |
 +                       OMAP24XX_AUTO_32KSYNC |
 +                       OMAP24XX_AUTO_GPT1,
 +                       WKUP_MOD, CM_AUTOIDLE);
 +
 +      /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 +       * stabilisation */
 +      prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
 +                                      OMAP24XX_PRCM_CLKSSETUP_OFFSET);
 +
 +      /* Configure automatic voltage transition */
 +      prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
 +                                      OMAP24XX_PRCM_VOLTSETUP_OFFSET);
 +      prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT |
 +                    (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
 +                    OMAP24XX_MEMRETCTRL |
 +                    (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
 +                    (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
 +                    OMAP24XX_GR_MOD, OMAP24XX_PRCM_VOLTCTRL_OFFSET);
 +
 +      /* Enable wake-up events */
 +      prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1,
 +                        WKUP_MOD, PM_WKEN);
 +}
 +
 +int __init omap2_pm_init(void)
 +{
 +      u32 l;
 +
 +      printk(KERN_INFO "Power Management for OMAP2 initializing\n");
 +      l = prm_read_mod_reg(OCP_MOD, OMAP24XX_PRM_REVISION_OFFSET);
 +      printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
 +
 +      /* Look up important powerdomains, clockdomains */
 +
 +      mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 +      if (!mpu_pwrdm)
 +              pr_err("PM: mpu_pwrdm not found\n");
 +
 +      core_pwrdm = pwrdm_lookup("core_pwrdm");
 +      if (!core_pwrdm)
 +              pr_err("PM: core_pwrdm not found\n");
 +
 +      dsp_clkdm = clkdm_lookup("dsp_clkdm");
 +      if (!dsp_clkdm)
 +              pr_err("PM: mpu_clkdm not found\n");
 +
 +      gfx_clkdm = clkdm_lookup("gfx_clkdm");
 +      if (!gfx_clkdm)
 +              pr_err("PM: gfx_clkdm not found\n");
 +
 +
 +      osc_ck = clk_get(NULL, "osc_ck");
 +      if (IS_ERR(osc_ck)) {
 +              printk(KERN_ERR "could not get osc_ck\n");
 +              return -ENODEV;
 +      }
 +
 +      if (cpu_is_omap242x()) {
 +              emul_ck = clk_get(NULL, "emul_ck");
 +              if (IS_ERR(emul_ck)) {
 +                      printk(KERN_ERR "could not get emul_ck\n");
 +                      clk_put(osc_ck);
 +                      return -ENODEV;
 +              }
 +      }
 +
 +      prcm_setup_regs();
 +
 +      pm_init_serial_console();
 +
 +      /* Hack to prevent MPU retention when STI console is enabled. */
 +      {
 +              const struct omap_sti_console_config *sti;
 +
 +              sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
 +                                    struct omap_sti_console_config);
 +              if (sti != NULL && sti->enable)
 +                      sti_console_enabled = 1;
 +      }
 +
 +      /*
 +       * We copy the assembler sleep/wakeup routines to SRAM.
 +       * These routines need to be in SRAM as that's the only
 +       * memory the MPU can see when it wakes up.
 +       */
 +      if (cpu_is_omap242x()) {
 +              omap2_sram_idle = omap_sram_push(omap242x_idle_loop_suspend,
 +                                               omap242x_idle_loop_suspend_sz);
 +
 +              omap2_sram_suspend = omap_sram_push(omap242x_cpu_suspend,
 +                                                  omap242x_cpu_suspend_sz);
 +      } else {
 +              omap2_sram_idle = omap_sram_push(omap243x_idle_loop_suspend,
 +                                               omap243x_idle_loop_suspend_sz);
 +
 +              omap2_sram_suspend = omap_sram_push(omap243x_cpu_suspend,
 +                                                  omap243x_cpu_suspend_sz);
 +      }
 +
 +      suspend_set_ops(&omap_pm_ops);
 +      pm_idle = omap2_pm_idle;
 +
 +      return 0;
 +}
index fc72c11e5828ad8c882136fc6a5c3d41cbe0ee53,0000000000000000000000000000000000000000..a57cf4172a0c965eb6633fe33ac47d9bd78e88fc
mode 100644,000000..100644
--- /dev/null
@@@ -1,498 -1,0 +1,498 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/sram.h>
- #include <asm/arch/pm.h>
- #include <asm/arch/clockdomain.h>
- #include <asm/arch/powerdomain.h>
 +/*
 + * linux/arch/arm/mach-omap2/pm34xx.c
 + *
 + * OMAP3 Power Management Routines
 + *
 + * Copyright (C) 2006-2008 Nokia Corporation
 + * Tony Lindgren <tony@atomide.com>
 + * Jouni Hogander
 + *
 + * Copyright (C) 2005 Texas Instruments, Inc.
 + * Richard Woodruff <r-woodruff2@ti.com>
 + *
 + * Based on pm.c for omap1
 + *
 + * 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/pm.h>
 +#include <linux/suspend.h>
 +#include <linux/interrupt.h>
 +#include <linux/module.h>
 +#include <linux/list.h>
 +#include <linux/err.h>
 +
++#include <mach/gpio.h>
++#include <mach/sram.h>
++#include <mach/pm.h>
++#include <mach/clockdomain.h>
++#include <mach/powerdomain.h>
 +
 +#include "cm.h"
 +#include "cm-regbits-34xx.h"
 +#include "prm-regbits-34xx.h"
 +
 +#include "prm.h"
 +#include "pm.h"
 +#include "smartreflex.h"
 +
 +struct power_state {
 +      struct powerdomain *pwrdm;
 +      u32 next_state;
 +      u32 saved_state;
 +      struct list_head node;
 +};
 +
 +static LIST_HEAD(pwrst_list);
 +
 +static void (*_omap_sram_idle)(u32 *addr, int save_state);
 +
 +static void (*saved_idle)(void);
 +
 +static struct powerdomain *mpu_pwrdm;
 +
 +/* PRCM Interrupt Handler for wakeups */
 +static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
 +{
 +      u32 wkst, irqstatus_mpu;
 +      u32 fclk, iclk;
 +
 +      /* WKUP */
 +      wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
 +      if (wkst) {
 +              iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
 +              fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
 +              cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN);
 +              cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN);
 +              prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST);
 +              while (prm_read_mod_reg(WKUP_MOD, PM_WKST));
 +              cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN);
 +              cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN);
 +      }
 +
 +      /* CORE */
 +      wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
 +      if (wkst) {
 +              iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
 +              fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 +              cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1);
 +              cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1);
 +              prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1);
 +              while (prm_read_mod_reg(CORE_MOD, PM_WKST1));
 +              cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1);
 +              cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1);
 +      }
 +      wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
 +      if (wkst) {
 +              iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
 +              fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
 +              cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3);
 +              cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
 +              prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3);
 +              while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3));
 +              cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3);
 +              cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
 +      }
 +
 +      /* PER */
 +      wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
 +      if (wkst) {
 +              iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
 +              fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
 +              cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN);
 +              cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN);
 +              prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST);
 +              while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST));
 +              cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN);
 +              cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN);
 +      }
 +
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
 +              /* USBHOST */
 +              wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
 +              if (wkst) {
 +                      iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
 +                                             CM_ICLKEN);
 +                      fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
 +                                             CM_FCLKEN);
 +                      cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
 +                                       CM_ICLKEN);
 +                      cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
 +                                       CM_FCLKEN);
 +                      prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD,
 +                                        PM_WKST);
 +                      while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
 +                                              PM_WKST));
 +                      cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD,
 +                                       CM_ICLKEN);
 +                      cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD,
 +                                       CM_FCLKEN);
 +              }
 +      }
 +
 +      irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
 +                                      OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +      prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
 +                                      OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
 +
 +      while (prm_read_mod_reg(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET));
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static void omap_sram_idle(void)
 +{
 +      /* Variable to tell what needs to be saved and restored
 +       * in omap_sram_idle*/
 +      /* save_state = 0 => Nothing to save and restored */
 +      /* save_state = 1 => Only L1 and logic lost */
 +      /* save_state = 2 => Only L2 lost */
 +      /* save_state = 3 => L1, L2 and logic lost */
 +      int save_state = 0, mpu_next_state;
 +
 +      if (!_omap_sram_idle)
 +              return;
 +
 +      mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
 +      switch (mpu_next_state) {
 +      case PWRDM_POWER_RET:
 +              /* No need to save context */
 +              save_state = 0;
 +              break;
 +      default:
 +              /* Invalid state */
 +              printk(KERN_ERR "Invalid mpu state in sram_idle\n");
 +              return;
 +      }
 +
 +      omap2_gpio_prepare_for_retention();
 +
 +      _omap_sram_idle(NULL, save_state);
 +
 +      omap2_gpio_resume_after_retention();
 +}
 +
 +static int omap3_can_sleep(void)
 +{
 +      if (!enable_dyn_sleep)
 +              return 0;
 +      if (atomic_read(&sleep_block) > 0)
 +              return 0;
 +      return 1;
 +}
 +
 +/* _clkdm_deny_idle - private callback function used by set_pwrdm_state() */
 +static int _clkdm_deny_idle(struct powerdomain *pwrdm,
 +                          struct clockdomain *clkdm)
 +{
 +      omap2_clkdm_deny_idle(clkdm);
 +      return 0;
 +}
 +
 +/* _clkdm_allow_idle - private callback function used by set_pwrdm_state() */
 +static int _clkdm_allow_idle(struct powerdomain *pwrdm,
 +                           struct clockdomain *clkdm)
 +{
 +      omap2_clkdm_allow_idle(clkdm);
 +      return 0;
 +}
 +
 +/* This sets pwrdm state (other than mpu & core. Currently only ON &
 + * RET are supported. Function is assuming that clkdm doesn't have
 + * hw_sup mode enabled. */
 +static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 +{
 +      u32 cur_state;
 +      int ret = 0;
 +
 +      if (pwrdm == NULL || IS_ERR(pwrdm))
 +              return -EINVAL;
 +
 +      cur_state = pwrdm_read_next_pwrst(pwrdm);
 +
 +      if (cur_state == state)
 +              return ret;
 +
 +      pwrdm_for_each_clkdm(pwrdm, _clkdm_deny_idle);
 +
 +      ret = pwrdm_set_next_pwrst(pwrdm, state);
 +      if (ret) {
 +              printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
 +                     pwrdm->name);
 +              goto err;
 +      }
 +
 +      pwrdm_for_each_clkdm(pwrdm, _clkdm_allow_idle);
 +
 +err:
 +      return ret;
 +}
 +
 +static void omap3_pm_idle(void)
 +{
 +      local_irq_disable();
 +      local_fiq_disable();
 +
 +      if (!omap3_can_sleep())
 +              goto out;
 +
 +      if (omap_irq_pending())
 +              goto out;
 +
 +      omap_sram_idle();
 +
 +out:
 +      local_fiq_enable();
 +      local_irq_enable();
 +}
 +
 +static int omap3_pm_prepare(void)
 +{
 +      saved_idle = pm_idle;
 +      pm_idle = NULL;
 +      return 0;
 +}
 +
 +static int omap3_pm_suspend(void)
 +{
 +      struct power_state *pwrst;
 +      int state, ret = 0;
 +
 +      /* XXX Disable smartreflex before entering suspend */
 +      disable_smartreflex(SR1);
 +      disable_smartreflex(SR2);
 +
 +      /* Read current next_pwrsts */
 +      list_for_each_entry(pwrst, &pwrst_list, node)
 +              pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
 +      /* Set ones wanted by suspend */
 +      list_for_each_entry(pwrst, &pwrst_list, node) {
 +              if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
 +                      goto restore;
 +              if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
 +                      goto restore;
 +      }
 +
 +      omap_sram_idle();
 +
 +restore:
 +      /* Restore next_pwrsts */
 +      list_for_each_entry(pwrst, &pwrst_list, node) {
 +              set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
 +              state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
 +              if (state != pwrst->next_state) {
 +                      printk(KERN_INFO "Powerdomain (%s) didn't enter "
 +                             "target state %d\n",
 +                             pwrst->pwrdm->name, pwrst->next_state);
 +                      ret = -1;
 +              }
 +      }
 +      if (ret)
 +              printk(KERN_ERR "Could not enter target state in pm_suspend\n");
 +      else
 +              printk(KERN_INFO "Successfully put all powerdomains "
 +                     "to target state\n");
 +
 +      /* XXX Enable smartreflex after suspend */
 +      enable_smartreflex(SR1);
 +      enable_smartreflex(SR2);
 +
 +      return ret;
 +}
 +
 +static int omap3_pm_enter(suspend_state_t state)
 +{
 +      int ret = 0;
 +
 +      switch (state) {
 +      case PM_SUSPEND_STANDBY:
 +      case PM_SUSPEND_MEM:
 +              ret = omap3_pm_suspend();
 +              break;
 +      default:
 +              ret = -EINVAL;
 +      }
 +
 +      return ret;
 +}
 +
 +static void omap3_pm_finish(void)
 +{
 +      pm_idle = saved_idle;
 +}
 +
 +static struct platform_suspend_ops omap_pm_ops = {
 +      .prepare        = omap3_pm_prepare,
 +      .enter          = omap3_pm_enter,
 +      .finish         = omap3_pm_finish,
 +      .valid          = suspend_valid_only_mem,
 +};
 +
 +static void __init prcm_setup_regs(void)
 +{
 +      /* XXX Reset all wkdeps. This should be done when initializing
 +       * powerdomains */
 +      prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
 +      prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
 +              prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
 +              prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
 +      } else
 +              prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
 +
 +      /* setup wakup source */
 +      prm_write_mod_reg(OMAP3430_EN_IO | OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1,
 +                        WKUP_MOD, PM_WKEN);
 +      /* No need to write EN_IO, that is always enabled */
 +      prm_write_mod_reg(OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1,
 +                        WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
 +      /* For some reason IO doesn't generate wakeup event even if
 +       * it is selected to mpu wakeup goup */
 +      prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
 +                      OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
 +}
 +
 +static int __init pwrdms_setup(struct powerdomain *pwrdm)
 +{
 +      struct power_state *pwrst;
 +
 +      if (!pwrdm->pwrsts)
 +              return 0;
 +
 +      pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL);
 +      if (!pwrst)
 +              return -ENOMEM;
 +      pwrst->pwrdm = pwrdm;
 +      pwrst->next_state = PWRDM_POWER_RET;
 +      list_add(&pwrst->node, &pwrst_list);
 +
 +      if (pwrdm_has_hdwr_sar(pwrdm))
 +              pwrdm_enable_hdwr_sar(pwrdm);
 +
 +      return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 +}
 +
 +int __init omap3_pm_init(void)
 +{
 +      struct power_state *pwrst;
 +      int ret;
 +
 +      printk(KERN_ERR "Power Management for TI OMAP3.\n");
 +
 +      /* XXX prcm_setup_regs needs to be before enabling hw
 +       * supervised mode for powerdomains */
 +      prcm_setup_regs();
 +
 +      ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
 +                        (irq_handler_t)prcm_interrupt_handler,
 +                        IRQF_DISABLED, "prcm", NULL);
 +      if (ret) {
 +              printk(KERN_ERR "request_irq failed to register for 0x%x\n",
 +                     INT_34XX_PRCM_MPU_IRQ);
 +              goto err1;
 +      }
 +
 +      ret = pwrdm_for_each(pwrdms_setup);
 +      if (ret) {
 +              printk(KERN_ERR "Failed to setup powerdomains\n");
 +              goto err2;
 +      }
 +
 +      mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 +      if (mpu_pwrdm == NULL) {
 +              printk(KERN_ERR "Failed to get mpu_pwrdm\n");
 +              goto err2;
 +      }
 +
 +      _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
 +                                      omap34xx_cpu_suspend_sz);
 +
 +      suspend_set_ops(&omap_pm_ops);
 +
 +      pm_idle = omap3_pm_idle;
 +
 +err1:
 +      return ret;
 +err2:
 +      free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
 +      list_for_each_entry(pwrst, &pwrst_list, node) {
 +              list_del(&pwrst->node);
 +              kfree(pwrst);
 +      }
 +      return ret;
 +}
 +
 +static void __init configure_vc(void)
 +{
 +      prm_write_mod_reg((R_SRI2C_SLAVE_ADDR << OMAP3430_SMPS_SA1_SHIFT) |
 +                      (R_SRI2C_SLAVE_ADDR << OMAP3430_SMPS_SA0_SHIFT),
 +                      OMAP3430_GR_MOD, OMAP3_PRM_VC_SMPS_SA_OFFSET);
 +      prm_write_mod_reg((R_VDD2_SR_CONTROL << OMAP3430_VOLRA1_SHIFT) |
 +                      (R_VDD1_SR_CONTROL << OMAP3430_VOLRA0_SHIFT),
 +                      OMAP3430_GR_MOD, OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET);
 +
 +      prm_write_mod_reg((OMAP3430_VC_CMD_VAL0_ON <<
 +              OMAP3430_VC_CMD_ON_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL0_ONLP << OMAP3430_VC_CMD_ONLP_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL0_RET << OMAP3430_VC_CMD_RET_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL0_OFF << OMAP3430_VC_CMD_OFF_SHIFT),
 +              OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
 +
 +      prm_write_mod_reg((OMAP3430_VC_CMD_VAL1_ON <<
 +              OMAP3430_VC_CMD_ON_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL1_ONLP << OMAP3430_VC_CMD_ONLP_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL1_RET << OMAP3430_VC_CMD_RET_SHIFT) |
 +              (OMAP3430_VC_CMD_VAL1_OFF << OMAP3430_VC_CMD_OFF_SHIFT),
 +              OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
 +
 +      prm_write_mod_reg(OMAP3430_CMD1 | OMAP3430_RAV1,
 +                              OMAP3430_GR_MOD,
 +                              OMAP3_PRM_VC_CH_CONF_OFFSET);
 +
 +      prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN | OMAP3430_SREN,
 +                              OMAP3430_GR_MOD,
 +                              OMAP3_PRM_VC_I2C_CFG_OFFSET);
 +
 +      /* Setup voltctrl and other setup times */
 +
 +#ifdef CONFIG_OMAP_SYSOFFMODE
 +      prm_write_mod_reg(OMAP3430_AUTO_OFF | OMAP3430_AUTO_RET |
 +                      OMAP3430_SEL_OFF, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_VOLTCTRL_OFFSET);
 +
 +      prm_write_mod_reg(OMAP3430_CLKSETUP_DURATION, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_CLKSETUP_OFFSET);
 +      prm_write_mod_reg((OMAP3430_VOLTSETUP_TIME2 <<
 +                      OMAP3430_SETUP_TIME2_SHIFT) |
 +                      (OMAP3430_VOLTSETUP_TIME1 <<
 +                      OMAP3430_SETUP_TIME1_SHIFT),
 +                      OMAP3430_GR_MOD, OMAP3_PRM_VOLTSETUP1_OFFSET);
 +
 +      prm_write_mod_reg(OMAP3430_VOLTOFFSET_DURATION, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_VOLTOFFSET_OFFSET);
 +      prm_write_mod_reg(OMAP3430_VOLTSETUP2_DURATION, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_VOLTSETUP2_OFFSET);
 +#else
 +      prm_set_mod_reg_bits(OMAP3430_AUTO_RET, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_VOLTCTRL_OFFSET);
 +#endif
 +
 +}
 +
 +static int __init omap3_pm_early_init(void)
 +{
 +      prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
 +                              OMAP3_PRM_POLCTRL_OFFSET);
 +
 +      configure_vc();
 +
 +      return 0;
 +}
 +
 +arch_initcall(omap3_pm_early_init);
index 7615f9d2ed7d8f02546842f717fb980ba73a1532,0000000000000000000000000000000000000000..73e2971b17573250e7ba4caaf7f7691b51c66266
mode 100644,000000..100644
--- /dev/null
@@@ -1,1113 -1,0 +1,1113 @@@
- #include <asm/arch/cpu.h>
- #include <asm/arch/powerdomain.h>
- #include <asm/arch/clockdomain.h>
 +/*
 + * OMAP powerdomain control
 + *
 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
 + * Copyright (C) 2007-2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN
 +# define DEBUG
 +#endif
 +
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/types.h>
 +#include <linux/delay.h>
 +#include <linux/spinlock.h>
 +#include <linux/list.h>
 +#include <linux/errno.h>
 +#include <linux/err.h>
 +#include <linux/io.h>
 +
 +#include <asm/atomic.h>
 +
 +#include "cm.h"
 +#include "cm-regbits-34xx.h"
 +#include "prm.h"
 +#include "prm-regbits-34xx.h"
 +
++#include <mach/cpu.h>
++#include <mach/powerdomain.h>
++#include <mach/clockdomain.h>
 +
 +/* pwrdm_list contains all registered struct powerdomains */
 +static LIST_HEAD(pwrdm_list);
 +
 +/*
 + * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
 + * protect pwrdm_clkdms[] during clkdm add/del ops
 + */
 +static DEFINE_RWLOCK(pwrdm_rwlock);
 +
 +
 +/* Private functions */
 +
 +static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
 +{
 +      u32 v;
 +
 +      v = prm_read_mod_reg(domain, idx);
 +      v &= mask;
 +      v >>= __ffs(mask);
 +
 +      return v;
 +}
 +
 +static struct powerdomain *_pwrdm_lookup(const char *name)
 +{
 +      struct powerdomain *pwrdm, *temp_pwrdm;
 +
 +      pwrdm = NULL;
 +
 +      list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
 +              if (!strcmp(name, temp_pwrdm->name)) {
 +                      pwrdm = temp_pwrdm;
 +                      break;
 +              }
 +      }
 +
 +      return pwrdm;
 +}
 +
 +/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
 +static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
 +                                            struct pwrdm_dep *deps)
 +{
 +      struct pwrdm_dep *pd;
 +
 +      if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
 +              return ERR_PTR(-EINVAL);
 +
 +      for (pd = deps; pd; pd++) {
 +
 +              if (!omap_chip_is(pd->omap_chip))
 +                      continue;
 +
 +              if (!pd->pwrdm && pd->pwrdm_name)
 +                      pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
 +
 +              if (pd->pwrdm == pwrdm)
 +                      break;
 +
 +      }
 +
 +      if (!pd)
 +              return ERR_PTR(-ENOENT);
 +
 +      return pd->pwrdm;
 +}
 +
 +
 +/* Public functions */
 +
 +/**
 + * pwrdm_init - set up the powerdomain layer
 + *
 + * Loop through the list of powerdomains, registering all that are
 + * available on the current CPU. If pwrdm_list is supplied and not
 + * null, all of the referenced powerdomains will be registered.  No
 + * return value.
 + */
 +void pwrdm_init(struct powerdomain **pwrdm_list)
 +{
 +      struct powerdomain **p = NULL;
 +
 +      if (pwrdm_list)
 +              for (p = pwrdm_list; *p; p++)
 +                      pwrdm_register(*p);
 +}
 +
 +/**
 + * pwrdm_register - register a powerdomain
 + * @pwrdm: struct powerdomain * to register
 + *
 + * Adds a powerdomain to the internal powerdomain list.  Returns
 + * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
 + * already registered by the provided name, or 0 upon success.
 + */
 +int pwrdm_register(struct powerdomain *pwrdm)
 +{
 +      unsigned long flags;
 +      int ret = -EINVAL;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (!omap_chip_is(pwrdm->omap_chip))
 +              return -EINVAL;
 +
 +      write_lock_irqsave(&pwrdm_rwlock, flags);
 +      if (_pwrdm_lookup(pwrdm->name)) {
 +              ret = -EEXIST;
 +              goto pr_unlock;
 +      }
 +
 +      list_add(&pwrdm->node, &pwrdm_list);
 +
 +      pr_debug("powerdomain: registered %s\n", pwrdm->name);
 +      ret = 0;
 +
 +pr_unlock:
 +      write_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return ret;
 +}
 +
 +/**
 + * pwrdm_unregister - unregister a powerdomain
 + * @pwrdm: struct powerdomain * to unregister
 + *
 + * Removes a powerdomain from the internal powerdomain list.  Returns
 + * -EINVAL if pwrdm argument is NULL.
 + */
 +int pwrdm_unregister(struct powerdomain *pwrdm)
 +{
 +      unsigned long flags;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      write_lock_irqsave(&pwrdm_rwlock, flags);
 +      list_del(&pwrdm->node);
 +      write_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_lookup - look up a powerdomain by name, return a pointer
 + * @name: name of powerdomain
 + *
 + * Find a registered powerdomain by its name.  Returns a pointer to the
 + * struct powerdomain if found, or NULL otherwise.
 + */
 +struct powerdomain *pwrdm_lookup(const char *name)
 +{
 +      struct powerdomain *pwrdm;
 +      unsigned long flags;
 +
 +      if (!name)
 +              return NULL;
 +
 +      read_lock_irqsave(&pwrdm_rwlock, flags);
 +      pwrdm = _pwrdm_lookup(name);
 +      read_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return pwrdm;
 +}
 +
 +/**
 + * pwrdm_for_each - call function on each registered clockdomain
 + * @fn: callback function *
 + *
 + * Call the supplied function for each registered powerdomain.  The
 + * callback function can return anything but 0 to bail out early from
 + * the iterator.  The callback function is called with the pwrdm_rwlock
 + * held for reading, so no powerdomain structure manipulation
 + * functions should be called from the callback, although hardware
 + * powerdomain control functions are fine.  Returns the last return
 + * value of the callback function, which should be 0 for success or
 + * anything else to indicate failure; or -EINVAL if the function
 + * pointer is null.
 + */
 +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
 +{
 +      struct powerdomain *temp_pwrdm;
 +      unsigned long flags;
 +      int ret = 0;
 +
 +      if (!fn)
 +              return -EINVAL;
 +
 +      read_lock_irqsave(&pwrdm_rwlock, flags);
 +      list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
 +              ret = (*fn)(temp_pwrdm);
 +              if (ret)
 +                      break;
 +      }
 +      read_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return ret;
 +}
 +
 +/**
 + * pwrdm_add_clkdm - add a clockdomain to a powerdomain
 + * @pwrdm: struct powerdomain * to add the clockdomain to
 + * @clkdm: struct clockdomain * to associate with a powerdomain
 + *
 + * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'.  This
 + * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
 + * presented with invalid pointers; -ENOMEM if memory could not be allocated;
 + * or 0 upon success.
 + */
 +int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 +{
 +      unsigned long flags;
 +      int i;
 +      int ret = -EINVAL;
 +
 +      if (!pwrdm || !clkdm)
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: associating clockdomain %s with powerdomain "
 +               "%s\n", clkdm->name, pwrdm->name);
 +
 +      write_lock_irqsave(&pwrdm_rwlock, flags);
 +
 +      for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
 +              if (!pwrdm->pwrdm_clkdms[i])
 +                      break;
 +#ifdef DEBUG
 +              if (pwrdm->pwrdm_clkdms[i] == clkdm) {
 +                      ret = -EINVAL;
 +                      goto pac_exit;
 +              }
 +#endif
 +      }
 +
 +      if (i == PWRDM_MAX_CLKDMS) {
 +              pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
 +                       "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
 +              WARN_ON(1);
 +              ret = -ENOMEM;
 +              goto pac_exit;
 +      }
 +
 +      pwrdm->pwrdm_clkdms[i] = clkdm;
 +
 +      ret = 0;
 +
 +pac_exit:
 +      write_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return ret;
 +}
 +
 +/**
 + * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
 + * @pwrdm: struct powerdomain * to add the clockdomain to
 + * @clkdm: struct clockdomain * to associate with a powerdomain
 + *
 + * Dissociate the clockdomain 'clkdm' from the powerdomain
 + * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
 + * -ENOENT if the clkdm was not associated with the powerdomain, or 0
 + * upon success.
 + */
 +int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 +{
 +      unsigned long flags;
 +      int ret = -EINVAL;
 +      int i;
 +
 +      if (!pwrdm || !clkdm)
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
 +               "%s\n", clkdm->name, pwrdm->name);
 +
 +      write_lock_irqsave(&pwrdm_rwlock, flags);
 +
 +      for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
 +              if (pwrdm->pwrdm_clkdms[i] == clkdm)
 +                      break;
 +
 +      if (i == PWRDM_MAX_CLKDMS) {
 +              pr_debug("powerdomain: clkdm %s not associated with pwrdm "
 +                       "%s ?!\n", clkdm->name, pwrdm->name);
 +              ret = -ENOENT;
 +              goto pdc_exit;
 +      }
 +
 +      pwrdm->pwrdm_clkdms[i] = NULL;
 +
 +      ret = 0;
 +
 +pdc_exit:
 +      write_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return ret;
 +}
 +
 +/**
 + * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
 + * @pwrdm: struct powerdomain * to iterate over
 + * @fn: callback function *
 + *
 + * Call the supplied function for each clockdomain in the powerdomain
 + * 'pwrdm'.  The callback function can return anything but 0 to bail
 + * out early from the iterator.  The callback function is called with
 + * the pwrdm_rwlock held for reading, so no powerdomain structure
 + * manipulation functions should be called from the callback, although
 + * hardware powerdomain control functions are fine.  Returns -EINVAL
 + * if presented with invalid pointers; or passes along the last return
 + * value of the callback function, which should be 0 for success or
 + * anything else to indicate failure.
 + */
 +int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 +                       int (*fn)(struct powerdomain *pwrdm,
 +                                 struct clockdomain *clkdm))
 +{
 +      unsigned long flags;
 +      int ret = 0;
 +      int i;
 +
 +      if (!fn)
 +              return -EINVAL;
 +
 +      read_lock_irqsave(&pwrdm_rwlock, flags);
 +
 +      for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
 +              ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
 +
 +      read_unlock_irqrestore(&pwrdm_rwlock, flags);
 +
 +      return ret;
 +}
 +
 +
 +/**
 + * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
 + * @pwrdm1: wake this struct powerdomain * up (dependent)
 + * @pwrdm2: when this struct powerdomain * wakes up (source)
 + *
 + * When the powerdomain represented by pwrdm2 wakes up (due to an
 + * interrupt), wake up pwrdm1.        Implemented in hardware on the OMAP,
 + * this feature is designed to reduce wakeup latency of the dependent
 + * powerdomain.  Returns -EINVAL if presented with invalid powerdomain
 + * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
 + * 0 upon success.
 + */
 +int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear wake up of "
 +                       "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
 +               pwrdm1->name, pwrdm2->name);
 +
 +      prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
 +                           pwrdm1->prcm_offs, PM_WKDEP);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
 + * @pwrdm1: wake this struct powerdomain * up (dependent)
 + * @pwrdm2: when this struct powerdomain * wakes up (source)
 + *
 + * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
 + * wakes up.  Returns -EINVAL if presented with invalid powerdomain
 + * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
 + * 0 upon success.
 + */
 +int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear wake up of "
 +                       "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      pr_debug("powerdomain: hardware will no longer wake up %s after %s "
 +               "wakes up\n", pwrdm1->name, pwrdm2->name);
 +
 +      prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
 +                             pwrdm1->prcm_offs, PM_WKDEP);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
 + * @pwrdm1: wake this struct powerdomain * up (dependent)
 + * @pwrdm2: when this struct powerdomain * wakes up (source)
 + *
 + * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
 + * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
 + * if either powerdomain pointer is invalid; or -ENOENT if the hardware
 + * is incapable.
 + *
 + * REVISIT: Currently this function only represents software-controllable
 + * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
 + * yet handled here.
 + */
 +int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear wake up of "
 +                       "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
 +                                      (1 << pwrdm2->dep_bit));
 +}
 +
 +/**
 + * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
 + * @pwrdm2: when this struct powerdomain * is active (source)
 + *
 + * Prevent pwrdm1 from automatically going inactive (and then to
 + * retention or off) if pwrdm2 is still active.        Returns -EINVAL if
 + * presented with invalid powerdomain pointers or called on a machine
 + * that does not support software-configurable hardware sleep dependencies,
 + * -ENOENT if the specified dependency cannot be set in hardware, or
 + * 0 upon success.
 + */
 +int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      if (!cpu_is_omap34xx())
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear sleep "
 +                       "dependency affecting %s from %s\n", pwrdm1->name,
 +                       pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
 +               pwrdm1->name, pwrdm2->name);
 +
 +      cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
 +                          pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
 + * @pwrdm2: when this struct powerdomain * is active (source)
 + *
 + * Allow pwrdm1 to automatically go inactive (and then to retention or
 + * off), independent of the activity state of pwrdm2.  Returns -EINVAL
 + * if presented with invalid powerdomain pointers or called on a machine
 + * that does not support software-configurable hardware sleep dependencies,
 + * -ENOENT if the specified dependency cannot be cleared in hardware, or
 + * 0 upon success.
 + */
 +int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      if (!cpu_is_omap34xx())
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear sleep "
 +                       "dependency affecting %s from %s\n", pwrdm1->name,
 +                       pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      pr_debug("powerdomain: will no longer prevent %s from sleeping if "
 +               "%s is active\n", pwrdm1->name, pwrdm2->name);
 +
 +      cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
 +                            pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
 + * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
 + * @pwrdm2: when this struct powerdomain * is active (source)
 + *
 + * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
 + * not be allowed to automatically go inactive if pwrdm2 is active;
 + * 0 if pwrdm1's automatic power state inactivity transition is independent
 + * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
 + * on a machine that does not support software-configurable hardware sleep
 + * dependencies; or -ENOENT if the hardware is incapable.
 + *
 + * REVISIT: Currently this function only represents software-controllable
 + * sleep dependencies.        Sleep dependencies fixed in hardware are not
 + * yet handled here.
 + */
 +int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
 +{
 +      struct powerdomain *p;
 +
 +      if (!pwrdm1)
 +              return -EINVAL;
 +
 +      if (!cpu_is_omap34xx())
 +              return -EINVAL;
 +
 +      p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
 +      if (IS_ERR(p)) {
 +              pr_debug("powerdomain: hardware cannot set/clear sleep "
 +                       "dependency affecting %s from %s\n", pwrdm1->name,
 +                       pwrdm2->name);
 +              return IS_ERR(p);
 +      }
 +
 +      return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
 +                                      (1 << pwrdm2->dep_bit));
 +}
 +
 +/**
 + * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
 + * @pwrdm: struct powerdomain *
 + *
 + * Return the number of controllable memory banks in powerdomain pwrdm,
 + * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
 + */
 +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      return pwrdm->banks;
 +}
 +
 +/**
 + * pwrdm_set_next_pwrst - set next powerdomain power state
 + * @pwrdm: struct powerdomain * to set
 + * @pwrst: one of the PWRDM_POWER_* macros
 + *
 + * Set the powerdomain pwrdm's next power state to pwrst.  The powerdomain
 + * may not enter this state immediately if the preconditions for this state
 + * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
 + * null or if the power state is invalid for the powerdomin, or returns 0
 + * upon success.
 + */
 +int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (!(pwrdm->pwrsts & (1 << pwrst)))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 +               pwrdm->name, pwrst);
 +
 +      prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
 +                           (pwrst << OMAP_POWERSTATE_SHIFT),
 +                           pwrdm->prcm_offs, PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_read_next_pwrst - get next powerdomain power state
 + * @pwrdm: struct powerdomain * to get power state
 + *
 + * Return the powerdomain pwrdm's next power state.  Returns -EINVAL
 + * if the powerdomain pointer is null or returns the next power state
 + * upon success.
 + */
 +int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
 +                                      OMAP_POWERSTATE_MASK);
 +}
 +
 +/**
 + * pwrdm_read_pwrst - get current powerdomain power state
 + * @pwrdm: struct powerdomain * to get power state
 + *
 + * Return the powerdomain pwrdm's current power state.        Returns -EINVAL
 + * if the powerdomain pointer is null or returns the current power state
 + * upon success.
 + */
 +int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
 +                                      OMAP_POWERSTATEST_MASK);
 +}
 +
 +/**
 + * pwrdm_read_prev_pwrst - get previous powerdomain power state
 + * @pwrdm: struct powerdomain * to get previous power state
 + *
 + * Return the powerdomain pwrdm's previous power state.  Returns -EINVAL
 + * if the powerdomain pointer is null or returns the previous power state
 + * upon success.
 + */
 +int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
 +                                      OMAP3430_LASTPOWERSTATEENTERED_MASK);
 +}
 +
 +/**
 + * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
 + * @pwrdm: struct powerdomain * to set
 + * @pwrst: one of the PWRDM_POWER_* macros
 + *
 + * Set the next power state that the logic portion of the powerdomain
 + * pwrdm will enter when the powerdomain enters retention.  This will
 + * be either RETENTION or OFF, if supported.  Returns -EINVAL if the
 + * powerdomain pointer is null or the target power state is not not
 + * supported, or returns 0 upon success.
 + */
 +int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
 +               pwrdm->name, pwrst);
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
 +                           (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
 +                           pwrdm->prcm_offs, PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_set_mem_onst - set memory power state while powerdomain ON
 + * @pwrdm: struct powerdomain * to set
 + * @bank: memory bank number to set (0-3)
 + * @pwrst: one of the PWRDM_POWER_* macros
 + *
 + * Set the next power state that memory bank x of the powerdomain
 + * pwrdm will enter when the powerdomain enters the ON state.  Bank
 + * will be a number from 0 to 3, and represents different types of
 + * memory, depending on the powerdomain.  Returns -EINVAL if the
 + * powerdomain pointer is null or the target power state is not not
 + * supported for this memory bank, -EEXIST if the target memory bank
 + * does not exist or is not controllable, or returns 0 upon success.
 + */
 +int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 +{
 +      u32 m;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (pwrdm->banks < (bank + 1))
 +              return -EEXIST;
 +
 +      if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: setting next memory powerstate for domain %s "
 +               "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      switch (bank) {
 +      case 0:
 +              m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
 +              break;
 +      case 1:
 +              m = OMAP3430_L1FLATMEMONSTATE_MASK;
 +              break;
 +      case 2:
 +              m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
 +              break;
 +      case 3:
 +              m = OMAP3430_L2FLATMEMONSTATE_MASK;
 +              break;
 +      default:
 +              WARN_ON(1); /* should never happen */
 +              return -EEXIST;
 +      }
 +
 +      prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
 +                           pwrdm->prcm_offs, PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
 + * @pwrdm: struct powerdomain * to set
 + * @bank: memory bank number to set (0-3)
 + * @pwrst: one of the PWRDM_POWER_* macros
 + *
 + * Set the next power state that memory bank x of the powerdomain
 + * pwrdm will enter when the powerdomain enters the RETENTION state.
 + * Bank will be a number from 0 to 3, and represents different types
 + * of memory, depending on the powerdomain.  pwrst will be either
 + * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
 + * pointer is null or the target power state is not not supported for
 + * this memory bank, -EEXIST if the target memory bank does not exist
 + * or is not controllable, or returns 0 upon success.
 + */
 +int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 +{
 +      u32 m;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (pwrdm->banks < (bank + 1))
 +              return -EEXIST;
 +
 +      if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: setting next memory powerstate for domain %s "
 +               "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      switch (bank) {
 +      case 0:
 +              m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
 +              break;
 +      case 1:
 +              m = OMAP3430_L1FLATMEMRETSTATE;
 +              break;
 +      case 2:
 +              m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
 +              break;
 +      case 3:
 +              m = OMAP3430_L2FLATMEMRETSTATE;
 +              break;
 +      default:
 +              WARN_ON(1); /* should never happen */
 +              return -EEXIST;
 +      }
 +
 +      prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
 +                           PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
 + * @pwrdm: struct powerdomain * to get current logic retention power state
 + *
 + * Return the current power state that the logic portion of
 + * powerdomain pwrdm will enter
 + * Returns -EINVAL if the powerdomain pointer is null or returns the
 + * current logic retention power state upon success.
 + */
 +int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
 +                                      OMAP3430_LOGICSTATEST);
 +}
 +
 +/**
 + * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
 + * @pwrdm: struct powerdomain * to get previous logic power state
 + *
 + * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
 + * if the powerdomain pointer is null or returns the previous logic
 + * power state upon success.
 + */
 +int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
 +                                      OMAP3430_LASTLOGICSTATEENTERED);
 +}
 +
 +/**
 + * pwrdm_read_mem_pwrst - get current memory bank power state
 + * @pwrdm: struct powerdomain * to get current memory bank power state
 + * @bank: memory bank number (0-3)
 + *
 + * Return the powerdomain pwrdm's current memory power state for bank
 + * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
 + * the target memory bank does not exist or is not controllable, or
 + * returns the current memory power state upon success.
 + */
 +int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 +{
 +      u32 m;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (pwrdm->banks < (bank + 1))
 +              return -EEXIST;
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      switch (bank) {
 +      case 0:
 +              m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
 +              break;
 +      case 1:
 +              m = OMAP3430_L1FLATMEMSTATEST_MASK;
 +              break;
 +      case 2:
 +              m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
 +              break;
 +      case 3:
 +              m = OMAP3430_L2FLATMEMSTATEST_MASK;
 +              break;
 +      default:
 +              WARN_ON(1); /* should never happen */
 +              return -EEXIST;
 +      }
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
 +}
 +
 +/**
 + * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
 + * @pwrdm: struct powerdomain * to get previous memory bank power state
 + * @bank: memory bank number (0-3)
 + *
 + * Return the powerdomain pwrdm's previous memory power state for bank
 + * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
 + * the target memory bank does not exist or is not controllable, or
 + * returns the previous memory power state upon success.
 + */
 +int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 +{
 +      u32 m;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (pwrdm->banks < (bank + 1))
 +              return -EEXIST;
 +
 +      /*
 +       * The register bit names below may not correspond to the
 +       * actual names of the bits in each powerdomain's register,
 +       * but the type of value returned is the same for each
 +       * powerdomain.
 +       */
 +      switch (bank) {
 +      case 0:
 +              m = OMAP3430_LASTMEM1STATEENTERED_MASK;
 +              break;
 +      case 1:
 +              m = OMAP3430_LASTMEM2STATEENTERED_MASK;
 +              break;
 +      case 2:
 +              m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
 +              break;
 +      case 3:
 +              m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
 +              break;
 +      default:
 +              WARN_ON(1); /* should never happen */
 +              return -EEXIST;
 +      }
 +
 +      return prm_read_mod_bits_shift(pwrdm->prcm_offs,
 +                                      OMAP3430_PM_PREPWSTST, m);
 +}
 +
 +/**
 + * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
 + * @pwrdm: struct powerdomain * to clear
 + *
 + * Clear the powerdomain's previous power state register.  Clears the
 + * entire register, including logic and memory bank previous power states.
 + * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
 + * success.
 + */
 +int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      /*
 +       * XXX should get the powerdomain's current state here;
 +       * warn & fail if it is not ON.
 +       */
 +
 +      pr_debug("powerdomain: clearing previous power state reg for %s\n",
 +               pwrdm->name);
 +
 +      prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
 + * @pwrdm: struct powerdomain *
 + *
 + * Enable automatic context save-and-restore upon power state change
 + * for some devices in a powerdomain.  Warning: this only affects a
 + * subset of devices in a powerdomain; check the TRM closely.  Returns
 + * -EINVAL if the powerdomain pointer is null or if the powerdomain
 + * does not support automatic save-and-restore, or returns 0 upon
 + * success.
 + */
 +int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
 +               pwrdm->name);
 +
 +      prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
 +                           pwrdm->prcm_offs, PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
 + * @pwrdm: struct powerdomain *
 + *
 + * Disable automatic context save-and-restore upon power state change
 + * for some devices in a powerdomain.  Warning: this only affects a
 + * subset of devices in a powerdomain; check the TRM closely.  Returns
 + * -EINVAL if the powerdomain pointer is null or if the powerdomain
 + * does not support automatic save-and-restore, or returns 0 upon
 + * success.
 + */
 +int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 +{
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 +              return -EINVAL;
 +
 +      pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
 +               pwrdm->name);
 +
 +      prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
 +                           pwrdm->prcm_offs, PM_PWSTCTRL);
 +
 +      return 0;
 +}
 +
 +/**
 + * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
 + * @pwrdm: struct powerdomain *
 + *
 + * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
 + * for some devices, or 0 if it does not.
 + */
 +bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
 +{
 +      return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 +}
 +
 +/**
 + * pwrdm_wait_transition - wait for powerdomain power transition to finish
 + * @pwrdm: struct powerdomain * to wait for
 + *
 + * If the powerdomain pwrdm is in the process of a state transition,
 + * spin until it completes the power transition, or until an iteration
 + * bailout value is reached. Returns -EINVAL if the powerdomain
 + * pointer is null, -EAGAIN if the bailout value was reached, or
 + * returns 0 upon success.
 + */
 +int pwrdm_wait_transition(struct powerdomain *pwrdm)
 +{
 +      u32 c = 0;
 +
 +      if (!pwrdm)
 +              return -EINVAL;
 +
 +      /*
 +       * REVISIT: pwrdm_wait_transition() may be better implemented
 +       * via a callback and a periodic timer check -- how long do we expect
 +       * powerdomain transitions to take?
 +       */
 +
 +      /* XXX Is this udelay() value meaningful? */
 +      while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
 +              OMAP_INTRANSITION) &&
 +             (c++ < PWRDM_TRANSITION_BAILOUT))
 +              udelay(1);
 +
 +      if (c >= PWRDM_TRANSITION_BAILOUT) {
 +              printk(KERN_ERR "powerdomain: waited too long for "
 +                     "powerdomain %s to complete transition\n", pwrdm->name);
 +              return -EAGAIN;
 +      }
 +
 +      pr_debug("powerdomain: completed transition in %d loops\n", c);
 +
 +      return 0;
 +}
 +
 +
index 315281148c01ab07cbb3b072c025e471debb75fa,0000000000000000000000000000000000000000..fba34406e6500f15882bf1066c1111fc3ed5547f
mode 100644,000000..100644
--- /dev/null
@@@ -1,188 -1,0 +1,188 @@@
- #include <asm/arch/powerdomain.h>
 +/*
 + * OMAP2/3 common powerdomain definitions
 + *
 + * Copyright (C) 2007-8 Texas Instruments, Inc.
 + * Copyright (C) 2007-8 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + * Debugging and integration fixes by Jouni Högander
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS
 +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS
 +
 +/*
 + * This file contains all of the powerdomains that have some element
 + * of software control for the OMAP24xx and OMAP34XX chips.
 + *
 + * A few notes:
 + *
 + * This is not an exhaustive listing of powerdomains on the chips; only
 + * powerdomains that can be controlled in software.
 + *
 + * A useful validation rule for struct powerdomain:
 + * Any powerdomain referenced by a wkdep_srcs or sleepdep_srcs array
 + * must have a dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really
 + * just software-controllable dependencies.  Non-software-controllable
 + * dependencies do exist, but they are not encoded below (yet).
 + *
 + * 24xx does not support programmable sleep dependencies (SLEEPDEP)
 + *
 + */
 +
 +/*
 + * The names for the DSP/IVA2 powerdomains are confusing.
 + *
 + * Most OMAP chips have an on-board DSP.
 + *
 + * On the 2420, this is a 'C55 DSP called, simply, the DSP.  Its
 + * powerdomain is called the "DSP power domain."  On the 2430, the
 + * on-board DSP is a 'C64 DSP, now called the IVA2 or IVA2.1.  Its
 + * powerdomain is still called the "DSP power domain."        On the 3430,
 + * the DSP is a 'C64 DSP like the 2430, also known as the IVA2; but
 + * its powerdomain is now called the "IVA2 power domain."
 + *
 + * The 2420 also has something called the IVA, which is a separate ARM
 + * core, and has nothing to do with the DSP/IVA2.
 + *
 + * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
 + * address offset is different between the C55 and C64 DSPs.
 + *
 + * The overly-specific dep_bit names are due to a bit name collision
 + * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
 + * value are the same for all powerdomains: 2
 + */
 +
 +/*
 + * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
 + * sanity check?
 + * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
 + */
 +
++#include <mach/powerdomain.h>
 +
 +#include "prcm-common.h"
 +#include "prm.h"
 +#include "cm.h"
 +
 +/* OMAP2/3-common powerdomains and wakeup dependencies */
 +
 +/*
 + * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
 + * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
 + * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
 + */
 +static struct pwrdm_dep gfx_sgx_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "iva2_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 +                                          CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 +                                          CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +/*
 + * 3430: CM_SLEEPDEP_CAM: MPU
 + * 3430ES1: CM_SLEEPDEP_GFX: MPU
 + * 3430ES2: CM_SLEEPDEP_SGX: MPU
 + */
 +static struct pwrdm_dep cam_gfx_sleepdeps[] = {
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +
 +#include "powerdomains24xx.h"
 +#include "powerdomains34xx.h"
 +
 +
 +/*
 + * OMAP2/3 common powerdomains
 + */
 +
 +/*
 + * The GFX powerdomain is not present on 3430ES2, but currently we do not
 + * have a macro to filter it out at compile-time.
 + */
 +static struct powerdomain gfx_pwrdm = {
 +      .name             = "gfx_pwrdm",
 +      .prcm_offs        = GFX_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 +                                         CHIP_IS_OMAP3430ES1),
 +      .wkdep_srcs       = gfx_sgx_wkdeps,
 +      .sleepdep_srcs    = cam_gfx_sleepdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +static struct powerdomain wkup_pwrdm = {
 +      .name           = "wkup_pwrdm",
 +      .prcm_offs      = WKUP_MOD,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 +      .dep_bit        = OMAP_EN_WKUP_SHIFT,
 +};
 +
 +
 +
 +/* As powerdomains are added or removed above, this list must also be changed */
 +static struct powerdomain *powerdomains_omap[] __initdata = {
 +
 +      &gfx_pwrdm,
 +      &wkup_pwrdm,
 +
 +#ifdef CONFIG_ARCH_OMAP24XX
 +      &dsp_pwrdm,
 +      &mpu_24xx_pwrdm,
 +      &core_24xx_pwrdm,
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP2430
 +      &mdm_pwrdm,
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP34XX
 +      &iva2_pwrdm,
 +      &mpu_34xx_pwrdm,
 +      &neon_pwrdm,
 +      &core_34xx_es1_pwrdm,
 +      &core_34xx_es2_pwrdm,
 +      &cam_pwrdm,
 +      &dss_pwrdm,
 +      &per_pwrdm,
 +      &emu_pwrdm,
 +      &sgx_pwrdm,
 +      &usbhost_pwrdm,
 +#endif
 +
 +      NULL
 +};
 +
 +
 +#endif
index 6f97c91b2347f046a3cc9630e3857a22ab66b665,0000000000000000000000000000000000000000..9f08dc3f7fd2e8bef3704d25fd9ca664bff57e44
mode 100644,000000..100644
--- /dev/null
@@@ -1,200 -1,0 +1,200 @@@
- #include <asm/arch/powerdomain.h>
 +/*
 + * OMAP24XX powerdomain definitions
 + *
 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
 + * Copyright (C) 2007-2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + * Debugging and integration fixes by Jouni Högander
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX
 +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX
 +
 +/*
 + * N.B. If powerdomains are added or removed from this file, update
 + * the array in mach-omap2/powerdomains.h.
 + */
 +
++#include <mach/powerdomain.h>
 +
 +#include "prcm-common.h"
 +#include "prm.h"
 +#include "prm-regbits-24xx.h"
 +#include "cm.h"
 +#include "cm-regbits-24xx.h"
 +
 +/* 24XX powerdomains and dependencies */
 +
 +#ifdef CONFIG_ARCH_OMAP24XX
 +
 +
 +/* Wakeup dependency source arrays */
 +
 +/*
 + * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
 + * 2430 PM_WKDEP_MDM: same as above
 + */
 +static struct pwrdm_dep dsp_mdm_24xx_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      { NULL },
 +};
 +
 +/*
 + * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
 + * 2430 adds MDM
 + */
 +static struct pwrdm_dep mpu_24xx_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "dsp_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "mdm_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 +      },
 +      { NULL },
 +};
 +
 +/*
 + * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
 + * 2430 adds MDM
 + */
 +static struct pwrdm_dep core_24xx_wkdeps[] = {
 +      {
 +              .pwrdm_name = "dsp_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "gfx_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 +      },
 +      {
 +              .pwrdm_name = "mdm_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 +      },
 +      { NULL },
 +};
 +
 +
 +/* Powerdomains */
 +
 +static struct powerdomain dsp_pwrdm = {
 +      .name             = "dsp_pwrdm",
 +      .prcm_offs        = OMAP24XX_DSP_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +      .dep_bit          = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
 +      .wkdep_srcs       = dsp_mdm_24xx_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET,
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,
 +      },
 +};
 +
 +static struct powerdomain mpu_24xx_pwrdm = {
 +      .name             = "mpu_pwrdm",
 +      .prcm_offs        = MPU_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +      .dep_bit          = OMAP24XX_EN_MPU_SHIFT,
 +      .wkdep_srcs       = mpu_24xx_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRSTS_OFF_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET,
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,
 +      },
 +};
 +
 +static struct powerdomain core_24xx_pwrdm = {
 +      .name             = "core_pwrdm",
 +      .prcm_offs        = CORE_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 +      .wkdep_srcs       = core_24xx_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .dep_bit          = OMAP24XX_EN_CORE_SHIFT,
 +      .banks            = 3,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRSTS_OFF_RET,    /* MEM1RETSTATE */
 +              [1] = PWRSTS_OFF_RET,    /* MEM2RETSTATE */
 +              [2] = PWRSTS_OFF_RET,    /* MEM3RETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 +              [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 +              [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 +      },
 +};
 +
 +#endif           /* CONFIG_ARCH_OMAP24XX */
 +
 +
 +
 +/*
 + * 2430-specific powerdomains
 + */
 +
 +#ifdef CONFIG_ARCH_OMAP2430
 +
 +/* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 +
 +/* Another case of bit name collisions between several registers: EN_MDM */
 +static struct powerdomain mdm_pwrdm = {
 +      .name             = "mdm_pwrdm",
 +      .prcm_offs        = OMAP2430_MDM_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 +      .dep_bit          = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
 +      .wkdep_srcs       = dsp_mdm_24xx_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +#endif     /* CONFIG_ARCH_OMAP2430 */
 +
 +
 +#endif
index 0c07bf75715b380b4aea4756d0e2b0f484d66d86,0000000000000000000000000000000000000000..adbfa9187a6c715c555ee7b3fe4f57c94f07e013
mode 100644,000000..100644
--- /dev/null
@@@ -1,347 -1,0 +1,347 @@@
- #include <asm/arch/powerdomain.h>
 +/*
 + * OMAP34XX powerdomain definitions
 + *
 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
 + * Copyright (C) 2007-2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + * Debugging and integration fixes by Jouni Högander
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX
 +#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX
 +
 +/*
 + * N.B. If powerdomains are added or removed from this file, update
 + * the array in mach-omap2/powerdomains.h.
 + */
 +
++#include <mach/powerdomain.h>
 +
 +#include "prcm-common.h"
 +#include "prm.h"
 +#include "prm-regbits-34xx.h"
 +#include "cm.h"
 +#include "cm-regbits-34xx.h"
 +
 +/*
 + * 34XX-specific powerdomains, dependencies
 + */
 +
 +#ifdef CONFIG_ARCH_OMAP34XX
 +
 +/*
 + * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
 + * (USBHOST is ES2 only)
 + */
 +static struct pwrdm_dep per_usbhost_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "iva2_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +/*
 + * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
 + */
 +static struct pwrdm_dep mpu_34xx_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "iva2_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "dss_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "per_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +/*
 + * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
 + */
 +static struct pwrdm_dep iva2_wkdeps[] = {
 +      {
 +              .pwrdm_name = "core_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "dss_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "per_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +
 +/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
 +static struct pwrdm_dep cam_dss_wkdeps[] = {
 +      {
 +              .pwrdm_name = "iva2_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "wkup_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +/* 3430: PM_WKDEP_NEON: MPU */
 +static struct pwrdm_dep neon_wkdeps[] = {
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +
 +/* Sleep dependency source arrays for 34xx-specific pwrdms - 34XX only */
 +
 +/*
 + * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
 + * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
 + */
 +static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = {
 +      {
 +              .pwrdm_name = "mpu_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      {
 +              .pwrdm_name = "iva2_pwrdm",
 +              .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 +      },
 +      { NULL },
 +};
 +
 +
 +/*
 + * Powerdomains
 + */
 +
 +static struct powerdomain iva2_pwrdm = {
 +      .name             = "iva2_pwrdm",
 +      .prcm_offs        = OMAP3430_IVA2_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .dep_bit          = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
 +      .wkdep_srcs       = iva2_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRSTS_OFF_RET,
 +      .banks            = 4,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRSTS_OFF_RET,
 +              [1] = PWRSTS_OFF_RET,
 +              [2] = PWRSTS_OFF_RET,
 +              [3] = PWRSTS_OFF_RET,
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,
 +              [1] = PWRDM_POWER_ON,
 +              [2] = PWRSTS_OFF_ON,
 +              [3] = PWRDM_POWER_ON,
 +      },
 +};
 +
 +static struct powerdomain mpu_34xx_pwrdm = {
 +      .name             = "mpu_pwrdm",
 +      .prcm_offs        = MPU_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .dep_bit          = OMAP3430_EN_MPU_SHIFT,
 +      .wkdep_srcs       = mpu_34xx_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRSTS_OFF_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRSTS_OFF_RET,
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRSTS_OFF_ON,
 +      },
 +};
 +
 +/* No wkdeps or sleepdeps for 34xx core apparently */
 +static struct powerdomain core_34xx_es1_pwrdm = {
 +      .name             = "core_pwrdm",
 +      .prcm_offs        = CORE_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .dep_bit          = OMAP3430_EN_CORE_SHIFT,
 +      .banks            = 2,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRSTS_OFF_RET,    /* MEM1RETSTATE */
 +              [1] = PWRSTS_OFF_RET,    /* MEM2RETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 +              [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 +      },
 +};
 +
 +/* No wkdeps or sleepdeps for 34xx core apparently */
 +static struct powerdomain core_34xx_es2_pwrdm = {
 +      .name             = "core_pwrdm",
 +      .prcm_offs        = CORE_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .dep_bit          = OMAP3430_EN_CORE_SHIFT,
 +      .flags            = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
 +      .banks            = 2,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRSTS_OFF_RET,    /* MEM1RETSTATE */
 +              [1] = PWRSTS_OFF_RET,    /* MEM2RETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 +              [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 +      },
 +};
 +
 +/* Another case of bit name collisions between several registers: EN_DSS */
 +static struct powerdomain dss_pwrdm = {
 +      .name             = "dss_pwrdm",
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .prcm_offs        = OMAP3430_DSS_MOD,
 +      .dep_bit          = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
 +      .wkdep_srcs       = cam_dss_wkdeps,
 +      .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +static struct powerdomain sgx_pwrdm = {
 +      .name             = "sgx_pwrdm",
 +      .prcm_offs        = OMAP3430ES2_SGX_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
 +      .wkdep_srcs       = gfx_sgx_wkdeps,
 +      .sleepdep_srcs    = cam_gfx_sleepdeps,
 +      /* XXX This is accurate for 3430 SGX, but what about GFX? */
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +static struct powerdomain cam_pwrdm = {
 +      .name             = "cam_pwrdm",
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .prcm_offs        = OMAP3430_CAM_MOD,
 +      .wkdep_srcs       = cam_dss_wkdeps,
 +      .sleepdep_srcs    = cam_gfx_sleepdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +static struct powerdomain per_pwrdm = {
 +      .name             = "per_pwrdm",
 +      .prcm_offs        = OMAP3430_PER_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .dep_bit          = OMAP3430_EN_PER_SHIFT,
 +      .wkdep_srcs       = per_usbhost_wkdeps,
 +      .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRSTS_OFF_RET,
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +static struct powerdomain emu_pwrdm = {
 +      .name           = "emu_pwrdm",
 +      .prcm_offs      = OMAP3430_EMU_MOD,
 +      .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +};
 +
 +static struct powerdomain neon_pwrdm = {
 +      .name             = "neon_pwrdm",
 +      .prcm_offs        = OMAP3430_NEON_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 +      .wkdep_srcs       = neon_wkdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +};
 +
 +static struct powerdomain usbhost_pwrdm = {
 +      .name             = "usbhost_pwrdm",
 +      .prcm_offs        = OMAP3430ES2_USBHOST_MOD,
 +      .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
 +      .wkdep_srcs       = per_usbhost_wkdeps,
 +      .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
 +      .pwrsts           = PWRSTS_OFF_RET_ON,
 +      .pwrsts_logic_ret = PWRDM_POWER_RET,
 +      .flags            = PWRDM_HAS_HDWR_SAR, /* for USBHOST ctrlr only */
 +      .banks            = 1,
 +      .pwrsts_mem_ret   = {
 +              [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
 +      },
 +      .pwrsts_mem_on    = {
 +              [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
 +      },
 +};
 +
 +#endif    /* CONFIG_ARCH_OMAP34XX */
 +
 +
 +#endif
index d7c41939604dac39fd43431eaff1303bc9a45eb3,0000000000000000000000000000000000000000..ef35415ca89fa8847e4012a66566e6629ad87620
mode 100644,000000..100644
--- /dev/null
@@@ -1,55 -1,0 +1,55 @@@
- #include <asm/arch/sdrc.h>
 +/*
 + * SDRC register values for the Micron MT46H32M32LF-6
 + *
 + * Copyright (C) 2008 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Paul Walmsley
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
 +#define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
 +
++#include <mach/sdrc.h>
 +
 +/* Micron MT46H32M32LF-6 */
 +/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */
 +static struct omap_sdrc_params mt46h32m32lf6_sdrc_params[] = {
 +      [0] = {
 +              .rate        = 165941176,
 +              .actim_ctrla = 0x9a9db4c6,
 +              .actim_ctrlb = 0x00011217,
 +              .rfr_ctrl    = 0x0004dc01,
 +              .mr          = 0x00000032,
 +      },
 +      [1] = {
 +              .rate        = 133333333,
 +              .actim_ctrla = 0x7a19b485,
 +              .actim_ctrlb = 0x00011213,
 +              .rfr_ctrl    = 0x0003de01,
 +              .mr          = 0x00000032,
 +      },
 +      [2] = {
 +              .rate        = 82970588,
 +              .actim_ctrla = 0x51512283,
 +              .actim_ctrlb = 0x0001120c,
 +              .rfr_ctrl    = 0x00025501,
 +              .mr          = 0x00000032,
 +      },
 +      [3] = {
 +              .rate        = 66666666,
 +              .actim_ctrla = 0x410d2243,
 +              .actim_ctrlb = 0x0001120a,
 +              .rfr_ctrl    = 0x0001d601,
 +              .mr          = 0x00000032,
 +      },
 +      [4] = {
 +              .rate        = 0
 +      },
 +};
 +
 +#endif
index c932a6d2eb9def16a655a1d52d96cb6115608b78,0000000000000000000000000000000000000000..74a92c862e63f35148d4e8a5e0494b32fb242565
mode 100644,000000..100644
--- /dev/null
@@@ -1,55 -1,0 +1,55 @@@
- #include <asm/arch/sdrc.h>
 +/*
 + * SDRC register values for the Qimonda HYB18M512160AF-6
 + *
 + * Copyright (C) 2008 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Paul Walmsley
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
 +#define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
 +
++#include <mach/sdrc.h>
 +
 +/* Qimonda HYB18M512160AF-6 */
 +/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */
 +static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = {
 +      [0] = {
 +              .rate        = 165941176,
 +              .actim_ctrla = 0x629db4c6,
 +              .actim_ctrlb = 0x00012214,
 +              .rfr_ctrl    = 0x0004dc01,
 +              .mr          = 0x00000032,
 +      },
 +      [1] = {
 +              .rate        = 133333333,
 +              .actim_ctrla = 0x5219b485,
 +              .actim_ctrlb = 0x00012210,
 +              .rfr_ctrl    = 0x0003de01,
 +              .mr          = 0x00000032,
 +      },
 +      [2] = {
 +              .rate        = 82970588,
 +              .actim_ctrla = 0x31512283,
 +              .actim_ctrlb = 0x0001220a,
 +              .rfr_ctrl    = 0x00025501,
 +              .mr          = 0x00000022,
 +      },
 +      [3] = {
 +              .rate        = 66666666,
 +              .actim_ctrla = 0x290d2243,
 +              .actim_ctrlb = 0x00012208,
 +              .rfr_ctrl    = 0x0001d601,
 +              .mr          = 0x00000022,
 +      },
 +      [4] = {
 +              .rate        = 0
 +      },
 +};
 +
 +#endif
index 7c2e36cf516a0f0e26bfe9a9ae49436803f8a624,0000000000000000000000000000000000000000..2a30060cb4b78ec897bb668b31c665c26c160827
mode 100644,000000..100644
--- /dev/null
@@@ -1,93 -1,0 +1,93 @@@
- #include <asm/arch/common.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/sram.h>
 +/*
 + * SMS/SDRC (SDRAM controller) common code for OMAP2/3
 + *
 + * Copyright (C) 2005, 2008 Texas Instruments Inc.
 + * Copyright (C) 2005, 2008 Nokia Corporation
 + *
 + * Tony Lindgren <tony@atomide.com>
 + * Paul Walmsley
 + * Richard Woodruff <r-woodruff2@ti.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#undef DEBUG
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/device.h>
 +#include <linux/list.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +
- #include <asm/arch/sdrc.h>
++#include <mach/common.h>
++#include <mach/clock.h>
++#include <mach/sram.h>
 +
 +#include "prm.h"
 +
++#include <mach/sdrc.h>
 +#include "sdrc.h"
 +
 +static struct omap_sdrc_params *sdrc_init_params;
 +
 +void __iomem *omap2_sdrc_base;
 +void __iomem *omap2_sms_base;
 +
 +
 +/**
 + * omap2_sdrc_get_params - return SDRC register values for a given clock rate
 + * @r: SDRC clock rate (in Hz)
 + *
 + * Return pre-calculated values for the SDRC_ACTIM_CTRLA,
 + * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given
 + * SDRC clock rate 'r'.  These parameters control various timing
 + * delays in the SDRAM controller that are expressed in terms of the
 + * number of SDRC clock cycles to wait; hence the clock rate
 + * dependency. Note that sdrc_init_params must be sorted rate
 + * descending.  Also assumes that both chip-selects use the same
 + * timing parameters.  Returns a struct omap_sdrc_params * upon
 + * success, or NULL upon failure.
 + */
 +struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
 +{
 +      struct omap_sdrc_params *sp;
 +
 +      sp = sdrc_init_params;
 +
 +      while (sp->rate != r)
 +              sp++;
 +
 +      if (!sp->rate)
 +              return NULL;
 +
 +      return sp;
 +}
 +
 +
 +void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 +{
 +      omap2_sdrc_base = omap2_globals->sdrc;
 +      omap2_sms_base = omap2_globals->sms;
 +}
 +
 +/* turn on smart idle modes for SDRAM scheduler and controller */
 +void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
 +{
 +      u32 l;
 +
 +      l = sms_read_reg(SMS_SYSCONFIG);
 +      l &= ~(0x3 << 3);
 +      l |= (0x2 << 3);
 +      sms_write_reg(l, SMS_SYSCONFIG);
 +
 +      l = sdrc_read_reg(SDRC_SYSCONFIG);
 +      l &= ~(0x3 << 3);
 +      l |= (0x2 << 3);
 +      sdrc_write_reg(l, SDRC_SYSCONFIG);
 +
 +      sdrc_init_params = sp;
 +}
index e98da5c4785019063bd2a8081f6633c63edd78b0,6b49cc9cbdcbcb31a03e674524cd27eb26e4139e..0723e59b587f95eddb4aebeceb7925504ae4e18e
  #include <linux/errno.h>
  #include <linux/delay.h>
  #include <linux/clk.h>
 -
 -#include <asm/io.h>
 +#include <linux/io.h>
  
- #include <asm/arch/common.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/sram.h>
+ #include <mach/common.h>
+ #include <mach/clock.h>
+ #include <mach/sram.h>
  
  #include "prm.h"
  
- #include <asm/arch/sdrc.h>
 -#include "memory.h"
++#include <mach/sdrc.h>
  #include "sdrc.h"
  
 -void __iomem *omap2_sdrc_base;
 -void __iomem *omap2_sms_base;
 +/* Memory timing, DLL mode flags */
 +#define M_DDR         1
 +#define M_LOCK_CTRL   (1 << 2)
 +#define M_UNLOCK      0
 +#define M_LOCK                1
 +
  
  static struct memory_timings mem_timings;
  static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
index b0fa582f3078a7b9e65e3429f5d9b9b08e4a2b08,adc8a26a8fb01757ee6f18ced5104ac9db1edaa8..d9fca6f343ffb31aa449f03711a0da1df8f5bb10
  #include <linux/serial_reg.h>
  #include <linux/clk.h>
  
 -#include <asm/io.h>
 +#include <linux/io.h>
  
- #include <asm/arch/common.h>
- #include <asm/arch/board.h>
+ #include <mach/common.h>
+ #include <mach/board.h>
  
 -static struct clk * uart1_ick = NULL;
 -static struct clk * uart1_fck = NULL;
 -static struct clk * uart2_ick = NULL;
 -static struct clk * uart2_fck = NULL;
 -static struct clk * uart3_ick = NULL;
 -static struct clk * uart3_fck = NULL;
 +static struct clk *uart_ick[OMAP_MAX_NR_PORTS];
 +static struct clk *uart_fck[OMAP_MAX_NR_PORTS];
  
  static struct plat_serial8250_port serial_platform_data[] = {
        {
index 33bdd019f3385866198046591bca4aaf3f588535,87a706fd5f8214f13fb1c9894f9f344161b6a3ed..5e38ab7822bc72ac5bfb764ed9f98dec83a5b92f
  
  #include <linux/linkage.h>
  #include <asm/assembler.h>
- #include <asm/arch/io.h>
- #include <asm/arch/pm.h>
+ #include <mach/io.h>
+ #include <mach/pm.h>
  
- #include <asm/arch/omap24xx.h>
++#include <mach/omap24xx.h>
 +
  #include "sdrc.h"
  
  /* First address of reserved address space?  apparently valid for OMAP2 & 3 */
index 9a2b4b7ff43d20df50d0cbc2a77821f5b1a68dcd,0000000000000000000000000000000000000000..e39ab5561777dddaee1677cf58974fb8436f5721
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,131 @@@
- #include <asm/arch/io.h>
- #include <asm/arch/pm.h>
 +/*
 + * linux/arch/arm/mach-omap2/sleep.S
 + *
 + * (C) Copyright 2004
 + * Texas Instruments, <www.ti.com>
 + * Richard Woodruff <r-woodruff2@ti.com>
 + *
 + * (C) Copyright 2006 Nokia Corporation
 + * Fixed idle loop sleep
 + * Igor Stoppa <igor.stoppa@nokia.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/linkage.h>
 +#include <asm/assembler.h>
- #include <asm/arch/omap24xx.h>
++#include <mach/io.h>
++#include <mach/pm.h>
 +
++#include <mach/omap24xx.h>
 +
 +#include "sdrc.h"
 +
 +/* First address of reserved address space?  apparently valid for OMAP2 & 3 */
 +#define A_SDRC0_V             (0xC0000000)
 +
 +      .text
 +
 +/*
 + * Forces OMAP into idle state
 + *
 + * omap243x_idle_loop_suspend() - This bit of code just executes the WFI
 + * for normal idles.
 + *
 + * Note: This code get's copied to internal SRAM at boot. When the OMAP
 + *     wakes up it continues execution at the point it went to sleep.
 + */
 +ENTRY(omap243x_idle_loop_suspend)
 +      stmfd   sp!, {r0, lr}           @ save registers on stack
 +      mov     r0, #0x0                @ clear for mrc call
 +      mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
 +      ldmfd   sp!, {r0, pc}           @ restore regs and return
 +
 +ENTRY(omap243x_idle_loop_suspend_sz)
 +      .word   . - omap243x_idle_loop_suspend
 +
 +/*
 + * omap243x_cpu_suspend() - Forces OMAP into deep sleep state by completing
 + * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
 + * SDRC.
 + *
 + * Input:
 + * R0 :       DLL ctrl value pre-Sleep
 + *
 + * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
 + * when we get called, but the DLL probably isn't.  We will wait a bit more in
 + * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
 + * if in unlocked mode.
 + *
 + * For less than 242x-ES2.2 upon wake from a sleep mode where the external
 + * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
 + * clock can pass into the PRCM can cause problems at DSP and IVA.
 + * To work around this the code will switch to the 32kHz source prior to sleep.
 + * Post sleep we will shift back to using the DPLL.  Apparently,
 + * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
 + * 3x12MHz + 3x32kHz clocks for a full switch.
 + *
 + * The DLL load value is not kept in RETENTION or OFF.        It needs to be restored
 + * at wake
 + */
 +ENTRY(omap243x_cpu_suspend)
 +      stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
 +      mov     r3, #0x0                @ clear for mrc call
 +      mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
 +      nop
 +      nop
 +      ldr     r3, omap2_ocs_sdrc_power        @ addr of sdrc power
 +      ldr     r4, [r3]                @ value of sdrc power
 +      orr     r4, r4, #0x40           @ enable self refresh on idle req
 +      mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
 +      str     r4, [r3]                @ make it so
 +      mov     r2, #0
 +      nop
 +      mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
 +      nop
 +loop:
 +      subs    r5, r5, #0x1            @ awake, wait just a bit
 +      bne     loop
 +
 +      /* The DPLL has on before we take the DDR out of self refresh */
 +      bic     r4, r4, #0x40           @ now clear self refresh bit.
 +      str     r4, [r3]                @ put vlaue back.
 +      ldr     r4, A_SDRC0             @ make a clock happen
 +      ldr     r4, [r4]
 +      nop                             @ start auto refresh only after clk ok
 +      movs    r0, r0                  @ see if DDR or SDR
 +      ldrne   r1, omap2_ocs_sdrc_dlla_ctrl    @ get addr of DLL ctrl
 +      strne   r0, [r1]                @ rewrite DLLA to force DLL reload
 +      addne   r1, r1, #0x8            @ move to DLLB
 +      strne   r0, [r1]                @ rewrite DLLB to force DLL reload
 +
 +      mov     r5, #0x1000
 +loop2:
 +      subs    r5, r5, #0x1
 +      bne     loop2
 +      /* resume*/
 +      ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
 +
 +omap2_ocs_sdrc_power:
 +      .word OMAP243X_SDRC_REGADDR(SDRC_POWER)
 +A_SDRC0:
 +      .word A_SDRC0_V
 +omap2_ocs_sdrc_dlla_ctrl:
 +      .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
 +
 +ENTRY(omap243x_cpu_suspend_sz)
 +      .word   . - omap243x_cpu_suspend
 +
index ebc7eb3a7f5c861a1ecd5f1c14247304a0dbad7c,0000000000000000000000000000000000000000..125b75affebbdf05525ef06c0ff7b18330d1648d
mode 100644,000000..100644
--- /dev/null
@@@ -1,544 -1,0 +1,544 @@@
- #include <asm/arch/io.h>
- #include <asm/arch/pm.h>
- #include <asm/arch/control.h>
 +/*
 + * linux/arch/arm/mach-omap2/sleep.S
 + *
 + * (C) Copyright 2007
 + * Texas Instruments
 + * Karthik Dasu <karthik-dp@ti.com>
 + *
 + * (C) Copyright 2004
 + * Texas Instruments, <www.ti.com>
 + * Richard Woodruff <r-woodruff2@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/linkage.h>
 +#include <asm/assembler.h>
++#include <mach/io.h>
++#include <mach/pm.h>
++#include <mach/control.h>
 +
 +#include "prm.h"
 +#include "sdrc.h"
 +
 +#define PM_PREPWSTST_CORE_V   OMAP34XX_PRM_REGADDR(CORE_MOD, \
 +                              OMAP3430_PM_PREPWSTST)
 +#define PM_PREPWSTST_MPU_V    OMAP34XX_PRM_REGADDR(MPU_MOD, \
 +                              OMAP3430_PM_PREPWSTST)
 +#define PM_PWSTCTRL_MPU_P     OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL)
 +#define SCRATCHPAD_MEM_OFFS   0x310 /* Move this as correct place is
 +                                     * available */
 +#define SCRATCHPAD_BASE_P     OMAP343X_CTRL_REGADDR(\
 +                              OMAP343X_CONTROL_MEM_WKUP +\
 +                              SCRATCHPAD_MEM_OFFS)
 +#define SDRC_POWER_V          OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 +
 +      .text
 +/* Function call to get the restore pointer for resume from OFF */
 +ENTRY(get_restore_pointer)
 +        stmfd   sp!, {lr}     @ save registers on stack
 +      adr     r0, restore
 +        ldmfd   sp!, {pc}     @ restore regs and return
 +ENTRY(get_restore_pointer_sz)
 +        .word   . - get_restore_pointer_sz
 +/*
 + * Forces OMAP into idle state
 + *
 + * omap34xx_suspend() - This bit of code just executes the WFI
 + * for normal idles.
 + *
 + * Note: This code get's copied to internal SRAM at boot. When the OMAP
 + *     wakes up it continues execution at the point it went to sleep.
 + */
 +ENTRY(omap34xx_cpu_suspend)
 +      stmfd   sp!, {r0-r12, lr}               @ save registers on stack
 +loop:
 +      /*b     loop*/  @Enable to debug by stepping through code
 +      /* r0 contains restore pointer in sdram */
 +      /* r1 contains information about saving context */
 +      ldr     r4, sdrc_power          @ read the SDRC_POWER register
 +      ldr     r5, [r4]                @ read the contents of SDRC_POWER
 +      orr     r5, r5, #0x40           @ enable self refresh on idle req
 +      str     r5, [r4]                @ write back to SDRC_POWER register
 +
 +      cmp     r1, #0x0
 +      /* If context save is required, do that and execute wfi */
 +      bne     save_context_wfi
 +      /* Data memory barrier and Data sync barrier */
 +      mov     r1, #0
 +      mcr     p15, 0, r1, c7, c10, 4
 +      mcr     p15, 0, r1, c7, c10, 5
 +
 +      wfi                             @ wait for interrupt
 +
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      bl i_dll_wait
 +
 +      ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
 +restore:
 +      /* b restore*/  @ Enable to debug restore code
 +        /* Check what was the reason for mpu reset and store the reason in r9*/
 +        /* 1 - Only L1 and logic lost */
 +        /* 2 - Only L2 lost - In this case, we wont be here */
 +        /* 3 - Both L1 and L2 lost */
 +      ldr     r1, pm_pwstctrl_mpu
 +      ldr     r2, [r1]
 +      and     r2, r2, #0x3
 +      cmp     r2, #0x0        @ Check if target power state was OFF or RET
 +        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
 +      movne   r9, #0x1        @ Only L1 and L2 lost => avoid L2 invalidation
 +      bne     logic_l1_restore
 +      /* Execute smi to invalidate L2 cache */
 +      mov r12, #0x1                         @ set up to invalide L2
 +smi:    .word 0xE1600070                @ Call SMI monitor (smieq)
 +logic_l1_restore:
 +      mov     r1, #0
 +      /* Invalidate all instruction caches to PoU
 +       * and flush branch target cache */
 +      mcr     p15, 0, r1, c7, c5, 0
 +
 +      ldr     r4, scratchpad_base
 +      ldr     r3, [r4,#0xBC]
 +      ldmia   r3!, {r4-r6}
 +      mov     sp, r4
 +      msr     spsr_cxsf, r5
 +      mov     lr, r6
 +
 +      ldmia   r3!, {r4-r9}
 +      /* Coprocessor access Control Register */
 +      mcr p15, 0, r4, c1, c0, 2
 +
 +      /* TTBR0 */
 +      MCR p15, 0, r5, c2, c0, 0
 +      /* TTBR1 */
 +      MCR p15, 0, r6, c2, c0, 1
 +      /* Translation table base control register */
 +      MCR p15, 0, r7, c2, c0, 2
 +      /*domain access Control Register */
 +      MCR p15, 0, r8, c3, c0, 0
 +      /* data fault status Register */
 +      MCR p15, 0, r9, c5, c0, 0
 +
 +      ldmia  r3!,{r4-r8}
 +      /* instruction fault status Register */
 +      MCR p15, 0, r4, c5, c0, 1
 +      /*Data Auxiliary Fault Status Register */
 +      MCR p15, 0, r5, c5, c1, 0
 +      /*Instruction Auxiliary Fault Status Register*/
 +      MCR p15, 0, r6, c5, c1, 1
 +      /*Data Fault Address Register */
 +      MCR p15, 0, r7, c6, c0, 0
 +      /*Instruction Fault Address Register*/
 +      MCR p15, 0, r8, c6, c0, 2
 +      ldmia  r3!,{r4-r7}
 +
 +      /* user r/w thread and process ID */
 +      MCR p15, 0, r4, c13, c0, 2
 +      /* user ro thread and process ID */
 +      MCR p15, 0, r5, c13, c0, 3
 +      /*Privileged only thread and process ID */
 +      MCR p15, 0, r6, c13, c0, 4
 +      /* cache size selection */
 +      MCR p15, 2, r7, c0, c0, 0
 +      ldmia  r3!,{r4-r8}
 +      /* Data TLB lockdown registers */
 +      MCR p15, 0, r4, c10, c0, 0
 +      /* Instruction TLB lockdown registers */
 +      MCR p15, 0, r5, c10, c0, 1
 +      /* Secure or Nonsecure Vector Base Address */
 +      MCR p15, 0, r6, c12, c0, 0
 +      /* FCSE PID */
 +      MCR p15, 0, r7, c13, c0, 0
 +      /* Context PID */
 +      MCR p15, 0, r8, c13, c0, 1
 +
 +      ldmia  r3!,{r4-r5}
 +      /* primary memory remap register */
 +      MCR p15, 0, r4, c10, c2, 0
 +      /*normal memory remap register */
 +      MCR p15, 0, r5, c10, c2, 1
 +
 +      /* Restore registers for other modes from SDRAM */
 +      /* Save current mode */
 +      mrs     r7, cpsr
 +
 +      /* FIQ mode */
 +      bic     r0, r7, #0x1F
 +      orr     r0, r0, #0x11
 +      msr     cpsr, r0
 +      ldmia   r3!, {r8-r12}
 +      /* load the SP and LR from SDRAM */
 +      ldmia  r3!,{r4-r6}
 +      mov    sp, r4   /*update the SP */
 +      mov    lr, r5   /*update the LR */
 +      msr    spsr, r6 /*update the SPSR*/
 +
 +      /* IRQ mode */
 +      bic    r0, r7, #0x1F
 +      orr    r0, r0, #0x12
 +      msr    cpsr, r0 /*go into IRQ mode*/
 +      ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM*/
 +      mov    sp, r4   /*update the SP */
 +      mov    lr, r5   /*update the LR */
 +      msr    spsr, r6 /*update the SPSR */
 +
 +      /* ABORT mode */
 +      bic    r0, r7, #0x1F
 +      orr    r0, r0, #0x17
 +      msr    cpsr, r0 /* go into ABORT mode */
 +      ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM */
 +      mov    sp, r4           /*update the SP */
 +      mov    lr, r5           /*update the LR */
 +      msr    spsr, r6         /*update the SPSR */
 +
 +      /* UNDEEF mode */
 +      bic    r0, r7, #0x1F
 +      orr    r0, r0, #0x1B
 +      msr    cpsr, r0         /*go into UNDEF mode */
 +      ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM */
 +      mov    sp, r4           /*update the SP*/
 +      mov    lr, r5           /*update the LR*/
 +      msr    spsr, r6         /*update the SPSR*/
 +
 +      /* SYSTEM (USER) mode */
 +      bic    r0, r7, #0x1F
 +      orr    r0, r0, #0x1F
 +      msr    cpsr, r0         /*go into USR mode */
 +      ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM*/
 +      mov    sp, r4           /*update the SP */
 +      mov    lr, r5           /*update the LR */
 +      msr    spsr, r6         /*update the SPSR */
 +      msr    cpsr, r7         /*back to original mode*/
 +
 +      /* Restore cpsr */
 +      ldmia   r3!,{r4}        /*load CPSR from SDRAM*/
 +      msr     cpsr, r4        /*store cpsr */
 +
 +      /* Enabling MMU here */
 +      mrc     p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
 +      /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
 +      and     r7, #0x7
 +      cmp     r7, #0x0
 +      beq     usettbr0
 +ttbr_error:
 +      /* More work needs to be done to support N[0:2] value other than 0
 +      * So looping here so that the error can be detected
 +      */
 +      b       ttbr_error
 +usettbr0:
 +      mrc     p15, 0, r2, c2, c0, 0
 +      ldr     r5, ttbrbit_mask
 +      and     r2, r5
 +      mov     r4, pc
 +      ldr     r5, table_index_mask
 +      and     r4, r5 /* r4 = 31 to 20 bits of pc */
 +      /* Extract the value to be written to table entry */
 +      ldr     r1, table_entry
 +      add     r1, r1, r4 /* r1 has value to be written to table entry*/
 +      /* Getting the address of table entry to modify */
 +      lsr     r4, #18
 +      add     r2, r4 /* r2 has the location which needs to be modified */
 +      /* Storing previous entry of location being modified */
 +      ldr     r5, scratchpad_base
 +      ldr     r4, [r2]
 +      str     r4, [r5, #0xC0]
 +      /* Modify the table entry */
 +      str     r1, [r2]
 +      /* Storing address of entry being modified
 +       * - will be restored after enabling MMU */
 +      ldr     r5, scratchpad_base
 +      str     r2, [r5, #0xC4]
 +
 +      mov     r0, #0
 +      mcr     p15, 0, r0, c7, c5, 4   @ Flush prefetch buffer
 +      mcr     p15, 0, r0, c7, c5, 6   @ Invalidate branch predictor array
 +      mcr     p15, 0, r0, c8, c5, 0   @ Invalidate instruction TLB
 +      mcr     p15, 0, r0, c8, c6, 0   @ Invalidate data TLB
 +      /* Restore control register  but dont enable caches here*/
 +      /* Caches will be enabled after restoring MMU table entry */
 +      ldmia   r3!, {r4}
 +      /* Store previous value of control register in scratchpad */
 +      str     r4, [r5, #0xC8]
 +      ldr     r2, cache_pred_disable_mask
 +      and     r4, r2
 +      mcr     p15, 0, r4, c1, c0, 0
 +
 +      ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
 +save_context_wfi:
 +      /*b     save_context_wfi*/      @ enable to debug save code
 +      mov     r8, r0 /* Store SDRAM address in r8 */
 +        /* Check what that target sleep state is:stored in r1*/
 +        /* 1 - Only L1 and logic lost */
 +        /* 2 - Only L2 lost */
 +        /* 3 - Both L1 and L2 lost */
 +      cmp     r1, #0x2 /* Only L2 lost */
 +      beq     clean_l2
 +      cmp     r1, #0x1 /* L2 retained */
 +      /* r9 stores whether to clean L2 or not*/
 +      moveq   r9, #0x0 /* Dont Clean L2 */
 +      movne   r9, #0x1 /* Clean L2 */
 +l1_logic_lost:
 +      /* Store sp and spsr to SDRAM */
 +      mov     r4, sp
 +      mrs     r5, spsr
 +      mov     r6, lr
 +      stmia   r8!, {r4-r6}
 +      /* Save all ARM registers */
 +      /* Coprocessor access control register */
 +      mrc     p15, 0, r6, c1, c0, 2
 +      stmia   r8!, {r6}
 +      /* TTBR0, TTBR1 and Translation table base control */
 +      mrc     p15, 0, r4, c2, c0, 0
 +      mrc     p15, 0, r5, c2, c0, 1
 +      mrc     p15, 0, r6, c2, c0, 2
 +      stmia   r8!, {r4-r6}
 +      /* Domain access control register, data fault status register,
 +      and instruction fault status register */
 +      mrc     p15, 0, r4, c3, c0, 0
 +      mrc     p15, 0, r5, c5, c0, 0
 +      mrc     p15, 0, r6, c5, c0, 1
 +      stmia   r8!, {r4-r6}
 +      /* Data aux fault status register, instruction aux fault status,
 +      datat fault address register and instruction fault address register*/
 +      mrc     p15, 0, r4, c5, c1, 0
 +      mrc     p15, 0, r5, c5, c1, 1
 +      mrc     p15, 0, r6, c6, c0, 0
 +      mrc     p15, 0, r7, c6, c0, 2
 +      stmia   r8!, {r4-r7}
 +      /* user r/w thread and process ID, user r/o thread and process ID,
 +      priv only thread and process ID, cache size selection */
 +      mrc     p15, 0, r4, c13, c0, 2
 +      mrc     p15, 0, r5, c13, c0, 3
 +      mrc     p15, 0, r6, c13, c0, 4
 +      mrc     p15, 2, r7, c0, c0, 0
 +      stmia   r8!, {r4-r7}
 +      /* Data TLB lockdown, instruction TLB lockdown registers */
 +      mrc     p15, 0, r5, c10, c0, 0
 +      mrc     p15, 0, r6, c10, c0, 1
 +      stmia   r8!, {r5-r6}
 +      /* Secure or non secure vector base address, FCSE PID, Context PID*/
 +      mrc     p15, 0, r4, c12, c0, 0
 +      mrc     p15, 0, r5, c13, c0, 0
 +      mrc     p15, 0, r6, c13, c0, 1
 +      stmia   r8!, {r4-r6}
 +      /* Primary remap, normal remap registers */
 +      mrc     p15, 0, r4, c10, c2, 0
 +      mrc     p15, 0, r5, c10, c2, 1
 +      stmia   r8!,{r4-r5}
 +      /* Store SP, LR, SPSR registers for SUP, FIQ, IRQ, ABORT and USER
 +      modes into SDRAM */
 +
 +      /* move SDRAM address to r7 as r8 is banked in FIQ*/
 +      mov     r7, r8
 +
 +      /* Save current mode */
 +      mrs     r2, cpsr
 +      /* FIQ mode */
 +      bic     r0, r2, #0x1F
 +      orr     r0, r0, #0x11
 +      msr     cpsr, r0 /* go to FIQ mode */
 +      stmia   r7!, {r8-r12}
 +      mov     r4, r13 /* move SP into r4*/
 +      mov     r5, r14
 +      mrs     r6, spsr
 +      stmia   r7!, {r4-r6}
 +
 +      /* IRQ mode */
 +      bic     r0, r2, #0x1F
 +      orr     r0, r0, #0x12
 +      msr     cpsr, r0
 +      mov     r4, r13
 +      mov     r5, r14
 +      mrs     r6, spsr
 +      stmia   r7!, {r4-r6}
 +
 +      /* Abort mode */
 +      bic     r0, r2, #0x1F
 +      orr     r0, r0, #0x17
 +      msr     cpsr, r0
 +      mov     r4, r13
 +      mov     r5, r14
 +      mrs     r6, spsr
 +      stmia   r7!, {r4-r6}
 +
 +      /* UNDEF mode */
 +      bic     r0, r2, #0x1F
 +      orr     r0, r0, #0x1B
 +      msr     cpsr, r0
 +      mov     r4, r13
 +      mov     r5, r14
 +      mrs     r6, spsr
 +      stmia   r7!, {r4-r6}
 +
 +      /* System (USER mode) */
 +      bic     r0, r2, #0x1F
 +      orr     r0, r0, #0x1F
 +      msr     cpsr, r0
 +      mov     r4, r13
 +      mov     r5, r14
 +      mrs     r6, spsr
 +      stmia   r7!, {r4-r6}
 +
 +      /* Back to original mode */
 +      msr     cpsr, r2
 +
 +      /* Store current cpsr*/
 +      stmia   r7!, {r2}
 +
 +      mrc     p15, 0, r4, c1, c0, 0
 +      /* save control register */
 +      stmia   r7!, {r4}
 +clean_caches:
 +      /* Clean Data or unified cache to POU*/
 +      /* How to invalidate only L1 cache???? - #FIX_ME# */
 +      /* mcr  p15, 0, r11, c7, c11, 1 */
 +      cmp     r9, #1 /* Check whether L2 inval is required or not*/
 +      bne     skip_l2_inval
 +clean_l2:
 +      /* read clidr */
 +      mrc     p15, 1, r0, c0, c0, 1
 +      /* extract loc from clidr */
 +      ands    r3, r0, #0x7000000
 +      /* left align loc bit field */
 +      mov     r3, r3, lsr #23
 +      /* if loc is 0, then no need to clean */
 +      beq     finished
 +      /* start clean at cache level 0 */
 +      mov     r10, #0
 +loop1:
 +      /* work out 3x current cache level */
 +      add     r2, r10, r10, lsr #1
 +      /* extract cache type bits from clidr*/
 +      mov     r1, r0, lsr r2
 +      /* mask of the bits for current cache only */
 +      and     r1, r1, #7
 +      /* see what cache we have at this level */
 +      cmp     r1, #2
 +      /* skip if no cache, or just i-cache */
 +      blt     skip
 +      /* select current cache level in cssr */
 +      mcr     p15, 2, r10, c0, c0, 0
 +      /* isb to sych the new cssr&csidr */
 +      isb
 +      /* read the new csidr */
 +      mrc     p15, 1, r1, c0, c0, 0
 +      /* extract the length of the cache lines */
 +      and     r2, r1, #7
 +      /* add 4 (line length offset) */
 +      add     r2, r2, #4
 +      ldr     r4, assoc_mask
 +      /* find maximum number on the way size */
 +      ands    r4, r4, r1, lsr #3
 +      /* find bit position of way size increment */
 +      clz     r5, r4
 +      ldr     r7, numset_mask
 +      /* extract max number of the index size*/
 +      ands    r7, r7, r1, lsr #13
 +loop2:
 +      mov     r9, r4
 +      /* create working copy of max way size*/
 +loop3:
 +      /* factor way and cache number into r11 */
 +      orr     r11, r10, r9, lsl r5
 +      /* factor index number into r11 */
 +      orr     r11, r11, r7, lsl r2
 +      /*clean & invalidate by set/way */
 +      mcr     p15, 0, r11, c7, c10, 2
 +      /* decrement the way*/
 +      subs    r9, r9, #1
 +      bge     loop3
 +      /*decrement the index */
 +      subs    r7, r7, #1
 +      bge     loop2
 +skip:
 +      add     r10, r10, #2
 +      /* increment cache number */
 +      cmp     r3, r10
 +      bgt     loop1
 +finished:
 +      /*swith back to cache level 0 */
 +      mov     r10, #0
 +      /* select current cache level in cssr */
 +      mcr     p15, 2, r10, c0, c0, 0
 +      isb
 +skip_l2_inval:
 +      /* Data memory barrier and Data sync barrier */
 +      mov     r1, #0
 +      mcr     p15, 0, r1, c7, c10, 4
 +      mcr     p15, 0, r1, c7, c10, 5
 +
 +      wfi                             @ wait for interrupt
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      bl i_dll_wait
 +      /* restore regs and return */
 +      ldmfd   sp!, {r0-r12, pc}
 +
 +i_dll_wait:
 +      ldr     r4, clk_stabilize_delay
 +
 +i_dll_delay:
 +      subs    r4, r4, #0x1
 +      bne     i_dll_delay
 +      ldr     r4, sdrc_power
 +      ldr     r5, [r4]
 +      bic     r5, r5, #0x40
 +      str     r5, [r4]
 +      bx      lr
 +pm_prepwstst_core:
 +      .word   PM_PREPWSTST_CORE_V
 +pm_prepwstst_mpu:
 +      .word   PM_PREPWSTST_MPU_V
 +pm_pwstctrl_mpu:
 +      .word   PM_PWSTCTRL_MPU_P
 +scratchpad_base:
 +      .word   SCRATCHPAD_BASE_P
 +sdrc_power:
 +      .word SDRC_POWER_V
 +context_mem:
 +      .word   0x803E3E14
 +clk_stabilize_delay:
 +      .word 0x000001FF
 +assoc_mask:
 +      .word   0x3ff
 +numset_mask:
 +      .word   0x7fff
 +ttbrbit_mask:
 +      .word   0xFFFFC000
 +table_index_mask:
 +      .word   0xFFF00000
 +table_entry:
 +      .word   0x00000C02
 +cache_pred_disable_mask:
 +      .word   0xFFFFE7FB
 +ENTRY(omap34xx_cpu_suspend_sz)
 +      .word   . - omap34xx_cpu_suspend
index 5b15d18a07397f3da50013f25f0d8f48042c2a48,0000000000000000000000000000000000000000..ffd49d114904e31f393c5c2a3c2b7b0a5a0bf852
mode 100644,000000..100644
--- /dev/null
@@@ -1,813 -1,0 +1,813 @@@
- #include <asm/arch/omap34xx.h>
- #include <asm/arch/control.h>
- #include <asm/arch/clock.h>
 +/*
 + * linux/arch/arm/mach-omap3/smartreflex.c
 + *
 + * OMAP34XX SmartReflex Voltage Control
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + * Kalle Jokiniemi
 + *
 + * Copyright (C) 2007 Texas Instruments, Inc.
 + * Lesly A M <x0080970@ti.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/interrupt.h>
 +#include <linux/module.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/sysfs.h>
 +#include <linux/kobject.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/io.h>
 +
++#include <mach/omap34xx.h>
++#include <mach/control.h>
++#include <mach/clock.h>
 +
 +#include "prm.h"
 +#include "smartreflex.h"
 +#include "prm-regbits-34xx.h"
 +
 +/* XXX: These should be relocated where-ever the OPP implementation will be */
 +u32 current_vdd1_opp;
 +u32 current_vdd2_opp;
 +
 +struct omap_sr {
 +      int             srid;
 +      int             is_sr_reset;
 +      int             is_autocomp_active;
 +      struct clk      *clk;
 +      u32             clk_length;
 +      u32             req_opp_no;
 +      u32             opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
 +      u32             opp5_nvalue;
 +      u32             senp_mod, senn_mod;
 +      u32             srbase_addr;
 +      u32             vpbase_addr;
 +};
 +
 +/* Custom clocks to enable SR specific enable/disable functions. */
 +struct sr_custom_clk {
 +      struct clk      clk;  /* meta-clock with custom enable/disable calls */
 +      struct clk      *fck; /* actual functional clock */
 +      struct omap_sr  *sr;
 +};
 +
 +#define SR_REGADDR(offs)     (__force void __iomem *)(sr->srbase_addr + offset)
 +
 +static inline void sr_write_reg(struct omap_sr *sr, int offset, u32 value)
 +{
 +      __raw_writel(value, SR_REGADDR(offset));
 +}
 +
 +static inline void sr_modify_reg(struct omap_sr *sr, int offset, u32 mask,
 +                                                              u32 value)
 +{
 +      u32 reg_val;
 +
 +      reg_val = __raw_readl(SR_REGADDR(offset));
 +      reg_val &= ~mask;
 +      reg_val |= value;
 +
 +      __raw_writel(reg_val, SR_REGADDR(offset));
 +}
 +
 +static inline u32 sr_read_reg(struct omap_sr *sr, int offset)
 +{
 +      return __raw_readl(SR_REGADDR(offset));
 +}
 +
 +/* Custom clock handling functions */
 +static int sr_clk_enable(struct clk *clk)
 +{
 +      struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
 +                                                                      clk);
 +
 +      if (clk_enable(sr_clk->fck) != 0) {
 +              printk(KERN_ERR "Could not enable %s\n", sr_clk->fck->name);
 +              goto clk_enable_err;
 +      }
 +
 +      /* set fclk- active , iclk- idle */
 +      sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
 +                                              SR_CLKACTIVITY_IOFF_FON);
 +
 +      return 0;
 +
 +clk_enable_err:
 +      return -1;
 +}
 +
 +static void sr_clk_disable(struct clk *clk)
 +{
 +      struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
 +                                                                      clk);
 +
 +      /* set fclk, iclk- idle */
 +      sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
 +                                              SR_CLKACTIVITY_IOFF_FOFF);
 +
 +      clk_disable(sr_clk->fck);
 +      sr_clk->sr->is_sr_reset = 1;
 +}
 +
 +static struct omap_sr sr1 = {
 +      .srid                   = SR1,
 +      .is_sr_reset            = 1,
 +      .is_autocomp_active     = 0,
 +      .clk_length             = 0,
 +      .srbase_addr            = OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE),
 +};
 +
 +static struct omap_sr sr2 = {
 +      .srid                   = SR2,
 +      .is_sr_reset            = 1,
 +      .is_autocomp_active     = 0,
 +      .clk_length             = 0,
 +      .srbase_addr            = OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
 +};
 +
 +static struct sr_custom_clk sr1_custom_clk = {
 +      .clk = {
 +                      .name           = "sr1_custom_clk",
 +                      .enable         = sr_clk_enable,
 +                      .disable        = sr_clk_disable,
 +      },
 +      .sr     = &sr1,
 +};
 +
 +static struct sr_custom_clk sr2_custom_clk = {
 +      .clk = {
 +                      .name           = "sr2_custom_clk",
 +                      .enable         = sr_clk_enable,
 +                      .disable        = sr_clk_disable,
 +      },
 +      .sr     = &sr2,
 +};
 +
 +static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
 +{
 +      u32 gn, rn, mul;
 +
 +      for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
 +              mul = 1 << (gn + 8);
 +              rn = mul / sensor;
 +              if (rn < R_MAXLIMIT) {
 +                      *sengain = gn;
 +                      *rnsen = rn;
 +              }
 +      }
 +}
 +
 +static u32 cal_test_nvalue(u32 sennval, u32 senpval)
 +{
 +      u32 senpgain, senngain;
 +      u32 rnsenp, rnsenn;
 +
 +      /* Calculating the gain and reciprocal of the SenN and SenP values */
 +      cal_reciprocal(senpval, &senpgain, &rnsenp);
 +      cal_reciprocal(sennval, &senngain, &rnsenn);
 +
 +      return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
 +              (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
 +              (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
 +              (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
 +}
 +
 +static void sr_clk_init(struct sr_custom_clk *sr_clk)
 +{
 +      if (sr_clk->sr->srid == SR1) {
 +              sr_clk->fck = clk_get(NULL, "sr1_fck");
 +              if (IS_ERR(sr_clk->fck))
 +                      printk(KERN_ERR "Could not get sr1_fck\n");
 +      } else if (sr_clk->sr->srid == SR2) {
 +              sr_clk->fck = clk_get(NULL, "sr2_fck");
 +              if (IS_ERR(sr_clk->fck))
 +                      printk(KERN_ERR "Could not get sr2_fck\n");
 +      }
 +      clk_register(&sr_clk->clk);
 +}
 +
 +static void sr_set_clk_length(struct omap_sr *sr)
 +{
 +      struct clk *osc_sys_ck;
 +      u32 sys_clk = 0;
 +
 +      osc_sys_ck = clk_get(NULL, "osc_sys_ck");
 +      sys_clk = clk_get_rate(osc_sys_ck);
 +      clk_put(osc_sys_ck);
 +
 +      switch (sys_clk) {
 +      case 12000000:
 +              sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
 +              break;
 +      case 13000000:
 +              sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
 +              break;
 +      case 19200000:
 +              sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
 +              break;
 +      case 26000000:
 +              sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
 +              break;
 +      case 38400000:
 +              sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
 +              break;
 +      default :
 +              printk(KERN_ERR "Invalid sysclk value: %d\n", sys_clk);
 +              break;
 +      }
 +}
 +
 +static void sr_set_efuse_nvalues(struct omap_sr *sr)
 +{
 +      if (sr->srid == SR1) {
 +              sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
 +                                      OMAP343X_SR1_SENNENABLE_MASK) >>
 +                                      OMAP343X_SR1_SENNENABLE_SHIFT;
 +
 +              sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
 +                                      OMAP343X_SR1_SENPENABLE_MASK) >>
 +                                      OMAP343X_SR1_SENPENABLE_SHIFT;
 +
 +              sr->opp5_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP5_VDD1);
 +              sr->opp4_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP4_VDD1);
 +              sr->opp3_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP3_VDD1);
 +              sr->opp2_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP2_VDD1);
 +              sr->opp1_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP1_VDD1);
 +      } else if (sr->srid == SR2) {
 +              sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
 +                                      OMAP343X_SR2_SENNENABLE_MASK) >>
 +                                      OMAP343X_SR2_SENNENABLE_SHIFT;
 +
 +              sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
 +                                      OMAP343X_SR2_SENPENABLE_MASK) >>
 +                                      OMAP343X_SR2_SENPENABLE_SHIFT;
 +
 +              sr->opp3_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP3_VDD2);
 +              sr->opp2_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP2_VDD2);
 +              sr->opp1_nvalue = omap_ctrl_readl(
 +                                      OMAP343X_CONTROL_FUSE_OPP1_VDD2);
 +      }
 +}
 +
 +/* Hard coded nvalues for testing purposes, may cause device to hang! */
 +static void sr_set_testing_nvalues(struct omap_sr *sr)
 +{
 +      if (sr->srid == SR1) {
 +              sr->senp_mod = 0x03;    /* SenN-M5 enabled */
 +              sr->senn_mod = 0x03;
 +
 +              /* calculate nvalues for each opp */
 +              sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
 +              sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
 +              sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
 +              sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
 +              sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
 +      } else if (sr->srid == SR2) {
 +              sr->senp_mod = 0x03;
 +              sr->senn_mod = 0x03;
 +
 +              sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
 +              sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
 +              sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
 +      }
 +
 +}
 +
 +static void sr_set_nvalues(struct omap_sr *sr)
 +{
 +      if (SR_TESTING_NVALUES)
 +              sr_set_testing_nvalues(sr);
 +      else
 +              sr_set_efuse_nvalues(sr);
 +}
 +
 +static void sr_configure_vp(int srid)
 +{
 +      u32 vpconfig;
 +
 +      if (srid == SR1) {
 +              vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN
 +                                      | PRM_VP1_CONFIG_INITVOLTAGE
 +                                      | PRM_VP1_CONFIG_TIMEOUTEN;
 +
 +              prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_CONFIG_OFFSET);
 +              prm_write_mod_reg(PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN |
 +                                      PRM_VP1_VSTEPMIN_VSTEPMIN,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_VSTEPMIN_OFFSET);
 +
 +              prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
 +                                      PRM_VP1_VSTEPMAX_VSTEPMAX,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
 +
 +              prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX |
 +                                      PRM_VP1_VLIMITTO_VDDMIN |
 +                                      PRM_VP1_VLIMITTO_TIMEOUT,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_VLIMITTO_OFFSET);
 +
 +              /* Trigger initVDD value copy to voltage processor */
 +              prm_set_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_CONFIG_OFFSET);
 +              /* Clear initVDD copy trigger bit */
 +              prm_clear_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_CONFIG_OFFSET);
 +
 +      } else if (srid == SR2) {
 +              vpconfig = PRM_VP2_CONFIG_ERROROFFSET | PRM_VP2_CONFIG_ERRORGAIN
 +                                      | PRM_VP2_CONFIG_INITVOLTAGE
 +                                      | PRM_VP2_CONFIG_TIMEOUTEN;
 +
 +              prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_CONFIG_OFFSET);
 +              prm_write_mod_reg(PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN |
 +                                      PRM_VP2_VSTEPMIN_VSTEPMIN,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_VSTEPMIN_OFFSET);
 +
 +              prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
 +                                      PRM_VP2_VSTEPMAX_VSTEPMAX,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
 +
 +              prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX |
 +                                      PRM_VP2_VLIMITTO_VDDMIN |
 +                                      PRM_VP2_VLIMITTO_TIMEOUT,
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_VLIMITTO_OFFSET);
 +
 +              /* Trigger initVDD value copy to voltage processor */
 +              prm_set_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_CONFIG_OFFSET);
 +              /* Reset initVDD copy trigger bit */
 +              prm_clear_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_CONFIG_OFFSET);
 +
 +      }
 +}
 +
 +static void sr_configure(struct omap_sr *sr)
 +{
 +      u32 sr_config;
 +      u32 senp_en , senn_en;
 +
 +      if (sr->clk_length == 0)
 +              sr_set_clk_length(sr);
 +
 +      senp_en = sr->senp_mod;
 +      senn_en = sr->senn_mod;
 +      if (sr->srid == SR1) {
 +              sr_config = SR1_SRCONFIG_ACCUMDATA |
 +                      (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
 +                      SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
 +                      SRCONFIG_MINMAXAVG_EN |
 +                      (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
 +                      (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
 +                      SRCONFIG_DELAYCTRL;
 +
 +              sr_write_reg(sr, SRCONFIG, sr_config);
 +              sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
 +                                      SR1_AVGWEIGHT_SENNAVGWEIGHT);
 +
 +              sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
 +                      SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
 +                      (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
 +
 +      } else if (sr->srid == SR2) {
 +              sr_config = SR2_SRCONFIG_ACCUMDATA |
 +                      (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
 +                      SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
 +                      SRCONFIG_MINMAXAVG_EN |
 +                      (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
 +                      (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
 +                      SRCONFIG_DELAYCTRL;
 +
 +              sr_write_reg(sr, SRCONFIG, sr_config);
 +              sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |
 +                                      SR2_AVGWEIGHT_SENNAVGWEIGHT);
 +              sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
 +                      SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
 +                      (SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT));
 +
 +      }
 +      sr->is_sr_reset = 0;
 +}
 +
 +static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
 +{
 +      u32 nvalue_reciprocal;
 +
 +      sr->req_opp_no = target_opp_no;
 +
 +      if (sr->srid == SR1) {
 +              switch (target_opp_no) {
 +              case 5:
 +                      nvalue_reciprocal = sr->opp5_nvalue;
 +                      break;
 +              case 4:
 +                      nvalue_reciprocal = sr->opp4_nvalue;
 +                      break;
 +              case 3:
 +                      nvalue_reciprocal = sr->opp3_nvalue;
 +                      break;
 +              case 2:
 +                      nvalue_reciprocal = sr->opp2_nvalue;
 +                      break;
 +              case 1:
 +                      nvalue_reciprocal = sr->opp1_nvalue;
 +                      break;
 +              default:
 +                      nvalue_reciprocal = sr->opp3_nvalue;
 +                      break;
 +              }
 +      } else {
 +              switch (target_opp_no) {
 +              case 3:
 +                      nvalue_reciprocal = sr->opp3_nvalue;
 +                      break;
 +              case 2:
 +                      nvalue_reciprocal = sr->opp2_nvalue;
 +                      break;
 +              case 1:
 +                      nvalue_reciprocal = sr->opp1_nvalue;
 +                      break;
 +              default:
 +                      nvalue_reciprocal = sr->opp3_nvalue;
 +                      break;
 +              }
 +      }
 +
 +      if (nvalue_reciprocal == 0) {
 +              printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n",
 +                                                              target_opp_no);
 +              return SR_FALSE;
 +      }
 +
 +      sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
 +
 +      /* Enable the interrupt */
 +      sr_modify_reg(sr, ERRCONFIG,
 +                      (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
 +                      (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
 +      if (sr->srid == SR1) {
 +              /* Enable VP1 */
 +              prm_set_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
 +                              OMAP3_PRM_VP1_CONFIG_OFFSET);
 +      } else if (sr->srid == SR2) {
 +              /* Enable VP2 */
 +              prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
 +                              OMAP3_PRM_VP2_CONFIG_OFFSET);
 +      }
 +
 +      /* SRCONFIG - enable SR */
 +      sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
 +      return SR_TRUE;
 +}
 +
 +static void sr_disable(struct omap_sr *sr)
 +{
 +      sr->is_sr_reset = 1;
 +
 +      /* SRCONFIG - disable SR */
 +      sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
 +
 +      if (sr->srid == SR1) {
 +              /* Disable VP1 */
 +              prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP1_CONFIG_OFFSET);
 +      } else if (sr->srid == SR2) {
 +              /* Disable VP2 */
 +              prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VP2_CONFIG_OFFSET);
 +      }
 +}
 +
 +
 +void sr_start_vddautocomap(int srid, u32 target_opp_no)
 +{
 +      struct omap_sr *sr = NULL;
 +
 +      if (srid == SR1)
 +              sr = &sr1;
 +      else if (srid == SR2)
 +              sr = &sr2;
 +
 +      if (sr->is_sr_reset == 1) {
 +              clk_enable(sr->clk);
 +              sr_configure(sr);
 +      }
 +
 +      if (sr->is_autocomp_active == 1)
 +              printk(KERN_WARNING "SR%d: VDD autocomp is already active\n",
 +                                                                      srid);
 +
 +      sr->is_autocomp_active = 1;
 +      if (!sr_enable(sr, target_opp_no)) {
 +              printk(KERN_WARNING "SR%d: VDD autocomp not activated\n", srid);
 +              sr->is_autocomp_active = 0;
 +              if (sr->is_sr_reset == 1)
 +                      clk_disable(sr->clk);
 +      }
 +}
 +EXPORT_SYMBOL(sr_start_vddautocomap);
 +
 +int sr_stop_vddautocomap(int srid)
 +{
 +      struct omap_sr *sr = NULL;
 +
 +      if (srid == SR1)
 +              sr = &sr1;
 +      else if (srid == SR2)
 +              sr = &sr2;
 +
 +      if (sr->is_autocomp_active == 1) {
 +              sr_disable(sr);
 +              clk_disable(sr->clk);
 +              sr->is_autocomp_active = 0;
 +              return SR_TRUE;
 +      } else {
 +              printk(KERN_WARNING "SR%d: VDD autocomp is not active\n",
 +                                                              srid);
 +              return SR_FALSE;
 +      }
 +
 +}
 +EXPORT_SYMBOL(sr_stop_vddautocomap);
 +
 +void enable_smartreflex(int srid)
 +{
 +      u32 target_opp_no = 0;
 +      struct omap_sr *sr = NULL;
 +
 +      if (srid == SR1)
 +              sr = &sr1;
 +      else if (srid == SR2)
 +              sr = &sr2;
 +
 +      if (sr->is_autocomp_active == 1) {
 +              if (sr->is_sr_reset == 1) {
 +                      /* Enable SR clks */
 +                      clk_enable(sr->clk);
 +
 +                      if (srid == SR1)
 +                              target_opp_no = get_opp_no(current_vdd1_opp);
 +                      else if (srid == SR2)
 +                              target_opp_no = get_opp_no(current_vdd2_opp);
 +
 +                      sr_configure(sr);
 +
 +                      if (!sr_enable(sr, target_opp_no))
 +                              clk_disable(sr->clk);
 +              }
 +      }
 +}
 +
 +void disable_smartreflex(int srid)
 +{
 +      struct omap_sr *sr = NULL;
 +
 +      if (srid == SR1)
 +              sr = &sr1;
 +      else if (srid == SR2)
 +              sr = &sr2;
 +
 +      if (sr->is_autocomp_active == 1) {
 +              if (sr->is_sr_reset == 0) {
 +
 +                      sr->is_sr_reset = 1;
 +                      /* SRCONFIG - disable SR */
 +                      sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
 +                                                      ~SRCONFIG_SRENABLE);
 +
 +                      /* Disable SR clk */
 +                      clk_disable(sr->clk);
 +                      if (sr->srid == SR1) {
 +                              /* Disable VP1 */
 +                              prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
 +                                              OMAP3430_GR_MOD,
 +                                              OMAP3_PRM_VP1_CONFIG_OFFSET);
 +                      } else if (sr->srid == SR2) {
 +                              /* Disable VP2 */
 +                              prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
 +                                              OMAP3430_GR_MOD,
 +                                              OMAP3_PRM_VP2_CONFIG_OFFSET);
 +                      }
 +              }
 +      }
 +}
 +
 +/* Voltage Scaling using SR VCBYPASS */
 +int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel)
 +{
 +      int sr_status = 0;
 +      u32 vdd, target_opp_no;
 +      u32 vc_bypass_value;
 +      u32 reg_addr = 0;
 +      u32 loop_cnt = 0, retries_cnt = 0;
 +
 +      vdd = get_vdd(target_opp);
 +      target_opp_no = get_opp_no(target_opp);
 +
 +      if (vdd == PRCM_VDD1) {
 +              sr_status = sr_stop_vddautocomap(SR1);
 +
 +              prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
 +                                      (vsel << OMAP3430_VC_CMD_ON_SHIFT),
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
 +              reg_addr = R_VDD1_SR_CONTROL;
 +
 +      } else if (vdd == PRCM_VDD2) {
 +              sr_status = sr_stop_vddautocomap(SR2);
 +
 +              prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
 +                                      (vsel << OMAP3430_VC_CMD_ON_SHIFT),
 +                                      OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
 +              reg_addr = R_VDD2_SR_CONTROL;
 +      }
 +
 +      vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
 +                      (reg_addr << OMAP3430_REGADDR_SHIFT) |
 +                      (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
 +
 +      prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
 +                      OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
 +
 +      vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
 +
 +      while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
 +              loop_cnt++;
 +              if (retries_cnt > 10) {
 +                      printk(KERN_INFO "Loop count exceeded in check SR I2C"
 +                                                              "write\n");
 +                      return SR_FAIL;
 +              }
 +              if (loop_cnt > 50) {
 +                      retries_cnt++;
 +                      loop_cnt = 0;
 +                      udelay(10);
 +              }
 +              vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
 +                                      OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
 +      }
 +
 +      udelay(T2_SMPS_UPDATE_DELAY);
 +
 +      if (sr_status) {
 +              if (vdd == PRCM_VDD1)
 +                      sr_start_vddautocomap(SR1, target_opp_no);
 +              else if (vdd == PRCM_VDD2)
 +                      sr_start_vddautocomap(SR2, target_opp_no);
 +      }
 +
 +      return SR_PASS;
 +}
 +
 +/* Sysfs interface to select SR VDD1 auto compensation */
 +static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
 +                                      struct kobj_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%d\n", sr1.is_autocomp_active);
 +}
 +
 +static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
 +                                      struct kobj_attribute *attr,
 +                                      const char *buf, size_t n)
 +{
 +      u32 current_vdd1opp_no;
 +      unsigned short value;
 +
 +      if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
 +              printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
 +              return -EINVAL;
 +      }
 +
 +      current_vdd1opp_no = get_opp_no(current_vdd1_opp);
 +
 +      if (value == 0)
 +              sr_stop_vddautocomap(SR1);
 +      else
 +              sr_start_vddautocomap(SR1, current_vdd1opp_no);
 +
 +      return n;
 +}
 +
 +static struct kobj_attribute sr_vdd1_autocomp = {
 +      .attr = {
 +      .name = __stringify(sr_vdd1_autocomp),
 +      .mode = 0644,
 +      },
 +      .show = omap_sr_vdd1_autocomp_show,
 +      .store = omap_sr_vdd1_autocomp_store,
 +};
 +
 +/* Sysfs interface to select SR VDD2 auto compensation */
 +static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
 +                                      struct kobj_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%d\n", sr2.is_autocomp_active);
 +}
 +
 +static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
 +                                      struct kobj_attribute *attr,
 +                                      const char *buf, size_t n)
 +{
 +      u32 current_vdd2opp_no;
 +      unsigned short value;
 +
 +      if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
 +              printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n");
 +              return -EINVAL;
 +      }
 +
 +      current_vdd2opp_no = get_opp_no(current_vdd2_opp);
 +
 +      if (value == 0)
 +              sr_stop_vddautocomap(SR2);
 +      else
 +              sr_start_vddautocomap(SR2, current_vdd2opp_no);
 +
 +      return n;
 +}
 +
 +static struct kobj_attribute sr_vdd2_autocomp = {
 +      .attr = {
 +      .name = __stringify(sr_vdd2_autocomp),
 +      .mode = 0644,
 +      },
 +      .show = omap_sr_vdd2_autocomp_show,
 +      .store = omap_sr_vdd2_autocomp_store,
 +};
 +
 +
 +
 +static int __init omap3_sr_init(void)
 +{
 +      int ret = 0;
 +      u8 RdReg;
 +
 +      if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
 +              current_vdd1_opp = PRCM_VDD1_OPP3;
 +              current_vdd2_opp = PRCM_VDD2_OPP3;
 +      } else {
 +              current_vdd1_opp = PRCM_VDD1_OPP1;
 +              current_vdd2_opp = PRCM_VDD1_OPP1;
 +      }
 +      if (cpu_is_omap34xx()) {
 +              sr_clk_init(&sr1_custom_clk);
 +              sr_clk_init(&sr2_custom_clk);
 +              sr1.clk = clk_get(NULL, "sr1_custom_clk");
 +              sr2.clk = clk_get(NULL, "sr2_custom_clk");
 +      }
 +      sr_set_clk_length(&sr1);
 +      sr_set_clk_length(&sr2);
 +
 +      /* Call the VPConfig, VCConfig, set N Values. */
 +      sr_set_nvalues(&sr1);
 +      sr_configure_vp(SR1);
 +
 +      sr_set_nvalues(&sr2);
 +      sr_configure_vp(SR2);
 +
 +      /* Enable SR on T2 */
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
 +                                      R_DCDC_GLOBAL_CFG);
 +
 +      RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
 +      ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
 +                                      R_DCDC_GLOBAL_CFG);
 +
 +      printk(KERN_INFO "SmartReflex driver initialized\n");
 +
 +      ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
 +      if (ret)
 +              printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
 +
 +      ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
 +      if (ret)
 +              printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
 +
 +      return 0;
 +}
 +
 +late_initcall(omap3_sr_init);
Simple merge
Simple merge
index 1acdbe89a803e12234a6d7bffb7f281dee858a99,0000000000000000000000000000000000000000..5185a31122d567f322a9f61b2820dd238b580058
mode 100644,000000..100644
--- /dev/null
@@@ -1,179 -1,0 +1,179 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/arch/arm/mach-omap3/sram.S
 + *
 + * Omap3 specific functions that need to be run in internal SRAM
 + *
 + * (C) Copyright 2007
 + * Texas Instruments Inc.
 + * Rajendra Nayak <rnayak@ti.com>
 + *
 + * (C) Copyright 2004
 + * Texas Instruments, <www.ti.com>
 + * Richard Woodruff <r-woodruff2@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/linkage.h>
 +#include <asm/assembler.h>
- #include <asm/arch/io.h>
++#include <mach/hardware.h>
 +
++#include <mach/io.h>
 +
 +#include "sdrc.h"
 +#include "cm.h"
 +
 +      .text
 +
 +/*
 + * Change frequency of core dpll
 + * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
 + */
 +ENTRY(omap3_sram_configure_core_dpll)
 +      stmfd   sp!, {r1-r12, lr}       @ store regs to stack
 +      cmp     r3, #0x2
 +      blne    configure_sdrc
 +      cmp     r3, #0x2
 +      blne    lock_dll
 +      cmp     r3, #0x1
 +      blne    unlock_dll
 +      bl      sdram_in_selfrefresh    @ put the SDRAM in self refresh
 +      bl      configure_core_dpll
 +      bl      enable_sdrc
 +      cmp     r3, #0x1
 +      blne    wait_dll_unlock
 +      cmp     r3, #0x2
 +      blne    wait_dll_lock
 +      cmp     r3, #0x1
 +      blne    configure_sdrc
 +      mov     r0, #0                  @ return value
 +      ldmfd   sp!, {r1-r12, pc}       @ restore regs and return
 +unlock_dll:
 +      ldr     r4, omap3_sdrc_dlla_ctrl
 +      ldr     r5, [r4]
 +      orr     r5, r5, #0x4
 +      str     r5, [r4]
 +      bx      lr
 +lock_dll:
 +      ldr     r4, omap3_sdrc_dlla_ctrl
 +      ldr     r5, [r4]
 +      bic     r5, r5, #0x4
 +      str     r5, [r4]
 +      bx      lr
 +sdram_in_selfrefresh:
 +      mov     r5, #0x0                @ Move 0 to R5
 +      mcr     p15, 0, r5, c7, c10, 5  @ memory barrier
 +      ldr     r4, omap3_sdrc_power    @ read the SDRC_POWER register
 +      ldr     r5, [r4]                @ read the contents of SDRC_POWER
 +      orr     r5, r5, #0x40           @ enable self refresh on idle req
 +      str     r5, [r4]                @ write back to SDRC_POWER register
 +      ldr     r4, omap3_cm_iclken1_core       @ read the CM_ICLKEN1_CORE reg
 +      ldr     r5, [r4]
 +      bic     r5, r5, #0x2            @ disable iclk bit for SRDC
 +      str     r5, [r4]
 +wait_sdrc_idle:
 +      ldr     r4, omap3_cm_idlest1_core
 +      ldr     r5, [r4]
 +      and     r5, r5, #0x2            @ check for SDRC idle
 +      cmp     r5, #2
 +      bne     wait_sdrc_idle
 +      bx      lr
 +configure_core_dpll:
 +      ldr     r4, omap3_cm_clksel1_pll
 +      ldr     r5, [r4]
 +      ldr     r6, core_m2_mask_val    @ modify m2 for core dpll
 +      and     r5, r5, r6
 +      orr     r5, r5, r3, lsl #0x1B   @ r3 contains the M2 val
 +      str     r5, [r4]
 +      mov     r5, #0x800              @ wait for the clock to stabilise
 +      cmp     r3, #2
 +      bne     wait_clk_stable
 +      bx      lr
 +wait_clk_stable:
 +      subs    r5, r5, #1
 +      bne     wait_clk_stable
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      nop
 +      bx      lr
 +enable_sdrc:
 +      ldr     r4, omap3_cm_iclken1_core
 +      ldr     r5, [r4]
 +      orr     r5, r5, #0x2            @ enable iclk bit for SDRC
 +      str     r5, [r4]
 +wait_sdrc_idle1:
 +      ldr     r4, omap3_cm_idlest1_core
 +      ldr     r5, [r4]
 +      and     r5, r5, #0x2
 +      cmp     r5, #0
 +      bne     wait_sdrc_idle1
 +      ldr     r4, omap3_sdrc_power
 +      ldr     r5, [r4]
 +      bic     r5, r5, #0x40
 +      str     r5, [r4]
 +      bx      lr
 +wait_dll_lock:
 +      ldr     r4, omap3_sdrc_dlla_status
 +      ldr     r5, [r4]
 +      and     r5, r5, #0x4
 +      cmp     r5, #0x4
 +      bne     wait_dll_lock
 +      bx      lr
 +wait_dll_unlock:
 +      ldr     r4, omap3_sdrc_dlla_status
 +      ldr     r5, [r4]
 +      and     r5, r5, #0x4
 +      cmp     r5, #0x0
 +      bne     wait_dll_unlock
 +      bx      lr
 +configure_sdrc:
 +      ldr     r4, omap3_sdrc_rfr_ctrl
 +      str     r0, [r4]
 +      ldr     r4, omap3_sdrc_actim_ctrla
 +      str     r1, [r4]
 +      ldr     r4, omap3_sdrc_actim_ctrlb
 +      str     r2, [r4]
 +      bx      lr
 +
 +omap3_sdrc_power:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 +omap3_cm_clksel1_pll:
 +      .word OMAP34XX_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
 +omap3_cm_idlest1_core:
 +      .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST)
 +omap3_cm_iclken1_core:
 +      .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
 +omap3_sdrc_rfr_ctrl:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0)
 +omap3_sdrc_actim_ctrla:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A)
 +omap3_sdrc_actim_ctrlb:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B)
 +omap3_sdrc_dlla_status:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 +omap3_sdrc_dlla_ctrl:
 +      .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 +core_m2_mask_val:
 +      .word 0x07FFFFFF
 +
 +ENTRY(omap3_sram_configure_core_dpll_sz)
 +      .word   . - omap3_sram_configure_core_dpll
Simple merge
index e178a0d4d920a956b99f50cb0fbb48ae3abc4a5d,0000000000000000000000000000000000000000..489439ddb0dd1f0eb0d84e6eaa4e5ee371e806e4
mode 100644,000000..100644
--- /dev/null
@@@ -1,165 -1,0 +1,165 @@@
- #include <asm/arch/mux.h>
 +/*
 + * linux/arch/arm/mach-omap2/usb-ehci.c
 + *
 + * This file will contain the board specific details for the
 + * Synopsys EHCI host controller on OMAP3430
 + *
 + * Copyright (C) 2007 Texas Instruments
 + * Author: Vikram Pandita <vikram.pandita@ti.com>
 + *
 + * Generalization by:
 + * Felipe Balbi <felipe.balbi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/types.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <asm/io.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/pm.h>
- #include <asm/arch/usb.h>
++#include <mach/mux.h>
 +#include <linux/usb/musb.h>
 +
++#include <mach/hardware.h>
++#include <mach/pm.h>
++#include <mach/usb.h>
 +
 +#if   defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
 +static struct resource ehci_resources[] = {
 +      [0] = {
 +              .start   = OMAP34XX_HSUSB_HOST_BASE + 0x800,
 +              .end     = OMAP34XX_HSUSB_HOST_BASE + 0x800 + SZ_1K - 1,
 +              .flags   = IORESOURCE_MEM,
 +      },
 +      [1] = {         /* general IRQ */
 +              .start   = INT_34XX_EHCI_IRQ,
 +              .flags   = IORESOURCE_IRQ,
 +      }
 +};
 +
 +static u64 ehci_dmamask = ~(u32)0;
 +static struct platform_device ehci_device = {
 +      .name           = "ehci-omap",
 +      .id             = 0,
 +      .dev = {
 +              .dma_mask               = &ehci_dmamask,
 +              .coherent_dma_mask      = 0xffffffff,
 +              .platform_data          = NULL,
 +      },
 +      .num_resources  = ARRAY_SIZE(ehci_resources),
 +      .resource       = ehci_resources,
 +};
 +
 +
 +/* MUX settings for EHCI pins */
 +/*
 + * setup_ehci_io_mux - initialize IO pad mux for USBHOST
 + */
 +static void setup_ehci_io_mux(void)
 +{
 +#ifdef CONFIG_OMAP_EHCI_PHY_MODE
 +      /* PHY mode of operation for board: 750-2083-001
 +       * ISP1504 connected to Port1 and Port2
 +       * Do Func Mux setting for 12-pin ULPI PHY mode
 +       */
 +
 +      /* Port1 */
 +      omap_cfg_reg(Y9_3430_USB1HS_PHY_STP);
 +      omap_cfg_reg(Y8_3430_USB1HS_PHY_CLK);
 +      omap_cfg_reg(AA14_3430_USB1HS_PHY_DIR);
 +      omap_cfg_reg(AA11_3430_USB1HS_PHY_NXT);
 +      omap_cfg_reg(W13_3430_USB1HS_PHY_DATA0);
 +      omap_cfg_reg(W12_3430_USB1HS_PHY_DATA1);
 +      omap_cfg_reg(W11_3430_USB1HS_PHY_DATA2);
 +      omap_cfg_reg(Y11_3430_USB1HS_PHY_DATA3);
 +      omap_cfg_reg(W9_3430_USB1HS_PHY_DATA4);
 +      omap_cfg_reg(Y12_3430_USB1HS_PHY_DATA5);
 +      omap_cfg_reg(W8_3430_USB1HS_PHY_DATA6);
 +      omap_cfg_reg(Y13_3430_USB1HS_PHY_DATA7);
 +
 +      /* Port2 */
 +      omap_cfg_reg(AA10_3430_USB2HS_PHY_STP);
 +      omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK);
 +      omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR);
 +      omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT);
 +      omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0);
 +      omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1);
 +      omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2);
 +      omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3);
 +      omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4);
 +      omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5);
 +      omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6);
 +      omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7);
 +
 +#else
 +      /* Set Func mux for :
 +       * TLL mode of operation
 +       * 12-pin ULPI SDR TLL mode for Port1/2/3
 +       */
 +
 +      /* Port1 */
 +      omap_cfg_reg(Y9_3430_USB1HS_TLL_STP);
 +      omap_cfg_reg(Y8_3430_USB1HS_TLL_CLK);
 +      omap_cfg_reg(AA14_3430_USB1HS_TLL_DIR);
 +      omap_cfg_reg(AA11_3430_USB1HS_TLL_NXT);
 +      omap_cfg_reg(W13_3430_USB1HS_TLL_DATA0);
 +      omap_cfg_reg(W12_3430_USB1HS_TLL_DATA1);
 +      omap_cfg_reg(W11_3430_USB1HS_TLL_DATA2);
 +      omap_cfg_reg(Y11_3430_USB1HS_TLL_DATA3);
 +      omap_cfg_reg(W9_3430_USB1HS_TLL_DATA4);
 +      omap_cfg_reg(Y12_3430_USB1HS_TLL_DATA5);
 +      omap_cfg_reg(W8_3430_USB1HS_TLL_DATA6);
 +      omap_cfg_reg(Y13_3430_USB1HS_TLL_DATA7);
 +
 +      /* Port2 */
 +      omap_cfg_reg(AA10_3430_USB2HS_TLL_STP);
 +      omap_cfg_reg(AA8_3430_USB2HS_TLL_CLK);
 +      omap_cfg_reg(AA9_3430_USB2HS_TLL_DIR);
 +      omap_cfg_reg(AB11_3430_USB2HS_TLL_NXT);
 +      omap_cfg_reg(AB10_3430_USB2HS_TLL_DATA0);
 +      omap_cfg_reg(AB9_3430_USB2HS_TLL_DATA1);
 +      omap_cfg_reg(W3_3430_USB2HS_TLL_DATA2);
 +      omap_cfg_reg(T4_3430_USB2HS_TLL_DATA3);
 +      omap_cfg_reg(T3_3430_USB2HS_TLL_DATA4);
 +      omap_cfg_reg(R3_3430_USB2HS_TLL_DATA5);
 +      omap_cfg_reg(R4_3430_USB2HS_TLL_DATA6);
 +      omap_cfg_reg(T2_3430_USB2HS_TLL_DATA7);
 +
 +      /* Port3 */
 +      omap_cfg_reg(AB3_3430_USB3HS_TLL_STP);
 +      omap_cfg_reg(AA6_3430_USB3HS_TLL_CLK);
 +      omap_cfg_reg(AA3_3430_USB3HS_TLL_DIR);
 +      omap_cfg_reg(Y3_3430_USB3HS_TLL_NXT);
 +      omap_cfg_reg(AA5_3430_USB3HS_TLL_DATA0);
 +      omap_cfg_reg(Y4_3430_USB3HS_TLL_DATA1);
 +      omap_cfg_reg(Y5_3430_USB3HS_TLL_DATA2);
 +      omap_cfg_reg(W5_3430_USB3HS_TLL_DATA3);
 +      omap_cfg_reg(AB12_3430_USB3HS_TLL_DATA4);
 +      omap_cfg_reg(AB13_3430_USB3HS_TLL_DATA5);
 +      omap_cfg_reg(AA13_3430_USB3HS_TLL_DATA6);
 +      omap_cfg_reg(AA12_3430_USB3HS_TLL_DATA7);
 +#endif /* CONFIG_OMAP_EHCI_PHY_MODE */
 +
 +      return;
 +}
 +
 +#endif /* EHCI specific data */
 +
 +void __init usb_ehci_init(void)
 +{
 +#if     defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
 +      /* Setup Pin IO MUX for EHCI */
 +      if (cpu_is_omap34xx())
 +              setup_ehci_io_mux();
 +
 +      if (platform_device_register(&ehci_device) < 0) {
 +              printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
 +              return;
 +      }
 +#endif
 +}
 +
index cbd59f8e81c0bec778524b98fb28611d48cd3768,0000000000000000000000000000000000000000..2a3593e7bfbce1051507dfdb05d03ec79c22a676
mode 100644,000000..100644
--- /dev/null
@@@ -1,116 -1,0 +1,116 @@@
- #include <asm/arch/mux.h>
 +/*
 + * linux/arch/arm/mach-omap2/usb-musb.c
 + *
 + * This file will contain the board specific details for the
 + * MENTOR USB OTG controller on OMAP3430
 + *
 + * Copyright (C) 2007-2008 Texas Instruments
 + * Copyright (C) 2008 Nokia Corporation
 + * Author: Vikram Pandita
 + *
 + * Generalization by:
 + * Felipe Balbi <felipe.balbi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/types.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <asm/io.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/pm.h>
- #include <asm/arch/usb.h>
++#include <mach/mux.h>
 +#include <linux/usb/musb.h>
 +
++#include <mach/hardware.h>
++#include <mach/pm.h>
++#include <mach/usb.h>
 +
 +#ifdef CONFIG_USB_MUSB_SOC
 +static struct resource musb_resources[] = {
 +      [0] = {
 +              .start  = cpu_is_omap34xx()
 +                      ? OMAP34XX_HSUSB_OTG_BASE
 +                      : OMAP243X_HS_BASE,
 +              .end    = cpu_is_omap34xx()
 +                      ? OMAP34XX_HSUSB_OTG_BASE + SZ_8K - 1
 +                      : OMAP243X_HS_BASE + SZ_8K -1,
 +              .flags  = IORESOURCE_MEM,
 +      },
 +      [1] = { /* general IRQ */
 +              .start  = INT_243X_HS_USB_MC,
 +              .flags  = IORESOURCE_IRQ,
 +      },
 +      [2] = { /* DMA IRQ */
 +              .start  = INT_243X_HS_USB_DMA,
 +              .flags  = IORESOURCE_IRQ,
 +      },
 +};
 +
 +static int clk_on;
 +
 +static int musb_set_clock(struct clk *clk, int state)
 +{
 +      if (state) {
 +              if (clk_on > 0)
 +                      return -ENODEV;
 +
 +              omap2_block_sleep();
 +              clk_enable(clk);
 +              clk_on = 1;
 +      } else {
 +              if (clk_on == 0)
 +                      return -ENODEV;
 +
 +              clk_disable(clk);
 +              clk_on = 0;
 +              omap2_allow_sleep();
 +      }
 +
 +      return 0;
 +}
 +
 +static struct musb_hdrc_platform_data musb_plat = {
 +#ifdef CONFIG_USB_MUSB_OTG
 +      .mode           = MUSB_OTG,
 +#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
 +      .mode           = MUSB_HOST,
 +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
 +      .mode           = MUSB_PERIPHERAL,
 +#endif
 +      .multipoint     = 1,
 +      .clock          = cpu_is_omap34xx()
 +                      ? "hsotgusb_ick"
 +                      : "usbhs_ick",
 +      .set_clock      = musb_set_clock,
 +};
 +
 +static u64 musb_dmamask = ~(u32)0;
 +
 +static struct platform_device musb_device = {
 +      .name           = "musb_hdrc",
 +      .id             = 0,
 +      .dev = {
 +              .dma_mask               = &musb_dmamask,
 +              .coherent_dma_mask      = 0xffffffff,
 +              .platform_data          = &musb_plat,
 +      },
 +      .num_resources  = ARRAY_SIZE(musb_resources),
 +      .resource       = musb_resources,
 +};
 +#endif
 +
 +
 +void __init usb_musb_init(void)
 +{
 +#ifdef CONFIG_USB_MUSB_SOC
 +      if (platform_device_register(&musb_device) < 0) {
 +              printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
 +              return;
 +      }
 +#endif
 +}
 +
Simple merge
index 253dfcf1ecc211b3e476d1f07819bd99907bd85c,0000000000000000000000000000000000000000..d527b1bb06f2858eb7cba8f84d053e69815f1955
mode 100644,000000..100644
--- /dev/null
@@@ -1,79 -1,0 +1,79 @@@
- #include <asm/arch/board.h>
 +/*
 + * linux/arch/arm/plat-omap/bootreason.c
 + *
 + * OMAP Bootreason passing
 + *
 + * Copyright (c) 2004 Nokia
 + *
 + * Written by David Weinehall <david.weinehall@nokia.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +#include <linux/proc_fs.h>
 +#include <linux/errno.h>
++#include <mach/board.h>
 +
 +static char boot_reason[16];
 +
 +static int omap_bootreason_read_proc(char *page, char **start, off_t off,
 +                                       int count, int *eof, void *data)
 +{
 +      int len = 0;
 +
 +      len += sprintf(page + len, "%s\n", boot_reason);
 +
 +      *start = page + off;
 +
 +      if (len > off)
 +              len -= off;
 +      else
 +              len = 0;
 +
 +      return len < count ? len  : count;
 +}
 +
 +static int __init bootreason_init(void)
 +{
 +      const struct omap_boot_reason_config *cfg;
 +      int reason_valid = 0;
 +
 +      cfg = omap_get_config(OMAP_TAG_BOOT_REASON, struct omap_boot_reason_config);
 +      if (cfg != NULL) {
 +              strncpy(boot_reason, cfg->reason_str, sizeof(cfg->reason_str));
 +              boot_reason[sizeof(cfg->reason_str)] = 0;
 +              reason_valid = 1;
 +      } else {
 +              /* Read the boot reason from the OMAP registers */
 +      }
 +
 +      if (!reason_valid)
 +              return -ENOENT;
 +
 +      printk(KERN_INFO "Bootup reason: %s\n", boot_reason);
 +
 +      if (!create_proc_read_entry("bootreason", S_IRUGO, NULL,
 +                                      omap_bootreason_read_proc, NULL))
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +
 +late_initcall(bootreason_init);
Simple merge
index a9fe63d5e729452d9b29ccd7fbfabbe315c7b9fa,0000000000000000000000000000000000000000..3c9d5230cd827d3f1e73e3694e19a5f17fbf8438
mode 100644,000000..100644
--- /dev/null
@@@ -1,65 -1,0 +1,65 @@@
- #include <asm/arch/board.h>
- #include <asm/arch/board-nokia.h>
 +/*
 + *  linux/arch/arm/plat-omap/component-version.c
 + *
 + *  Copyright (C) 2005 Nokia Corporation
 + *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/init.h>
 +#include <linux/module.h>
 +#include <linux/err.h>
 +#include <linux/proc_fs.h>
++#include <mach/board.h>
++#include <mach/board-nokia.h>
 +
 +static int component_version_read_proc(char *page, char **start, off_t off,
 +                                     int count, int *eof, void *data)
 +{
 +      int len, i;
 +      const struct omap_version_config *ver;
 +      char *p;
 +
 +      i = 0;
 +      p = page;
 +      while ((ver = omap_get_nr_config(OMAP_TAG_VERSION_STR,
 +                                       struct omap_version_config, i)) != NULL) {
 +              p += sprintf(p, "%-12s%s\n", ver->component, ver->version);
 +              i++;
 +      }
 +
 +      len = (p - page) - off;
 +      if (len < 0)
 +              len = 0;
 +
 +      *eof = (len <= count) ? 1 : 0;
 +      *start = page + off;
 +
 +      return len;
 +}
 +
 +static int __init component_version_init(void)
 +{
 +      if (omap_get_config(OMAP_TAG_VERSION_STR, struct omap_version_config) == NULL)
 +              return -ENODEV;
 +      if (!create_proc_read_entry("component_version", S_IRUGO, NULL,
 +                                  component_version_read_proc, NULL))
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +
 +static void __exit component_version_exit(void)
 +{
 +      remove_proc_entry("component_version", NULL);
 +}
 +
 +late_initcall(component_version_init);
 +module_exit(component_version_exit);
 +
 +MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>");
 +MODULE_DESCRIPTION("Component version driver");
 +MODULE_LICENSE("GPL");
index fc6cd5e2b081d6b4e4d57d9fa74bb8747c67f61e,ae1de308aaad2e5c9db136e8c9ed3d4841db976d..dbfcca908519c0d4e89e77261c1c1df6130bff4a
  #include <linux/err.h>
  #include <linux/clk.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/io.h>
  #include <asm/system.h>
- #include <asm/arch/clock.h>
++#include <mach/clock.h>
  
  #define VERY_HI_RATE  900000000
  
index 5a11311977520ff14abcf4b15377c8594365a654,187e3d8bfdfe89512a454c128b0de4d8cb97a3b6..f22ccbb280cf37541e637c29526c6a9e84874df7
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/platform_device.h>
 +#include <linux/i2c/menelaus.h>
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/io.h>
  #include <asm/mach-types.h>
  #include <asm/mach/map.h>
  
- #include <asm/arch/tc.h>
- #include <asm/arch/control.h>
- #include <asm/arch/board.h>
- #include <asm/arch/mmc.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/dsp_common.h>
- #include <asm/arch/mcbsp.h>
+ #include <mach/tc.h>
++#include <mach/control.h>
+ #include <mach/board.h>
++#include <mach/mmc.h>
+ #include <mach/mux.h>
+ #include <mach/gpio.h>
 -#include <mach/menelaus.h>
++#include <mach/dsp_common.h>
+ #include <mach/mcbsp.h>
  
  #if   defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
  
Simple merge
index 7c94fc3c080bd3eb854d30ad9c8e0d1505e85e56,0000000000000000000000000000000000000000..f2dd67a676452abf09694dee3c295ffcb9da2f2c
mode 100644,000000..100644
--- /dev/null
@@@ -1,550 -1,0 +1,550 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/irqs.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/board.h>
- #include <asm/arch/gpio-switch.h>
 +/*
 + *  linux/arch/arm/plat-omap/gpio-switch.c
 + *
 + *  Copyright (C) 2004-2006 Nokia Corporation
 + *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
 + *         and Paul Mundt <paul.mundt@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/init.h>
 +#include <linux/list.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/timer.h>
 +#include <linux/err.h>
++#include <mach/hardware.h>
++#include <mach/gpio.h>
++#include <mach/irqs.h>
++#include <mach/mux.h>
++#include <mach/board.h>
++#include <mach/gpio-switch.h>
 +
 +struct gpio_switch {
 +      char            name[14];
 +      u16             gpio;
 +      unsigned        flags:4;
 +      unsigned        type:4;
 +      unsigned        state:1;
 +      unsigned        both_edges:1;
 +
 +      u16             debounce_rising;
 +      u16             debounce_falling;
 +
 +      void (* notify)(void *data, int state);
 +      void *notify_data;
 +
 +      struct work_struct      work;
 +      struct timer_list       timer;
 +      struct platform_device  pdev;
 +
 +      struct list_head        node;
 +};
 +
 +static LIST_HEAD(gpio_switches);
 +static struct platform_device *gpio_sw_platform_dev;
 +static struct platform_driver gpio_sw_driver;
 +
 +static const struct omap_gpio_switch *board_gpio_sw_table;
 +static int board_gpio_sw_count;
 +
 +static const char *cover_str[2] = { "open", "closed" };
 +static const char *connection_str[2] = { "disconnected", "connected" };
 +static const char *activity_str[2] = { "inactive", "active" };
 +
 +/*
 + * GPIO switch state default debounce delay in ms
 + */
 +#define OMAP_GPIO_SW_DEFAULT_DEBOUNCE         10
 +
 +static const char **get_sw_str(struct gpio_switch *sw)
 +{
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +              return cover_str;
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +              return connection_str;
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              return activity_str;
 +      default:
 +              BUG();
 +              return NULL;
 +      }
 +}
 +
 +static const char *get_sw_type(struct gpio_switch *sw)
 +{
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +              return "cover";
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +              return "connection";
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              return "activity";
 +      default:
 +              BUG();
 +              return NULL;
 +      }
 +}
 +
 +static void print_sw_state(struct gpio_switch *sw, int state)
 +{
 +      const char **str;
 +
 +      str = get_sw_str(sw);
 +      if (str != NULL)
 +              printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]);
 +}
 +
 +static int gpio_sw_get_state(struct gpio_switch *sw)
 +{
 +      int state;
 +
 +      state = omap_get_gpio_datain(sw->gpio);
 +      if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +              state = !state;
 +
 +      return state;
 +}
 +
 +static ssize_t gpio_sw_state_store(struct device *dev,
 +                                 struct device_attribute *attr,
 +                                 const char *buf,
 +                                 size_t count)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      const char **str;
 +      char state[16];
 +      int enable;
 +
 +      if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT))
 +              return -EPERM;
 +
 +      if (sscanf(buf, "%15s", state) != 1)
 +              return -EINVAL;
 +
 +      str = get_sw_str(sw);
 +      if (strcmp(state, str[0]) == 0)
 +              sw->state = enable = 0;
 +      else if (strcmp(state, str[1]) == 0)
 +              sw->state = enable = 1;
 +      else
 +              return -EINVAL;
 +
 +      if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +              enable = !enable;
 +      omap_set_gpio_dataout(sw->gpio, enable);
 +
 +      return count;
 +}
 +
 +static ssize_t gpio_sw_state_show(struct device *dev,
 +                                struct device_attribute *attr,
 +                                char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      const char **str;
 +
 +      str = get_sw_str(sw);
 +      return sprintf(buf, "%s\n", str[sw->state]);
 +}
 +
 +static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show,
 +                 gpio_sw_state_store);
 +
 +static ssize_t gpio_sw_type_show(struct device *dev,
 +                               struct device_attribute *attr,
 +                               char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%s\n", get_sw_type(sw));
 +}
 +
 +static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL);
 +
 +static ssize_t gpio_sw_direction_show(struct device *dev,
 +                                    struct device_attribute *attr,
 +                                    char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      int is_output;
 +
 +      is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT;
 +      return sprintf(buf, "%s\n", is_output ? "output" : "input");
 +}
 +
 +static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL);
 +
 +
 +static irqreturn_t gpio_sw_irq_handler(int irq, void *arg)
 +{
 +      struct gpio_switch *sw = arg;
 +      unsigned long timeout;
 +      int state;
 +
 +      if (!sw->both_edges) {
 +              if (omap_get_gpio_datain(sw->gpio))
 +                      set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_FALLING);
 +              else
 +                      set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_RISING);
 +      }
 +
 +      state = gpio_sw_get_state(sw);
 +      if (sw->state == state)
 +              return IRQ_HANDLED;
 +
 +      if (state)
 +              timeout = sw->debounce_rising;
 +      else
 +              timeout = sw->debounce_falling;
 +      if (!timeout)
 +              schedule_work(&sw->work);
 +      else
 +              mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout));
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static void gpio_sw_timer(unsigned long arg)
 +{
 +      struct gpio_switch *sw = (struct gpio_switch *) arg;
 +
 +      schedule_work(&sw->work);
 +}
 +
 +static void gpio_sw_handler(struct work_struct *work)
 +{
 +      struct gpio_switch *sw = container_of(work, struct gpio_switch, work);
 +      int state;
 +
 +      state = gpio_sw_get_state(sw);
 +      if (sw->state == state)
 +              return;
 +
 +      sw->state = state;
 +      if (sw->notify != NULL)
 +              sw->notify(sw->notify_data, state);
 +      sysfs_notify(&sw->pdev.dev.kobj, NULL, "state");
 +      print_sw_state(sw, state);
 +}
 +
 +static int __init can_do_both_edges(struct gpio_switch *sw)
 +{
 +      if (!cpu_class_is_omap1())
 +              return 1;
 +      if (OMAP_GPIO_IS_MPUIO(sw->gpio))
 +              return 0;
 +      else
 +              return 1;
 +}
 +
 +static void gpio_sw_release(struct device *dev)
 +{
 +}
 +
 +static int __init new_switch(struct gpio_switch *sw)
 +{
 +      int r, direction, trigger;
 +
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              break;
 +      default:
 +              printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type);
 +              return -EINVAL;
 +      }
 +
 +      sw->pdev.name   = sw->name;
 +      sw->pdev.id     = -1;
 +
 +      sw->pdev.dev.parent = &gpio_sw_platform_dev->dev;
 +      sw->pdev.dev.driver = &gpio_sw_driver.driver;
 +      sw->pdev.dev.release = gpio_sw_release;
 +
 +      r = platform_device_register(&sw->pdev);
 +      if (r) {
 +              printk(KERN_ERR "gpio-switch: platform device registration "
 +                     "failed for %s", sw->name);
 +              return r;
 +      }
 +      dev_set_drvdata(&sw->pdev.dev, sw);
 +
 +      r = omap_request_gpio(sw->gpio);
 +      if (r < 0) {
 +              platform_device_unregister(&sw->pdev);
 +              return r;
 +      }
 +
 +      /* input: 1, output: 0 */
 +      direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT);
 +      omap_set_gpio_direction(sw->gpio, direction);
 +
 +      sw->state = gpio_sw_get_state(sw);
 +
 +      r = 0;
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_state);
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_type);
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_direction);
 +      if (r)
 +              printk(KERN_ERR "gpio-switch: attribute file creation "
 +                     "failed for %s\n", sw->name);
 +
 +      if (!direction)
 +              return 0;
 +
 +      if (can_do_both_edges(sw)) {
 +              trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
 +              sw->both_edges = 1;
 +      } else {
 +              if (omap_get_gpio_datain(sw->gpio))
 +                      trigger = IRQF_TRIGGER_FALLING;
 +              else
 +                      trigger = IRQF_TRIGGER_RISING;
 +      }
 +      r = request_irq(OMAP_GPIO_IRQ(sw->gpio), gpio_sw_irq_handler,
 +                      IRQF_SHARED | trigger, sw->name, sw);
 +      if (r < 0) {
 +              printk(KERN_ERR "gpio-switch: request_irq() failed "
 +                     "for GPIO %d\n", sw->gpio);
 +              platform_device_unregister(&sw->pdev);
 +              omap_free_gpio(sw->gpio);
 +              return r;
 +      }
 +
 +      INIT_WORK(&sw->work, gpio_sw_handler);
 +      init_timer(&sw->timer);
 +
 +      sw->timer.function = gpio_sw_timer;
 +      sw->timer.data = (unsigned long)sw;
 +
 +      list_add(&sw->node, &gpio_switches);
 +
 +      return 0;
 +}
 +
 +static int __init add_atag_switches(void)
 +{
 +      const struct omap_gpio_switch_config *cfg;
 +      struct gpio_switch *sw;
 +      int i, r;
 +
 +      for (i = 0; ; i++) {
 +              cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH,
 +                                       struct omap_gpio_switch_config, i);
 +              if (cfg == NULL)
 +                      break;
 +              sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 +              if (sw == NULL) {
 +                      printk(KERN_ERR "gpio-switch: kmalloc failed\n");
 +                      return -ENOMEM;
 +              }
 +              strncpy(sw->name, cfg->name, sizeof(cfg->name));
 +              sw->gpio = cfg->gpio;
 +              sw->flags = cfg->flags;
 +              sw->type = cfg->type;
 +              sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
 +              sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
 +              if ((r = new_switch(sw)) < 0) {
 +                      kfree(sw);
 +                      return r;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static struct gpio_switch * __init find_switch(int gpio, const char *name)
 +{
 +      struct gpio_switch *sw;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              if ((gpio < 0 || sw->gpio != gpio) &&
 +                  (name == NULL || strcmp(sw->name, name) != 0))
 +                      continue;
 +
 +              if (gpio < 0 || name == NULL)
 +                      goto no_check;
 +
 +              if (strcmp(sw->name, name) != 0)
 +                      printk("gpio-switch: name mismatch for %d (%s, %s)\n",
 +                             gpio, name, sw->name);
 +              else if (sw->gpio != gpio)
 +                      printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n",
 +                             name, gpio, sw->gpio);
 +no_check:
 +              return sw;
 +      }
 +      return NULL;
 +}
 +
 +static int __init add_board_switches(void)
 +{
 +      int i;
 +
 +      for (i = 0; i < board_gpio_sw_count; i++) {
 +              const struct omap_gpio_switch *cfg;
 +              struct gpio_switch *sw;
 +              int r;
 +
 +              cfg = board_gpio_sw_table + i;
 +              if (strlen(cfg->name) > sizeof(sw->name) - 1)
 +                      return -EINVAL;
 +              /* Check whether we only update an existing switch
 +               * or add a new switch. */
 +              sw = find_switch(cfg->gpio, cfg->name);
 +              if (sw != NULL) {
 +                      sw->debounce_rising = cfg->debounce_rising;
 +                      sw->debounce_falling = cfg->debounce_falling;
 +                      sw->notify = cfg->notify;
 +                      sw->notify_data = cfg->notify_data;
 +                      continue;
 +              } else {
 +                      if (cfg->gpio < 0 || cfg->name == NULL) {
 +                              printk("gpio-switch: required switch not "
 +                                     "found (%d, %s)\n", cfg->gpio,
 +                                     cfg->name);
 +                              continue;
 +                      }
 +              }
 +              sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 +              if (sw == NULL) {
 +                      printk(KERN_ERR "gpio-switch: kmalloc failed\n");
 +                      return -ENOMEM;
 +              }
 +              strlcpy(sw->name, cfg->name, sizeof(sw->name));
 +              sw->gpio = cfg->gpio;
 +              sw->flags = cfg->flags;
 +              sw->type = cfg->type;
 +              sw->debounce_rising = cfg->debounce_rising;
 +              sw->debounce_falling = cfg->debounce_falling;
 +              sw->notify = cfg->notify;
 +              sw->notify_data = cfg->notify_data;
 +              if ((r = new_switch(sw)) < 0) {
 +                      kfree(sw);
 +                      return r;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static void gpio_sw_cleanup(void)
 +{
 +      struct gpio_switch *sw = NULL, *old = NULL;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              if (old != NULL)
 +                      kfree(old);
 +              flush_scheduled_work();
 +              del_timer_sync(&sw->timer);
 +
 +              free_irq(OMAP_GPIO_IRQ(sw->gpio), sw);
 +
 +              device_remove_file(&sw->pdev.dev, &dev_attr_state);
 +              device_remove_file(&sw->pdev.dev, &dev_attr_type);
 +              device_remove_file(&sw->pdev.dev, &dev_attr_direction);
 +
 +              platform_device_unregister(&sw->pdev);
 +              omap_free_gpio(sw->gpio);
 +              old = sw;
 +      }
 +      kfree(old);
 +}
 +
 +static void __init report_initial_state(void)
 +{
 +      struct gpio_switch *sw;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              int state;
 +
 +              state = omap_get_gpio_datain(sw->gpio);
 +              if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +                      state = !state;
 +              if (sw->notify != NULL)
 +                      sw->notify(sw->notify_data, state);
 +              print_sw_state(sw, state);
 +      }
 +}
 +
 +static int gpio_sw_remove(struct platform_device *dev)
 +{
 +      return 0;
 +}
 +
 +static struct platform_driver gpio_sw_driver = {
 +      .remove         = gpio_sw_remove,
 +      .driver         = {
 +              .name   = "gpio-switch",
 +      },
 +};
 +
 +void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
 +                                      int count)
 +{
 +      BUG_ON(board_gpio_sw_table != NULL);
 +
 +      board_gpio_sw_table = tbl;
 +      board_gpio_sw_count = count;
 +}
 +
 +static int __init gpio_sw_init(void)
 +{
 +      int r;
 +
 +      printk(KERN_INFO "OMAP GPIO switch handler initializing\n");
 +
 +      r = platform_driver_register(&gpio_sw_driver);
 +      if (r)
 +              return r;
 +
 +      gpio_sw_platform_dev = platform_device_register_simple("gpio-switch",
 +                                                             -1, NULL, 0);
 +      if (IS_ERR(gpio_sw_platform_dev)) {
 +              r = PTR_ERR(gpio_sw_platform_dev);
 +              goto err1;
 +      }
 +
 +      r = add_atag_switches();
 +      if (r < 0)
 +              goto err2;
 +
 +      r = add_board_switches();
 +      if (r < 0)
 +              goto err2;
 +
 +      report_initial_state();
 +
 +      return 0;
 +err2:
 +      gpio_sw_cleanup();
 +      platform_device_unregister(gpio_sw_platform_dev);
 +err1:
 +      platform_driver_unregister(&gpio_sw_driver);
 +      return r;
 +}
 +
 +static void __exit gpio_sw_exit(void)
 +{
 +      gpio_sw_cleanup();
 +      platform_device_unregister(gpio_sw_platform_dev);
 +      platform_driver_unregister(&gpio_sw_driver);
 +}
 +
 +#ifndef MODULE
 +late_initcall(gpio_sw_init);
 +#else
 +module_init(gpio_sw_init);
 +#endif
 +module_exit(gpio_sw_exit);
 +
 +MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com");
 +MODULE_DESCRIPTION("GPIO switch driver");
 +MODULE_LICENSE("GPL");
Simple merge
index aec2d65636229a5a49b05e970481eaf2386986db,5ccedac775268aa4b197a1ce1e9394a4a8db7816..188fe8b1308892feb5c4c82c5eef49ead206c7da
  #define TLV320AIC23ID1                  (0x1a)        // cs low
  #define TLV320AIC23ID2                  (0x1b)        // cs high
  
--void aic23_power_up(void);
--void aic23_power_down(void);
++#ifdef CONFIG_SENSORS_TLV320AIC23
++extern void aic23_power_up(void);
++extern void aic23_power_down(void);
++#else
++static inline void aic23_power_up(void)
++{
++}
++
++static inline void aic23_power_down(void)
++{
++}
++#endif
  
  #endif /* __ASM_ARCH_AIC23_H */
index 51eb8a572923a25990aeefd304f326a4676a1db6,0000000000000000000000000000000000000000..9baf59e24c5faf806a3c0971d10d21012b7184d0
mode 100644,000000..100644
--- /dev/null
@@@ -1,17 -1,0 +1,17 @@@
-  *  linux/include/asm-arm/arch-omap/bci.h
 +/*
++ *  arch/arm/plat-omap/include/mach/bci.h
 + *
 + *  Copyright (C) 2008 Texas Instruments, Inc.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#ifndef ASMARM_ARCH_BCI_H
 +#define ASMARM_ARCH_BCI_H
 +struct twl4030_bci_platform_data {
 +      int *battery_tmp_tbl;
 +      unsigned int tblsize;
 +};
 +#endif
 +
index 60d915b3725293f82c9ca0f09edef4a90035a4bb,0000000000000000000000000000000000000000..67d3f784f8ff9d241a66179706bcdf8ad1eef6c0
mode 100644,000000..100644
--- /dev/null
@@@ -1,72 -1,0 +1,72 @@@
-  * linux/include/asm-arm/arch-omap/board-3430sdp.h
 +/*
++ * arch/arm/plat-omap/include/mach/board-3430sdp.h
 + *
 + * Hardware definitions for TI OMAP3430 SDP board.
 + *
 + * Initial creation by Syed Mohammed Khasim
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP_3430SDP_H
 +#define __ASM_ARCH_OMAP_3430SDP_H
 +
 +extern void sdp3430_usb_init(void);
 +extern void sdp3430_flash_init(void);
 +extern void twl4030_bci_battery_init(void);
 +
 +#define DEBUG_BASE                    0x08000000  /* debug board */
 +
 +/* Placeholder for 3430SDP specific defines */
 +
 +#define OMAP34XX_ETHR_START           DEBUG_BASE
 +#define OMAP34XX_ETHR_GPIO_IRQ_SDPV1  29
 +#define OMAP34XX_ETHR_GPIO_IRQ_SDPV2  6
 +
 +/*
 + * GPIO used for TSC2046, TI's Touchscreen controller
 + */
 +#define OMAP34XX_TS_GPIO_IRQ_SDPV1     3
 +#define OMAP34XX_TS_GPIO_IRQ_SDPV2     2
 +
 +/* NAND */
 +/* IMPORTANT NOTE ON MAPPING
 + * 3430SDP - 34XX
 + * ----------
 + * NOR always on 0x04000000 for SDPV1
 + * NOR always on 0x10000000 for SDPV2
 + * MPDB always on 0x08000000
 + * NAND always on 0x0C000000
 + * OneNand Mapped to 0x20000000
 + * Boot Mode(NAND/NOR). The other on CS1
 + */
 +#define FLASH_BASE_SDPV1      0x04000000 /* NOR flash (64 Meg aligned) */
 +#define FLASH_BASE_SDPV2      0x10000000 /* NOR flash (256 Meg aligned) */
 +#define DEBUG_BASE            0x08000000 /* debug board */
 +#define NAND_BASE             0x0C000000 /* NAND flash */
 +#define ONENAND_MAP           0x20000000 /* OneNand flash */
 +
 +/* various memory sizes */
 +#define FLASH_SIZE_SDPV1      SZ_64M
 +#define FLASH_SIZE_SDPV2      SZ_128M
 +
 +#endif /* __ASM_ARCH_OMAP_3430SDP_H */
 +
index 9cc2ff7e40ade8f133232db88509f86a91a33ad5,1470cd3e519b80d746388cb0414b0fa59f596d43..7c3fa0f0a65e1512b2efe9e55debfe199d87a789
@@@ -1,7 -1,7 +1,7 @@@
  /*
-  * linux/include/asm-arm/arch-omap/board-h4.h
+  * arch/arm/plat-omap/include/mach/board-h4.h
   *
 - * Hardware definitions for TI OMAP1610 H4 board.
 + * Hardware definitions for TI OMAP2420 H4 board.
   *
   * Initial creation by Dirk Behme <dirk.behme@de.bosch.com>
   *
index b22756136cbadf5a4fb8dda66891739cdd422209,0000000000000000000000000000000000000000..283fa01c9b246a78b10ffaef18b143f86be33e03
mode 100644,000000..100644
--- /dev/null
@@@ -1,34 -1,0 +1,34 @@@
-  * linux/include/asm-arm/arch-omap/board-ldp.h
 +/*
++ * arch/arm/plat-omap/include/mach/board-ldp.h
 + *
 + * Hardware definitions for TI OMAP3 LDP.
 + *
 + * Copyright (C) 2008 Texas Instruments Inc.
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP_LDP_H
 +#define __ASM_ARCH_OMAP_LDP_H
 +
 +#define TWL4030_IRQNUM                INT_34XX_SYS_NIRQ
 +
 +#endif /* __ASM_ARCH_OMAP_LDP_H */
index d770c5824c162804c50a42f695c1e89fd92df869,0000000000000000000000000000000000000000..ec548d4b70504e4863281ebc219f08742b8569a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,37 -1,0 +1,37 @@@
-  * linux/include/asm-arm/arch-omap/board-omap2evm.h
 +/*
++ * arch/arm/plat-omap/include/mach/board-omap2evm.h
 + *
 + * Hardware definitions for Mistral's OMAP2EVM board.
 + *
 + * Based on board-2430sdp.h
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP2_EVM_H
 +#define __ASM_ARCH_OMAP2_EVM_H
 +
 +/* Placeholder for OMAP2EVM specific defines */
 +#define OMAP2EVM_ETHR_START                   0x2c000000
 +#define OMAP2EVM_ETHR_SIZE                    1024
 +#define OMAP2EVM_ETHR_GPIO_IRQ                149
 +
 +#endif /* __ASM_ARCH_OMAP2_EVM_H */
index 46dff31032e1611cfc72092c0a6d3ddc162429e5,0000000000000000000000000000000000000000..3080d52d877a3997a194580477c32dcdf84d821b
mode 100644,000000..100644
--- /dev/null
@@@ -1,33 -1,0 +1,33 @@@
-  * linux/include/asm-arm/arch-omap/board-omap3beagle.h
 +/*
++ * arch/arm/plat-omap/include/mach/board-omap3beagle.h
 + *
 + * Hardware definitions for TI OMAP3 BEAGLE.
 + *
 + * Initial creation by Syed Mohammed Khasim <khasim@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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP3_BEAGLE_H
 +#define __ASM_ARCH_OMAP3_BEAGLE_H
 +
 +#endif /* __ASM_ARCH_OMAP3_BEAGLE_H */
 +
index 784d7f2f830652c735cd8f1331a278018ee7e498,0000000000000000000000000000000000000000..7a540e9e1af654856b55cc04583f59c8711c43ca
mode 100644,000000..100644
--- /dev/null
@@@ -1,44 -1,0 +1,44 @@@
-  * linux/include/asm-arm/arch-omap/board-omap3evm.h
 +/*
++ * arch/arm/plat-omap/include/mach/board-omap3evm.h
 + *
 + * Hardware definitions for TI OMAP3 EVM.
 + *
 + * Initial creation by Syed Mohammed Khasim <khasim@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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP3_EVM_H
 +#define __ASM_ARCH_OMAP3_EVM_H
 +
 +extern void omap3evm_flash_init(void);
 +
 +#define OMAP3_EVM_TS_GPIO     175
 +
 +#define ONENAND_MAP           0x20000000
 +
 +#define OMAP3EVM_ETHR_START   0x2c000000
 +#define OMAP3EVM_ETHR_SIZE    1024
 +#define OMAP3EVM_ETHR_GPIO_IRQ        176
 +#define OMAP3EVM_SMC911X_CS   5
 +
 +#endif /* __ASM_ARCH_OMAP3_EVM_H */
 +
index b58bb73b5895b1973e10c901d43ec064185460da,0000000000000000000000000000000000000000..b9d0dd2da89b4f4f47378e31157e895639e30d29
mode 100644,000000..100644
--- /dev/null
@@@ -1,110 -1,0 +1,110 @@@
-  * linux/include/asm-arm/arch-omap/clockdomain.h
 +/*
- #include <asm/arch/powerdomain.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/cpu.h>
++ * arch/arm/plat-omap/include/mach/clockdomain.h
 + *
 + * OMAP2/3 clockdomain framework functions
 + *
 + * Copyright (C) 2008 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
 +#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
 +
++#include <mach/powerdomain.h>
++#include <mach/clock.h>
++#include <mach/cpu.h>
 +
 +/* Clockdomain capability flags */
 +#define CLKDM_CAN_FORCE_SLEEP                 (1 << 0)
 +#define CLKDM_CAN_FORCE_WAKEUP                        (1 << 1)
 +#define CLKDM_CAN_ENABLE_AUTO                 (1 << 2)
 +#define CLKDM_CAN_DISABLE_AUTO                        (1 << 3)
 +
 +#define CLKDM_CAN_HWSUP               (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 +#define CLKDM_CAN_SWSUP               (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
 +#define CLKDM_CAN_HWSUP_SWSUP (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
 +
 +/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
 +#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO               0x0
 +#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO                0x1
 +
 +/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
 +#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO               0x0
 +#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP                0x1
 +#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP               0x2
 +#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO                0x3
 +
 +/*
 + * struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps
 + * and sleepdeps added when a powerdomain should stay active in hwsup mode;
 + * and conversely, removed when the powerdomain should be allowed to go
 + * inactive in hwsup mode.
 + */
 +struct clkdm_pwrdm_autodep {
 +
 +      union {
 +              /* Name of the powerdomain to add a wkdep/sleepdep on */
 +              const char *name;
 +
 +              /* Powerdomain pointer (looked up at clkdm_init() time) */
 +              struct powerdomain *ptr;
 +      } pwrdm;
 +
 +      /* OMAP chip types that this clockdomain dep is valid on */
 +      const struct omap_chip_id omap_chip;
 +
 +};
 +
 +struct clockdomain {
 +
 +      /* Clockdomain name */
 +      const char *name;
 +
 +      union {
 +              /* Powerdomain enclosing this clockdomain */
 +              const char *name;
 +
 +              /* Powerdomain pointer assigned at clkdm_register() */
 +              struct powerdomain *ptr;
 +      } pwrdm;
 +
 +      /* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
 +      const u16 clktrctrl_mask;
 +
 +      /* Clockdomain capability flags */
 +      const u8 flags;
 +
 +      /* OMAP chip types that this clockdomain is valid on */
 +      const struct omap_chip_id omap_chip;
 +
 +      /* Usecount tracking */
 +      atomic_t usecount;
 +
 +      struct list_head node;
 +
 +};
 +
 +void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps);
 +int clkdm_register(struct clockdomain *clkdm);
 +int clkdm_unregister(struct clockdomain *clkdm);
 +struct clockdomain *clkdm_lookup(const char *name);
 +
 +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm));
 +struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 +
 +void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
 +void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
 +
 +int omap2_clkdm_wakeup(struct clockdomain *clkdm);
 +int omap2_clkdm_sleep(struct clockdomain *clkdm);
 +
 +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
 +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 +
 +#endif
index 6e64fe76016b2904d5727f7a24c8d13c77fd131e,e3fd62d9a995115bc2514807a8203f52dfe31684..e15d6e988185df252e0b302048a4109419de6ffe
   * the Free Software Foundation.
   */
  
- #include <asm/arch/io.h>
 +#ifndef __ASM_ARCH_CONTROL_H
 +#define __ASM_ARCH_CONTROL_H
 +
+ #include <mach/io.h>
  
 +#ifndef __ASSEMBLY__
  #define OMAP242X_CTRL_REGADDR(reg)                                    \
 -      (void __iomem *)IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
 +      (__force void __iomem *)IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
  #define OMAP243X_CTRL_REGADDR(reg)                                    \
 -      (void __iomem *)IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
 +      (__force void __iomem *)IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
  #define OMAP343X_CTRL_REGADDR(reg)                                    \
 -      (void __iomem *)IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
 +      (__force void __iomem *)IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
 +#else
 +#define OMAP242X_CTRL_REGADDR(reg)    IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
 +#define OMAP243X_CTRL_REGADDR(reg)    IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
 +#define OMAP343X_CTRL_REGADDR(reg)    IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
 +#endif /* __ASSEMBLY__ */
  
  /*
   * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
Simple merge
index ae71eb80483756d72669a49fc8b8cd5eafa2e6c2,0000000000000000000000000000000000000000..ae71eb80483756d72669a49fc8b8cd5eafa2e6c2
mode 100644,000000..100644
--- /dev/null
index 5951fdb9f8ff91d5cd523a13d20b927958085aaa,d4e9043bf2013c23b08f34c9eefcba9322059c45..a8fca9d9845b00102ba036958736452a78b89a54
  1510:
                .endm
  
 -#elif defined(CONFIG_ARCH_OMAP24XX)
 +#endif
 +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
  
- #include <asm/arch/omap24xx.h>
 +#if defined(CONFIG_ARCH_OMAP24XX)
- #include <asm/arch/omap34xx.h>
+ #include <mach/omap24xx.h>
 +#endif
 +#if defined(CONFIG_ARCH_OMAP34XX)
++#include <mach/omap34xx.h>
 +#endif
 +
 +#define INTCPS_SIR_IRQ_OFFSET 0x0040          /* Active interrupt number */
  
                .macro  disable_fiq
                .endm
index 74c84328761b43f8013db45c37db6a7bc2374459,0000000000000000000000000000000000000000..74c84328761b43f8013db45c37db6a7bc2374459
mode 100644,000000..100644
--- /dev/null
index 587e8abb33acb959e037369f3b14e5f1b2a9a750,0000000000000000000000000000000000000000..587e8abb33acb959e037369f3b14e5f1b2a9a750
mode 100644,000000..100644
--- /dev/null
Simple merge
index f901e8b42577b7dd31dd008fa2a7b720409e59dd,17248bbf3f27e5bbfe3dfc0d54bf260183f80bfa..e51e5e65920c839e243e74fc910e0650cf5eccd5
  
  #ifndef __ASSEMBLY__
  extern void omap_init_irq(void);
 +extern int omap_irq_pending(void);
  #endif
  
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  
  #endif
Simple merge
index d970b71a4905cfbe6e964094145e13a0c7908343,0000000000000000000000000000000000000000..d970b71a4905cfbe6e964094145e13a0c7908343
mode 100644,000000..100644
--- /dev/null
Simple merge
index 58879bcec0cd153ce34611f8bdc955d856e9819f,bdf30a0f87f2f2c81a0477bfff20a38a714b78c8..b0341e7a0cfa412affe303f4929a10b389eaf75b
  #ifndef __OMAP_ALSA_H
  #define __OMAP_ALSA_H
  
- #include <asm/arch/dma.h>
+ #include <mach/dma.h>
  #include <sound/core.h>
  #include <sound/pcm.h>
- #include <asm/arch/mcbsp.h>
+ #include <mach/mcbsp.h>
  #include <linux/platform_device.h>
 +/*
 + * Debug functions
 + */
 +#undef DEBUG
 +/* #define DEBUG */
 +
 +#define ERR(ARGS...)                                          \
 +      do {                                                    \
 +              printk(KERN_ERR "{%s}-ERROR: ", __func__);      \
 +              printk(ARGS);                                   \
 +      } while (0)
 +
 +#ifdef DEBUG
 +#define DPRINTK(ARGS...)                                      \
 +      do {                                                    \
 +              printk(KERN_INFO "<%s>: ", __func__);           \
 +              printk(ARGS);                                   \
 +      } while (0)
 +#define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __func__, __LINE__)
 +#define FN_IN printk(KERN_INFO "[%s]: start\n", __func__)
 +#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n", __func__, n)
 +#else
 +#define DPRINTK(ARGS...)      /* nop */
 +#define ADEBUG()              /* nop */
 +#define FN_IN                 /* nop */
 +#define FN_OUT(n)             /* nop */
 +#endif
  
  #define DMA_BUF_SIZE  (1024 * 8)
  
index bafe109f29e59fd497e64d4e652ecb62f2ec1401,bfa09325a5ffad992a7c2aadd05b84d899ccf36d..713bcc9e1432d031cbd333763c892c967bd39609
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * linux/include/asm/arch-omap/pm.h
 - * arch/arm/plat-omap/include/mach/pm.h
++ * linux/include/mach-omap/pm.h
   *
   * Header file for OMAP Power Management Routines
   *
index 0e794594404f38b6d9a02529f12ae7dc73785be3,0000000000000000000000000000000000000000..4948cb7af5bfe4147c10106610ff3e253296c3ed
mode 100644,000000..100644
--- /dev/null
@@@ -1,167 -1,0 +1,167 @@@
- #include <asm/arch/cpu.h>
 +/*
 + * OMAP2/3 powerdomain control
 + *
 + * Copyright (C) 2007-8 Texas Instruments, Inc.
 + * Copyright (C) 2007-8 Nokia Corporation
 + *
 + * Written by Paul Walmsley
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#ifndef ASM_ARM_ARCH_OMAP_POWERDOMAIN
 +#define ASM_ARM_ARCH_OMAP_POWERDOMAIN
 +
 +#include <linux/types.h>
 +#include <linux/list.h>
 +
 +#include <asm/atomic.h>
 +
++#include <mach/cpu.h>
 +
 +
 +/* Powerdomain basic power states */
 +#define PWRDM_POWER_OFF               0x0
 +#define PWRDM_POWER_RET               0x1
 +#define PWRDM_POWER_INACTIVE  0x2
 +#define PWRDM_POWER_ON                0x3
 +
 +/* Powerdomain allowable state bitfields */
 +#define PWRSTS_OFF_ON         ((1 << PWRDM_POWER_OFF) | \
 +                               (1 << PWRDM_POWER_ON))
 +
 +#define PWRSTS_OFF_RET                ((1 << PWRDM_POWER_OFF) | \
 +                               (1 << PWRDM_POWER_RET))
 +
 +#define PWRSTS_OFF_RET_ON     (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
 +
 +
 +/* Powerdomain flags */
 +#define PWRDM_HAS_HDWR_SAR    (1 << 0) /* hardware save-and-restore support */
 +
 +
 +/*
 + * Number of memory banks that are power-controllable.        On OMAP3430, the
 + * maximum is 4.
 + */
 +#define PWRDM_MAX_MEM_BANKS   4
 +
 +/*
 + * Maximum number of clockdomains that can be associated with a powerdomain.
 + * CORE powerdomain is probably the worst case.
 + */
 +#define PWRDM_MAX_CLKDMS      3
 +
 +/* XXX A completely arbitrary number. What is reasonable here? */
 +#define PWRDM_TRANSITION_BAILOUT 100000
 +
 +struct clockdomain;
 +struct powerdomain;
 +
 +/* Encodes dependencies between powerdomains - statically defined */
 +struct pwrdm_dep {
 +
 +      /* Powerdomain name */
 +      const char *pwrdm_name;
 +
 +      /* Powerdomain pointer - resolved by the powerdomain code */
 +      struct powerdomain *pwrdm;
 +
 +      /* Flags to mark OMAP chip restrictions, etc. */
 +      const struct omap_chip_id omap_chip;
 +
 +};
 +
 +struct powerdomain {
 +
 +      /* Powerdomain name */
 +      const char *name;
 +
 +      /* the address offset from CM_BASE/PRM_BASE */
 +      const s16 prcm_offs;
 +
 +      /* Used to represent the OMAP chip types containing this pwrdm */
 +      const struct omap_chip_id omap_chip;
 +
 +      /* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */
 +      const u8 dep_bit;
 +
 +      /* Powerdomains that can be told to wake this powerdomain up */
 +      struct pwrdm_dep *wkdep_srcs;
 +
 +      /* Powerdomains that can be told to keep this pwrdm from inactivity */
 +      struct pwrdm_dep *sleepdep_srcs;
 +
 +      /* Possible powerdomain power states */
 +      const u8 pwrsts;
 +
 +      /* Possible logic power states when pwrdm in RETENTION */
 +      const u8 pwrsts_logic_ret;
 +
 +      /* Powerdomain flags */
 +      const u8 flags;
 +
 +      /* Number of software-controllable memory banks in this powerdomain */
 +      const u8 banks;
 +
 +      /* Possible memory bank pwrstates when pwrdm in RETENTION */
 +      const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
 +
 +      /* Possible memory bank pwrstates when pwrdm is ON */
 +      const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
 +
 +      /* Clockdomains in this powerdomain */
 +      struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 +
 +      struct list_head node;
 +
 +};
 +
 +
 +void pwrdm_init(struct powerdomain **pwrdm_list);
 +
 +int pwrdm_register(struct powerdomain *pwrdm);
 +int pwrdm_unregister(struct powerdomain *pwrdm);
 +struct powerdomain *pwrdm_lookup(const char *name);
 +
 +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm));
 +
 +int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 +int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 +int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 +                       int (*fn)(struct powerdomain *pwrdm,
 +                                 struct clockdomain *clkdm));
 +
 +int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
 +
 +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 +
 +int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 +int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
 +int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 +int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 +int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 +
 +int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 +int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 +int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 +
 +int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
 +int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
 +int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
 +int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
 +
 +int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
 +int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 +bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 +
 +int pwrdm_wait_transition(struct powerdomain *pwrdm);
 +
 +#endif
index d818dc6552d7bbca683f546bc6c983d29056cef2,0000000000000000000000000000000000000000..d818dc6552d7bbca683f546bc6c983d29056cef2
mode 100644,000000..100644
--- /dev/null
index 4faeb9fc7aeec224384a203678572179790d50af,06a28c7b98de7020054497fbfcb4714dec9ac321..61d9f36722a60db3085645080721a4f0791d0da0
@@@ -7,10 -7,8 +7,10 @@@
  #include <linux/clk.h>
  
  #include <asm/mach-types.h>
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  
- #include <asm/arch/prcm.h>
++#include <mach/prcm.h>
 +
  #ifndef CONFIG_MACH_VOICEBLUE
  #define voiceblue_reset()             do {} while (0)
  #endif
index 2ae3eeac2b0f58c5d324746d369eb14b81078d57,0000000000000000000000000000000000000000..4419bd14dfbf2dcffbf49bc4cdba5fee2ab068a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,35 -1,0 +1,35 @@@
-  * linux/include/asm-arm/arch-omap/usb-ehci.h
 +/*
++ * arch/arm/plat-omap/include/mach/usb-ehci.h
 + *
 + * Hardware definitions for Synopsys EHCI host controller.
 + *
 + * Initial creation by Felipe Balbi.
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP_USB_EHCI_H
 +#define __ASM_ARCH_OMAP_USB_EHCI_H
 +
 +extern void usb_ehci_init(void);
 +
 +#endif /* __ASM_ARCH_OMAP_USB_EHCI_H */
 +
index 4f0c8309668cf14debdc9e11de897d90ed7296cd,0000000000000000000000000000000000000000..b455b29a3adc394b79511c49a565a46973a4737b
mode 100644,000000..100644
--- /dev/null
@@@ -1,35 -1,0 +1,35 @@@
-  * linux/include/asm-arm/arch-omap/usb-musb.h
 +/*
++ * arch/arm/plat-omap/include/mach/usb-musb.h
 + *
 + * Hardware definitions for Mentor Graphics MUSBMHDRC.
 + *
 + * Initial creation by Felipe Balbi.
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#ifndef __ASM_ARCH_OMAP_USB_MUSB_H
 +#define __ASM_ARCH_OMAP_USB_MUSB_H
 +
 +extern void usb_musb_init(void);
 +
 +#endif /* __ASM_ARCH_OMAP_USB_MUSB_H */
 +
Simple merge
index 70944a5c615a5e9fd987cfbd8ec23c0b1d81fa51,d0844050f2d2da0febf9e95e287f032ed95f3ef7..0f0e3f3cd2a5bb10cb7a774ecf3558c38f0b2371
  #include <linux/delay.h>
  #include <linux/io.h>
  
- #include <asm/arch/dma.h>
- #include <asm/arch/mcbsp.h>
+ #include <mach/dma.h>
+ #include <mach/mcbsp.h>
  
 -static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
 +struct omap_mcbsp **mcbsp_ptr;
 +int omap_mcbsp_count;
  
 -#define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \
 -                                      mcbsp[id].pdata->ops && \
 -                                      mcbsp[id].pdata->ops->check && \
 -                                      (mcbsp[id].pdata->ops->check(id) == 0))
 +void omap_mcbsp_write(u32 io_base, u16 reg, u32 val)
 +{
 +      if (cpu_class_is_omap1() || cpu_is_omap2420())
 +              __raw_writew((u16)val, io_base + reg);
 +      else
 +              __raw_writel(val, io_base + reg);
 +}
 +
 +int omap_mcbsp_read(u32 io_base, u16 reg)
 +{
 +      if (cpu_class_is_omap1() || cpu_is_omap2420())
 +              return __raw_readw(io_base + reg);
 +      else
 +              return __raw_readl(io_base + reg);
 +}
 +
 +#define OMAP_MCBSP_READ(base, reg) \
 +                      omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
 +#define OMAP_MCBSP_WRITE(base, reg, val) \
 +                      omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val)
 +
 +#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
 +#define id_to_mcbsp_ptr(id)           mcbsp_ptr[id];
  
  static void omap_mcbsp_dump_reg(u8 id)
  {
index 4b1ba8e99835a39342a1193d458dcb8bc6c346bc,0000000000000000000000000000000000000000..d81a1488bd93621db45051d84e23225c250fba1e
mode 100644,000000..100644
--- /dev/null
@@@ -1,1563 -1,0 +1,1563 @@@
- #include <asm/arch/mmu.h>
 +/*
 + * linux/arch/arm/plat-omap/mmu.c
 + *
 + * OMAP MMU management framework
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation
 + *
 + * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *        and Paul Mundt <lethal@linux-sh.org>
 + *
 + * TWL support: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#include <linux/module.h>
 +#include <linux/mempool.h>
 +#include <linux/init.h>
 +#include <linux/delay.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/device.h>
 +#include <linux/interrupt.h>
 +#include <linux/uaccess.h>
 +#include <linux/io.h>
 +#include <asm/pgalloc.h>
 +#include <asm/pgtable.h>
- #include <asm/arch/dsp_common.h>
++#include <mach/mmu.h>
 +#include <asm/sizes.h>
++#include <mach/dsp_common.h>
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +#include "../mach-omap1/mmu.h"
 +#elif defined(CONFIG_ARCH_OMAP2)
 +#include "../mach-omap2/mmu.h"
 +#endif
 +
 +/*
 + * On OMAP2 MMU_LOCK_xxx_MASK only applies to the IVA and DSP, the camera
 + * MMU has base and victim implemented in different bits in the LOCK
 + * register (shifts are still the same), all of the other registers are
 + * the same on all of the MMUs..
 + */
 +#define MMU_LOCK_BASE_SHIFT           10
 +#define MMU_LOCK_VICTIM_SHIFT         4
 +
 +#define CAMERA_MMU_LOCK_BASE_MASK     (0x7 << MMU_LOCK_BASE_SHIFT)
 +#define CAMERA_MMU_LOCK_VICTIM_MASK   (0x7 << MMU_LOCK_VICTIM_SHIFT)
 +
 +#define is_aligned(adr, align)        (!((adr)&((align)-1)))
 +#define ORDER_1MB     (20 - PAGE_SHIFT)
 +#define ORDER_64KB    (16 - PAGE_SHIFT)
 +#define ORDER_4KB     (12 - PAGE_SHIFT)
 +
 +#define MMU_CNTL_EMUTLBUPDATE (1<<3)
 +#define MMU_CNTL_TWLENABLE    (1<<2)
 +#define MMU_CNTL_MMUENABLE    (1<<1)
 +
 +static mempool_t *mempool_1M;
 +static mempool_t *mempool_64K;
 +
 +#define omap_mmu_for_each_tlb_entry(mmu, entry)                       \
 +      for (entry = mmu->exmap_tbl; prefetch(entry + 1),       \
 +           entry < (mmu->exmap_tbl + mmu->nr_tlb_entries);    \
 +           entry++)
 +
 +#define to_dev(obj)   container_of(obj, struct device, kobj)
 +
 +static void *mempool_alloc_from_pool(mempool_t *pool,
 +                                   unsigned int __nocast gfp_mask)
 +{
 +      spin_lock_irq(&pool->lock);
 +      if (likely(pool->curr_nr)) {
 +              void *element = pool->elements[--pool->curr_nr];
 +              spin_unlock_irq(&pool->lock);
 +              return element;
 +      }
 +
 +      spin_unlock_irq(&pool->lock);
 +      return mempool_alloc(pool, gfp_mask);
 +}
 +
 +/*
 + * kmem_reserve(), kmem_release():
 + * reserve or release kernel memory for exmap().
 + *
 + * exmap() might request consecutive 1MB or 64kB,
 + * but it will be difficult after memory pages are fragmented.
 + * So, user can reserve such memory blocks in the early phase
 + * through kmem_reserve().
 + */
 +static void *omap_mmu_pool_alloc(unsigned int __nocast gfp, void *order)
 +{
 +      return (void *)__get_dma_pages(gfp, (unsigned int)order);
 +}
 +
 +static void omap_mmu_pool_free(void *buf, void *order)
 +{
 +      free_pages((unsigned long)buf, (unsigned int)order);
 +}
 +
 +int omap_mmu_kmem_reserve(struct omap_mmu *mmu, unsigned long size)
 +{
 +      unsigned long len = size;
 +
 +      /* alignment check */
 +      if (!is_aligned(size, SZ_64K)) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: size(0x%lx) is not multiple of 64KB.\n",
 +                      mmu->name, size);
 +              return -EINVAL;
 +      }
 +
 +      if (size > (1 << mmu->addrspace)) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: size(0x%lx) is larger than external device "
 +                      " memory space size (0x%x.\n", mmu->name, size,
 +                      (1 << mmu->addrspace));
 +              return -EINVAL;
 +      }
 +
 +      if (size >= SZ_1M) {
 +              int nr = size >> 20;
 +
 +              if (likely(!mempool_1M))
 +                      mempool_1M = mempool_create(nr, omap_mmu_pool_alloc,
 +                                                  omap_mmu_pool_free,
 +                                                  (void *)ORDER_1MB);
 +              else
 +                      mempool_resize(mempool_1M, mempool_1M->min_nr + nr,
 +                                     GFP_KERNEL);
 +
 +              size &= ~(0xf << 20);
 +      }
 +
 +      if (size >= SZ_64K) {
 +              int nr = size >> 16;
 +
 +              if (likely(!mempool_64K))
 +                      mempool_64K = mempool_create(nr, omap_mmu_pool_alloc,
 +                                                   omap_mmu_pool_free,
 +                                                   (void *)ORDER_64KB);
 +              else
 +                      mempool_resize(mempool_64K, mempool_64K->min_nr + nr,
 +                                     GFP_KERNEL);
 +
 +              size &= ~(0xf << 16);
 +      }
 +
 +      if (size)
 +              len -= size;
 +
 +      return len;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_kmem_reserve);
 +
 +void omap_mmu_kmem_release(void)
 +{
 +      if (mempool_64K) {
 +              mempool_destroy(mempool_64K);
 +              mempool_64K = NULL;
 +      }
 +
 +      if (mempool_1M) {
 +              mempool_destroy(mempool_1M);
 +              mempool_1M = NULL;
 +      }
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_kmem_release);
 +
 +static void omap_mmu_free_pages(unsigned long buf, unsigned int order)
 +{
 +      struct page *page, *ps, *pe;
 +
 +      ps = virt_to_page(buf);
 +      pe = virt_to_page(buf + (1 << (PAGE_SHIFT + order)));
 +
 +      for (page = ps; page < pe; page++)
 +              ClearPageReserved(page);
 +
 +      if ((order == ORDER_64KB) && likely(mempool_64K))
 +              mempool_free((void *)buf, mempool_64K);
 +      else if ((order == ORDER_1MB) && likely(mempool_1M))
 +              mempool_free((void *)buf, mempool_1M);
 +      else
 +              free_pages(buf, order);
 +}
 +
 +/*
 + * ARM MMU operations
 + */
 +int exmap_set_armmmu(struct omap_mmu *mmu, unsigned long virt,
 +                   unsigned long phys, unsigned long size)
 +{
 +      long off;
 +      unsigned long sz_left;
 +      pmd_t *pmdp;
 +      pte_t *ptep;
 +      int prot_pmd, prot_pte;
 +
 +      dev_dbg(mmu->dev,
 +              "MMU %s: mapping in ARM MMU, v=0x%08lx, p=0x%08lx, sz=0x%lx\n",
 +              mmu->name, virt, phys, size);
 +
 +      prot_pmd = PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_IO);
 +      prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE;
 +
 +      pmdp = pmd_offset(pgd_offset_k(virt), virt);
 +      if (pmd_none(*pmdp)) {
 +              ptep = pte_alloc_one_kernel(&init_mm, 0);
 +              if (ptep == NULL)
 +                      return -ENOMEM;
 +              /* note: two PMDs will be set  */
 +              pmd_populate_kernel(&init_mm, pmdp, ptep);
 +      }
 +
 +      off = phys - virt;
 +      for (sz_left = size;
 +           sz_left >= PAGE_SIZE;
 +           sz_left -= PAGE_SIZE, virt += PAGE_SIZE) {
 +              ptep = pte_offset_kernel(pmdp, virt);
 +              set_pte_ext(ptep, __pte((virt + off) | prot_pte), 0);
 +      }
 +      if (sz_left)
 +              BUG();
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(exmap_set_armmmu);
 +
 +void exmap_clear_armmmu(struct omap_mmu *mmu, unsigned long virt,
 +                      unsigned long size)
 +{
 +      unsigned long sz_left;
 +      pmd_t *pmdp;
 +      pte_t *ptep;
 +
 +      dev_dbg(mmu->dev,
 +              "MMU %s: unmapping in ARM MMU, v=0x%08lx, sz=0x%lx\n",
 +              mmu->name, virt, size);
 +
 +      for (sz_left = size;
 +           sz_left >= PAGE_SIZE;
 +           sz_left -= PAGE_SIZE, virt += PAGE_SIZE) {
 +              pmdp = pmd_offset(pgd_offset_k(virt), virt);
 +              ptep = pte_offset_kernel(pmdp, virt);
 +              pte_clear(&init_mm, virt, ptep);
 +      }
 +      if (sz_left)
 +              BUG();
 +}
 +EXPORT_SYMBOL_GPL(exmap_clear_armmmu);
 +
 +int exmap_valid(struct omap_mmu *mmu, void *vadr, size_t len)
 +{
 +      /* exmap_sem should be held before calling this function */
 +      struct exmap_tbl *ent;
 +
 +start:
 +      omap_mmu_for_each_tlb_entry(mmu, ent) {
 +              void *mapadr;
 +              unsigned long mapsize;
 +
 +              if (!ent->valid)
 +                      continue;
 +              mapadr = (void *)ent->vadr;
 +              mapsize = 1 << (ent->order + PAGE_SHIFT);
 +              if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) {
 +                      if (vadr + len <= mapadr + mapsize) {
 +                              /* this map covers whole address. */
 +                              return 1;
 +                      } else {
 +                              /*
 +                               * this map covers partially.
 +                               * check rest portion.
 +                               */
 +                              len -= mapadr + mapsize - vadr;
 +                              vadr = mapadr + mapsize;
 +                              goto start;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(exmap_valid);
 +
 +/*
 + * omap_mmu_exmap_use(), unuse():
 + * when the mapped area is exported to user space with mmap,
 + * the usecount is incremented.
 + * while the usecount > 0, that area can't be released.
 + */
 +void omap_mmu_exmap_use(struct omap_mmu *mmu, void *vadr, size_t len)
 +{
 +      struct exmap_tbl *ent;
 +
 +      down_write(&mmu->exmap_sem);
 +      omap_mmu_for_each_tlb_entry(mmu, ent) {
 +              void *mapadr;
 +              unsigned long mapsize;
 +
 +              if (!ent->valid)
 +                      continue;
 +              mapadr = (void *)ent->vadr;
 +              mapsize = 1 << (ent->order + PAGE_SHIFT);
 +              if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
 +                      ent->usecount++;
 +      }
 +      up_write(&mmu->exmap_sem);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_exmap_use);
 +
 +void omap_mmu_exmap_unuse(struct omap_mmu *mmu, void *vadr, size_t len)
 +{
 +      struct exmap_tbl *ent;
 +
 +      down_write(&mmu->exmap_sem);
 +      omap_mmu_for_each_tlb_entry(mmu, ent) {
 +              void *mapadr;
 +              unsigned long mapsize;
 +
 +              if (!ent->valid)
 +                      continue;
 +              mapadr = (void *)ent->vadr;
 +              mapsize = 1 << (ent->order + PAGE_SHIFT);
 +              if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
 +                      ent->usecount--;
 +      }
 +      up_write(&mmu->exmap_sem);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_exmap_unuse);
 +
 +/*
 + * omap_mmu_virt_to_phys()
 + * returns physical address, and sets len to valid length
 + */
 +unsigned long
 +omap_mmu_virt_to_phys(struct omap_mmu *mmu, void *vadr, size_t *len)
 +{
 +      struct exmap_tbl *ent;
 +
 +      if (omap_mmu_internal_memory(mmu, vadr)) {
 +              unsigned long addr = (unsigned long)vadr;
 +              *len = mmu->membase + mmu->memsize - addr;
 +              return addr;
 +      }
 +
 +      /* EXRAM */
 +      omap_mmu_for_each_tlb_entry(mmu, ent) {
 +              void *mapadr;
 +              unsigned long mapsize;
 +
 +              if (!ent->valid)
 +                      continue;
 +              mapadr = (void *)ent->vadr;
 +              mapsize = 1 << (ent->order + PAGE_SHIFT);
 +              if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) {
 +                      *len = mapadr + mapsize - vadr;
 +                      return __pa(ent->buf) + vadr - mapadr;
 +              }
 +      }
 +
 +      /* valid mapping not found */
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_virt_to_phys);
 +
 +/*
 + * PTE operations
 + */
 +static inline void
 +omap_mmu_alloc_section(struct mm_struct *mm, unsigned long virt,
 +                     unsigned long phys, int prot)
 +{
 +      pmd_t *pmdp = pmd_offset(pgd_offset(mm, virt), virt);
 +      if (virt & (1 << SECTION_SHIFT))
 +              pmdp++;
 +      *pmdp = __pmd((phys & SECTION_MASK) | prot | PMD_TYPE_SECT);
 +      flush_pmd_entry(pmdp);
 +}
 +
 +static inline void
 +omap_mmu_alloc_supersection(struct mm_struct *mm, unsigned long virt,
 +                          unsigned long phys, int prot)
 +{
 +      int i;
 +      for (i = 0; i < 16; i += 1) {
 +              omap_mmu_alloc_section(mm, virt, phys, prot | PMD_SECT_SUPER);
 +              virt += (PGDIR_SIZE / 2);
 +      }
 +}
 +
 +static inline int
 +omap_mmu_alloc_page(struct mm_struct *mm, unsigned long virt,
 +                  unsigned long phys, pgprot_t prot)
 +{
 +      pte_t *ptep;
 +      pmd_t *pmdp = pmd_offset(pgd_offset(mm, virt), virt);
 +
 +      if (!(prot & PTE_TYPE_MASK))
 +              prot |= PTE_TYPE_SMALL;
 +
 +      if (pmd_none(*pmdp)) {
 +              ptep = pte_alloc_one_kernel(mm, virt);
 +              if (ptep == NULL)
 +                      return -ENOMEM;
 +              pmd_populate_kernel(mm, pmdp, ptep);
 +      }
 +      ptep = pte_offset_kernel(pmdp, virt);
 +      ptep -= PTRS_PER_PTE;
 +      *ptep = pfn_pte(phys >> PAGE_SHIFT, prot);
 +      flush_pmd_entry((pmd_t *)ptep);
 +      return 0;
 +}
 +
 +static inline int
 +omap_mmu_alloc_largepage(struct mm_struct *mm, unsigned long virt,
 +                       unsigned long phys, pgprot_t prot)
 +{
 +      int i, ret;
 +      for (i = 0; i < 16; i += 1) {
 +              ret = omap_mmu_alloc_page(mm, virt, phys,
 +                                        prot | PTE_TYPE_LARGE);
 +              if (ret)
 +                      return -ENOMEM; /* only 1st time */
 +              virt += PAGE_SIZE;
 +      }
 +      return 0;
 +}
 +
 +static int omap_mmu_load_pte(struct omap_mmu *mmu,
 +                           struct omap_mmu_tlb_entry *e)
 +{
 +      int ret = 0;
 +      struct mm_struct *mm = mmu->twl_mm;
 +      const unsigned long va = e->va;
 +      const unsigned long pa = e->pa;
 +      const pgprot_t prot = mmu->ops->pte_get_attr(e);
 +
 +      spin_lock(&mm->page_table_lock);
 +
 +      switch (e->pgsz) {
 +      case OMAP_MMU_CAM_PAGESIZE_16MB:
 +              omap_mmu_alloc_supersection(mm, va, pa, prot);
 +              break;
 +      case OMAP_MMU_CAM_PAGESIZE_1MB:
 +              omap_mmu_alloc_section(mm, va, pa, prot);
 +              break;
 +      case OMAP_MMU_CAM_PAGESIZE_64KB:
 +              ret = omap_mmu_alloc_largepage(mm, va, pa, prot);
 +              break;
 +      case OMAP_MMU_CAM_PAGESIZE_4KB:
 +              ret = omap_mmu_alloc_page(mm, va, pa, prot);
 +              break;
 +      default:
 +              BUG();
 +              break;
 +      }
 +
 +      spin_unlock(&mm->page_table_lock);
 +
 +      return ret;
 +}
 +
 +static void omap_mmu_clear_pte(struct omap_mmu *mmu, unsigned long virt)
 +{
 +      pte_t *ptep, *end;
 +      pmd_t *pmdp;
 +      struct mm_struct *mm = mmu->twl_mm;
 +
 +      spin_lock(&mm->page_table_lock);
 +
 +      pmdp = pmd_offset(pgd_offset(mm, virt), virt);
 +
 +      if (pmd_none(*pmdp))
 +              goto out;
 +
 +      if (!pmd_table(*pmdp))
 +              goto invalidate_pmd;
 +
 +      ptep = pte_offset_kernel(pmdp, virt);
 +      pte_clear(mm, virt, ptep);
 +      flush_pmd_entry((pmd_t *)ptep);
 +
 +      /* zap pte */
 +      end = pmd_page_vaddr(*pmdp);
 +      ptep = end - PTRS_PER_PTE;
 +      while (ptep < end) {
 +              if (!pte_none(*ptep))
 +                      goto out;
 +              ptep++;
 +      }
 +      pte_free_kernel(mm, pmd_page_vaddr(*pmdp));
 +
 + invalidate_pmd:
 +      pmd_clear(pmdp);
 +      flush_pmd_entry(pmdp);
 + out:
 +      spin_unlock(&mm->page_table_lock);
 +}
 +
 +/*
 + * TLB operations
 + */
 +static struct cam_ram_regset *
 +omap_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry)
 +{
 +      return mmu->ops->cam_ram_alloc(mmu, entry);
 +}
 +
 +static int omap_mmu_cam_ram_valid(struct omap_mmu *mmu,
 +                                struct cam_ram_regset *cr)
 +{
 +      return mmu->ops->cam_ram_valid(cr);
 +}
 +
 +static inline void
 +omap_mmu_get_tlb_lock(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *tlb_lock)
 +{
 +      unsigned long lock = omap_mmu_read_reg(mmu, OMAP_MMU_LOCK);
 +      int mask;
 +
 +      mask = (mmu->type == OMAP_MMU_CAMERA) ?
 +                      CAMERA_MMU_LOCK_BASE_MASK : MMU_LOCK_BASE_MASK;
 +      tlb_lock->base = (lock & mask) >> MMU_LOCK_BASE_SHIFT;
 +
 +      mask = (mmu->type == OMAP_MMU_CAMERA) ?
 +                      CAMERA_MMU_LOCK_VICTIM_MASK : MMU_LOCK_VICTIM_MASK;
 +      tlb_lock->victim = (lock & mask) >> MMU_LOCK_VICTIM_SHIFT;
 +}
 +
 +static inline void
 +omap_mmu_set_tlb_lock(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *lock)
 +{
 +      omap_mmu_write_reg(mmu,
 +                         (lock->base << MMU_LOCK_BASE_SHIFT) |
 +                         (lock->victim << MMU_LOCK_VICTIM_SHIFT),
 +                         OMAP_MMU_LOCK);
 +}
 +
 +static inline void omap_mmu_flush(struct omap_mmu *mmu)
 +{
 +      omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_FLUSH_ENTRY);
 +}
 +
 +static inline void omap_mmu_ldtlb(struct omap_mmu *mmu)
 +{
 +      omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_LD_TLB);
 +}
 +
 +void omap_mmu_read_tlb(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *lock,
 +                     struct cam_ram_regset *cr)
 +{
 +      /* set victim */
 +      omap_mmu_set_tlb_lock(mmu, lock);
 +
 +      if (likely(mmu->ops->read_tlb))
 +              mmu->ops->read_tlb(mmu, cr);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_read_tlb);
 +
 +void omap_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      if (likely(mmu->ops->load_tlb))
 +              mmu->ops->load_tlb(mmu, cr);
 +
 +      /* flush the entry */
 +      omap_mmu_flush(mmu);
 +
 +      /* load a TLB entry */
 +      omap_mmu_ldtlb(mmu);
 +}
 +
 +int omap_mmu_load_tlb_entry(struct omap_mmu *mmu,
 +                          struct omap_mmu_tlb_entry *entry)
 +{
 +      struct omap_mmu_tlb_lock lock;
 +      struct cam_ram_regset *cr;
 +      int ret;
 +
 +      clk_enable(mmu->clk);
 +      ret = omap_dsp_request_mem();
 +      if (ret < 0)
 +              goto out;
 +
 +      omap_mmu_get_tlb_lock(mmu, &lock);
 +      for (lock.victim = 0; lock.victim < lock.base; lock.victim++) {
 +              struct cam_ram_regset tmp;
 +
 +              /* read a TLB entry */
 +              omap_mmu_read_tlb(mmu, &lock, &tmp);
 +              if (!omap_mmu_cam_ram_valid(mmu, &tmp))
 +                      goto found_victim;
 +      }
 +      omap_mmu_set_tlb_lock(mmu, &lock);
 +
 +found_victim:
 +      /* The last entry cannot be locked? */
 +      if (lock.victim == (mmu->nr_tlb_entries - 1)) {
 +              dev_err(mmu->dev, "MMU %s: TLB is full.\n", mmu->name);
 +              return -EBUSY;
 +      }
 +
 +      cr = omap_mmu_cam_ram_alloc(mmu, entry);
 +      if (IS_ERR(cr))
 +              return PTR_ERR(cr);
 +
 +      omap_mmu_load_tlb(mmu, cr);
 +      kfree(cr);
 +
 +      /* update lock base */
 +      if (lock.victim == lock.base)
 +              lock.base++;
 +
 +      omap_mmu_set_tlb_lock(mmu, &lock);
 +
 +      omap_dsp_release_mem();
 +out:
 +      clk_disable(mmu->clk);
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_load_tlb_entry);
 +
 +static inline unsigned long
 +omap_mmu_cam_va(struct omap_mmu *mmu, struct cam_ram_regset *cr)
 +{
 +      return mmu->ops->cam_va(cr);
 +}
 +
 +int omap_mmu_clear_tlb_entry(struct omap_mmu *mmu, unsigned long vadr)
 +{
 +      struct omap_mmu_tlb_lock lock;
 +      int i, ret = 0;
 +      int max_valid = 0;
 +
 +      clk_enable(mmu->clk);
 +      ret = omap_dsp_request_mem();
 +      if (ret < 0)
 +              goto out;
 +
 +      omap_mmu_get_tlb_lock(mmu, &lock);
 +      for (i = 0; i < lock.base; i++) {
 +              struct cam_ram_regset cr;
 +
 +              /* read a TLB entry */
 +              lock.victim = i;
 +              omap_mmu_read_tlb(mmu, &lock, &cr);
 +              if (!omap_mmu_cam_ram_valid(mmu, &cr))
 +                      continue;
 +
 +              if (omap_mmu_cam_va(mmu, &cr) == vadr)
 +                      /* flush the entry */
 +                      omap_mmu_flush(mmu);
 +              else
 +                      max_valid = i;
 +      }
 +
 +      /* set new lock base */
 +      lock.base = lock.victim = max_valid + 1;
 +      omap_mmu_set_tlb_lock(mmu, &lock);
 +
 +      omap_dsp_release_mem();
 +out:
 +      clk_disable(mmu->clk);
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_clear_tlb_entry);
 +
 +static void omap_mmu_gflush(struct omap_mmu *mmu)
 +{
 +      struct omap_mmu_tlb_lock lock;
 +      int ret;
 +
 +      clk_enable(mmu->clk);
 +      ret = omap_dsp_request_mem();
 +      if (ret < 0)
 +              goto out;
 +
 +      omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_GFLUSH);
 +      lock.base = lock.victim = mmu->nr_exmap_preserved;
 +      omap_mmu_set_tlb_lock(mmu, &lock);
 +
 +      omap_dsp_release_mem();
 +out:
 +      clk_disable(mmu->clk);
 +}
 +
 +int omap_mmu_load_pte_entry(struct omap_mmu *mmu,
 +                          struct omap_mmu_tlb_entry *entry)
 +{
 +      int ret = -1;
 +      /*XXX use PG_flag for prsvd */
 +      ret = omap_mmu_load_pte(mmu, entry);
 +      if (ret)
 +              return ret;
 +      if (entry->tlb)
 +              ret = omap_mmu_load_tlb_entry(mmu, entry);
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_load_pte_entry);
 +
 +int omap_mmu_clear_pte_entry(struct omap_mmu *mmu, unsigned long vadr)
 +{
 +      int ret = omap_mmu_clear_tlb_entry(mmu, vadr);
 +      if (ret)
 +              return ret;
 +      omap_mmu_clear_pte(mmu, vadr);
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_clear_pte_entry);
 +
 +/*
 + * omap_mmu_exmap()
 + *
 + * MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
 + * In this case, the buffer for external device is allocated in this routine,
 + * then it is mapped.
 + * On the other hand, for example - frame buffer sharing, calls
 + * this function with padr set. It means some known address space
 + * pointed with padr is going to be shared with external device.
 + */
 +int omap_mmu_exmap(struct omap_mmu *mmu, unsigned long devadr,
 +                 unsigned long padr, unsigned long size,
 +                 enum exmap_type type)
 +{
 +      unsigned long pgsz;
 +      void *buf;
 +      unsigned int order = 0;
 +      unsigned long unit;
 +      int prev = -1;
 +      unsigned long _devadr = devadr;
 +      unsigned long _padr = padr;
 +      void *_vadr = omap_mmu_to_virt(mmu, devadr);
 +      unsigned long _size = size;
 +      struct omap_mmu_tlb_entry tlb_ent;
 +      struct exmap_tbl *exmap_ent, *tmp_ent;
 +      int status;
 +      int idx;
 +
 +#define MINIMUM_PAGESZ        SZ_4K
 +      /*
 +       * alignment check
 +       */
 +      if (!is_aligned(size, MINIMUM_PAGESZ)) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: size(0x%lx) is not multiple of 4KB.\n",
 +                      mmu->name, size);
 +              return -EINVAL;
 +      }
 +      if (!is_aligned(devadr, MINIMUM_PAGESZ)) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: external device address(0x%lx) is not"
 +                      " aligned.\n", mmu->name, devadr);
 +              return -EINVAL;
 +      }
 +      if (!is_aligned(padr, MINIMUM_PAGESZ)) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: physical address(0x%lx) is not aligned.\n",
 +                      mmu->name, padr);
 +              return -EINVAL;
 +      }
 +
 +      /* address validity check */
 +      if ((devadr < mmu->memsize) ||
 +          (devadr >= (1 << mmu->addrspace))) {
 +              dev_err(mmu->dev,
 +                      "MMU %s: illegal address/size for %s().\n",
 +                      mmu->name, __func__);
 +              return -EINVAL;
 +      }
 +
 +      down_write(&mmu->exmap_sem);
 +
 +      /* overlap check */
 +      omap_mmu_for_each_tlb_entry(mmu, tmp_ent) {
 +              unsigned long mapsize;
 +
 +              if (!tmp_ent->valid)
 +                      continue;
 +              mapsize = 1 << (tmp_ent->order + PAGE_SHIFT);
 +              if ((_vadr + size > tmp_ent->vadr) &&
 +                  (_vadr < tmp_ent->vadr + mapsize)) {
 +                      dev_err(mmu->dev, "MMU %s: exmap page overlap!\n",
 +                              mmu->name);
 +                      up_write(&mmu->exmap_sem);
 +                      return -EINVAL;
 +              }
 +      }
 +
 +start:
 +      buf = NULL;
 +      /* Are there any free TLB lines?  */
 +      for (idx = 0; idx < mmu->nr_tlb_entries; idx++)
 +              if (!mmu->exmap_tbl[idx].valid)
 +                      goto found_free;
 +
 +      dev_err(mmu->dev, "MMU %s: TLB is full.\n", mmu->name);
 +      status = -EBUSY;
 +      goto fail;
 +
 +found_free:
 +      exmap_ent = mmu->exmap_tbl + idx;
 +
 +      if ((_size >= SZ_1M) &&
 +          (is_aligned(_padr, SZ_1M) || (padr == 0)) &&
 +          is_aligned(_devadr, SZ_1M)) {
 +              unit = SZ_1M;
 +              pgsz = OMAP_MMU_CAM_PAGESIZE_1MB;
 +      } else if ((_size >= SZ_64K) &&
 +                 (is_aligned(_padr, SZ_64K) || (padr == 0)) &&
 +                 is_aligned(_devadr, SZ_64K)) {
 +              unit = SZ_64K;
 +              pgsz = OMAP_MMU_CAM_PAGESIZE_64KB;
 +      } else {
 +              unit = SZ_4K;
 +              pgsz = OMAP_MMU_CAM_PAGESIZE_4KB;
 +      }
 +
 +      order = get_order(unit);
 +
 +      /* buffer allocation */
 +      if (type == EXMAP_TYPE_MEM) {
 +              struct page *page, *ps, *pe;
 +
 +              if ((order == ORDER_1MB) && likely(mempool_1M))
 +                      buf = mempool_alloc_from_pool(mempool_1M, GFP_KERNEL);
 +              else if ((order == ORDER_64KB) && likely(mempool_64K))
 +                      buf = mempool_alloc_from_pool(mempool_64K, GFP_KERNEL);
 +              else {
 +                      buf = (void *)__get_dma_pages(GFP_KERNEL, order);
 +                      if (buf == NULL) {
 +                              status = -ENOMEM;
 +                              goto fail;
 +                      }
 +              }
 +
 +              /* mark the pages as reserved; this is needed for mmap */
 +              ps = virt_to_page(buf);
 +              pe = virt_to_page(buf + unit);
 +
 +              for (page = ps; page < pe; page++)
 +                      SetPageReserved(page);
 +
 +              _padr = __pa(buf);
 +      }
 +
 +      /*
 +       * mapping for ARM MMU:
 +       * we should not access to the allocated memory through 'buf'
 +       * since this area should not be cached.
 +       */
 +      status = exmap_set_armmmu(mmu, (unsigned long)_vadr, _padr, unit);
 +      if (status < 0)
 +              goto fail;
 +
 +      /* loading external device PTE entry */
 +      INIT_TLB_ENTRY(&tlb_ent, _devadr, _padr, pgsz);
 +      status = omap_mmu_load_pte_entry(mmu, &tlb_ent);
 +      if (status < 0) {
 +              exmap_clear_armmmu(mmu, (unsigned long)_vadr, unit);
 +              goto fail;
 +      }
 +
 +      INIT_EXMAP_TBL_ENTRY(exmap_ent, buf, _vadr, type, order);
 +      exmap_ent->link.prev = prev;
 +      if (prev >= 0)
 +              mmu->exmap_tbl[prev].link.next = idx;
 +
 +      if ((_size -= unit) == 0) {     /* normal completion */
 +              up_write(&mmu->exmap_sem);
 +              return size;
 +      }
 +
 +      _devadr += unit;
 +      _vadr   += unit;
 +      _padr = padr ? _padr + unit : 0;
 +      prev = idx;
 +      goto start;
 +
 +fail:
 +      up_write(&mmu->exmap_sem);
 +      if (buf)
 +              omap_mmu_free_pages((unsigned long)buf, order);
 +      omap_mmu_exunmap(mmu, devadr);
 +      return status;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_exmap);
 +
 +static unsigned long unmap_free_arm(struct omap_mmu *mmu,
 +                                  struct exmap_tbl *ent)
 +{
 +      unsigned long size;
 +
 +      /* clearing ARM MMU */
 +      size = 1 << (ent->order + PAGE_SHIFT);
 +      exmap_clear_armmmu(mmu, (unsigned long)ent->vadr, size);
 +
 +      /* freeing allocated memory */
 +      if (ent->type == EXMAP_TYPE_MEM) {
 +              omap_mmu_free_pages((unsigned long)ent->buf, ent->order);
 +              dev_dbg(mmu->dev, "MMU %s: freeing 0x%lx bytes @ adr 0x%8p\n",
 +                      mmu->name, size, ent->buf);
 +      }
 +
 +      ent->valid = 0;
 +      return size;
 +}
 +
 +int omap_mmu_exunmap(struct omap_mmu *mmu, unsigned long devadr)
 +{
 +      void *vadr;
 +      unsigned long size;
 +      int total = 0;
 +      struct exmap_tbl *ent;
 +      int idx;
 +
 +      vadr = omap_mmu_to_virt(mmu, devadr);
 +      down_write(&mmu->exmap_sem);
 +      for (idx = 0; idx < mmu->nr_tlb_entries; idx++) {
 +              ent = mmu->exmap_tbl + idx;
 +              if (!ent->valid || ent->prsvd)
 +                      continue;
 +              if (ent->vadr == vadr)
 +                      goto found_map;
 +      }
 +      up_write(&mmu->exmap_sem);
 +      dev_warn(mmu->dev, "MMU %s: address %06lx not found in exmap_tbl.\n",
 +               mmu->name, devadr);
 +      return -EINVAL;
 +
 +found_map:
 +      if (ent->usecount > 0) {
 +              dev_err(mmu->dev, "MMU %s: exmap reference count is not 0.\n"
 +                      "   idx=%d, vadr=%p, order=%d, usecount=%d\n",
 +                      mmu->name, idx, ent->vadr, ent->order, ent->usecount);
 +              up_write(&mmu->exmap_sem);
 +              return -EINVAL;
 +      }
 +      /* clearing external device PTE entry */
 +      omap_mmu_clear_pte_entry(mmu, devadr);
 +
 +      /* clear ARM MMU and free buffer */
 +      size = unmap_free_arm(mmu, ent);
 +      total += size;
 +
 +      /* we don't free PTEs */
 +
 +      /* flush TLB */
 +      flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size);
 +
 +      /* check if next mapping is in same group */
 +      idx = ent->link.next;
 +      if (idx < 0)
 +              goto up_out;    /* normal completion */
 +      ent = mmu->exmap_tbl + idx;
 +      devadr += size;
 +      vadr   += size;
 +      if (ent->vadr == vadr)
 +              goto found_map; /* continue */
 +
 +      dev_err(mmu->dev, "MMU %s: illegal exmap_tbl grouping!\n"
 +              "expected vadr = %p, exmap_tbl[%d].vadr = %p\n",
 +              mmu->name, vadr, idx, ent->vadr);
 +      up_write(&mmu->exmap_sem);
 +      return -EINVAL;
 +
 +up_out:
 +      up_write(&mmu->exmap_sem);
 +      return total;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_exunmap);
 +
 +void omap_mmu_exmap_flush(struct omap_mmu *mmu)
 +{
 +      struct exmap_tbl *ent;
 +
 +      down_write(&mmu->exmap_sem);
 +
 +      /* clearing TLB entry */
 +      omap_mmu_gflush(mmu);
 +
 +      omap_mmu_for_each_tlb_entry(mmu, ent)
 +              if (ent->valid && !ent->prsvd)
 +                      unmap_free_arm(mmu, ent);
 +
 +      /* flush TLB */
 +      if (likely(mmu->membase))
 +              flush_tlb_kernel_range(mmu->membase + mmu->memsize,
 +                                     mmu->membase + (1 << mmu->addrspace));
 +
 +      up_write(&mmu->exmap_sem);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_exmap_flush);
 +
 +void exmap_setup_preserved_mem_page(struct omap_mmu *mmu, void *buf,
 +                                  unsigned long devadr, int index)
 +{
 +      unsigned long phys;
 +      void *virt;
 +      struct omap_mmu_tlb_entry tlb_ent;
 +
 +      phys = __pa(buf);
 +      virt = omap_mmu_to_virt(mmu, devadr);
 +      exmap_set_armmmu(mmu, (unsigned long)virt, phys, PAGE_SIZE);
 +      INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(mmu->exmap_tbl + index, buf, virt);
 +      INIT_TLB_ENTRY_4KB_PRESERVED(&tlb_ent, devadr, phys);
 +      omap_mmu_load_pte_entry(mmu, &tlb_ent);
 +}
 +EXPORT_SYMBOL_GPL(exmap_setup_preserved_mem_page);
 +
 +void exmap_clear_mem_page(struct omap_mmu *mmu, unsigned long devadr)
 +{
 +      void *virt = omap_mmu_to_virt(mmu, devadr);
 +
 +      exmap_clear_armmmu(mmu, (unsigned long)virt, PAGE_SIZE);
 +      /* DSP MMU is shutting down. not handled here. */
 +}
 +EXPORT_SYMBOL_GPL(exmap_clear_mem_page);
 +
 +static void omap_mmu_reset(struct omap_mmu *mmu)
 +{
 +#if defined(CONFIG_ARCH_OMAP2) /* FIXME */
 +      int i;
 +
 +      omap_mmu_write_reg(mmu, 0x2, OMAP_MMU_SYSCONFIG);
 +
 +      for (i = 0; i < 10000; i++)
 +              if (likely(omap_mmu_read_reg(mmu, OMAP_MMU_SYSSTATUS) & 0x1))
 +                      break;
 +#endif
 +}
 +
 +void omap_mmu_disable(struct omap_mmu *mmu)
 +{
 +      omap_mmu_write_reg(mmu, 0x00, OMAP_MMU_CNTL);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_disable);
 +
 +void omap_mmu_enable(struct omap_mmu *mmu, int reset)
 +{
 +      u32 val = OMAP_MMU_CNTL_MMU_EN | MMU_CNTL_TWLENABLE;
 +
 +      if (likely(reset))
 +              omap_mmu_reset(mmu);
 +#if defined(CONFIG_ARCH_OMAP2) /* FIXME */
 +      omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd),
 +                         OMAP_MMU_TTB);
 +#else
 +      omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd) & 0xffff,
 +                         OMAP_MMU_TTB_L);
 +      omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd) >> 16,
 +                         OMAP_MMU_TTB_H);
 +      val |= OMAP_MMU_CNTL_RESET_SW;
 +#endif
 +      omap_mmu_write_reg(mmu, val, OMAP_MMU_CNTL);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_enable);
 +
 +static irqreturn_t omap_mmu_interrupt(int irq, void *dev_id)
 +{
 +      struct omap_mmu *mmu = dev_id;
 +
 +      if (likely(mmu->ops->interrupt))
 +              mmu->ops->interrupt(mmu);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static int omap_mmu_init(struct omap_mmu *mmu)
 +{
 +      struct omap_mmu_tlb_lock tlb_lock;
 +      int ret = 0;
 +
 +      clk_enable(mmu->clk);
 +      ret = omap_dsp_request_mem();
 +      if (ret < 0)
 +              goto out;
 +
 +      down_write(&mmu->exmap_sem);
 +
 +      ret = request_irq(mmu->irq, omap_mmu_interrupt, IRQF_DISABLED,
 +                        mmu->name,  mmu);
 +      if (ret < 0) {
 +              dev_err(mmu->dev, "MMU %s: failed to register MMU interrupt:"
 +                      " %d\n", mmu->name, ret);
 +              goto fail;
 +      }
 +
 +      omap_mmu_disable(mmu);  /* clear all */
 +      udelay(100);
 +      omap_mmu_enable(mmu, 1);
 +
 +      memset(&tlb_lock, 0, sizeof(struct omap_mmu_tlb_lock));
 +      omap_mmu_set_tlb_lock(mmu, &tlb_lock);
 +
 +      if (unlikely(mmu->ops->startup))
 +              ret = mmu->ops->startup(mmu);
 +fail:
 +      up_write(&mmu->exmap_sem);
 +      omap_dsp_release_mem();
 +out:
 +      clk_disable(mmu->clk);
 +
 +      return ret;
 +}
 +
 +static void omap_mmu_shutdown(struct omap_mmu *mmu)
 +{
 +      free_irq(mmu->irq, mmu);
 +
 +      if (unlikely(mmu->ops->shutdown))
 +              mmu->ops->shutdown(mmu);
 +
 +      omap_mmu_exmap_flush(mmu);
 +      omap_mmu_disable(mmu); /* clear all */
 +}
 +
 +/*
 + * omap_mmu_mem_enable() / disable()
 + */
 +int omap_mmu_mem_enable(struct omap_mmu *mmu, void *addr)
 +{
 +      if (unlikely(mmu->ops->mem_enable))
 +              return mmu->ops->mem_enable(mmu, addr);
 +
 +      down_read(&mmu->exmap_sem);
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_mem_enable);
 +
 +void omap_mmu_mem_disable(struct omap_mmu *mmu, void *addr)
 +{
 +      if (unlikely(mmu->ops->mem_disable)) {
 +              mmu->ops->mem_disable(mmu, addr);
 +              return;
 +      }
 +
 +      up_read(&mmu->exmap_sem);
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_mem_disable);
 +
 +/*
 + * dsp_mem file operations
 + */
 +static ssize_t intmem_read(struct omap_mmu *mmu, char *buf, size_t count,
 +                         loff_t *ppos)
 +{
 +      unsigned long p = *ppos;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +      ssize_t size = mmu->memsize;
 +      ssize_t read;
 +
 +      if (p >= size)
 +              return 0;
 +      clk_enable(mmu->memclk);
 +      read = count;
 +      if (count > size - p)
 +              read = size - p;
 +      if (copy_to_user(buf, vadr, read)) {
 +              read = -EFAULT;
 +              goto out;
 +      }
 +      *ppos += read;
 +out:
 +      clk_disable(mmu->memclk);
 +      return read;
 +}
 +
 +static ssize_t exmem_read(struct omap_mmu *mmu, char *buf, size_t count,
 +                        loff_t *ppos)
 +{
 +      unsigned long p = *ppos;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +
 +      if (!exmap_valid(mmu, vadr, count)) {
 +              dev_err(mmu->dev, "MMU %s: external device address %08lx / "
 +                      "size %08x is not valid!\n", mmu->name, p, count);
 +              return -EFAULT;
 +      }
 +      if (count > (1 << mmu->addrspace) - p)
 +              count = (1 << mmu->addrspace) - p;
 +      if (copy_to_user(buf, vadr, count))
 +              return -EFAULT;
 +      *ppos += count;
 +
 +      return count;
 +}
 +
 +static ssize_t omap_mmu_mem_read(struct kobject *kobj,
 +                               struct bin_attribute *attr,
 +                               char *buf, loff_t offset, size_t count)
 +{
 +      struct device *dev = to_dev(kobj);
 +      struct omap_mmu *mmu = dev_get_drvdata(dev);
 +      unsigned long p = (unsigned long)offset;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +      int ret;
 +
 +      if (omap_mmu_mem_enable(mmu, vadr) < 0)
 +              return -EBUSY;
 +
 +      if (p < mmu->memsize)
 +              ret = intmem_read(mmu, buf, count, &offset);
 +      else
 +              ret = exmem_read(mmu, buf, count, &offset);
 +
 +      omap_mmu_mem_disable(mmu, vadr);
 +
 +      return ret;
 +}
 +
 +static ssize_t intmem_write(struct omap_mmu *mmu, const char *buf, size_t count,
 +                          loff_t *ppos)
 +{
 +      unsigned long p = *ppos;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +      ssize_t size = mmu->memsize;
 +      ssize_t written;
 +
 +      if (p >= size)
 +              return 0;
 +      clk_enable(mmu->memclk);
 +      written = count;
 +      if (count > size - p)
 +              written = size - p;
 +      if (copy_from_user(vadr, buf, written)) {
 +              written = -EFAULT;
 +              goto out;
 +      }
 +      *ppos += written;
 +out:
 +      clk_disable(mmu->memclk);
 +      return written;
 +}
 +
 +static ssize_t exmem_write(struct omap_mmu *mmu, char *buf, size_t count,
 +                         loff_t *ppos)
 +{
 +      unsigned long p = *ppos;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +
 +      if (!exmap_valid(mmu, vadr, count)) {
 +              dev_err(mmu->dev, "MMU %s: external device address %08lx "
 +                      "/ size %08x is not valid!\n", mmu->name, p, count);
 +              return -EFAULT;
 +      }
 +      if (count > (1 << mmu->addrspace) - p)
 +              count = (1 << mmu->addrspace) - p;
 +      if (copy_from_user(vadr, buf, count))
 +              return -EFAULT;
 +      *ppos += count;
 +
 +      return count;
 +}
 +
 +static ssize_t omap_mmu_mem_write(struct kobject *kobj,
 +                                struct bin_attribute *attr,
 +                                char *buf, loff_t offset, size_t count)
 +{
 +      struct device *dev = to_dev(kobj);
 +      struct omap_mmu *mmu = dev_get_drvdata(dev);
 +      unsigned long p = (unsigned long)offset;
 +      void *vadr = omap_mmu_to_virt(mmu, p);
 +      int ret;
 +
 +      if (omap_mmu_mem_enable(mmu, vadr) < 0)
 +              return -EBUSY;
 +
 +      if (p < mmu->memsize)
 +              ret = intmem_write(mmu, buf, count, &offset);
 +      else
 +              ret = exmem_write(mmu, buf, count, &offset);
 +
 +      omap_mmu_mem_disable(mmu, vadr);
 +
 +      return ret;
 +}
 +
 +static struct bin_attribute dev_attr_mem = {
 +      .attr   = {
 +              .name   = "mem",
 +              .owner  = THIS_MODULE,
 +              .mode   = S_IRUSR | S_IWUSR | S_IRGRP,
 +      },
 +
 +      .read   = omap_mmu_mem_read,
 +      .write  = omap_mmu_mem_write,
 +};
 +
 +/* To be obsolete for backward compatibility */
 +ssize_t __omap_mmu_mem_read(struct omap_mmu *mmu,
 +                          struct bin_attribute *attr,
 +                          char *buf, loff_t offset, size_t count)
 +{
 +      return omap_mmu_mem_read(&mmu->dev->kobj, attr, buf, offset, count);
 +}
 +EXPORT_SYMBOL_GPL(__omap_mmu_mem_read);
 +
 +ssize_t __omap_mmu_mem_write(struct omap_mmu *mmu,
 +                           struct bin_attribute *attr,
 +                           char *buf, loff_t offset, size_t count)
 +{
 +      return omap_mmu_mem_write(&mmu->dev->kobj, attr, buf, offset, count);
 +}
 +EXPORT_SYMBOL_GPL(__omap_mmu_mem_write);
 +
 +/*
 + * sysfs files
 + */
 +static ssize_t omap_mmu_show(struct device *dev, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      struct omap_mmu *mmu = dev_get_drvdata(dev);
 +      struct omap_mmu_tlb_lock tlb_lock;
 +      int ret;
 +
 +      clk_enable(mmu->clk);
 +      ret = omap_dsp_request_mem();
 +      if (ret < 0)
 +              goto out;
 +
 +      down_read(&mmu->exmap_sem);
 +
 +      omap_mmu_get_tlb_lock(mmu, &tlb_lock);
 +
 +      ret = -EIO;
 +      if (likely(mmu->ops->show))
 +              ret = mmu->ops->show(mmu, buf, &tlb_lock);
 +
 +      /* restore victim entry */
 +      omap_mmu_set_tlb_lock(mmu, &tlb_lock);
 +
 +      up_read(&mmu->exmap_sem);
 +      omap_dsp_release_mem();
 +out:
 +      clk_disable(mmu->clk);
 +
 +      return ret;
 +}
 +
 +static DEVICE_ATTR(mmu, S_IRUGO, omap_mmu_show, NULL);
 +
 +static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf)
 +{
 +      struct omap_mmu *mmu = dev_get_drvdata(dev);
 +      struct exmap_tbl *ent;
 +      int len;
 +      int i = 0;
 +
 +      down_read(&mmu->exmap_sem);
 +      len = sprintf(buf, "  devadr     size         buf     size uc\n");
 +                       /* 0x300000 0x123000  0xc0171000 0x100000  0*/
 +
 +      omap_mmu_for_each_tlb_entry(mmu, ent) {
 +              void *vadr;
 +              unsigned long size;
 +              enum exmap_type type;
 +              int idx;
 +
 +              /* find a top of link */
 +              if (!ent->valid || (ent->link.prev >= 0))
 +                      continue;
 +
 +              vadr = ent->vadr;
 +              type = ent->type;
 +              size = 0;
 +              idx = i;
 +              do {
 +                      ent = mmu->exmap_tbl + idx;
 +                      size += PAGE_SIZE << ent->order;
 +              } while ((idx = ent->link.next) >= 0);
 +
 +              len += sprintf(buf + len, "0x%06lx %#8lx",
 +                             virt_to_omap_mmu(mmu, vadr), size);
 +
 +              if (type == EXMAP_TYPE_FB) {
 +                      len += sprintf(buf + len, "    framebuf\n");
 +              } else {
 +                      len += sprintf(buf + len, "\n");
 +                      idx = i;
 +                      do {
 +                              ent = mmu->exmap_tbl + idx;
 +                              len += sprintf(buf + len,
 +                                             /* 0xc0171000 0x100000  0*/
 +                                             "%19s0x%8p %#8lx %2d\n",
 +                                             "", ent->buf,
 +                                             PAGE_SIZE << ent->order,
 +                                             ent->usecount);
 +                      } while ((idx = ent->link.next) >= 0);
 +              }
 +
 +              i++;
 +      }
 +
 +      up_read(&mmu->exmap_sem);
 +      return len;
 +}
 +
 +static ssize_t exmap_store(struct device *dev, struct device_attribute *attr,
 +                         const char *buf,
 +                         size_t count)
 +{
 +      struct omap_mmu *mmu = dev_get_drvdata(dev);
 +      unsigned long base = 0, len = 0;
 +      int ret;
 +
 +      sscanf(buf, "%lx %lx", &base, &len);
 +
 +      if (!base)
 +              return -EINVAL;
 +
 +      if (len) {
 +              /* Add the mapping */
 +              ret = omap_mmu_exmap(mmu, base, 0, len, EXMAP_TYPE_MEM);
 +              if (ret < 0)
 +                      return ret;
 +      } else {
 +              /* Remove the mapping */
 +              ret = omap_mmu_exunmap(mmu, base);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
 +      return count;
 +}
 +
 +static DEVICE_ATTR(exmap, S_IRUGO | S_IWUSR, exmap_show, exmap_store);
 +
 +static ssize_t mempool_show(struct class *class, char *buf)
 +{
 +      int min_nr_1M = 0, curr_nr_1M = 0;
 +      int min_nr_64K = 0, curr_nr_64K = 0;
 +      int total = 0;
 +
 +      if (likely(mempool_1M)) {
 +              min_nr_1M  = mempool_1M->min_nr;
 +              curr_nr_1M = mempool_1M->curr_nr;
 +              total += min_nr_1M * SZ_1M;
 +      }
 +      if (likely(mempool_64K)) {
 +              min_nr_64K  = mempool_64K->min_nr;
 +              curr_nr_64K = mempool_64K->curr_nr;
 +              total += min_nr_64K * SZ_64K;
 +      }
 +
 +      return sprintf(buf,
 +                     "0x%x\n"
 +                     "1M  buffer: %d (%d free)\n"
 +                     "64K buffer: %d (%d free)\n",
 +                     total, min_nr_1M, curr_nr_1M, min_nr_64K, curr_nr_64K);
 +}
 +
 +
 +static CLASS_ATTR(mempool, S_IRUGO, mempool_show, NULL);
 +
 +static struct class omap_mmu_class = {
 +      .name           = "mmu",
 +};
 +
 +int omap_mmu_register(struct omap_mmu *mmu)
 +{
 +      int ret;
 +
 +      mmu->dev = device_create(&omap_mmu_class, NULL, 0, "%s", mmu->name);
 +      if (unlikely(IS_ERR(mmu->dev)))
 +              return PTR_ERR(mmu->dev);
 +      dev_set_drvdata(mmu->dev, mmu);
 +
 +      mmu->exmap_tbl = kcalloc(mmu->nr_tlb_entries, sizeof(struct exmap_tbl),
 +                               GFP_KERNEL);
 +      if (!mmu->exmap_tbl)
 +              return -ENOMEM;
 +
 +      mmu->twl_mm = mm_alloc();
 +      if (!mmu->twl_mm) {
 +              ret = -ENOMEM;
 +              goto err_mm_alloc;
 +      }
 +
 +      init_rwsem(&mmu->exmap_sem);
 +
 +      ret = omap_mmu_init(mmu);
 +      if (unlikely(ret))
 +              goto err_mmu_init;
 +
 +      ret = device_create_file(mmu->dev, &dev_attr_mmu);
 +      if (unlikely(ret))
 +              goto err_dev_create_mmu;
 +      ret = device_create_file(mmu->dev, &dev_attr_exmap);
 +      if (unlikely(ret))
 +              goto err_dev_create_exmap;
 +
 +      if (likely(mmu->membase)) {
 +              dev_attr_mem.size = mmu->memsize;
 +              ret = device_create_bin_file(mmu->dev,
 +                                           &dev_attr_mem);
 +              if (unlikely(ret))
 +                      goto err_bin_create_mem;
 +      }
 +      return 0;
 +
 +err_bin_create_mem:
 +      device_remove_file(mmu->dev, &dev_attr_exmap);
 +err_dev_create_exmap:
 +      device_remove_file(mmu->dev, &dev_attr_mmu);
 +err_dev_create_mmu:
 +      omap_mmu_shutdown(mmu);
 +err_mmu_init:
 +      kfree(mmu->twl_mm);
 +      mmu->twl_mm = NULL;
 +err_mm_alloc:
 +      kfree(mmu->exmap_tbl);
 +      mmu->exmap_tbl = NULL;
 +      device_unregister(mmu->dev);
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_register);
 +
 +void omap_mmu_unregister(struct omap_mmu *mmu)
 +{
 +      omap_mmu_shutdown(mmu);
 +      omap_mmu_kmem_release();
 +
 +      device_remove_file(mmu->dev, &dev_attr_mmu);
 +      device_remove_file(mmu->dev, &dev_attr_exmap);
 +
 +      if (likely(mmu->membase))
 +              device_remove_bin_file(mmu->dev, &dev_attr_mem);
 +
 +      device_unregister(mmu->dev);
 +
 +      kfree(mmu->exmap_tbl);
 +      mmu->exmap_tbl = NULL;
 +
 +      if (mmu->twl_mm) {
 +              __mmdrop(mmu->twl_mm);
 +              mmu->twl_mm = NULL;
 +      }
 +}
 +EXPORT_SYMBOL_GPL(omap_mmu_unregister);
 +
 +static int __init omap_mmu_class_init(void)
 +{
 +      int ret = class_register(&omap_mmu_class);
 +      if (!ret)
 +              ret = class_create_file(&omap_mmu_class, &class_attr_mempool);
 +
 +      return ret;
 +}
 +
 +static void __exit omap_mmu_class_exit(void)
 +{
 +      class_remove_file(&omap_mmu_class, &class_attr_mempool);
 +      class_unregister(&omap_mmu_class);
 +}
 +
 +subsys_initcall(omap_mmu_class_init);
 +module_exit(omap_mmu_class_exit);
 +
 +MODULE_LICENSE("GPL");
Simple merge
index ccb7f089d1b63e44ccb60e8b1990ec976069f89a,0000000000000000000000000000000000000000..f47b22fd7d0aad6562b69a8d8e1fae525a71d302
mode 100644,000000..100644
--- /dev/null
@@@ -1,1041 -1,0 +1,1041 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
- #include <asm/arch/irqs.h>
 +/*
 + *  linux/drivers/bluetooth/brf6150/brf6150.c
 + *
 + *  Copyright (C) 2005 Nokia Corporation
 + *  Written by Ville Tervo <ville.tervo@nokia.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/kernel.h>
 +#include <linux/init.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/spinlock.h>
 +#include <linux/serial_reg.h>
 +#include <linux/skbuff.h>
 +#include <linux/firmware.h>
 +#include <linux/irq.h>
 +#include <linux/timer.h>
 +#include <linux/clk.h>
 +#include <linux/platform_device.h>
 +
++#include <mach/hardware.h>
++#include <mach/gpio.h>
++#include <mach/board.h>
++#include <mach/irqs.h>
 +
 +#include <net/bluetooth/bluetooth.h>
 +#include <net/bluetooth/hci_core.h>
 +#include <net/bluetooth/hci.h>
 +
 +#include "brf6150.h"
 +
 +#if 0
 +#define NBT_DBG(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_FW(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_FW(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_POWER(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_POWER(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_TRANSFER(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_TRANSFER(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_TRANSFER_NF(fmt, arg...)  printk(fmt "" , ## arg)
 +#else
 +#define NBT_DBG_TRANSFER_NF(...)
 +#endif
 +
 +#define PM_TIMEOUT (2000)
 +
 +static void brf6150_device_release(struct device *dev);
 +static struct brf6150_info *exit_info;
 +
 +static struct platform_device brf6150_device = {
 +      .name           = BT_DEVICE,
 +      .id             = -1,
 +      .num_resources  = 0,
 +      .dev = {
 +              .release = brf6150_device_release,
 +      }
 +};
 +
 +static struct device_driver brf6150_driver = {
 +      .name           = BT_DRIVER,
 +      .bus            = &platform_bus_type,
 +};
 +
 +static inline void brf6150_outb(struct brf6150_info *info, unsigned int offset, u8 val)
 +{
 +      outb(val, info->uart_base + (offset << 2));
 +}
 +
 +static inline u8 brf6150_inb(struct brf6150_info *info, unsigned int offset)
 +{
 +      return inb(info->uart_base + (offset << 2));
 +}
 +
 +static void brf6150_set_rts(struct brf6150_info *info, int active)
 +{
 +      u8 b;
 +
 +      b = brf6150_inb(info, UART_MCR);
 +      if (active)
 +              b |= UART_MCR_RTS;
 +      else
 +              b &= ~UART_MCR_RTS;
 +      brf6150_outb(info, UART_MCR, b);
 +}
 +
 +static void brf6150_wait_for_cts(struct brf6150_info *info, int active,
 +                               int timeout_ms)
 +{
 +      int okay;
 +      unsigned long timeout;
 +
 +      okay = 0;
 +      timeout = jiffies + msecs_to_jiffies(timeout_ms);
 +      for (;;) {
 +              int state;
 +
 +              state = brf6150_inb(info, UART_MSR) & UART_MSR_CTS;
 +              if (active) {
 +                      if (state)
 +                              break;
 +              } else {
 +                      if (!state)
 +                              break;
 +              }
 +              if (jiffies > timeout)
 +                      break;
 +      }
 +}
 +
 +static inline void brf6150_set_auto_ctsrts(struct brf6150_info *info, int on)
 +{
 +      u8 lcr, b;
 +
 +      lcr = brf6150_inb(info, UART_LCR);
 +      brf6150_outb(info, UART_LCR, 0xbf);
 +      b = brf6150_inb(info, UART_EFR);
 +      if (on)
 +              b |= UART_EFR_CTS | UART_EFR_RTS;
 +      else
 +              b &= ~(UART_EFR_CTS | UART_EFR_RTS);
 +      brf6150_outb(info, UART_EFR, b);
 +      brf6150_outb(info, UART_LCR, lcr);
 +}
 +
 +static inline void brf6150_enable_pm_rx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->rx_pm_enabled = 1;
 +      }
 +}
 +
 +static inline void brf6150_disable_pm_rx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->rx_pm_enabled = 0;
 +      }
 +}
 +
 +static void brf6150_enable_pm_tx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              mod_timer(&info->pm_timer, jiffies + msecs_to_jiffies(PM_TIMEOUT));
 +              info->tx_pm_enabled = 1;
 +      }
 +}
 +
 +static void brf6150_disable_pm_tx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->tx_pm_enabled = 0;
 +              omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 1);
 +      }
 +      if (omap_get_gpio_datain(info->btinfo->host_wakeup_gpio))
 +              tasklet_schedule(&info->tx_task);
 +}
 +
 +static void brf6150_pm_timer(unsigned long data)
 +{
 +      struct brf6150_info *info;
 +
 +      info = (struct brf6150_info *)data;
 +      if (info->tx_pm_enabled && info->rx_pm_enabled && !test_bit(HCI_INQUIRY, &info->hdev->flags))
 +              omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
 +      else
 +              mod_timer(&info->pm_timer, jiffies + msecs_to_jiffies(PM_TIMEOUT));
 +}
 +
 +static int brf6150_change_speed(struct brf6150_info *info, unsigned long speed)
 +{
 +      unsigned int divisor;
 +      u8 lcr, mdr1;
 +
 +      NBT_DBG("Setting speed %lu\n", speed);
 +
 +      if (speed >= 460800) {
 +              divisor = UART_CLOCK / 13 / speed;
 +              mdr1 = 3;
 +      } else {
 +              divisor = UART_CLOCK / 16 / speed;
 +              mdr1 = 0;
 +      }
 +
 +      brf6150_outb(info, UART_OMAP_MDR1, 7); /* Make sure UART mode is disabled */
 +      lcr = brf6150_inb(info, UART_LCR);
 +      brf6150_outb(info, UART_LCR, UART_LCR_DLAB);     /* Set DLAB */
 +      brf6150_outb(info, UART_DLL, divisor & 0xff);    /* Set speed */
 +      brf6150_outb(info, UART_DLM, divisor >> 8);
 +      brf6150_outb(info, UART_LCR, lcr);
 +      brf6150_outb(info, UART_OMAP_MDR1, mdr1); /* Make sure UART mode is enabled */
 +
 +      return 0;
 +}
 +
 +/* Firmware handling */
 +static int brf6150_open_firmware(struct brf6150_info *info)
 +{
 +      int err;
 +
 +      info->fw_pos = 0;
 +      err = request_firmware(&info->fw_entry, "brf6150fw.bin", &brf6150_device.dev);
 +
 +      return err;
 +}
 +
 +static struct sk_buff *brf6150_read_fw_cmd(struct brf6150_info *info, int how)
 +{
 +      struct sk_buff *skb;
 +      unsigned int cmd_len;
 +
 +      if (info->fw_pos >= info->fw_entry->size) {
 +              return NULL;
 +      }
 +
 +      cmd_len = info->fw_entry->data[info->fw_pos++];
 +      if (!cmd_len)
 +              return NULL;
 +
 +      if (info->fw_pos + cmd_len > info->fw_entry->size) {
 +              printk(KERN_WARNING "Corrupted firmware image\n");
 +              return NULL;
 +      }
 +
 +      skb = bt_skb_alloc(cmd_len, how);
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot reserve memory for buffer\n");
 +              return NULL;
 +      }
 +      memcpy(skb_put(skb, cmd_len), &info->fw_entry->data[info->fw_pos], cmd_len);
 +
 +      info->fw_pos += cmd_len;
 +
 +      return skb;
 +}
 +
 +static int brf6150_close_firmware(struct brf6150_info *info)
 +{
 +      release_firmware(info->fw_entry);
 +      return 0;
 +}
 +
 +static int brf6150_send_alive_packet(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +
 +      NBT_DBG("Sending alive packet\n");
 +      skb = brf6150_read_fw_cmd(info, GFP_ATOMIC);
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot read alive command");
 +              return -1;
 +      }
 +
 +      clk_enable(info->uart_ck);
 +      skb_queue_tail(&info->txq, skb);
 +      tasklet_schedule(&info->tx_task);
 +
 +      NBT_DBG("Alive packet sent\n");
 +      return 0;
 +}
 +
 +static void brf6150_alive_packet(struct brf6150_info *info, struct sk_buff *skb)
 +{
 +      NBT_DBG("Received alive packet\n");
 +      if (skb->data[1] == 0xCC) {
 +              complete(&info->init_completion);
 +      }
 +
 +      kfree_skb(skb);
 +}
 +
 +static int brf6150_send_negotiation(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +      NBT_DBG("Sending negotiation..\n");
 +
 +      brf6150_change_speed(info, INIT_SPEED);
 +
 +      skb = brf6150_read_fw_cmd(info, GFP_KERNEL);
 +
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot read negoatiation message");
 +              return -1;
 +      }
 +
 +      clk_enable(info->uart_ck);
 +      skb_queue_tail(&info->txq, skb);
 +      tasklet_schedule(&info->tx_task);
 +
 +
 +      NBT_DBG("Negotiation sent\n");
 +      return 0;
 +}
 +
 +static void brf6150_negotiation_packet(struct brf6150_info *info,
 +                                     struct sk_buff *skb)
 +{
 +      if (skb->data[1] == 0x20) {
 +              /* Change to operational settings */
 +              brf6150_set_rts(info, 0);
 +              brf6150_wait_for_cts(info, 0, 100);
 +              brf6150_change_speed(info, MAX_BAUD_RATE);
 +              brf6150_set_rts(info, 1);
 +              brf6150_wait_for_cts(info, 1, 100);
 +              brf6150_set_auto_ctsrts(info, 1);
 +              brf6150_send_alive_packet(info);
 +      } else {
 +              printk(KERN_WARNING "Could not negotiate brf6150 settings\n");
 +      }
 +      kfree_skb(skb);
 +}
 +
 +static int brf6150_get_hdr_len(u8 pkt_type)
 +{
 +      long retval;
 +
 +      switch (pkt_type) {
 +      case H4_EVT_PKT:
 +              retval = HCI_EVENT_HDR_SIZE;
 +              break;
 +      case H4_ACL_PKT:
 +              retval = HCI_ACL_HDR_SIZE;
 +              break;
 +      case H4_SCO_PKT:
 +              retval = HCI_SCO_HDR_SIZE;
 +              break;
 +      case H4_NEG_PKT:
 +              retval = 9;
 +              break;
 +      case H4_ALIVE_PKT:
 +              retval = 3;
 +              break;
 +      default:
 +              printk(KERN_ERR "brf6150: Unknown H4 packet");
 +              retval = -1;
 +              break;
 +      }
 +
 +      return retval;
 +}
 +
 +static unsigned int brf6150_get_data_len(struct brf6150_info *info,
 +                                       struct sk_buff *skb)
 +{
 +      long retval = -1;
 +      struct hci_event_hdr *evt_hdr;
 +      struct hci_acl_hdr *acl_hdr;
 +      struct hci_sco_hdr *sco_hdr;
 +
 +      switch (bt_cb(skb)->pkt_type) {
 +      case H4_EVT_PKT:
 +              evt_hdr = (struct hci_event_hdr *)skb->data;
 +              retval = evt_hdr->plen;
 +              break;
 +      case H4_ACL_PKT:
 +              acl_hdr = (struct hci_acl_hdr *)skb->data;
 +              retval = le16_to_cpu(acl_hdr->dlen);
 +              break;
 +      case H4_SCO_PKT:
 +              sco_hdr = (struct hci_sco_hdr *)skb->data;
 +              retval = sco_hdr->dlen;
 +              break;
 +      case H4_NEG_PKT:
 +              retval = 0;
 +              break;
 +      case H4_ALIVE_PKT:
 +              retval = 0;
 +              break;
 +      }
 +
 +      return retval;
 +}
 +
 +static void brf6150_parse_fw_event(struct brf6150_info *info)
 +{
 +      struct hci_fw_event *ev;
 +
 +      if (bt_cb(info->rx_skb)->pkt_type != H4_EVT_PKT) {
 +              printk(KERN_WARNING "Got non event fw packet.\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      ev = (struct hci_fw_event *)info->rx_skb->data;
 +      if (ev->hev.evt != HCI_EV_CMD_COMPLETE) {
 +              printk(KERN_WARNING "Got non cmd complete fw event\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      if (ev->status != 0) {
 +              printk(KERN_WARNING "Got error status from fw command\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      complete(&info->fw_completion);
 +}
 +
 +static inline void brf6150_recv_frame(struct brf6150_info *info,
 +                                    struct sk_buff *skb)
 +{
 +      if (unlikely(!test_bit(HCI_RUNNING, &info->hdev->flags))) {
 +              NBT_DBG("fw_event\n");
 +              brf6150_parse_fw_event(info);
 +              kfree_skb(skb);
 +      } else {
 +              hci_recv_frame(skb);
 +              if (!(brf6150_inb(info, UART_LSR) & UART_LSR_DR))
 +                      brf6150_enable_pm_rx(info);
 +              NBT_DBG("Frame sent to upper layer\n");
 +      }
 +
 +}
 +
 +static inline void brf6150_rx(struct brf6150_info *info)
 +{
 +      u8 byte;
 +
 +      NBT_DBG_TRANSFER("rx_tasklet woke up\ndata ");
 +
 +      while (brf6150_inb(info, UART_LSR) & UART_LSR_DR) {
 +              if (info->rx_skb == NULL) {
 +                      info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
 +                      if (!info->rx_skb) {
 +                              printk(KERN_WARNING "brf6150: Can't allocate memory for new packet\n");
 +                              return;
 +                      }
 +                      info->rx_state = WAIT_FOR_PKT_TYPE;
 +                      info->rx_skb->dev = (void *)info->hdev;
 +                      brf6150_disable_pm_rx(info);
 +                      clk_enable(info->uart_ck);
 +              }
 +
 +              byte = brf6150_inb(info, UART_RX);
 +              if (info->garbage_bytes) {
 +                      info->garbage_bytes--;
 +                      info->hdev->stat.err_rx++;
 +                      continue;
 +              }
 +              info->hdev->stat.byte_rx++;
 +              NBT_DBG_TRANSFER_NF("0x%.2x  ", byte);
 +              switch (info->rx_state) {
 +              case WAIT_FOR_PKT_TYPE:
 +                      bt_cb(info->rx_skb)->pkt_type = byte;
 +                      info->rx_count = brf6150_get_hdr_len(byte);
 +                      if (info->rx_count >= 0) {
 +                              info->rx_state = WAIT_FOR_HEADER;
 +                      } else {
 +                              info->hdev->stat.err_rx++;
 +                              kfree_skb(info->rx_skb);
 +                              info->rx_skb = NULL;
 +                              clk_disable(info->uart_ck);
 +                      }
 +                      break;
 +              case WAIT_FOR_HEADER:
 +                      info->rx_count--;
 +                      *skb_put(info->rx_skb, 1) = byte;
 +                      if (info->rx_count == 0) {
 +                              info->rx_count = brf6150_get_data_len(info, info->rx_skb);
 +                              if (info->rx_count > skb_tailroom(info->rx_skb)) {
 +                                      printk(KERN_WARNING "brf6150: Frame is %ld bytes too long.\n",
 +                                             info->rx_count - skb_tailroom(info->rx_skb));
 +                                      info->rx_skb = NULL;
 +                                      info->garbage_bytes = info->rx_count - skb_tailroom(info->rx_skb);
 +                                      clk_disable(info->uart_ck);
 +                                      break;
 +                              }
 +                              info->rx_state = WAIT_FOR_DATA;
 +                              if (bt_cb(info->rx_skb)->pkt_type == H4_NEG_PKT) {
 +                                      brf6150_negotiation_packet(info, info->rx_skb);
 +                                      info->rx_skb = NULL;
 +                                      clk_disable(info->uart_ck);
 +                                      return;
 +                              }
 +                              if (bt_cb(info->rx_skb)->pkt_type == H4_ALIVE_PKT) {
 +                                      brf6150_alive_packet(info, info->rx_skb);
 +                                      info->rx_skb = NULL;
 +                                      clk_disable(info->uart_ck);
 +                                      return;
 +                              }
 +                      }
 +                      break;
 +              case WAIT_FOR_DATA:
 +                      info->rx_count--;
 +                      *skb_put(info->rx_skb, 1) = byte;
 +                      if (info->rx_count == 0) {
 +                              brf6150_recv_frame(info, info->rx_skb);
 +                              info->rx_skb = NULL;
 +                              clk_disable(info->uart_ck);
 +                      }
 +                      break;
 +              default:
 +                      WARN_ON(1);
 +                      break;
 +              }
 +      }
 +
 +      NBT_DBG_TRANSFER_NF("\n");
 +}
 +
 +static void brf6150_tx_tasklet(unsigned long data)
 +{
 +      unsigned int sent = 0;
 +      unsigned long flags;
 +      struct sk_buff *skb;
 +      struct brf6150_info *info = (struct brf6150_info *)data;
 +
 +      NBT_DBG_TRANSFER("tx_tasklet woke up\n data ");
 +
 +      skb = skb_dequeue(&info->txq);
 +      if (!skb) {
 +              /* No data in buffer */
 +              brf6150_enable_pm_tx(info);
 +              return;
 +      }
 +
 +      /* Copy data to tx fifo */
 +      while (!(brf6150_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) &&
 +             (sent < skb->len)) {
 +              NBT_DBG_TRANSFER_NF("0x%.2x ", skb->data[sent]);
 +              brf6150_outb(info, UART_TX, skb->data[sent]);
 +              sent++;
 +      }
 +
 +      info->hdev->stat.byte_tx += sent;
 +      NBT_DBG_TRANSFER_NF("\n");
 +      if (skb->len == sent) {
 +              kfree_skb(skb);
 +              clk_disable(info->uart_ck);
 +      } else {
 +              skb_pull(skb, sent);
 +              skb_queue_head(&info->txq, skb);
 +      }
 +
 +      spin_lock_irqsave(&info->lock, flags);
 +      brf6150_outb(info, UART_IER, brf6150_inb(info, UART_IER) | UART_IER_THRI);
 +      spin_unlock_irqrestore(&info->lock, flags);
 +}
 +
 +static irqreturn_t brf6150_interrupt(int irq, void *data)
 +{
 +      struct brf6150_info *info = (struct brf6150_info *)data;
 +      u8 iir, msr;
 +      int ret;
 +      unsigned long flags;
 +
 +      ret = IRQ_NONE;
 +
 +      clk_enable(info->uart_ck);
 +      iir = brf6150_inb(info, UART_IIR);
 +      if (iir & UART_IIR_NO_INT) {
 +              printk("Interrupt but no reason irq 0x%.2x\n", iir);
 +              clk_disable(info->uart_ck);
 +              return IRQ_HANDLED;
 +      }
 +
 +      NBT_DBG("In interrupt handler iir 0x%.2x\n", iir);
 +
 +      iir &= UART_IIR_ID;
 +
 +      if (iir == UART_IIR_MSI) {
 +              msr = brf6150_inb(info, UART_MSR);
 +              ret = IRQ_HANDLED;
 +      }
 +      if (iir == UART_IIR_RLSI) {
 +              brf6150_inb(info, UART_RX);
 +              brf6150_inb(info, UART_LSR);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      if (iir == UART_IIR_RDI) {
 +              brf6150_rx(info);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      if (iir == UART_IIR_THRI) {
 +              spin_lock_irqsave(&info->lock, flags);
 +              brf6150_outb(info, UART_IER, brf6150_inb(info, UART_IER) & ~UART_IER_THRI);
 +              spin_unlock_irqrestore(&info->lock, flags);
 +              tasklet_schedule(&info->tx_task);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      clk_disable(info->uart_ck);
 +      return ret;
 +}
 +
 +static irqreturn_t brf6150_wakeup_interrupt(int irq, void *dev_inst)
 +{
 +      struct brf6150_info *info = dev_inst;
 +      int should_wakeup;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&info->lock, flags);
 +      should_wakeup = omap_get_gpio_datain(info->btinfo->host_wakeup_gpio);
 +      NBT_DBG_POWER("gpio interrupt %d\n", should_wakeup);
 +      if (should_wakeup) {
 +              clk_enable(info->uart_ck);
 +              brf6150_set_auto_ctsrts(info, 1);
 +              brf6150_rx(info);
 +              tasklet_schedule(&info->tx_task);
 +      } else {
 +              brf6150_set_auto_ctsrts(info, 0);
 +              brf6150_set_rts(info, 0);
 +              clk_disable(info->uart_ck);
 +      }
 +
 +      spin_unlock_irqrestore(&info->lock, flags);
 +      return IRQ_HANDLED;
 +}
 +
 +static int brf6150_init_uart(struct brf6150_info *info)
 +{
 +      int count = 0;
 +
 +      /* Reset the  UART */
 +      brf6150_outb(info, UART_OMAP_SYSC, UART_SYSC_OMAP_RESET);
 +      while (!(brf6150_inb(info, UART_OMAP_SYSS) & UART_SYSS_RESETDONE)) {
 +              if (count++ > 100) {
 +                      printk(KERN_ERR "brf6150: UART reset timeout\n");
 +                      return -1;
 +              }
 +              udelay(1);
 +      }
 +
 +      /* Enable and setup FIFO */
 +      brf6150_outb(info, UART_LCR, UART_LCR_WLEN8);
 +      brf6150_outb(info, UART_OMAP_MDR1, 0x00); /* Make sure UART mode is enabled */
 +      brf6150_outb(info, UART_OMAP_SCR, 0x00);
 +      brf6150_outb(info, UART_EFR, brf6150_inb(info, UART_EFR) | UART_EFR_ECB);
 +      brf6150_outb(info, UART_MCR, brf6150_inb(info, UART_MCR) | UART_MCR_TCRTLR);
 +      brf6150_outb(info, UART_TI752_TLR, 0xff);
 +      brf6150_outb(info, UART_TI752_TCR, 0x1f);
 +      brf6150_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
 +      brf6150_outb(info, UART_IER, UART_IER_RDI);
 +
 +      return 0;
 +}
 +
 +static int brf6150_reset(struct brf6150_info *info)
 +{
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
 +      omap_set_gpio_dataout(info->btinfo->reset_gpio, 0);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(10));
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 1);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(100));
 +      omap_set_gpio_dataout(info->btinfo->reset_gpio, 1);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(100));
 +
 +      return 0;
 +}
 +
 +static int brf6150_send_firmware(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +
 +      init_completion(&info->fw_completion);
 +      info->fw_error = 0;
 +
 +      while ((skb = brf6150_read_fw_cmd(info, GFP_KERNEL)) != NULL) {
 +              clk_enable(info->uart_ck);
 +              skb_queue_tail(&info->txq, skb);
 +              tasklet_schedule(&info->tx_task);
 +
 +              if (!wait_for_completion_timeout(&info->fw_completion, HZ)) {
 +                      return -1;
 +              }
 +
 +              if (info->fw_error) {
 +                      return -1;
 +              }
 +      }
 +      NBT_DBG_FW("Firmware sent\n");
 +
 +      return 0;
 +
 +}
 +
 +/* hci callback functions */
 +static int brf6150_hci_flush(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info;
 +      info = hdev->driver_data;
 +
 +      skb_queue_purge(&info->txq);
 +
 +      return 0;
 +}
 +
 +static int brf6150_hci_open(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info;
 +      int err;
 +
 +      info = hdev->driver_data;
 +
 +      if (test_bit(HCI_RUNNING, &hdev->flags))
 +              return 0;
 +
 +      if (brf6150_open_firmware(info) < 0) {
 +              printk("Cannot open firmware\n");
 +              return -1;
 +      }
 +
 +      info->rx_state = WAIT_FOR_PKT_TYPE;
 +      info->rx_count = 0;
 +      info->garbage_bytes = 0;
 +      info->rx_skb = NULL;
 +      info->pm_enabled = 0;
 +      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +      init_completion(&info->fw_completion);
 +
 +      clk_enable(info->uart_ck);
 +
 +      brf6150_init_uart(info);
 +      brf6150_set_auto_ctsrts(info, 0);
 +      brf6150_set_rts(info, 0);
 +      brf6150_reset(info);
 +      brf6150_wait_for_cts(info, 1, 10);
 +      brf6150_set_rts(info, 1);
 +      if (brf6150_send_negotiation(info)) {
 +              brf6150_close_firmware(info);
 +              return -1;
 +      }
 +
 +      if (!wait_for_completion_interruptible_timeout(&info->init_completion, HZ)) {
 +              brf6150_close_firmware(info);
 +              clk_disable(info->uart_ck);
 +              clear_bit(HCI_RUNNING, &hdev->flags);
 +              return -1;
 +      }
 +      brf6150_set_auto_ctsrts(info, 1);
 +
 +      err = brf6150_send_firmware(info);
 +      brf6150_close_firmware(info);
 +      if (err < 0)
 +              printk(KERN_ERR "brf6150: Sending firmware failed. Bluetooth won't work properly\n");
 +
 +      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_EDGE_BOTH);
 +      info->pm_enabled = 1;
 +      set_bit(HCI_RUNNING, &hdev->flags);
 +      return 0;
 +}
 +
 +static int brf6150_hci_close(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info = hdev->driver_data;
 +      if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 +              return 0;
 +
 +      brf6150_hci_flush(hdev);
 +      clk_disable(info->uart_ck);
 +      del_timer_sync(&info->pm_timer);
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
 +      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +
 +      return 0;
 +}
 +
 +static void brf6150_hci_destruct(struct hci_dev *hdev)
 +{
 +}
 +
 +static int brf6150_hci_send_frame(struct sk_buff *skb)
 +{
 +      struct brf6150_info *info;
 +      struct hci_dev *hdev = (struct hci_dev *)skb->dev;
 +
 +      if (!hdev) {
 +              printk(KERN_WARNING "brf6150: Frame for unknown device\n");
 +              return -ENODEV;
 +      }
 +
 +      if (!test_bit(HCI_RUNNING, &hdev->flags)) {
 +              printk(KERN_WARNING "brf6150: Frame for non-running device\n");
 +              return -EIO;
 +      }
 +
 +      info = hdev->driver_data;
 +
 +      switch (bt_cb(skb)->pkt_type) {
 +              case HCI_COMMAND_PKT:
 +                      hdev->stat.cmd_tx++;
 +                      break;
 +              case HCI_ACLDATA_PKT:
 +                      hdev->stat.acl_tx++;
 +                      break;
 +              case HCI_SCODATA_PKT:
 +                      hdev->stat.sco_tx++;
 +                      break;
 +      };
 +
 +      /* Push frame type to skb */
 +      clk_enable(info->uart_ck);
 +      *skb_push(skb, 1) = bt_cb(skb)->pkt_type;
 +      skb_queue_tail(&info->txq, skb);
 +
 +      brf6150_disable_pm_tx(info);
 +
 +      return 0;
 +}
 +
 +static int brf6150_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
 +{
 +      return -ENOIOCTLCMD;
 +}
 +
 +static void brf6150_device_release(struct device *dev)
 +{
 +}
 +
 +static int brf6150_register_hdev(struct brf6150_info *info)
 +{
 +      struct hci_dev *hdev;
 +
 +      /* Initialize and register HCI device */
 +
 +      hdev = hci_alloc_dev();
 +      if (!hdev) {
 +              printk(KERN_WARNING "brf6150: Can't allocate memory for device\n");
 +              return -ENOMEM;
 +      }
 +      info->hdev = hdev;
 +
 +      hdev->type = HCI_UART;
 +      hdev->driver_data = info;
 +
 +      hdev->open = brf6150_hci_open;
 +      hdev->close = brf6150_hci_close;
 +      hdev->destruct = brf6150_hci_destruct;
 +      hdev->flush = brf6150_hci_flush;
 +      hdev->send = brf6150_hci_send_frame;
 +      hdev->destruct = brf6150_hci_destruct;
 +      hdev->ioctl = brf6150_hci_ioctl;
 +
 +      hdev->owner = THIS_MODULE;
 +
 +      if (hci_register_dev(hdev) < 0) {
 +              printk(KERN_WARNING "brf6150: Can't register HCI device %s.\n", hdev->name);
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +static int __init brf6150_init(void)
 +{
 +      struct brf6150_info *info;
 +      int irq, err;
 +
 +      info = kmalloc(sizeof(struct brf6150_info), GFP_KERNEL);
 +      if (!info)
 +              return -ENOMEM;
 +      memset(info, 0, sizeof(struct brf6150_info));
 +
 +      brf6150_device.dev.driver_data = info;
 +      init_completion(&info->init_completion);
 +      init_completion(&info->fw_completion);
 +      info->pm_enabled = 0;
 +      info->rx_pm_enabled = 0;
 +      info->tx_pm_enabled = 0;
 +      info->garbage_bytes = 0;
 +      tasklet_init(&info->tx_task, brf6150_tx_tasklet, (unsigned long)info);
 +      spin_lock_init(&info->lock);
 +      skb_queue_head_init(&info->txq);
 +      init_timer(&info->pm_timer);
 +      info->pm_timer.function = brf6150_pm_timer;
 +      info->pm_timer.data = (unsigned long)info;
 +      exit_info = NULL;
 +
 +      info->btinfo = omap_get_config(OMAP_TAG_NOKIA_BT, struct omap_bluetooth_config);
 +      if (info->btinfo == NULL)
 +              return -1;
 +
 +      NBT_DBG("RESET gpio: %d\n", info->btinfo->reset_gpio);
 +      NBT_DBG("BTWU gpio: %d\n", info->btinfo->bt_wakeup_gpio);
 +      NBT_DBG("HOSTWU gpio: %d\n", info->btinfo->host_wakeup_gpio);
 +      NBT_DBG("Uart: %d\n", info->btinfo->bt_uart);
 +      NBT_DBG("sysclk: %d\n", info->btinfo->bt_sysclk);
 +
 +      err = omap_request_gpio(info->btinfo->reset_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line %d", 
 +                     info->btinfo->reset_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      err = omap_request_gpio(info->btinfo->bt_wakeup_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line 0x%d",
 +                     info->btinfo->bt_wakeup_gpio);
 +              omap_free_gpio(info->btinfo->reset_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      err = omap_request_gpio(info->btinfo->host_wakeup_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line %d",
 +                     info->btinfo->host_wakeup_gpio);
 +              omap_free_gpio(info->btinfo->reset_gpio);
 +              omap_free_gpio(info->btinfo->bt_wakeup_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      omap_set_gpio_direction(info->btinfo->reset_gpio, 0);
 +      omap_set_gpio_direction(info->btinfo->bt_wakeup_gpio, 0);
 +      omap_set_gpio_direction(info->btinfo->host_wakeup_gpio, 1);
 +      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +
 +      switch (info->btinfo->bt_uart) {
 +      case 1:
 +              irq = INT_UART1;
 +              info->uart_ck = clk_get(NULL, "uart1_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART1_BASE);
 +              break;
 +      case 2:
 +              irq = INT_UART2;
 +              info->uart_ck = clk_get(NULL, "uart2_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART2_BASE);
 +              break;
 +      case 3:
 +              irq = INT_UART3;
 +              info->uart_ck = clk_get(NULL, "uart3_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART3_BASE);
 +              break;
 +      default:
 +              printk(KERN_ERR "No uart defined\n");
 +              goto cleanup;
 +      }
 +
 +      info->irq = irq;
 +      err = request_irq(irq, brf6150_interrupt, 0, "brf6150", (void *)info);
 +      if (err < 0) {
 +              printk(KERN_ERR "brf6150: unable to get IRQ %d\n", irq);
 +              goto cleanup;
 +      }
 +
 +      err = request_irq(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio),
 +                      brf6150_wakeup_interrupt, 0, "brf6150_wkup", (void *)info);
 +      if (err < 0) {
 +              printk(KERN_ERR "brf6150: unable to get wakeup IRQ %d\n",
 +                              OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio));
 +              free_irq(irq, (void *)info);
 +              goto cleanup;
 +      }
 +
 +      /* Register with LDM */
 +      if (platform_device_register(&brf6150_device)) {
 +              printk(KERN_ERR "failed to register brf6150 device\n");
 +              err = -ENODEV;
 +              goto cleanup_irq;
 +      }
 +      /* Register the driver with LDM */
 +      if (driver_register(&brf6150_driver)) {
 +              printk(KERN_WARNING "failed to register brf6150 driver\n");
 +              platform_device_unregister(&brf6150_device);
 +              err = -ENODEV;
 +              goto cleanup_irq;
 +      }
 +
 +      if (brf6150_register_hdev(info) < 0) {
 +              printk(KERN_WARNING "failed to register brf6150 hci device\n");
 +              platform_device_unregister(&brf6150_device);
 +              driver_unregister(&brf6150_driver);
 +              goto cleanup_irq;
 +      }
 +
 +      exit_info = info;
 +      return 0;
 +
 +cleanup_irq:
 +      free_irq(irq, (void *)info);
 +      free_irq(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), (void *)info);
 +cleanup:
 +      omap_free_gpio(info->btinfo->reset_gpio);
 +      omap_free_gpio(info->btinfo->bt_wakeup_gpio);
 +      omap_free_gpio(info->btinfo->host_wakeup_gpio);
 +      kfree(info);
 +
 +      return err;
 +}
 +
 +static void __exit brf6150_exit(void)
 +{
 +      brf6150_hci_close(exit_info->hdev);
 +      hci_free_dev(exit_info->hdev);
 +      omap_free_gpio(exit_info->btinfo->reset_gpio);
 +      omap_free_gpio(exit_info->btinfo->bt_wakeup_gpio);
 +      omap_free_gpio(exit_info->btinfo->host_wakeup_gpio);
 +      free_irq(exit_info->irq, (void *)exit_info);
 +      free_irq(OMAP_GPIO_IRQ(exit_info->btinfo->host_wakeup_gpio), (void *)exit_info);
 +      kfree(exit_info);
 +}
 +
 +module_init(brf6150_init);
 +module_exit(brf6150_exit);
 +
 +MODULE_DESCRIPTION("brf6150 hci driver");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Ville Tervo <ville.tervo@nokia.com>");
index 334a72e5908f00f0d6c972d633478c9357a763f5,0000000000000000000000000000000000000000..e8b29880e9fb517ea011cea1b1f8c123df715da3
mode 100644,000000..100644
--- /dev/null
@@@ -1,91 -1,0 +1,91 @@@
- #include <asm/arch/board.h>
 +/*
 + *  linux/drivers/bluetooth/brf6150/brf6150.h
 + *
 + *  Copyright (C) 2005 Nokia Corporation
 + *  Written by Ville Tervo <ville.tervo@nokia.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 <mach/board.h>
 +
 +#ifndef __DRIVERS_BLUETOOTH_BRF6150_H
 +#define __DRIVERS_BLUETOOTH_BRF6150_H
 +
 +#define UART_SYSC_OMAP_RESET  0x02
 +#define UART_SYSS_RESETDONE   0x01
 +#define UART_OMAP_SCR_EMPTY_THR       0x08
 +#define UART_OMAP_SCR_WAKEUP  0x10
 +#define UART_OMAP_SSR_WAKEUP  0x02
 +#define UART_OMAP_SSR_TXFULL  0x01
 +
 +struct brf6150_info {
 +      struct hci_dev *hdev;
 +      spinlock_t lock;
 +
 +      struct clk *uart_ck;
 +      unsigned long uart_base;
 +      unsigned int irq;
 +
 +      struct sk_buff_head txq;
 +      struct sk_buff *rx_skb;
 +      const struct omap_bluetooth_config *btinfo;
 +      const struct firmware *fw_entry;
 +      int fw_pos;
 +      int fw_error;
 +      struct completion fw_completion;
 +      struct completion init_completion;
 +      struct tasklet_struct tx_task;
 +      long rx_count;
 +      unsigned long garbage_bytes;
 +      unsigned long rx_state;
 +      int pm_enabled;
 +      int rx_pm_enabled;
 +      int tx_pm_enabled;
 +      struct timer_list pm_timer;
 +};
 +
 +#define BT_DEVICE "nokia_btuart"
 +#define BT_DRIVER "nokia_btuart"
 +
 +#define MAX_BAUD_RATE         921600
 +#define UART_CLOCK            48000000
 +#define BT_INIT_DIVIDER               320
 +#define BT_BAUDRATE_DIVIDER   384000000
 +#define BT_SYSCLK_DIV         1000
 +#define INIT_SPEED            120000
 +
 +#define H4_TYPE_SIZE          1
 +
 +/* H4+ packet types */
 +#define H4_CMD_PKT            0x01
 +#define H4_ACL_PKT            0x02
 +#define H4_SCO_PKT            0x03
 +#define H4_EVT_PKT            0x04
 +#define H4_NEG_PKT            0x06
 +#define H4_ALIVE_PKT          0x07
 +
 +/* TX states */
 +#define WAIT_FOR_PKT_TYPE     1
 +#define WAIT_FOR_HEADER               2
 +#define WAIT_FOR_DATA         3
 +
 +struct hci_fw_event {
 +      struct hci_event_hdr hev;
 +      struct hci_ev_cmd_complete cmd;
 +      __u8 status;
 +} __attribute__ ((packed));
 +
 +#endif /* __DRIVERS_BLUETOOTH_BRF6150_H */
index eff38be50880e9c8a3e2ee28aec88ce7c4730cd0,0000000000000000000000000000000000000000..289557c4a246030b0086237c8f032dc9dc87c229
mode 100644,000000..100644
--- /dev/null
@@@ -1,293 -1,0 +1,293 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
 +/*
 + * drivers/cbus/cbus.c
 + *
 + * Support functions for CBUS serial protocol
 + *
 + * Copyright (C) 2004, 2005 Nokia Corporation
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          David Weinehall <david.weinehall@nokia.com>, and
 + *          Mikko Ylinen <mikko.k.ylinen@nokia.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.
 + *
 + * 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/device.h>
 +#include <linux/init.h>
 +#include <linux/kernel.h>
 +#include <linux/delay.h>
 +#include <linux/spinlock.h>
 +
++#include <mach/gpio.h>
++#include <mach/board.h>
 +
 +#include <asm/io.h>
 +
 +#include "cbus.h"
 +
 +struct cbus_host *cbus_host = NULL;
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +/* We use our own MPUIO functions to get closer to 1MHz bus speed */
 +
 +static inline void cbus_set_gpio_direction(u32 base, int mpuio, int is_input)
 +{
 +      u16 w;
 +
 +      mpuio &= 0x0f;
 +      w = __raw_readw(base + OMAP_MPUIO_IO_CNTL);
 +      if (is_input)
 +              w |= 1 << mpuio;
 +      else
 +              w &= ~(1 << mpuio);
 +      __raw_writew(w, base + OMAP_MPUIO_IO_CNTL);
 +
 +}
 +
 +static inline void cbus_set_gpio_dataout(u32 base, int mpuio, int enable)
 +{
 +      u16 w;
 +
 +      mpuio &= 0x0f;
 +      w = __raw_readw(base + OMAP_MPUIO_OUTPUT);
 +      if (enable)
 +              w |= 1 << mpuio;
 +      else
 +              w &= ~(1 << mpuio);
 +      __raw_writew(w, base + OMAP_MPUIO_OUTPUT);
 +}
 +
 +static inline int cbus_get_gpio_datain(u32 base, int mpuio)
 +{
 +      mpuio &= 0x0f;
 +
 +      return (__raw_readw(base + OMAP_MPUIO_INPUT_LATCH) & (1 << mpuio)) != 0;
 +}
 +
 +static void cbus_send_bit(struct cbus_host *host, u32 base, int bit,
 +                        int set_to_input)
 +{
 +      cbus_set_gpio_dataout(base, host->dat_gpio, bit ? 1 : 0);
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 1);
 +
 +      /* The data bit is read on the rising edge of CLK */
 +      if (set_to_input)
 +              cbus_set_gpio_direction(base, host->dat_gpio, 1);
 +
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 0);
 +}
 +
 +static u8 cbus_receive_bit(struct cbus_host *host, u32 base)
 +{
 +      u8 ret;
 +
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 1);
 +      ret = cbus_get_gpio_datain(base, host->dat_gpio);
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 0);
 +
 +      return ret;
 +}
 +
 +#else
 +
 +#define cbus_set_gpio_direction(base, gpio, is_input) omap_set_gpio_direction(gpio, is_input)
 +#define cbus_set_gpio_dataout(base, gpio, enable) omap_set_gpio_dataout(gpio, enable)
 +#define cbus_get_gpio_datain(base, int, gpio) omap_get_gpio_datain(gpio)
 +
 +static void _cbus_send_bit(struct cbus_host *host, int bit, int set_to_input)
 +{
 +      omap_set_gpio_dataout(host->dat_gpio, bit ? 1 : 0);
 +      omap_set_gpio_dataout(host->clk_gpio, 1);
 +
 +      /* The data bit is read on the rising edge of CLK */
 +      if (set_to_input)
 +              omap_set_gpio_direction(host->dat_gpio, 1);
 +
 +      omap_set_gpio_dataout(host->clk_gpio, 0);
 +}
 +
 +static u8 _cbus_receive_bit(struct cbus_host *host)
 +{
 +      u8 ret;
 +
 +      omap_set_gpio_dataout(host->clk_gpio, 1);
 +      ret = omap_get_gpio_datain(host->dat_gpio);
 +      omap_set_gpio_dataout(host->clk_gpio, 0);
 +
 +      return ret;
 +}
 +
 +#define cbus_send_bit(host, base, bit, set_to_input) _cbus_send_bit(host, bit, set_to_input)
 +#define cbus_receive_bit(host, base) _cbus_receive_bit(host)
 +
 +#endif
 +
 +static int cbus_transfer(struct cbus_host *host, int dev, int reg, int data)
 +{
 +      int i;
 +      int is_read = 0;
 +      unsigned long flags;
 +      u32 base;
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +      base = (u32) io_p2v(OMAP_MPUIO_BASE);
 +#else
 +      base = 0;
 +#endif
 +
 +      if (data < 0)
 +              is_read = 1;
 +
 +      /* We don't want interrupts disturbing our transfer */
 +      spin_lock_irqsave(&host->lock, flags);
 +
 +      /* Reset state and start of transfer, SEL stays down during transfer */
 +      cbus_set_gpio_dataout(base, host->sel_gpio, 0);
 +
 +      /* Set the DAT pin to output */
 +      cbus_set_gpio_direction(base, host->dat_gpio, 0);
 +
 +      /* Send the device address */
 +      for (i = 3; i > 0; i--)
 +              cbus_send_bit(host, base, dev & (1 << (i - 1)), 0);
 +
 +      /* Send the rw flag */
 +      cbus_send_bit(host, base, is_read, 0);
 +
 +      /* Send the register address */
 +      for (i = 5; i > 0; i--) {
 +              int set_to_input = 0;
 +
 +              if (is_read && i == 1)
 +                      set_to_input = 1;
 +
 +              cbus_send_bit(host, base, reg & (1 << (i - 1)), set_to_input);
 +      }
 +
 +      if (!is_read) {
 +              for (i = 16; i > 0; i--)
 +                      cbus_send_bit(host, base, data & (1 << (i - 1)), 0);
 +      } else {
 +              cbus_set_gpio_dataout(base, host->clk_gpio, 1);
 +              data = 0;
 +
 +              for (i = 16; i > 0; i--) {
 +                      u8 bit = cbus_receive_bit(host, base);
 +
 +                      if (bit)
 +                              data |= 1 << (i - 1);
 +              }
 +      }
 +
 +      /* Indicate end of transfer, SEL goes up until next transfer */
 +      cbus_set_gpio_dataout(base, host->sel_gpio, 1);
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 1);
 +      cbus_set_gpio_dataout(base, host->clk_gpio, 0);
 +
 +      spin_unlock_irqrestore(&host->lock, flags);
 +
 +      return is_read ? data : 0;
 +}
 +
 +/*
 + * Read a given register from the device
 + */
 +int cbus_read_reg(struct cbus_host *host, int dev, int reg)
 +{
 +      return cbus_host ? cbus_transfer(host, dev, reg, -1) : -ENODEV;
 +}
 +
 +/*
 + * Write to a given register of the device
 + */
 +int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val)
 +{
 +      return cbus_host ? cbus_transfer(host, dev, reg, (int)val) : -ENODEV;
 +}
 +
 +int __init cbus_bus_init(void)
 +{
 +      const struct omap_cbus_config * cbus_config;
 +      struct cbus_host *chost;
 +      int ret;
 +
 +      chost = kmalloc(sizeof (*chost), GFP_KERNEL);
 +      if (chost == NULL)
 +              return -ENOMEM;
 +
 +      memset(chost, 0, sizeof (*chost));
 +
 +      spin_lock_init(&chost->lock);
 +
 +      cbus_config = omap_get_config(OMAP_TAG_CBUS, struct omap_cbus_config);
 +
 +      if (cbus_config == NULL) {
 +              printk(KERN_ERR "cbus: Unable to retrieve config data\n");
 +              return -ENODATA;
 +      }
 +
 +      chost->clk_gpio = cbus_config->clk_gpio;
 +      chost->dat_gpio = cbus_config->dat_gpio;
 +      chost->sel_gpio = cbus_config->sel_gpio;
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +      if (!OMAP_GPIO_IS_MPUIO(chost->clk_gpio) ||
 +          !OMAP_GPIO_IS_MPUIO(chost->dat_gpio) ||
 +          !OMAP_GPIO_IS_MPUIO(chost->sel_gpio)) {
 +              printk(KERN_ERR "cbus: Only MPUIO pins supported\n");
 +              ret = -ENODEV;
 +              goto exit1;
 +      }
 +#endif
 +
 +      if ((ret = omap_request_gpio(chost->clk_gpio)) < 0)
 +              goto exit1;
 +
 +      if ((ret = omap_request_gpio(chost->dat_gpio)) < 0)
 +              goto exit2;
 +
 +      if ((ret = omap_request_gpio(chost->sel_gpio)) < 0)
 +              goto exit3;
 +
 +      omap_set_gpio_dataout(chost->clk_gpio, 0);
 +      omap_set_gpio_dataout(chost->sel_gpio, 1);
 +
 +      omap_set_gpio_direction(chost->clk_gpio, 0);
 +      omap_set_gpio_direction(chost->dat_gpio, 1);
 +      omap_set_gpio_direction(chost->sel_gpio, 0);
 +
 +      omap_set_gpio_dataout(chost->clk_gpio, 1);
 +      omap_set_gpio_dataout(chost->clk_gpio, 0);
 +
 +      cbus_host = chost;
 +
 +      return 0;
 +exit3:
 +      omap_free_gpio(chost->dat_gpio);
 +exit2:
 +      omap_free_gpio(chost->clk_gpio);
 +exit1:
 +      kfree(chost);
 +      return ret;
 +}
 +
 +subsys_initcall(cbus_bus_init);
 +
 +EXPORT_SYMBOL(cbus_host);
 +EXPORT_SYMBOL(cbus_read_reg);
 +EXPORT_SYMBOL(cbus_write_reg);
 +
 +MODULE_DESCRIPTION("CBUS serial protocol");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");
index ceb93d03e2d682f12b0d686255c9f8588f7c3585,0000000000000000000000000000000000000000..d94110b8a0bd68ff921481bf6709b00b258bad4b
mode 100644,000000..100644
--- /dev/null
@@@ -1,466 -1,0 +1,466 @@@
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
 +/**
 + * drivers/cbus/retu.c
 + *
 + * Support functions for Retu ASIC
 + *
 + * Copyright (C) 2004, 2005 Nokia Corporation
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          David Weinehall <david.weinehall@nokia.com>, and
 + *          Mikko Ylinen <mikko.k.ylinen@nokia.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.
 + *
 + * 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/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/device.h>
 +#include <linux/miscdevice.h>
 +#include <linux/poll.h>
 +#include <linux/fs.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +
 +#include <asm/uaccess.h>
 +
++#include <mach/mux.h>
++#include <mach/gpio.h>
++#include <mach/board.h>
 +
 +#include "cbus.h"
 +#include "retu.h"
 +
 +#define RETU_ID                       0x01
 +#define PFX                   "retu: "
 +
 +static int retu_initialized;
 +static int retu_irq_pin;
 +static int retu_is_vilma;
 +
 +static struct tasklet_struct retu_tasklet;
 +spinlock_t retu_lock = SPIN_LOCK_UNLOCKED;
 +
 +static struct completion device_release;
 +
 +struct retu_irq_handler_desc {
 +      int (*func)(unsigned long);
 +      unsigned long arg;
 +      char name[8];
 +};
 +
 +static struct retu_irq_handler_desc retu_irq_handlers[MAX_RETU_IRQ_HANDLERS];
 +
 +/**
 + * retu_read_reg - Read a value from a register in Retu
 + * @reg: the register to read from
 + *
 + * This function returns the contents of the specified register
 + */
 +int retu_read_reg(int reg)
 +{
 +      BUG_ON(!retu_initialized);
 +      return cbus_read_reg(cbus_host, RETU_ID, reg);
 +}
 +
 +/**
 + * retu_write_reg - Write a value to a register in Retu
 + * @reg: the register to write to
 + * @reg: the value to write to the register
 + *
 + * This function writes a value to the specified register
 + */
 +void retu_write_reg(int reg, u16 val)
 +{
 +      BUG_ON(!retu_initialized);
 +      cbus_write_reg(cbus_host, RETU_ID, reg, val);
 +}
 +
 +void retu_set_clear_reg_bits(int reg, u16 set, u16 clear)
 +{
 +      unsigned long flags;
 +      u16 w;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +      w = retu_read_reg(reg);
 +      w &= ~clear;
 +      w |= set;
 +      retu_write_reg(reg, w);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +#define ADC_MAX_CHAN_NUMBER   13
 +
 +int retu_read_adc(int channel)
 +{
 +      unsigned long flags;
 +      int res;
 +
 +      if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER)
 +              return -EINVAL;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +
 +      if ((channel == 8) && retu_is_vilma) {
 +              int scr = retu_read_reg(RETU_REG_ADCSCR);
 +              int ch = (retu_read_reg(RETU_REG_ADCR) >> 10) & 0xf;
 +              if (((scr & 0xff) != 0) && (ch != 8))
 +                      retu_write_reg (RETU_REG_ADCSCR, (scr & ~0xff));
 +      }
 +
 +      /* Select the channel and read result */
 +      retu_write_reg(RETU_REG_ADCR, channel << 10);
 +      res = retu_read_reg(RETU_REG_ADCR) & 0x3ff;
 +
 +      if (retu_is_vilma)
 +              retu_write_reg(RETU_REG_ADCR, (1 << 13));
 +
 +      /* Unlock retu */
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +
 +      return res;
 +}
 +
 +
 +static u16 retu_disable_bogus_irqs(u16 mask)
 +{
 +       int i;
 +
 +       for (i = 0; i < MAX_RETU_IRQ_HANDLERS; i++) {
 +               if (mask & (1 << i))
 +                       continue;
 +               if (retu_irq_handlers[i].func != NULL)
 +                       continue;
 +               /* an IRQ was enabled but we don't have a handler for it */
 +               printk(KERN_INFO PFX "disabling bogus IRQ %d\n", i);
 +               mask |= (1 << i);
 +       }
 +       return mask;
 +}
 +
 +/*
 + * Disable given RETU interrupt
 + */
 +void retu_disable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +      mask = retu_read_reg(RETU_REG_IMR);
 +      mask |= 1 << id;
 +      mask = retu_disable_bogus_irqs(mask);
 +      retu_write_reg(RETU_REG_IMR, mask);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +/*
 + * Enable given RETU interrupt
 + */
 +void retu_enable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      if (id == 3) {
 +              printk("Enabling Retu IRQ %d\n", id);
 +              dump_stack();
 +      }
 +      spin_lock_irqsave(&retu_lock, flags);
 +      mask = retu_read_reg(RETU_REG_IMR);
 +      mask &= ~(1 << id);
 +      mask = retu_disable_bogus_irqs(mask);
 +      retu_write_reg(RETU_REG_IMR, mask);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +/*
 + * Acknowledge given RETU interrupt
 + */
 +void retu_ack_irq(int id)
 +{
 +      retu_write_reg(RETU_REG_IDR, 1 << id);
 +}
 +
 +/*
 + * RETU interrupt handler. Only schedules the tasklet.
 + */
 +static irqreturn_t retu_irq_handler(int irq, void *dev_id)
 +{
 +      tasklet_schedule(&retu_tasklet);
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Tasklet handler
 + */
 +static void retu_tasklet_handler(unsigned long data)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +      u16 id;
 +      u16 im;
 +      int i;
 +
 +      for (;;) {
 +              id = retu_read_reg(RETU_REG_IDR);
 +              im = ~retu_read_reg(RETU_REG_IMR);
 +              id &= im;
 +
 +              if (!id)
 +                      break;
 +
 +              for (i = 0; id != 0; i++, id >>= 1) {
 +                      if (!(id & 1))
 +                              continue;
 +                      hnd = &retu_irq_handlers[i];
 +                      if (hnd->func == NULL) {
 +                               /* Spurious retu interrupt - disable and ack it */
 +                              printk(KERN_INFO "Spurious Retu interrupt "
 +                                               "(id %d)\n", i);
 +                              retu_disable_irq(i);
 +                              retu_ack_irq(i);
 +                              continue;
 +                      }
 +                      hnd->func(hnd->arg);
 +                      /*
 +                       * Don't acknowledge the interrupt here
 +                       * It must be done explicitly
 +                       */
 +              }
 +      }
 +}
 +
 +/*
 + * Register the handler for a given RETU interrupt source.
 + */
 +int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +
 +      if (irq_handler == NULL || id >= MAX_RETU_IRQ_HANDLERS ||
 +          name == NULL) {
 +              printk(KERN_ERR PFX "Invalid arguments to %s\n",
 +                     __FUNCTION__);
 +              return -EINVAL;
 +      }
 +      hnd = &retu_irq_handlers[id];
 +      if (hnd->func != NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already reserved\n", id);
 +              return -EBUSY;
 +      }
 +      printk(KERN_INFO PFX "Registering interrupt %d for device %s\n",
 +             id, name);
 +      hnd->func = irq_handler;
 +      hnd->arg = arg;
 +      strlcpy(hnd->name, name, sizeof(hnd->name));
 +
 +      retu_ack_irq(id);
 +      retu_enable_irq(id);
 +
 +      return 0;
 +}
 +
 +/*
 + * Unregister the handler for a given RETU interrupt source.
 + */
 +void retu_free_irq(int id)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +
 +      if (id >= MAX_RETU_IRQ_HANDLERS) {
 +              printk(KERN_ERR PFX "Invalid argument to %s\n",
 +                     __FUNCTION__);
 +              return;
 +      }
 +      hnd = &retu_irq_handlers[id];
 +      if (hnd->func == NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already freed\n", id);
 +              return;
 +      }
 +
 +      retu_disable_irq(id);
 +      hnd->func = NULL;
 +}
 +
 +/**
 + * retu_power_off - Shut down power to system
 + *
 + * This function puts the system in power off state
 + */
 +static void retu_power_off(void)
 +{
 +      /* Ignore power button state */
 +      retu_write_reg(RETU_REG_CC1, retu_read_reg(RETU_REG_CC1) | 2);
 +      /* Expire watchdog immediately */
 +      retu_write_reg(RETU_REG_WATCHDOG, 0);
 +      /* Wait for poweroff*/
 +      for (;;);
 +}
 +
 +/**
 + * retu_probe - Probe for Retu ASIC
 + * @dev: the Retu device
 + *
 + * Probe for the Retu ASIC and allocate memory
 + * for its device-struct if found
 + */
 +static int __devinit retu_probe(struct device *dev)
 +{
 +      const struct omap_em_asic_bb5_config * em_asic_config;
 +      int rev, ret;
 +
 +      /* Prepare tasklet */
 +      tasklet_init(&retu_tasklet, retu_tasklet_handler, 0);
 +
 +      em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5,
 +                                       struct omap_em_asic_bb5_config);
 +      if (em_asic_config == NULL) {
 +              printk(KERN_ERR PFX "Unable to retrieve config data\n");
 +              return -ENODATA;
 +      }
 +
 +      retu_irq_pin = em_asic_config->retu_irq_gpio;
 +
 +      if ((ret = omap_request_gpio(retu_irq_pin)) < 0) {
 +              printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
 +              return ret;
 +      }
 +
 +      /* Set the pin as input */
 +      omap_set_gpio_direction(retu_irq_pin, 1);
 +
 +      /* Rising edge triggers the IRQ */
 +      set_irq_type(OMAP_GPIO_IRQ(retu_irq_pin), IRQ_TYPE_EDGE_RISING);
 +
 +      retu_initialized = 1;
 +
 +      rev = retu_read_reg(RETU_REG_ASICR) & 0xff;
 +      if (rev & (1 << 7))
 +              retu_is_vilma = 1;
 +
 +      printk(KERN_INFO "%s v%d.%d found\n", retu_is_vilma ? "Vilma" : "Retu",
 +             (rev >> 4) & 0x07, rev & 0x0f);
 +
 +      /* Mask all RETU interrupts */
 +      retu_write_reg(RETU_REG_IMR, 0xffff);
 +
 +      ret = request_irq(OMAP_GPIO_IRQ(retu_irq_pin), retu_irq_handler, 0,
 +                        "retu", 0);
 +      if (ret < 0) {
 +              printk(KERN_ERR PFX "Unable to register IRQ handler\n");
 +              omap_free_gpio(retu_irq_pin);
 +              return ret;
 +      }
 +      set_irq_wake(OMAP_GPIO_IRQ(retu_irq_pin), 1);
 +
 +      /* Register power off function */
 +      pm_power_off = retu_power_off;
 +
 +#ifdef CONFIG_CBUS_RETU_USER
 +      /* Initialize user-space interface */
 +      if (retu_user_init() < 0) {
 +              printk(KERN_ERR "Unable to initialize driver\n");
 +              free_irq(OMAP_GPIO_IRQ(retu_irq_pin), 0);
 +              omap_free_gpio(retu_irq_pin);
 +              return ret;
 +      }
 +#endif
 +
 +      return 0;
 +}
 +
 +static int retu_remove(struct device *dev)
 +{
 +#ifdef CONFIG_CBUS_RETU_USER
 +      retu_user_cleanup();
 +#endif
 +      /* Mask all RETU interrupts */
 +      retu_write_reg(RETU_REG_IMR, 0xffff);
 +      free_irq(OMAP_GPIO_IRQ(retu_irq_pin), 0);
 +      omap_free_gpio(retu_irq_pin);
 +      tasklet_kill(&retu_tasklet);
 +
 +      return 0;
 +}
 +
 +static void retu_device_release(struct device *dev)
 +{
 +      complete(&device_release);
 +}
 +
 +static struct device_driver retu_driver = {
 +      .name           = "retu",
 +      .bus            = &platform_bus_type,
 +      .probe          = retu_probe,
 +      .remove         = retu_remove,
 +};
 +
 +static struct platform_device retu_device = {
 +      .name           = "retu",
 +      .id             = -1,
 +      .dev = {
 +              .release = retu_device_release,
 +      }
 +};
 +
 +/**
 + * retu_init - initialise Retu driver
 + *
 + * Initialise the Retu driver and return 0 if everything worked ok
 + */
 +static int __init retu_init(void)
 +{
 +      int ret = 0;
 +
 +      printk(KERN_INFO "Retu/Vilma driver initialising\n");
 +
 +      init_completion(&device_release);
 +
 +      if ((ret = driver_register(&retu_driver)) < 0)
 +              return ret;
 +
 +      if ((ret = platform_device_register(&retu_device)) < 0) {
 +              driver_unregister(&retu_driver);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Cleanup
 + */
 +static void __exit retu_exit(void)
 +{
 +      platform_device_unregister(&retu_device);
 +      driver_unregister(&retu_driver);
 +      wait_for_completion(&device_release);
 +}
 +
 +EXPORT_SYMBOL(retu_request_irq);
 +EXPORT_SYMBOL(retu_free_irq);
 +EXPORT_SYMBOL(retu_enable_irq);
 +EXPORT_SYMBOL(retu_disable_irq);
 +EXPORT_SYMBOL(retu_ack_irq);
 +EXPORT_SYMBOL(retu_read_reg);
 +EXPORT_SYMBOL(retu_write_reg);
 +
 +subsys_initcall(retu_init);
 +module_exit(retu_exit);
 +
 +MODULE_DESCRIPTION("Retu ASIC control");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");
index 65ea14ffe6ef21f64075198b8cd0d66dd44315ad,0000000000000000000000000000000000000000..d8ad836d50153cb8c686ccdd81b66c03ff16e61a
mode 100644,000000..100644
--- /dev/null
@@@ -1,777 -1,0 +1,777 @@@
- #include <asm/arch/usb.h>
 +/**
 + * drivers/cbus/tahvo-usb.c
 + *
 + * Tahvo USB transeiver
 + *
 + * Copyright (C) 2005-2006 Nokia Corporation
 + *
 + * Parts copied from drivers/i2c/chips/isp1301_omap.c
 + * Copyright (C) 2004 Texas Instruments
 + * Copyright (C) 2004 David Brownell
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          Tony Lindgren <tony@atomide.com>, and
 + *          Timo Teräs <timo.teras@nokia.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.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/slab.h>
 +#include <linux/io.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +#include <linux/usb/ch9.h>
 +#include <linux/usb/gadget.h>
 +#include <linux/usb.h>
 +#include <linux/usb/otg.h>
 +#include <linux/i2c.h>
 +#include <linux/workqueue.h>
 +#include <linux/kobject.h>
 +#include <linux/clk.h>
 +#include <linux/mutex.h>
 +
 +#include <asm/irq.h>
++#include <mach/usb.h>
 +
 +#include "cbus.h"
 +#include "tahvo.h"
 +
 +#define DRIVER_NAME     "tahvo-usb"
 +
 +#define USBR_SLAVE_CONTROL    (1 << 8)
 +#define USBR_VPPVIO_SW                (1 << 7)
 +#define USBR_SPEED            (1 << 6)
 +#define USBR_REGOUT           (1 << 5)
 +#define USBR_MASTER_SW2               (1 << 4)
 +#define USBR_MASTER_SW1               (1 << 3)
 +#define USBR_SLAVE_SW         (1 << 2)
 +#define USBR_NSUSPEND         (1 << 1)
 +#define USBR_SEMODE           (1 << 0)
 +
 +/* bits in OTG_CTRL */
 +
 +/* Bits that are controlled by OMAP OTG and are read-only */
 +#define OTG_CTRL_OMAP_MASK    (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|\
 +                              OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
 +/* Bits that are controlled by transceiver */
 +#define OTG_CTRL_XCVR_MASK    (OTG_ASESSVLD|OTG_BSESSEND|\
 +                              OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
 +/* Bits that are controlled by system */
 +#define OTG_CTRL_SYS_MASK     (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|\
 +                              OTG_B_HNPEN|OTG_BUSDROP)
 +
 +#if defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OTG)
 +#error tahvo-otg.c does not work with OCHI yet!
 +#endif
 +
 +#define TAHVO_MODE_HOST               0
 +#define TAHVO_MODE_PERIPHERAL 1
 +
 +#ifdef CONFIG_USB_OTG
 +#define TAHVO_MODE(tu)                (tu)->tahvo_mode
 +#elif defined(CONFIG_USB_GADGET_OMAP)
 +#define TAHVO_MODE(tu)                TAHVO_MODE_PERIPHERAL
 +#else
 +#define TAHVO_MODE(tu)                TAHVO_MODE_HOST
 +#endif
 +
 +struct tahvo_usb {
 +      struct platform_device *pt_dev;
 +      struct otg_transceiver otg;
 +      int vbus_state;
 +      struct work_struct irq_work;
 +      struct mutex serialize;
 +#ifdef CONFIG_USB_OTG
 +      int tahvo_mode;
 +#endif
 +};
 +static struct platform_device tahvo_usb_device;
 +
 +/*
 + * ---------------------------------------------------------------------------
 + * OTG related functions
 + *
 + * These shoud be separated into omap-otg.c driver module, as they are used
 + * by various transceivers. These functions are needed in the UDC-only case
 + * as well. These functions are copied from GPL isp1301_omap.c
 + * ---------------------------------------------------------------------------
 + */
 +static struct platform_device *tahvo_otg_dev;
 +
 +static irqreturn_t omap_otg_irq(int irq, void *arg)
 +{
 +      struct platform_device *otg_dev = (struct platform_device *) arg;
 +      struct tahvo_usb *tu = (struct tahvo_usb *) otg_dev->dev.driver_data;
 +      u16 otg_irq;
 +
 +      otg_irq = omap_readw(OTG_IRQ_SRC);
 +      if (otg_irq & OPRT_CHG) {
 +              omap_writew(OPRT_CHG, OTG_IRQ_SRC);
 +      } else if (otg_irq & B_SRP_TMROUT) {
 +              omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
 +      } else if (otg_irq & B_HNP_FAIL) {
 +              omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
 +      } else if (otg_irq & A_SRP_DETECT) {
 +              omap_writew(A_SRP_DETECT, OTG_IRQ_SRC);
 +      } else if (otg_irq & A_REQ_TMROUT) {
 +              omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
 +      } else if (otg_irq & A_VBUS_ERR) {
 +              omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
 +      } else if (otg_irq & DRIVER_SWITCH) {
 +              if ((!(omap_readl(OTG_CTRL) & OTG_DRIVER_SEL)) &&
 +                 tu->otg.host && tu->otg.state == OTG_STATE_A_HOST) {
 +                      /* role is host */
 +                      usb_bus_start_enum(tu->otg.host,
 +                                         tu->otg.host->otg_port);
 +              }
 +              omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC);
 +      } else
 +              return IRQ_NONE;
 +
 +      return IRQ_HANDLED;
 +
 +}
 +
 +static int omap_otg_init(void)
 +{
 +      u32 l;
 +
 +#ifdef CONFIG_USB_OTG
 +      if (!tahvo_otg_dev) {
 +              printk("tahvo-usb: no tahvo_otg_dev\n");
 +              return -ENODEV;
 +      }
 +#endif
 +
 +      l = omap_readl(OTG_SYSCON_1);
 +      l &= ~OTG_IDLE_EN;
 +      omap_writel(l, OTG_SYSCON_1);
 +      udelay(100);
 +
 +      /* some of these values are board-specific... */
 +      l = omap_readl(OTG_SYSCON_2);
 +      l |= OTG_EN
 +              /* for B-device: */
 +              | SRP_GPDATA            /* 9msec Bdev D+ pulse */
 +              | SRP_GPDVBUS           /* discharge after VBUS pulse */
 +              // | (3 << 24)          /* 2msec VBUS pulse */
 +              /* for A-device: */
 +              | (0 << 20)             /* 200ms nominal A_WAIT_VRISE timer */
 +              | SRP_DPW               /* detect 167+ns SRP pulses */
 +              | SRP_DATA | SRP_VBUS;  /* accept both kinds of SRP pulse */
 +      omap_writel(l, OTG_SYSCON_2);
 +
 +      omap_writew(DRIVER_SWITCH | OPRT_CHG
 +                      | B_SRP_TMROUT | B_HNP_FAIL
 +                                | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT,
 +                                      OTG_IRQ_EN);
 +      l = omap_readl(OTG_SYSCON_2);
 +      l |= OTG_EN;
 +      omap_writel(l, OTG_SYSCON_2);
 +
 +      return 0;
 +}
 +
 +static int omap_otg_probe(struct device *dev)
 +{
 +      int ret;
 +
 +      tahvo_otg_dev = to_platform_device(dev);
 +      ret = omap_otg_init();
 +      if (ret != 0) {
 +              printk(KERN_ERR "tahvo-usb: omap_otg_init failed\n");
 +              return ret;
 +      }
 +
 +      return request_irq(tahvo_otg_dev->resource[1].start,
 +                         omap_otg_irq, IRQF_DISABLED, DRIVER_NAME,
 +                         &tahvo_usb_device);
 +}
 +
 +static int omap_otg_remove(struct device *dev)
 +{
 +      free_irq(tahvo_otg_dev->resource[1].start, &tahvo_usb_device);
 +      tahvo_otg_dev = NULL;
 +
 +      return 0;
 +}
 +
 +struct device_driver omap_otg_driver = {
 +      .name           = "omap_otg",
 +      .bus            = &platform_bus_type,
 +      .probe          = omap_otg_probe,
 +      .remove         = omap_otg_remove,
 +};
 +
 +/*
 + * ---------------------------------------------------------------------------
 + * Tahvo related functions
 + * These are Nokia proprietary code, except for the OTG register settings,
 + * which are copied from isp1301.c
 + * ---------------------------------------------------------------------------
 + */
 +static ssize_t vbus_state_show(struct device *device,
 +                             struct device_attribute *attr, char *buf)
 +{
 +      struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data;
 +      return sprintf(buf, "%d\n", tu->vbus_state);
 +}
 +static DEVICE_ATTR(vbus_state, 0444, vbus_state_show, NULL);
 +
 +int vbus_active = 0;
 +
 +#if 0
 +
 +static int host_suspend(struct tahvo_usb *tu)
 +{
 +      struct device   *dev;
 +
 +      if (!tu->otg.host)
 +              return -ENODEV;
 +
 +      /* Currently ASSUMES only the OTG port matters;
 +       * other ports could be active...
 +       */
 +      dev = tu->otg.host->controller;
 +      return dev->driver->suspend(dev, PMSG_SUSPEND);
 +}
 +
 +static int host_resume(struct tahvo_usb *tu)
 +{
 +      struct device   *dev;
 +
 +      if (!tu->otg.host)
 +              return -ENODEV;
 +
 +      dev = tu->otg.host->controller;
 +      return dev->driver->resume(dev);
 +}
 +
 +#else
 +
 +static int host_suspend(struct tahvo_usb *tu)
 +{
 +      return 0;
 +}
 +
 +static int host_resume(struct tahvo_usb *tu)
 +{
 +      return 0;
 +}
 +
 +#endif
 +
 +static void check_vbus_state(struct tahvo_usb *tu)
 +{
 +      int reg, prev_state;
 +
 +      reg = tahvo_read_reg(TAHVO_REG_IDSR);
 +      if (reg & 0x01) {
 +              u32 l;
 +
 +              vbus_active = 1;
 +              switch (tu->otg.state) {
 +              case OTG_STATE_B_IDLE:
 +                      /* Enable the gadget driver */
 +                      if (tu->otg.gadget)
 +                              usb_gadget_vbus_connect(tu->otg.gadget);
 +                      /* Set B-session valid and not B-sessio ended to indicate
 +                       * Vbus to be ok. */
 +                      l = omap_readl(OTG_CTRL);
 +                      l &= ~OTG_BSESSEND;
 +                      l |= OTG_BSESSVLD;
 +                      omap_writel(l, OTG_CTRL);
 +
 +                      tu->otg.state = OTG_STATE_B_PERIPHERAL;
 +                      break;
 +              case OTG_STATE_A_IDLE:
 +                      /* Session is now valid assuming the USB hub is driving Vbus */
 +                      tu->otg.state = OTG_STATE_A_HOST;
 +                      host_resume(tu);
 +                      break;
 +              default:
 +                      break;
 +              }
 +              printk("USB cable connected\n");
 +      } else {
 +              switch (tu->otg.state) {
 +              case OTG_STATE_B_PERIPHERAL:
 +                      if (tu->otg.gadget)
 +                              usb_gadget_vbus_disconnect(tu->otg.gadget);
 +                      tu->otg.state = OTG_STATE_B_IDLE;
 +                      break;
 +              case OTG_STATE_A_HOST:
 +                      tu->otg.state = OTG_STATE_A_IDLE;
 +                      break;
 +              default:
 +                      break;
 +              }
 +              printk("USB cable disconnected\n");
 +              vbus_active = 0;
 +      }
 +
 +      prev_state = tu->vbus_state;
 +      tu->vbus_state = reg & 0x01;
 +      if (prev_state != tu->vbus_state)
 +              sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
 +}
 +
 +static void tahvo_usb_become_host(struct tahvo_usb *tu)
 +{
 +      u32 l;
 +
 +      /* Clear system and transceiver controlled bits
 +       * also mark the A-session is always valid */
 +      omap_otg_init();
 +
 +      l = omap_readl(OTG_CTRL);
 +      l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK);
 +      l |= OTG_ASESSVLD;
 +      omap_writel(l, OTG_CTRL);
 +
 +      /* Power up the transceiver in USB host mode */
 +      tahvo_write_reg(TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
 +                      USBR_MASTER_SW2 | USBR_MASTER_SW1);
 +      tu->otg.state = OTG_STATE_A_IDLE;
 +
 +      check_vbus_state(tu);
 +}
 +
 +static void tahvo_usb_stop_host(struct tahvo_usb *tu)
 +{
 +      host_suspend(tu);
 +      tu->otg.state = OTG_STATE_A_IDLE;
 +}
 +
 +static void tahvo_usb_become_peripheral(struct tahvo_usb *tu)
 +{
 +      u32 l;
 +
 +      /* Clear system and transceiver controlled bits
 +       * and enable ID to mark peripheral mode and
 +       * BSESSEND to mark no Vbus */
 +      omap_otg_init();
 +      l = omap_readl(OTG_CTRL);
 +      l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD);
 +      l |= OTG_ID | OTG_BSESSEND;
 +      omap_writel(l, OTG_CTRL);
 +
 +      /* Power up transceiver and set it in USB perhiperal mode */
 +      tahvo_write_reg(TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT | USBR_NSUSPEND | USBR_SLAVE_SW);
 +      tu->otg.state = OTG_STATE_B_IDLE;
 +
 +      check_vbus_state(tu);
 +}
 +
 +static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu)
 +{
 +      u32 l;
 +
 +      l = omap_readl(OTG_CTRL);
 +      l &= ~OTG_BSESSVLD;
 +      l |= OTG_BSESSEND;
 +      omap_writel(l, OTG_CTRL);
 +
 +      if (tu->otg.gadget)
 +              usb_gadget_vbus_disconnect(tu->otg.gadget);
 +      tu->otg.state = OTG_STATE_B_IDLE;
 +
 +}
 +
 +static void tahvo_usb_power_off(struct tahvo_usb *tu)
 +{
 +      u32 l;
 +      int id;
 +
 +      /* Disable gadget controller if any */
 +      if (tu->otg.gadget)
 +              usb_gadget_vbus_disconnect(tu->otg.gadget);
 +
 +      host_suspend(tu);
 +
 +      /* Disable OTG and interrupts */
 +      if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL)
 +              id = OTG_ID;
 +      else
 +              id = 0;
 +      l = omap_readl(OTG_CTRL);
 +      l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD);
 +      l |= id | OTG_BSESSEND;
 +      omap_writel(l, OTG_CTRL);
 +      omap_writew(0, OTG_IRQ_EN);
 +
 +      l = omap_readl(OTG_SYSCON_2);
 +      l &= ~OTG_EN;
 +      omap_writel(l, OTG_SYSCON_2);
 +
 +      l = omap_readl(OTG_SYSCON_1);
 +      l |= OTG_IDLE_EN;
 +      omap_writel(l, OTG_SYSCON_1);
 +
 +      /* Power off transceiver */
 +      tahvo_write_reg(TAHVO_REG_USBR, 0);
 +      tu->otg.state = OTG_STATE_UNDEFINED;
 +}
 +
 +
 +static int tahvo_usb_set_power(struct otg_transceiver *dev, unsigned mA)
 +{
 +      struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg);
 +
 +      dev_dbg(&tu->pt_dev->dev, "set_power %d mA\n", mA);
 +
 +      if (dev->state == OTG_STATE_B_PERIPHERAL) {
 +              /* REVISIT: Can Tahvo charge battery from VBUS? */
 +      }
 +      return 0;
 +}
 +
 +static int tahvo_usb_set_suspend(struct otg_transceiver *dev, int suspend)
 +{
 +      struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg);
 +      u16 w;
 +
 +      dev_dbg(&tu->pt_dev->dev, "set_suspend\n");
 +
 +      w = tahvo_read_reg(TAHVO_REG_USBR);
 +      if (suspend)
 +              w &= ~USBR_NSUSPEND;
 +      else
 +              w |= USBR_NSUSPEND;
 +      tahvo_write_reg(TAHVO_REG_USBR, w);
 +
 +      return 0;
 +}
 +
 +static int tahvo_usb_start_srp(struct otg_transceiver *dev)
 +{
 +      struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg);
 +      u32 otg_ctrl;
 +
 +      dev_dbg(&tu->pt_dev->dev, "start_srp\n");
 +
 +      if (!dev || tu->otg.state != OTG_STATE_B_IDLE)
 +              return -ENODEV;
 +
 +      otg_ctrl = omap_readl(OTG_CTRL);
 +      if (!(otg_ctrl & OTG_BSESSEND))
 +              return -EINVAL;
 +
 +      otg_ctrl |= OTG_B_BUSREQ;
 +      otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_SYS_MASK;
 +      omap_writel(otg_ctrl, OTG_CTRL);
 +      tu->otg.state = OTG_STATE_B_SRP_INIT;
 +
 +      return 0;
 +}
 +
 +static int tahvo_usb_start_hnp(struct otg_transceiver *otg)
 +{
 +      struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg);
 +
 +      dev_dbg(&tu->pt_dev->dev, "start_hnp\n");
 +#ifdef CONFIG_USB_OTG
 +      /* REVISIT: Add this for OTG */
 +#endif
 +      return -EINVAL;
 +}
 +
 +static int tahvo_usb_set_host(struct otg_transceiver *otg, struct usb_bus *host)
 +{
 +      struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg);
 +      u32 l;
 +
 +      dev_dbg(&tu->pt_dev->dev, "set_host %p\n", host);
 +
 +      if (otg == NULL)
 +              return -ENODEV;
 +
 +#if defined(CONFIG_USB_OTG) || !defined(CONFIG_USB_GADGET_OMAP)
 +
 +      mutex_lock(&tu->serialize);
 +
 +      if (host == NULL) {
 +              if (TAHVO_MODE(tu) == TAHVO_MODE_HOST)
 +                      tahvo_usb_power_off(tu);
 +              tu->otg.host = NULL;
 +              mutex_unlock(&tu->serialize);
 +              return 0;
 +      }
 +
 +      l = omap_readl(OTG_SYSCON_1);
 +      l &= ~(OTG_IDLE_EN | HST_IDLE_EN | DEV_IDLE_EN);
 +      omap_writel(l, OTG_SYSCON_1);
 +
 +      if (TAHVO_MODE(tu) == TAHVO_MODE_HOST) {
 +              tu->otg.host = NULL;
 +              tahvo_usb_become_host(tu);
 +      } else
 +              host_suspend(tu);
 +
 +      tu->otg.host = host;
 +
 +      mutex_unlock(&tu->serialize);
 +#else
 +      /* No host mode configured, so do not allow host controlled to be set */
 +      return -EINVAL;
 +#endif
 +
 +      return 0;
 +}
 +
 +static int tahvo_usb_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
 +{
 +      struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg);
 +
 +      dev_dbg(&tu->pt_dev->dev, "set_peripheral %p\n", gadget);
 +
 +      if (!otg)
 +              return -ENODEV;
 +
 +#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_GADGET_OMAP)
 +
 +      mutex_lock(&tu->serialize);
 +
 +      if (!gadget) {
 +              if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL)
 +                      tahvo_usb_power_off(tu);
 +              tu->otg.gadget = NULL;
 +              mutex_unlock(&tu->serialize);
 +              return 0;
 +      }
 +
 +      tu->otg.gadget = gadget;
 +      if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL)
 +              tahvo_usb_become_peripheral(tu);
 +
 +      mutex_unlock(&tu->serialize);
 +#else
 +      /* No gadget mode configured, so do not allow host controlled to be set */
 +      return -EINVAL;
 +#endif
 +
 +      return 0;
 +}
 +
 +static void tahvo_usb_irq_work(struct work_struct *work)
 +{
 +      struct tahvo_usb *tu = container_of(work, struct tahvo_usb, irq_work);
 +
 +      mutex_lock(&tu->serialize);
 +      check_vbus_state(tu);
 +      mutex_unlock(&tu->serialize);
 +}
 +
 +static void tahvo_usb_vbus_interrupt(unsigned long arg)
 +{
 +      struct tahvo_usb *tu = (struct tahvo_usb *) arg;
 +
 +      tahvo_ack_irq(TAHVO_INT_VBUSON);
 +      /* Seems we need this to acknowledge the interrupt */
 +      tahvo_read_reg(TAHVO_REG_IDSR);
 +      schedule_work(&tu->irq_work);
 +}
 +
 +#ifdef CONFIG_USB_OTG
 +static ssize_t otg_mode_show(struct device *device,
 +                           struct device_attribute *attr, char *buf)
 +{
 +      struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data;
 +      switch (tu->tahvo_mode) {
 +      case TAHVO_MODE_HOST:
 +              return sprintf(buf, "host\n");
 +      case TAHVO_MODE_PERIPHERAL:
 +              return sprintf(buf, "peripheral\n");
 +      }
 +      return sprintf(buf, "unknown\n");
 +}
 +
 +static ssize_t otg_mode_store(struct device *device,
 +                            struct device_attribute *attr,
 +                            const char *buf, size_t count)
 +{
 +      struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data;
 +      int r;
 +
 +      r = strlen(buf);
 +      mutex_lock(&tu->serialize);
 +      if (strncmp(buf, "host", 4) == 0) {
 +              if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
 +                      tahvo_usb_stop_peripheral(tu);
 +              tu->tahvo_mode = TAHVO_MODE_HOST;
 +              if (tu->otg.host) {
 +                      printk(KERN_INFO "Selected HOST mode: host controller present.\n");
 +                      tahvo_usb_become_host(tu);
 +              } else {
 +                      printk(KERN_INFO "Selected HOST mode: no host controller, powering off.\n");
 +                      tahvo_usb_power_off(tu);
 +              }
 +      } else if (strncmp(buf, "peripheral", 10) == 0) {
 +              if (tu->tahvo_mode == TAHVO_MODE_HOST)
 +                      tahvo_usb_stop_host(tu);
 +              tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
 +              if (tu->otg.gadget) {
 +                      printk(KERN_INFO "Selected PERIPHERAL mode: gadget driver present.\n");
 +                      tahvo_usb_become_peripheral(tu);
 +              } else {
 +                      printk(KERN_INFO "Selected PERIPHERAL mode: no gadget driver, powering off.\n");
 +                      tahvo_usb_power_off(tu);
 +              }
 +      } else
 +              r = -EINVAL;
 +
 +      mutex_unlock(&tu->serialize);
 +      return r;
 +}
 +
 +static DEVICE_ATTR(otg_mode, 0644, otg_mode_show, otg_mode_store);
 +#endif
 +
 +static int tahvo_usb_probe(struct device *dev)
 +{
 +      struct tahvo_usb *tu;
 +      int ret;
 +
 +      dev_dbg(dev, "probe\n");
 +
 +      /* Create driver data */
 +      tu = kmalloc(sizeof(*tu), GFP_KERNEL);
 +      if (!tu)
 +              return -ENOMEM;
 +      memset(tu, 0, sizeof(*tu));
 +      tu->pt_dev = container_of(dev, struct platform_device, dev);
 +#ifdef CONFIG_USB_OTG
 +      /* Default mode */
 +#ifdef CONFIG_CBUS_TAHVO_USB_HOST_BY_DEFAULT
 +      tu->tahvo_mode = TAHVO_MODE_HOST;
 +#else
 +      tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
 +#endif
 +#endif
 +
 +      INIT_WORK(&tu->irq_work, tahvo_usb_irq_work);
 +      mutex_init(&tu->serialize);
 +
 +      /* Set initial state, so that we generate kevents only on
 +       * state changes */
 +      tu->vbus_state = tahvo_read_reg(TAHVO_REG_IDSR) & 0x01;
 +
 +      /* We cannot enable interrupt until omap_udc is initialized */
 +      ret = tahvo_request_irq(TAHVO_INT_VBUSON, tahvo_usb_vbus_interrupt,
 +                              (unsigned long) tu, "vbus_interrupt");
 +      if (ret != 0) {
 +              kfree(tu);
 +              printk(KERN_ERR "Could not register Tahvo interrupt for VBUS\n");
 +              return ret;
 +      }
 +
 +      /* Attributes */
 +      ret = device_create_file(dev, &dev_attr_vbus_state);
 +#ifdef CONFIG_USB_OTG
 +      ret |= device_create_file(dev, &dev_attr_otg_mode);
 +#endif
 +      if (ret)
 +              printk(KERN_ERR "attribute creation failed: %d\n", ret);
 +
 +      /* Create OTG interface */
 +      tahvo_usb_power_off(tu);
 +      tu->otg.state = OTG_STATE_UNDEFINED;
 +      tu->otg.label = DRIVER_NAME;
 +      tu->otg.set_host = tahvo_usb_set_host;
 +      tu->otg.set_peripheral = tahvo_usb_set_peripheral;
 +      tu->otg.set_power = tahvo_usb_set_power;
 +      tu->otg.set_suspend = tahvo_usb_set_suspend;
 +      tu->otg.start_srp = tahvo_usb_start_srp;
 +      tu->otg.start_hnp = tahvo_usb_start_hnp;
 +
 +      ret = otg_set_transceiver(&tu->otg);
 +      if (ret < 0) {
 +              printk(KERN_ERR "Cannot register USB transceiver\n");
 +              kfree(tu);
 +              tahvo_free_irq(TAHVO_INT_VBUSON);
 +              return ret;
 +      }
 +
 +      dev->driver_data = tu;
 +
 +      /* Act upon current vbus state once at startup. A vbus state irq may or
 +       * may not be generated in addition to this. */
 +      schedule_work(&tu->irq_work);
 +      return 0;
 +}
 +
 +static int tahvo_usb_remove(struct device *dev)
 +{
 +      dev_dbg(dev, "remove\n");
 +
 +      tahvo_free_irq(TAHVO_INT_VBUSON);
 +      flush_scheduled_work();
 +      otg_set_transceiver(0);
 +      device_remove_file(dev, &dev_attr_vbus_state);
 +#ifdef CONFIG_USB_OTG
 +      device_remove_file(dev, &dev_attr_otg_mode);
 +#endif
 +      return 0;
 +}
 +
 +static struct device_driver tahvo_usb_driver = {
 +      .name           = "tahvo-usb",
 +      .bus            = &platform_bus_type,
 +      .probe          = tahvo_usb_probe,
 +      .remove         = tahvo_usb_remove,
 +};
 +
 +static struct platform_device tahvo_usb_device = {
 +      .name           = "tahvo-usb",
 +      .id             = -1,
 +};
 +
 +static int __init tahvo_usb_init(void)
 +{
 +      int ret = 0;
 +
 +      printk(KERN_INFO "Tahvo USB transceiver driver initializing\n");
 +      ret = driver_register(&tahvo_usb_driver);
 +      if (ret)
 +              return ret;
 +      ret = platform_device_register(&tahvo_usb_device);
 +      if (ret < 0) {
 +              driver_unregister(&tahvo_usb_driver);
 +              return ret;
 +      }
 +      ret = driver_register(&omap_otg_driver);
 +      if (ret) {
 +              platform_device_unregister(&tahvo_usb_device);
 +              driver_unregister(&tahvo_usb_driver);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +subsys_initcall(tahvo_usb_init);
 +
 +static void __exit tahvo_usb_exit(void)
 +{
 +      driver_unregister(&omap_otg_driver);
 +      platform_device_unregister(&tahvo_usb_device);
 +      driver_unregister(&tahvo_usb_driver);
 +}
 +module_exit(tahvo_usb_exit);
 +
 +MODULE_DESCRIPTION("Tahvo USB OTG Transceiver Driver");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, Tony Lindgren, and Timo Teräs");
index bc7a4b6c69ad253e463ed8a658efc0cb702a88e0,0000000000000000000000000000000000000000..5876b684662eda7bc5f53659fc12502e0a4ab305
mode 100644,000000..100644
--- /dev/null
@@@ -1,441 -1,0 +1,441 @@@
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/board.h>
 +/**
 + * drivers/cbus/tahvo.c
 + *
 + * Support functions for Tahvo ASIC
 + *
 + * Copyright (C) 2004, 2005 Nokia Corporation
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          David Weinehall <david.weinehall@nokia.com>, and
 + *          Mikko Ylinen <mikko.k.ylinen@nokia.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.
 + *
 + * 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/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/device.h>
 +#include <linux/miscdevice.h>
 +#include <linux/poll.h>
 +#include <linux/fs.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +
 +#include <asm/uaccess.h>
 +
++#include <mach/mux.h>
++#include <mach/gpio.h>
++#include <mach/board.h>
 +
 +#include "cbus.h"
 +#include "tahvo.h"
 +
 +#define TAHVO_ID              0x02
 +#define PFX                   "tahvo: "
 +
 +static int tahvo_initialized;
 +static int tahvo_irq_pin;
 +static int tahvo_is_betty;
 +
 +static struct tasklet_struct tahvo_tasklet;
 +spinlock_t tahvo_lock = SPIN_LOCK_UNLOCKED;
 +
 +static struct completion device_release;
 +
 +struct tahvo_irq_handler_desc {
 +      int (*func)(unsigned long);
 +      unsigned long arg;
 +      char name[8];
 +};
 +
 +static struct tahvo_irq_handler_desc tahvo_irq_handlers[MAX_TAHVO_IRQ_HANDLERS];
 +
 +/**
 + * tahvo_read_reg - Read a value from a register in Tahvo
 + * @reg: the register to read from
 + *
 + * This function returns the contents of the specified register
 + */
 +int tahvo_read_reg(int reg)
 +{
 +      BUG_ON(!tahvo_initialized);
 +      return cbus_read_reg(cbus_host, TAHVO_ID, reg);
 +}
 +
 +/**
 + * tahvo_write_reg - Write a value to a register in Tahvo
 + * @reg: the register to write to
 + * @reg: the value to write to the register
 + *
 + * This function writes a value to the specified register
 + */
 +void tahvo_write_reg(int reg, u16 val)
 +{
 +      BUG_ON(!tahvo_initialized);
 +      cbus_write_reg(cbus_host, TAHVO_ID, reg, val);
 +}
 +
 +/**
 + * tahvo_set_clear_reg_bits - set and clear register bits atomically
 + * @reg: the register to write to
 + * @bits: the bits to set
 + *
 + * This function sets and clears the specified Tahvo register bits atomically
 + */
 +void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear)
 +{
 +      unsigned long flags;
 +      u16 w;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      w = tahvo_read_reg(reg);
 +      w &= ~clear;
 +      w |= set;
 +      tahvo_write_reg(reg, w);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Disable given TAHVO interrupt
 + */
 +void tahvo_disable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      mask = tahvo_read_reg(TAHVO_REG_IMR);
 +      mask |= 1 << id;
 +      tahvo_write_reg(TAHVO_REG_IMR, mask);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Enable given TAHVO interrupt
 + */
 +void tahvo_enable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      mask = tahvo_read_reg(TAHVO_REG_IMR);
 +      mask &= ~(1 << id);
 +      tahvo_write_reg(TAHVO_REG_IMR, mask);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Acknowledge given TAHVO interrupt
 + */
 +void tahvo_ack_irq(int id)
 +{
 +      tahvo_write_reg(TAHVO_REG_IDR, 1 << id);
 +}
 +
 +static int tahvo_7bit_backlight;
 +
 +int tahvo_get_backlight_level(void)
 +{
 +      int mask;
 +
 +      if (tahvo_7bit_backlight)
 +              mask = 0x7f;
 +      else
 +              mask = 0x0f;
 +      return tahvo_read_reg(TAHVO_REG_LEDPWMR) & mask;
 +}
 +
 +int tahvo_get_max_backlight_level(void)
 +{
 +      if (tahvo_7bit_backlight)
 +              return 0x7f;
 +      else
 +              return 0x0f;
 +}
 +
 +void tahvo_set_backlight_level(int level)
 +{
 +      int max_level;
 +
 +      max_level = tahvo_get_max_backlight_level();
 +      if (level > max_level)
 +              level = max_level;
 +      tahvo_write_reg(TAHVO_REG_LEDPWMR, level);
 +}
 +
 +/*
 + * TAHVO interrupt handler. Only schedules the tasklet.
 + */
 +static irqreturn_t tahvo_irq_handler(int irq, void *dev_id)
 +{
 +      tasklet_schedule(&tahvo_tasklet);
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Tasklet handler
 + */
 +static void tahvo_tasklet_handler(unsigned long data)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +      u16 id;
 +      u16 im;
 +      int i;
 +
 +      for (;;) {
 +              id = tahvo_read_reg(TAHVO_REG_IDR);
 +              im = ~tahvo_read_reg(TAHVO_REG_IMR);
 +              id &= im;
 +
 +              if (!id)
 +                      break;
 +
 +              for (i = 0; id != 0; i++, id >>= 1) {
 +                      if (!(id & 1))
 +                              continue;
 +                      hnd = &tahvo_irq_handlers[i];
 +                      if (hnd->func == NULL) {
 +                              /* Spurious tahvo interrupt - just ack it */
 +                              printk(KERN_INFO "Spurious Tahvo interrupt "
 +                                               "(id %d)\n", i);
 +                              tahvo_disable_irq(i);
 +                              tahvo_ack_irq(i);
 +                              continue;
 +                      }
 +                      hnd->func(hnd->arg);
 +                      /*
 +                       * Don't acknowledge the interrupt here
 +                       * It must be done explicitly
 +                       */
 +              }
 +      }
 +}
 +
 +/*
 + * Register the handler for a given TAHVO interrupt source.
 + */
 +int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +
 +      if (irq_handler == NULL || id >= MAX_TAHVO_IRQ_HANDLERS ||
 +          name == NULL) {
 +              printk(KERN_ERR PFX "Invalid arguments to %s\n",
 +                     __FUNCTION__);
 +              return -EINVAL;
 +      }
 +      hnd = &tahvo_irq_handlers[id];
 +      if (hnd->func != NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already reserved\n", id);
 +              return -EBUSY;
 +      }
 +      printk(KERN_INFO PFX "Registering interrupt %d for device %s\n",
 +             id, name);
 +      hnd->func = irq_handler;
 +      hnd->arg = arg;
 +      strlcpy(hnd->name, name, sizeof(hnd->name));
 +
 +      tahvo_ack_irq(id);
 +      tahvo_enable_irq(id);
 +
 +      return 0;
 +}
 +
 +/*
 + * Unregister the handler for a given TAHVO interrupt source.
 + */
 +void tahvo_free_irq(int id)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +
 +      if (id >= MAX_TAHVO_IRQ_HANDLERS) {
 +              printk(KERN_ERR PFX "Invalid argument to %s\n",
 +                     __FUNCTION__);
 +              return;
 +      }
 +      hnd = &tahvo_irq_handlers[id];
 +      if (hnd->func == NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already freed\n", id);
 +              return;
 +      }
 +
 +      tahvo_disable_irq(id);
 +      hnd->func = NULL;
 +}
 +
 +/**
 + * tahvo_probe - Probe for Tahvo ASIC
 + * @dev: the Tahvo device
 + *
 + * Probe for the Tahvo ASIC and allocate memory
 + * for its device-struct if found
 + */
 +static int __devinit tahvo_probe(struct device *dev)
 +{
 +      const struct omap_em_asic_bb5_config * em_asic_config;
 +      int rev, id, ret;
 +
 +      /* Prepare tasklet */
 +      tasklet_init(&tahvo_tasklet, tahvo_tasklet_handler, 0);
 +
 +      em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5,
 +                                       struct omap_em_asic_bb5_config);
 +      if (em_asic_config == NULL) {
 +              printk(KERN_ERR PFX "Unable to retrieve config data\n");
 +              return -ENODATA;
 +      }
 +
 +      tahvo_initialized = 1;
 +
 +      rev = tahvo_read_reg(TAHVO_REG_ASICR);
 +
 +      id = (rev >> 8) & 0xff;
 +      if (id == 0x03) {
 +              if ((rev & 0xff) >= 0x50)
 +                      tahvo_7bit_backlight = 1;
 +      } else if (id == 0x0b) {
 +              tahvo_is_betty = 1;
 +              tahvo_7bit_backlight = 1;
 +      } else {
 +              printk(KERN_ERR "Tahvo/Betty chip not found");
 +              return -ENODEV;
 +      }
 +
 +      printk(KERN_INFO "%s v%d.%d found\n", tahvo_is_betty ? "Betty" : "Tahvo",
 +             (rev >> 4) & 0x0f, rev & 0x0f);
 +
 +      tahvo_irq_pin = em_asic_config->tahvo_irq_gpio;
 +
 +      if ((ret = omap_request_gpio(tahvo_irq_pin)) < 0) {
 +              printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
 +              return ret;
 +      }
 +
 +      /* Set the pin as input */
 +      omap_set_gpio_direction(tahvo_irq_pin, 1);
 +
 +      /* Rising edge triggers the IRQ */
 +      set_irq_type(OMAP_GPIO_IRQ(tahvo_irq_pin), IRQ_TYPE_EDGE_RISING);
 +
 +      /* Mask all TAHVO interrupts */
 +      tahvo_write_reg(TAHVO_REG_IMR, 0xffff);
 +
 +      ret = request_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), tahvo_irq_handler, 0,
 +                        "tahvo", 0);
 +      if (ret < 0) {
 +              printk(KERN_ERR PFX "Unable to register IRQ handler\n");
 +              omap_free_gpio(tahvo_irq_pin);
 +              return ret;
 +      }
 +#ifdef CONFIG_CBUS_TAHVO_USER
 +      /* Initialize user-space interface */
 +      if (tahvo_user_init() < 0) {
 +              printk(KERN_ERR "Unable to initialize driver\n");
 +              free_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), 0);
 +              omap_free_gpio(tahvo_irq_pin);
 +              return ret;
 +      }
 +#endif
 +      return 0;
 +}
 +
 +static int tahvo_remove(struct device *dev)
 +{
 +#ifdef CONFIG_CBUS_TAHVO_USER
 +      tahvo_user_cleanup();
 +#endif
 +      /* Mask all TAHVO interrupts */
 +      tahvo_write_reg(TAHVO_REG_IMR, 0xffff);
 +      free_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), 0);
 +      omap_free_gpio(tahvo_irq_pin);
 +      tasklet_kill(&tahvo_tasklet);
 +
 +      return 0;
 +}
 +
 +static void tahvo_device_release(struct device *dev)
 +{
 +      complete(&device_release);
 +}
 +
 +static struct device_driver tahvo_driver = {
 +      .name           = "tahvo",
 +      .bus            = &platform_bus_type,
 +      .probe          = tahvo_probe,
 +      .remove         = tahvo_remove,
 +};
 +
 +static struct platform_device tahvo_device = {
 +      .name           = "tahvo",
 +      .id             = -1,
 +      .dev = {
 +              .release = tahvo_device_release,
 +      }
 +};
 +
 +/**
 + * tahvo_init - initialise Tahvo driver
 + *
 + * Initialise the Tahvo driver and return 0 if everything worked ok
 + */
 +static int __init tahvo_init(void)
 +{
 +      int ret = 0;
 +
 +      printk(KERN_INFO "Tahvo/Betty driver initialising\n");
 +
 +      init_completion(&device_release);
 +
 +      if ((ret = driver_register(&tahvo_driver)) < 0)
 +              return ret;
 +
 +      if ((ret = platform_device_register(&tahvo_device)) < 0) {
 +              driver_unregister(&tahvo_driver);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Cleanup
 + */
 +static void __exit tahvo_exit(void)
 +{
 +      platform_device_unregister(&tahvo_device);
 +      driver_unregister(&tahvo_driver);
 +      wait_for_completion(&device_release);
 +}
 +
 +EXPORT_SYMBOL(tahvo_request_irq);
 +EXPORT_SYMBOL(tahvo_free_irq);
 +EXPORT_SYMBOL(tahvo_enable_irq);
 +EXPORT_SYMBOL(tahvo_disable_irq);
 +EXPORT_SYMBOL(tahvo_ack_irq);
 +EXPORT_SYMBOL(tahvo_read_reg);
 +EXPORT_SYMBOL(tahvo_write_reg);
 +EXPORT_SYMBOL(tahvo_get_backlight_level);
 +EXPORT_SYMBOL(tahvo_get_max_backlight_level);
 +EXPORT_SYMBOL(tahvo_set_backlight_level);
 +
 +subsys_initcall(tahvo_init);
 +module_exit(tahvo_exit);
 +
 +MODULE_DESCRIPTION("Tahvo ASIC control");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");
index 2a3dc244813dec0dce61b3d5e119afc81c8a8d70,0000000000000000000000000000000000000000..84e7ceaa0376f7d4082c924d062b7af8ddb11616
mode 100644,000000..100644
--- /dev/null
@@@ -1,391 -1,0 +1,391 @@@
- #include <asm/arch/dsp_common.h>
- #include <asm/arch/mmu.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#ifndef __PLAT_OMAP_DSP_DSP_H
 +#define __PLAT_OMAP_DSP_DSP_H
 +
 +#include "hardware_dsp.h"
++#include <mach/dsp_common.h>
++#include <mach/mmu.h>
 +
 +
 +#ifdef CONFIG_ARCH_OMAP2
 +#include "../../../arch/arm/mach-omap2/prm.h"
 +#include "../../../arch/arm/mach-omap2/prm-regbits-24xx.h"
 +#include "../../../arch/arm/mach-omap2/cm.h"
 +#include "../../../arch/arm/mach-omap2/cm-regbits-24xx.h"
 +#endif
 +
 +/*
 + * MAJOR device number: !! allocated arbitrary !!
 + */
 +#define OMAP_DSP_CTL_MAJOR            96
 +#define OMAP_DSP_TASK_MAJOR           97
 +
 +#define OLD_BINARY_SUPPORT    y
 +
 +#ifdef OLD_BINARY_SUPPORT
 +#define MBREV_3_0     0x0017
 +#define MBREV_3_2     0x0018
 +#endif
 +
 +#define DSP_INIT_PAGE 0xfff000
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +/* idle program will be placed at IDLEPG_BASE. */
 +#define IDLEPG_BASE   0xfffe00
 +#define IDLEPG_SIZE   0x100
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +/* timeout value for DSP response */
 +#define DSP_TIMEOUT   (10 * HZ)
 +
 +enum dsp_mem_type_e {
 +      MEM_TYPE_CROSSING = -1,
 +      MEM_TYPE_NONE = 0,
 +      MEM_TYPE_DARAM,
 +      MEM_TYPE_SARAM,
 +      MEM_TYPE_EXTERN,
 +};
 +
 +
 +typedef int __bitwise arm_dsp_dir_t;
 +#define DIR_A2D       ((__force arm_dsp_dir_t) 1)
 +#define DIR_D2A       ((__force arm_dsp_dir_t) 2)
 +
 +enum cfgstat_e {
 +      CFGSTAT_CLEAN = 0,
 +      CFGSTAT_READY,
 +      CFGSTAT_SUSPEND,
 +      CFGSTAT_RESUME, /* request only */
 +      CFGSTAT_MAX
 +};
 +
 +enum errcode_e {
 +      ERRCODE_WDT = 0,
 +      ERRCODE_MMU,
 +      ERRCODE_MAX
 +};
 +
 +/* keep 2 entries for TID_FREE and TID_ANON */
 +#define TASKDEV_MAX   254
 +
 +#define MK32(uw,lw)   (((u32)(uw)) << 16 | (lw))
 +#define MKLONG(uw,lw) (((unsigned long)(uw)) << 16 | (lw))
 +#define MKVIRT(uw,lw) dspword_to_virt(MKLONG((uw), (lw)));
 +
 +struct sync_seq {
 +      u16 da_dsp;
 +      u16 da_arm;
 +      u16 ad_dsp;
 +      u16 ad_arm;
 +};
 +
 +struct mem_sync_struct {
 +      struct sync_seq *DARAM;
 +      struct sync_seq *SARAM;
 +      struct sync_seq *SDRAM;
 +};
 +
 +/* struct mbcmd and union mbcmd_hw must be compatible */
 +struct mbcmd {
 +      u32 data:16;
 +      u32 cmd_l:8;
 +      u32 cmd_h:7;
 +      u32 seq:1;
 +};
 +
 +#define MBCMD_INIT(h, l, d) { \
 +              .cmd_h = (h), \
 +              .cmd_l = (l), \
 +              .data  = (d), \
 +      }
 +
 +struct mb_exarg {
 +      u8 tid;
 +      int argc;
 +      u16 *argv;
 +};
 +
 +typedef u32 dsp_long_t;       /* must have ability to carry TADD_ABORTADR */
 +
 +extern void dsp_mbox_start(void);
 +extern void dsp_mbox_stop(void);
 +extern int dsp_mbox_config(void *p);
 +extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt);
 +extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
 +                                int recovery_flag);
 +#define dsp_mbcmd_send(mb)            __dsp_mbcmd_send_exarg((mb), NULL, 0)
 +#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send_exarg((mb), (arg), 0)
 +extern int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
 +                                       wait_queue_head_t *q);
 +#define dsp_mbcmd_send_and_wait(mb, q) \
 +      dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q))
 +
 +static inline int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data,
 +                                           struct mb_exarg *arg,
 +                                           int recovery_flag)
 +{
 +      struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
 +      return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag);
 +}
 +#define mbcompose_send(cmd_h, cmd_l, data) \
 +      __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0)
 +#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \
 +      __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0)
 +#define mbcompose_send_recovery(cmd_h, cmd_l, data) \
 +      __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1)
 +
 +static inline int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l,
 +                                                    u16 data,
 +                                                    struct mb_exarg *arg,
 +                                                    wait_queue_head_t *q)
 +{
 +      struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
 +      return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q);
 +}
 +#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \
 +      __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
 +                                      NULL, (q))
 +#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \
 +      __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
 +                                      (arg), (q))
 +
 +extern struct ipbuf_head *bid_to_ipbuf(u16 bid);
 +extern void ipbuf_start(void);
 +extern void ipbuf_stop(void);
 +extern int ipbuf_config(u16 ln, u16 lsz, void *base);
 +extern int ipbuf_sys_config(void *p, arm_dsp_dir_t dir);
 +extern int ipbuf_p_validate(void *p, arm_dsp_dir_t dir);
 +extern struct ipbuf_head *get_free_ipbuf(u8 tid);
 +extern void release_ipbuf(struct ipbuf_head *ipb_h);
 +extern void balance_ipbuf(void);
 +extern void unuse_ipbuf(struct ipbuf_head *ipb_h);
 +extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h);
 +
 +#define release_ipbuf_pvt(ipbuf_pvt) \
 +      do { \
 +              (ipbuf_pvt)->s = TID_FREE; \
 +      } while(0)
 +
 +extern int mbox_revision;
 +
 +extern int dsp_cfgstat_request(enum cfgstat_e st);
 +extern enum cfgstat_e dsp_cfgstat_get_stat(void);
 +extern int dsp_set_runlevel(u8 level);
 +
 +extern int dsp_task_config_all(u8 n);
 +extern void dsp_task_unconfig_all(void);
 +extern u8 dsp_task_count(void);
 +extern int dsp_taskmod_busy(void);
 +extern int dsp_mkdev(char *name);
 +extern int dsp_rmdev(char *name);
 +extern int dsp_tadd_minor(unsigned char minor, dsp_long_t adr);
 +extern int dsp_tdel_minor(unsigned char minor);
 +extern int dsp_tkill_minor(unsigned char minor);
 +extern long taskdev_state_stale(unsigned char minor);
 +extern int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz);
 +extern void dsp_dbg_stop(void);
 +
 +extern int ipbuf_is_held(u8 tid, u16 bid);
 +
 +extern int dsp_mem_sync_inc(void);
 +extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
 +extern enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len);
 +extern int dsp_address_validate(void *p, size_t len, char *fmt, ...);
 +#ifdef CONFIG_ARCH_OMAP1
 +extern void dsp_mem_usecount_clear(void);
 +#endif
 +extern void exmap_use(void *vadr, size_t len);
 +extern void exmap_unuse(void *vadr, size_t len);
 +extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len);
 +extern void dsp_mem_start(void);
 +extern void dsp_mem_stop(void);
 +
 +extern void dsp_twch_start(void);
 +extern void dsp_twch_stop(void);
 +extern void dsp_twch_touch(void);
 +
 +extern void dsp_err_start(void);
 +extern void dsp_err_stop(void);
 +extern void dsp_err_set(enum errcode_e code, unsigned long arg);
 +extern void dsp_err_clear(enum errcode_e code);
 +extern int dsp_err_isset(enum errcode_e code);
 +
 +enum cmd_l_type_e {
 +      CMD_L_TYPE_NULL,
 +      CMD_L_TYPE_TID,
 +      CMD_L_TYPE_SUBCMD,
 +};
 +
 +struct cmdinfo {
 +      char *name;
 +      enum cmd_l_type_e cmd_l_type;
 +      void (*handler)(struct mbcmd *mb);
 +};
 +
 +extern const struct cmdinfo *cmdinfo[];
 +
 +#define cmd_name(mb)  (cmdinfo[(mb).cmd_h]->name)
 +extern char *subcmd_name(struct mbcmd *mb);
 +
 +extern void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir);
 +
 +extern struct omap_mmu dsp_mmu;
 +
 +#define dsp_mem_enable(addr)  omap_mmu_mem_enable(&dsp_mmu, (addr))
 +#define dsp_mem_disable(addr) omap_mmu_mem_disable(&dsp_mmu, (addr))
 +
 +#define DSPSPACE_SIZE 0x1000000
 +
 +#define omap_set_bit_regw(b,r) \
 +      do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
 +#define omap_clr_bit_regw(b,r) \
 +      do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
 +#define omap_set_bit_regl(b,r) \
 +      do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
 +#define omap_clr_bit_regl(b,r) \
 +      do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
 +#define omap_set_bits_regl(val,mask,r) \
 +      do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
 +
 +#define dspword_to_virt(dw)   ((void *)(dspmem_base + ((dw) << 1)))
 +#define dspbyte_to_virt(db)   ((void *)(dspmem_base + (db)))
 +#define virt_to_dspword(va) \
 +      ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
 +#define virt_to_dspbyte(va) \
 +      ((dsp_long_t)((unsigned long)(va) - dspmem_base))
 +#define is_dsp_internal_mem(va) \
 +      (((unsigned long)(va) >= dspmem_base) &&  \
 +       ((unsigned long)(va) < dspmem_base + dspmem_size))
 +#define is_dspbyte_internal_mem(db)   ((db) < dspmem_size)
 +#define is_dspword_internal_mem(dw)   (((dw) << 1) < dspmem_size)
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +/*
 + * MPUI byteswap/wordswap on/off
 + *   default setting: wordswap = all, byteswap = APIMEM only
 + */
 +#define mpui_wordswap_on() \
 +      omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
 +                         MPUI_CTRL)
 +
 +#define mpui_wordswap_off() \
 +      omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
 +                         MPUI_CTRL)
 +
 +#define mpui_byteswap_on() \
 +      omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
 +                         MPUI_CTRL)
 +
 +#define mpui_byteswap_off() \
 +      omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
 +                         MPUI_CTRL)
 +
 +/*
 + * TC wordswap on / off
 + */
 +#define tc_wordswap() \
 +      do { \
 +              omap_writel(TC_ENDIANISM_SWAP_WORD | TC_ENDIANISM_EN, \
 +                          TC_ENDIANISM); \
 +      } while(0)
 +
 +#define tc_noswap()   omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
 +
 +/*
 + * enable priority registers, EMIF, MPUI control logic
 + */
 +#define __dsp_enable()        omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
 +#define __dsp_disable()       omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
 +#define __dsp_run()   omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
 +#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +#ifdef CONFIG_ARCH_OMAP2
 +/*
 + * PRCM / IPI control logic
 + *
 + * REVISIT: these macros should probably be static inline functions
 + */
 +#define __dsp_core_enable() \
 +      do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
 +           & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
 +#define __dsp_core_disable() \
 +      do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
 +           | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
 +#define __dsp_per_enable() \
 +      do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
 +           & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
 +#define __dsp_per_disable() \
 +      do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
 +           | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
 +#endif /* CONFIG_ARCH_OMAP2 */
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +extern struct clk *dsp_ck_handle;
 +extern struct clk *api_ck_handle;
 +#elif defined(CONFIG_ARCH_OMAP2)
 +extern struct clk *dsp_fck_handle;
 +extern struct clk *dsp_ick_handle;
 +#endif
 +extern dsp_long_t dspmem_base, dspmem_size,
 +                daram_base, daram_size,
 +                saram_base, saram_size;
 +
 +enum cpustat_e {
 +      CPUSTAT_RESET = 0,
 +#ifdef CONFIG_ARCH_OMAP1
 +      CPUSTAT_GBL_IDLE,
 +      CPUSTAT_CPU_IDLE,
 +#endif
 +      CPUSTAT_RUN,
 +      CPUSTAT_MAX
 +};
 +
 +int dsp_set_rstvect(dsp_long_t adr);
 +dsp_long_t dsp_get_rstvect(void);
 +void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
 +void dsp_reset_idle_boot_base(void);
 +void dsp_cpustat_request(enum cpustat_e req);
 +enum cpustat_e dsp_cpustat_get_stat(void);
 +u16 dsp_cpustat_get_icrmask(void);
 +void dsp_cpustat_set_icrmask(u16 mask);
 +void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
 +void dsp_unregister_mem_cb(void);
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +#define command_dvfs_stop(m) (0)
 +#define command_dvfs_start(m) (0)
 +#elif defined(CONFIG_ARCH_OMAP2)
 +#define command_dvfs_stop(m) \
 +      (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP))
 +#define command_dvfs_start(m) \
 +      (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START))
 +#endif
 +
 +extern struct omap_dsp *omap_dsp;
 +
 +extern int dsp_late_init(void);
 +
 +#endif /* __PLAT_OMAP_DSP_DSP_H */
index 7a4be53b563bfd9979f83e01b86421d400cfdebb,0000000000000000000000000000000000000000..9dffda2252e56a4ea5e6f6a3224e75aa622ce36f
mode 100644,000000..100644
--- /dev/null
@@@ -1,639 -1,0 +1,639 @@@
- #include <asm/arch/dsp_common.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/sched.h>
 +#include <linux/delay.h>
 +#include <linux/mm.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/mutex.h>
 +#include <linux/interrupt.h>
 +#include <asm/io.h>
 +#include <asm/tlbflush.h>
 +#include <asm/irq.h>
- #include <asm/arch/tc.h>
++#include <mach/dsp_common.h>
 +#include "dsp.h"
 +
 +#ifdef CONFIG_ARCH_OMAP1
++#include <mach/tc.h>
 +#endif
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
 +#endif
 +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 +#define dsp_boot_config(mode) writel((mode), DSP_IPI_DSPBOOTCONFIG)
 +#endif
 +
 +struct omap_dsp *omap_dsp;
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +struct clk *dsp_ck_handle;
 +struct clk *api_ck_handle;
 +#elif defined(CONFIG_ARCH_OMAP2)
 +struct clk *dsp_fck_handle;
 +struct clk *dsp_ick_handle;
 +#endif
 +dsp_long_t dspmem_base, dspmem_size,
 +         daram_base, daram_size,
 +         saram_base, saram_size;
 +
 +static struct cpustat {
 +      struct mutex lock;
 +      enum cpustat_e stat;
 +      enum cpustat_e req;
 +      u16 icrmask;
 +#ifdef CONFIG_ARCH_OMAP1
 +      struct {
 +              int mpui;
 +              int mem;
 +              int mem_delayed;
 +      } usecount;
 +      int (*mem_req_cb)(void);
 +      void (*mem_rel_cb)(void);
 +#endif
 +} cpustat = {
 +      .stat = CPUSTAT_RESET,
 +      .icrmask = 0xffff,
 +};
 +
 +int dsp_set_rstvect(dsp_long_t adr)
 +{
 +      unsigned long *dst_adr;
 +
 +      if (adr >= DSPSPACE_SIZE)
 +              return -EINVAL;
 +
 +      dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
 +      /* word swap */
 +      *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
 +      /* fill 8 bytes! */
 +      *(dst_adr + 1) = 0;
 +      /* direct boot */
 +      dsp_boot_config(DSP_BOOT_CONFIG_DIRECT);
 +
 +      return 0;
 +}
 +
 +dsp_long_t dsp_get_rstvect(void)
 +{
 +      unsigned long *dst_adr;
 +
 +      dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
 +      return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16);
 +}
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +static void simple_load_code(unsigned char *src_c, u16 *dst, int len)
 +{
 +      int i;
 +      u16 *src = (u16 *)src_c;
 +      int len_w;
 +
 +      /* len must be multiple of 2. */
 +      if (len & 1)
 +              BUG();
 +
 +      len_w = len / 2;
 +      for (i = 0; i < len_w; i++) {
 +              /* byte swap copy */
 +              *dst = ((*src & 0x00ff) << 8) |
 +                     ((*src & 0xff00) >> 8);
 +              src++;
 +              dst++;
 +      }
 +}
 +
 +/* program size must be multiple of 2 */
 +#define GBL_IDLE_TEXT_SIZE    52
 +#define GBL_IDLE_TEXT_INIT { \
 +      /* SAM */ \
 +      0x3c, 0x4a,                     /* 0x3c4a:     MOV 0x4, AR2 */ \
 +      0xf4, 0x41, 0xfc, 0xff,         /* 0xf441fcff: AND 0xfcff, *AR2 */ \
 +      /* disable WDT */ \
 +      0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
 +      0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      /* *IER0 = 0, *IER1 = 0 */ \
 +      0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
 +      0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
 +      0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
 +      0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
 +      /* *ICR = 0xffff */ \
 +      0x3c, 0x1b,                     /* 0x3c1b:     MOV 0x1, AR3 */ \
 +      0xfb, 0x61, 0xff, 0xff,         /* 0xfb61ffff: MOV 0xffff, *AR3 */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      /* HOM */ \
 +      0xf5, 0x41, 0x03, 0x00,         /* 0xf5410300: OR 0x0300, *AR2 */ \
 +      /* idle and loop forever */ \
 +      0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
 +      0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
 +      0x20, 0x20, 0x20,               /* 0x20:       NOP */ \
 +}
 +
 +/* program size must be multiple of 2 */
 +#define CPU_IDLE_TEXT_SIZE    48
 +#define CPU_IDLE_TEXT_INIT(icrh, icrl) { \
 +      /* SAM */ \
 +      0x3c, 0x4b,                     /* 0x3c4b:     MOV 0x4, AR3 */ \
 +      0xf4, 0x61, 0xfc, 0xff,         /* 0xf461fcff: AND 0xfcff, *AR3 */ \
 +      /* disable WDT */ \
 +      0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
 +      0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      /* *IER0 = 0, *IER1 = 0 */ \
 +      0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
 +      0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
 +      0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
 +      0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
 +      /* set ICR = icr */ \
 +      0x3c, 0x1b,                     /* 0x3c1b:     MOV AR3 0x1 */ \
 +      0xfb, 0x61, (icrh), (icrl),     /* 0xfb61****: MOV *AR3, icr */ \
 +      0x9a,                           /* 0x9a:       PORT */ \
 +      /* idle and loop forever */ \
 +      0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
 +      0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
 +      0x20, 0x20, 0x20                /* 0x20: nop */ \
 +}
 +
 +/*
 + * idle_boot base:
 + * Initialized with DSP_BOOT_ADR_MPUI (=0x010000).
 + * This value is used before DSP Gateway driver is initialized.
 + * DSP Gateway driver will overwrite this value with other value,
 + * to avoid confliction with the user program.
 + */
 +static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI;
 +
 +static void dsp_gbl_idle(void)
 +{
 +      unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT;
 +
 +      __dsp_reset();
 +      clk_enable(api_ck_handle);
 +
 +#if 0
 +      dsp_boot_config(DSP_BOOT_CONFIG_IDLE);
 +#endif
 +      simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
 +                       GBL_IDLE_TEXT_SIZE);
 +      if (idle_boot_base == DSP_BOOT_ADR_MPUI)
 +              dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
 +      else
 +              dsp_set_rstvect(idle_boot_base);
 +
 +      __dsp_run();
 +      udelay(100);    /* to make things stable */
 +      clk_disable(api_ck_handle);
 +}
 +
 +static void dsp_cpu_idle(void)
 +{
 +      u16 icr_tmp;
 +      unsigned char icrh, icrl;
 +
 +      __dsp_reset();
 +      clk_enable(api_ck_handle);
 +
 +      /*
 +       * icr settings:
 +       * DMA should not sleep for DARAM/SARAM access
 +       * DPLL should not sleep while any other domain is active
 +       */
 +      icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL);
 +      icrh = icr_tmp >> 8;
 +      icrl = icr_tmp & 0xff;
 +      {
 +              unsigned char idle_text[CPU_IDLE_TEXT_SIZE] = CPU_IDLE_TEXT_INIT(icrh, icrl);
 +              simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
 +                               CPU_IDLE_TEXT_SIZE);
 +      }
 +      if (idle_boot_base == DSP_BOOT_ADR_MPUI)
 +              dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
 +      else
 +              dsp_set_rstvect(idle_boot_base);
 +      __dsp_run();
 +      udelay(100);    /* to make things stable */
 +      clk_disable(api_ck_handle);
 +}
 +
 +void dsp_set_idle_boot_base(dsp_long_t adr, size_t size)
 +{
 +      if (adr == idle_boot_base)
 +              return;
 +      idle_boot_base = adr;
 +      if ((size < GBL_IDLE_TEXT_SIZE) ||
 +          (size < CPU_IDLE_TEXT_SIZE)) {
 +              printk(KERN_ERR
 +                     "omapdsp: size for idle program is not enough!\n");
 +              BUG();
 +      }
 +
 +      /* restart idle program with new base address */
 +      if (cpustat.stat == CPUSTAT_GBL_IDLE)
 +              dsp_gbl_idle();
 +      if (cpustat.stat == CPUSTAT_CPU_IDLE)
 +              dsp_cpu_idle();
 +}
 +
 +void dsp_reset_idle_boot_base(void)
 +{
 +      idle_boot_base = DSP_BOOT_ADR_MPUI;
 +}
 +#else
 +void dsp_reset_idle_boot_base(void) { }
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +static int init_done;
 +
 +static int omap_dsp_init(void)
 +{
 +      mutex_init(&cpustat.lock);
 +
 +      dspmem_size = 0;
 +#ifdef CONFIG_ARCH_OMAP15XX
 +      if (cpu_is_omap15xx()) {
 +              dspmem_base = OMAP1510_DSP_BASE;
 +              dspmem_size = OMAP1510_DSP_SIZE;
 +              daram_base = OMAP1510_DARAM_BASE;
 +              daram_size = OMAP1510_DARAM_SIZE;
 +              saram_base = OMAP1510_SARAM_BASE;
 +              saram_size = OMAP1510_SARAM_SIZE;
 +      }
 +#endif
 +#ifdef CONFIG_ARCH_OMAP16XX
 +      if (cpu_is_omap16xx()) {
 +              dspmem_base = OMAP16XX_DSP_BASE;
 +              dspmem_size = OMAP16XX_DSP_SIZE;
 +              daram_base = OMAP16XX_DARAM_BASE;
 +              daram_size = OMAP16XX_DARAM_SIZE;
 +              saram_base = OMAP16XX_SARAM_BASE;
 +              saram_size = OMAP16XX_SARAM_SIZE;
 +      }
 +#endif
 +#ifdef CONFIG_ARCH_OMAP24XX
 +      if (cpu_is_omap24xx()) {
 +              dspmem_base = DSP_MEM_24XX_VIRT;
 +              dspmem_size = DSP_MEM_24XX_SIZE;
 +              daram_base = OMAP24XX_DARAM_BASE;
 +              daram_size = OMAP24XX_DARAM_SIZE;
 +              saram_base = OMAP24XX_SARAM_BASE;
 +              saram_size = OMAP24XX_SARAM_SIZE;
 +      }
 +#endif
 +#ifdef CONFIG_ARCH_OMAP34XX
 +      /* To be Revisited for 3430 */
 +      if (cpu_is_omap34xx()) {
 +              return -ENODEV;
 +      }
 +#endif
 +      if (dspmem_size == 0) {
 +              printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
 +              return -ENODEV;
 +      }
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +      dsp_ck_handle = clk_get(NULL, "dsp_ck");
 +      if (IS_ERR(dsp_ck_handle)) {
 +              printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
 +              return PTR_ERR(dsp_ck_handle);
 +      }
 +
 +      api_ck_handle = clk_get(NULL, "api_ck");
 +      if (IS_ERR(api_ck_handle)) {
 +              printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
 +              if (dsp_ck_handle != NULL)
 +                      clk_put(dsp_ck_handle);
 +              return PTR_ERR(api_ck_handle);
 +      }
 +
 +      /* This is needed for McBSP init, released in late_initcall */
 +      clk_enable(api_ck_handle);
 +
 +      __dsp_enable();
 +      mpui_byteswap_off();
 +      mpui_wordswap_on();
 +      tc_wordswap();
 +#elif defined(CONFIG_ARCH_OMAP2)
 +      dsp_fck_handle = clk_get(NULL, "dsp_fck");
 +      if (IS_ERR(dsp_fck_handle)) {
 +              printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n");
 +              return PTR_ERR(dsp_fck_handle);
 +      }
 +
 +# if defined(CONFIG_ARCH_OMAP2420)
 +      dsp_ick_handle = clk_get(NULL, "dsp_ick");
 +# elif defined(CONFIG_ARCH_OMAP2430)
 +      /*
 +       * 2430 has no separate switch for DSP ICLK, but this at least
 +       * involves the minimal change to the rest of the code.
 +       */
 +      dsp_ick_handle = clk_get(NULL, "iva2_1_ick");
 +# endif
 +      if (IS_ERR(dsp_ick_handle)) {
 +              printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n");
 +              if (dsp_fck_handle != NULL)
 +                      clk_put(dsp_fck_handle);
 +              return PTR_ERR(dsp_ick_handle);
 +      }
 +#endif
 +
 +      init_done = 1;
 +      pr_info("omap_dsp_init() done\n");
 +      return 0;
 +}
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +static int __dsp_late_init(void)
 +{
 +      clk_disable(api_ck_handle);
 +      return 0;
 +}
 +late_initcall(__dsp_late_init);
 +#endif
 +
 +static void dsp_cpustat_update(void)
 +{
 +      if (!init_done)
 +              omap_dsp_init();
 +
 +      if (cpustat.req == CPUSTAT_RUN) {
 +              if (cpustat.stat < CPUSTAT_RUN) {
 +#if defined(CONFIG_ARCH_OMAP1)
 +                      __dsp_reset();
 +                      clk_enable(api_ck_handle);
 +                      udelay(10);
 +                      __dsp_run();
 +#elif defined(CONFIG_ARCH_OMAP2)
 +                      __dsp_core_disable();
 +                      udelay(10);
 +                      __dsp_core_enable();
 +#endif
 +                      cpustat.stat = CPUSTAT_RUN;
 +              }
 +              return;
 +      }
 +
 +      /* cpustat.req < CPUSTAT_RUN */
 +
 +      if (cpustat.stat == CPUSTAT_RUN) {
 +#ifdef CONFIG_ARCH_OMAP1
 +              clk_disable(api_ck_handle);
 +#endif
 +      }
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +      /*
 +       * (1) when ARM wants DARAM access, MPUI should be SAM and
 +       *     DSP needs to be on.
 +       * (2) if any bits of icr is masked, we can not enter global idle.
 +       */
 +      if ((cpustat.req == CPUSTAT_CPU_IDLE) ||
 +          (cpustat.usecount.mem > 0) ||
 +          (cpustat.usecount.mem_delayed > 0) ||
 +          ((cpustat.usecount.mpui > 0) && (cpustat.icrmask != 0xffff))) {
 +              if (cpustat.stat != CPUSTAT_CPU_IDLE) {
 +                      dsp_cpu_idle();
 +                      cpustat.stat = CPUSTAT_CPU_IDLE;
 +              }
 +              return;
 +      }
 +
 +      /*
 +       * when ARM only needs MPUI access, MPUI can be HOM and
 +       * DSP can be idling.
 +       */
 +      if ((cpustat.req == CPUSTAT_GBL_IDLE) ||
 +          (cpustat.usecount.mpui > 0)) {
 +              if (cpustat.stat != CPUSTAT_GBL_IDLE) {
 +                      dsp_gbl_idle();
 +                      cpustat.stat = CPUSTAT_GBL_IDLE;
 +              }
 +              return;
 +      }
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +      /*
 +       * no user, no request
 +       */
 +      if (cpustat.stat != CPUSTAT_RESET) {
 +#if defined(CONFIG_ARCH_OMAP1)
 +              __dsp_reset();
 +#elif defined(CONFIG_ARCH_OMAP2)
 +              __dsp_core_disable();
 +#endif
 +              cpustat.stat = CPUSTAT_RESET;
 +      }
 +}
 +
 +void dsp_cpustat_request(enum cpustat_e req)
 +{
 +      mutex_lock(&cpustat.lock);
 +      cpustat.req = req;
 +      dsp_cpustat_update();
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +enum cpustat_e dsp_cpustat_get_stat(void)
 +{
 +      return cpustat.stat;
 +}
 +
 +u16 dsp_cpustat_get_icrmask(void)
 +{
 +      return cpustat.icrmask;
 +}
 +
 +void dsp_cpustat_set_icrmask(u16 mask)
 +{
 +      mutex_lock(&cpustat.lock);
 +      cpustat.icrmask = mask;
 +      dsp_cpustat_update();
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +void omap_dsp_request_mpui(void)
 +{
 +      mutex_lock(&cpustat.lock);
 +      if (cpustat.usecount.mpui++ == 0)
 +              dsp_cpustat_update();
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +void omap_dsp_release_mpui(void)
 +{
 +      mutex_lock(&cpustat.lock);
 +      if (cpustat.usecount.mpui-- == 0) {
 +              printk(KERN_ERR
 +                     "omapdsp: unbalanced mpui request/release detected.\n"
 +                     "         cpustat.usecount.mpui is going to be "
 +                     "less than zero! ... fixed to be zero.\n");
 +              cpustat.usecount.mpui = 0;
 +      }
 +      if (cpustat.usecount.mpui == 0)
 +              dsp_cpustat_update();
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK)
 +int omap_dsp_request_mem(void)
 +{
 +      int ret = 0;
 +
 +      mutex_lock(&cpustat.lock);
 +      if ((cpustat.usecount.mem++ == 0) &&
 +          (cpustat.usecount.mem_delayed == 0)) {
 +              if (cpustat.mem_req_cb) {
 +                      if ((ret = cpustat.mem_req_cb()) < 0) {
 +                              cpustat.usecount.mem--;
 +                              goto out;
 +                      }
 +              }
 +              dsp_cpustat_update();
 +      }
 +out:
 +      mutex_unlock(&cpustat.lock);
 +
 +      return ret;
 +}
 +
 +/*
 + * release_mem will be delayed.
 + */
 +static void do_release_mem(struct work_struct *dummy)
 +{
 +      mutex_lock(&cpustat.lock);
 +      cpustat.usecount.mem_delayed = 0;
 +      if (cpustat.usecount.mem == 0) {
 +              dsp_cpustat_update();
 +              if (cpustat.mem_rel_cb)
 +                      cpustat.mem_rel_cb();
 +      }
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +static DECLARE_DELAYED_WORK(mem_rel_work, do_release_mem);
 +
 +int omap_dsp_release_mem(void)
 +{
 +      mutex_lock(&cpustat.lock);
 +
 +      /* cancel previous release work */
 +      cancel_delayed_work(&mem_rel_work);
 +      cpustat.usecount.mem_delayed = 0;
 +
 +      if (cpustat.usecount.mem-- == 0) {
 +              printk(KERN_ERR
 +                     "omapdsp: unbalanced memory request/release detected.\n"
 +                     "         cpustat.usecount.mem is going to be "
 +                     "less than zero! ... fixed to be zero.\n");
 +              cpustat.usecount.mem = 0;
 +      }
 +      if (cpustat.usecount.mem == 0) {
 +              cpustat.usecount.mem_delayed = 1;
 +              schedule_delayed_work(&mem_rel_work, HZ);
 +      }
 +
 +      mutex_unlock(&cpustat.lock);
 +
 +      return 0;
 +}
 +#endif
 +
 +void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void))
 +{
 +      mutex_lock(&cpustat.lock);
 +
 +      cpustat.mem_req_cb = req_cb;
 +      cpustat.mem_rel_cb = rel_cb;
 +
 +      /*
 +       * This function must be called while mem is enabled!
 +       */
 +      BUG_ON(cpustat.usecount.mem == 0);
 +
 +      mutex_unlock(&cpustat.lock);
 +}
 +
 +void dsp_unregister_mem_cb(void)
 +{
 +      mutex_lock(&cpustat.lock);
 +      cpustat.mem_req_cb = NULL;
 +      cpustat.mem_rel_cb = NULL;
 +      mutex_unlock(&cpustat.lock);
 +}
 +#else
 +void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)) { }
 +void dsp_unregister_mem_cb(void) { }
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +arch_initcall(omap_dsp_init);
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +EXPORT_SYMBOL(omap_dsp_request_mpui);
 +EXPORT_SYMBOL(omap_dsp_release_mpui);
 +#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK)
 +EXPORT_SYMBOL(omap_dsp_request_mem);
 +EXPORT_SYMBOL(omap_dsp_release_mem);
 +#endif
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +#ifdef CONFIG_OMAP_DSP_MODULE
 +#if defined(CONFIG_ARCH_OMAP1)
 +EXPORT_SYMBOL(dsp_ck_handle);
 +EXPORT_SYMBOL(api_ck_handle);
 +#elif defined(CONFIG_ARCH_OMAP2)
 +EXPORT_SYMBOL(dsp_fck_handle);
 +EXPORT_SYMBOL(dsp_ick_handle);
 +#endif
 +EXPORT_SYMBOL(omap_dsp);
 +EXPORT_SYMBOL(dspmem_base);
 +EXPORT_SYMBOL(dspmem_size);
 +EXPORT_SYMBOL(daram_base);
 +EXPORT_SYMBOL(daram_size);
 +EXPORT_SYMBOL(saram_base);
 +EXPORT_SYMBOL(saram_size);
 +EXPORT_SYMBOL(dsp_set_rstvect);
 +EXPORT_SYMBOL(dsp_get_rstvect);
 +#ifdef CONFIG_ARCH_OMAP1
 +EXPORT_SYMBOL(dsp_set_idle_boot_base);
 +EXPORT_SYMBOL(dsp_reset_idle_boot_base);
 +#endif /* CONFIG_ARCH_OMAP1 */
 +EXPORT_SYMBOL(dsp_cpustat_request);
 +EXPORT_SYMBOL(dsp_cpustat_get_stat);
 +EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
 +EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
 +EXPORT_SYMBOL(dsp_register_mem_cb);
 +EXPORT_SYMBOL(dsp_unregister_mem_cb);
 +
 +EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
 +EXPORT_SYMBOL(cpu_architecture);
 +EXPORT_SYMBOL(pmd_clear_bad);
 +#endif
index 68cc9e643ff3de2ded58a8d925e1c00e5f9ca2f9,0000000000000000000000000000000000000000..f2368fb32d8bc3f60d5999cb861c40818a2ed73b
mode 100644,000000..100644
--- /dev/null
@@@ -1,646 -1,0 +1,646 @@@
- #include <asm/arch/mailbox.h>
- #include <asm/arch/dsp.h>
- #include <asm/arch/dsp_common.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/init.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/sched.h>
 +#include <linux/mutex.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <asm/delay.h>
++#include <mach/mailbox.h>
++#include <mach/dsp.h>
++#include <mach/dsp_common.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +
 +MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
 +MODULE_DESCRIPTION("OMAP DSP driver module");
 +MODULE_LICENSE("GPL");
 +
 +static struct sync_seq *mbseq;
 +static u16 mbseq_expect_tmp;
 +static u16 *mbseq_expect = &mbseq_expect_tmp;
 +
 +extern int dsp_mem_late_init(void);
 +
 +/*
 + * mailbox commands
 + */
 +extern void mbox_wdsnd(struct mbcmd *mb);
 +extern void mbox_wdreq(struct mbcmd *mb);
 +extern void mbox_bksnd(struct mbcmd *mb);
 +extern void mbox_bkreq(struct mbcmd *mb);
 +extern void mbox_bkyld(struct mbcmd *mb);
 +extern void mbox_bksndp(struct mbcmd *mb);
 +extern void mbox_bkreqp(struct mbcmd *mb);
 +extern void mbox_tctl(struct mbcmd *mb);
 +extern void mbox_poll(struct mbcmd *mb);
 +#ifdef OLD_BINARY_SUPPORT
 +/* v3.3 obsolete */
 +extern void mbox_wdt(struct mbcmd *mb);
 +#endif
 +extern void mbox_suspend(struct mbcmd *mb);
 +static void mbox_kfunc(struct mbcmd *mb);
 +extern void mbox_tcfg(struct mbcmd *mb);
 +extern void mbox_tadd(struct mbcmd *mb);
 +extern void mbox_tdel(struct mbcmd *mb);
 +extern void mbox_dspcfg(struct mbcmd *mb);
 +extern void mbox_regrw(struct mbcmd *mb);
 +extern void mbox_getvar(struct mbcmd *mb);
 +extern void mbox_err(struct mbcmd *mb);
 +extern void mbox_dbg(struct mbcmd *mb);
 +
 +static const struct cmdinfo
 +      cif_wdsnd    = { "WDSND",    CMD_L_TYPE_TID,    mbox_wdsnd   },
 +      cif_wdreq    = { "WDREQ",    CMD_L_TYPE_TID,    mbox_wdreq   },
 +      cif_bksnd    = { "BKSND",    CMD_L_TYPE_TID,    mbox_bksnd   },
 +      cif_bkreq    = { "BKREQ",    CMD_L_TYPE_TID,    mbox_bkreq   },
 +      cif_bkyld    = { "BKYLD",    CMD_L_TYPE_NULL,   mbox_bkyld   },
 +      cif_bksndp   = { "BKSNDP",   CMD_L_TYPE_TID,    mbox_bksndp  },
 +      cif_bkreqp   = { "BKREQP",   CMD_L_TYPE_TID,    mbox_bkreqp  },
 +      cif_tctl     = { "TCTL",     CMD_L_TYPE_TID,    mbox_tctl    },
 +      cif_poll     = { "POLL",     CMD_L_TYPE_NULL,   mbox_poll    },
 +#ifdef OLD_BINARY_SUPPORT
 +      /* v3.3 obsolete */
 +      cif_wdt      = { "WDT",      CMD_L_TYPE_NULL,   mbox_wdt     },
 +#endif
 +      cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL        },
 +      cif_pm       = { "PM",       CMD_L_TYPE_SUBCMD, NULL        },
 +      cif_suspend  = { "SUSPEND",  CMD_L_TYPE_NULL,   mbox_suspend },
 +      cif_kfunc    = { "KFUNC",    CMD_L_TYPE_SUBCMD, mbox_kfunc   },
 +      cif_tcfg     = { "TCFG",     CMD_L_TYPE_TID,    mbox_tcfg    },
 +      cif_tadd     = { "TADD",     CMD_L_TYPE_TID,    mbox_tadd    },
 +      cif_tdel     = { "TDEL",     CMD_L_TYPE_TID,    mbox_tdel    },
 +      cif_tstop    = { "TSTOP",    CMD_L_TYPE_TID,    NULL        },
 +      cif_dspcfg   = { "DSPCFG",   CMD_L_TYPE_SUBCMD, mbox_dspcfg  },
 +      cif_regrw    = { "REGRW",    CMD_L_TYPE_SUBCMD, mbox_regrw   },
 +      cif_getvar   = { "GETVAR",   CMD_L_TYPE_SUBCMD, mbox_getvar  },
 +      cif_setvar   = { "SETVAR",   CMD_L_TYPE_SUBCMD, NULL        },
 +      cif_err      = { "ERR",      CMD_L_TYPE_SUBCMD, mbox_err     },
 +      cif_dbg      = { "DBG",      CMD_L_TYPE_NULL,   mbox_dbg     };
 +
 +#define MBOX_CMD_MAX  0x80
 +const struct cmdinfo *cmdinfo[MBOX_CMD_MAX] = {
 +      [MBOX_CMD_DSP_WDSND]    = &cif_wdsnd,
 +      [MBOX_CMD_DSP_WDREQ]    = &cif_wdreq,
 +      [MBOX_CMD_DSP_BKSND]    = &cif_bksnd,
 +      [MBOX_CMD_DSP_BKREQ]    = &cif_bkreq,
 +      [MBOX_CMD_DSP_BKYLD]    = &cif_bkyld,
 +      [MBOX_CMD_DSP_BKSNDP]   = &cif_bksndp,
 +      [MBOX_CMD_DSP_BKREQP]   = &cif_bkreqp,
 +      [MBOX_CMD_DSP_TCTL]     = &cif_tctl,
 +      [MBOX_CMD_DSP_POLL]     = &cif_poll,
 +#ifdef OLD_BINARY_SUPPORT
 +      [MBOX_CMD_DSP_WDT]      = &cif_wdt, /* v3.3 obsolete */
 +#endif
 +      [MBOX_CMD_DSP_RUNLEVEL] = &cif_runlevel,
 +      [MBOX_CMD_DSP_PM]       = &cif_pm,
 +      [MBOX_CMD_DSP_SUSPEND]  = &cif_suspend,
 +      [MBOX_CMD_DSP_KFUNC]    = &cif_kfunc,
 +      [MBOX_CMD_DSP_TCFG]     = &cif_tcfg,
 +      [MBOX_CMD_DSP_TADD]     = &cif_tadd,
 +      [MBOX_CMD_DSP_TDEL]     = &cif_tdel,
 +      [MBOX_CMD_DSP_TSTOP]    = &cif_tstop,
 +      [MBOX_CMD_DSP_DSPCFG]   = &cif_dspcfg,
 +      [MBOX_CMD_DSP_REGRW]    = &cif_regrw,
 +      [MBOX_CMD_DSP_GETVAR]   = &cif_getvar,
 +      [MBOX_CMD_DSP_SETVAR]   = &cif_setvar,
 +      [MBOX_CMD_DSP_ERR]      = &cif_err,
 +      [MBOX_CMD_DSP_DBG]      = &cif_dbg,
 +};
 +
 +#define list_for_each_entry_safe_natural(p,n,h,m) \
 +                      list_for_each_entry_safe(p,n,h,m)
 +#define __BUILD_KFUNC(fn, dir)                                                        \
 +static int __dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage)\
 +{                                                                             \
 +      struct dsp_kfunc_device *p, *tmp;                                       \
 +      int ret, fail = 0;                                                      \
 +                                                                              \
 +      list_for_each_entry_safe_##dir(p, tmp, dsp->kdev_list, entry) {         \
 +              if (type && (p->type != type))                                  \
 +                      continue;                                               \
 +              if (p->fn == NULL)                                              \
 +                      continue;                                               \
 +              ret = p->fn(p, stage);                                          \
 +              if (ret) {                                                      \
 +                      printk(KERN_ERR "%s %s failed\n", #fn, p->name);        \
 +                      fail++;                                                 \
 +              }                                                               \
 +      }                                                                       \
 +      return fail;                                                            \
 +}
 +#define BUILD_KFUNC(fn, dir)                                          \
 +__BUILD_KFUNC(fn, dir)                                                        \
 +static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp)      \
 +{                                                                     \
 +      return __dsp_kfunc_##fn##_devices(dsp, 0, 0);                   \
 +}
 +#define BUILD_KFUNC_CTL(fn, dir)                                                      \
 +__BUILD_KFUNC(fn, dir)                                                                        \
 +static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage) \
 +{                                                                                     \
 +      return __dsp_kfunc_##fn##_devices(dsp, type, stage);                            \
 +}
 +
 +BUILD_KFUNC(probe, natural)
 +BUILD_KFUNC(remove, reverse)
 +BUILD_KFUNC_CTL(enable, natural)
 +BUILD_KFUNC_CTL(disable, reverse)
 +
 +int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
 +{
 +      int try;
 +
 +      if (*(volatile u16 *)adr == val)
 +              return 0;
 +
 +      for (try = 0; try < try_cnt; try++) {
 +              udelay(1);
 +              if (*(volatile u16 *)adr == val) {
 +                      /* success! */
 +                      pr_info("omapdsp: sync_with_dsp(): try = %d\n", try);
 +                      return 0;
 +              }
 +      }
 +
 +      /* fail! */
 +      return -1;
 +}
 +
 +static int mbcmd_sender_prepare(void *data)
 +{
 +      struct mb_exarg *arg = data;
 +      int i, ret = 0;
 +      /*
 +       * even if ipbuf_sys_ad is in DSP internal memory,
 +       * dsp_mem_enable() never cause to call PM mailbox command
 +       * because in that case DSP memory should be always enabled.
 +       * (see ipbuf_sys_hold_mem_active in ipbuf.c)
 +       *
 +       * Therefore, we can call this function here safely.
 +       */
 +      dsp_mem_enable(ipbuf_sys_ad);
 +      if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) {
 +              printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
 +              ret = -EBUSY;
 +              goto out;
 +      }
 +
 +      for (i = 0; i < arg->argc; i++) {
 +              ipbuf_sys_ad->d[i] = arg->argv[i];
 +      }
 +      ipbuf_sys_ad->s = arg->tid;
 + out:
 +      dsp_mem_disable(ipbuf_sys_ad);
 +      return ret;
 +}
 +
 +/*
 + * __dsp_mbcmd_send_exarg(): mailbox dispatcher
 + */
 +int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
 +                         int recovery_flag)
 +{
 +      int ret = 0;
 +
 +      if (unlikely(omap_dsp->enabled == 0)) {
 +              ret = dsp_kfunc_enable_devices(omap_dsp,
 +                                             DSP_KFUNC_DEV_TYPE_COMMON, 0);
 +              if (ret == 0)
 +                      omap_dsp->enabled = 1;
 +      }
 +
 +      /*
 +       * while MMU fault is set,
 +       * only recovery command can be executed
 +       */
 +      if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) {
 +              printk(KERN_ERR
 +                     "mbox: mmu interrupt is set. %s is aborting.\n",
 +                     cmd_name(*mb));
 +              goto out;
 +      }
 +
 +      ret = omap_mbox_msg_send(omap_dsp->mbox,
 +                               *(mbox_msg_t *)mb, (void*)arg);
 +      if (ret)
 +              goto out;
 +
 +      if (mbseq)
 +              mbseq->ad_arm++;
 +
 +      mblog_add(mb, DIR_A2D);
 + out:
 +      return ret;
 +}
 +
 +int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
 +                                wait_queue_head_t *q)
 +{
 +      int ret;
 +
 +      DEFINE_WAIT(wait);
 +      prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
 +      ret = dsp_mbcmd_send_exarg(mb, arg);
 +      if (ret < 0)
 +              goto out;
 +      schedule_timeout(DSP_TIMEOUT);
 + out:
 +      finish_wait(q, &wait);
 +      return ret;
 +}
 +
 +/*
 + * mbcmd receiver
 + */
 +static int mbcmd_receiver(void* msg)
 +{
 +      struct mbcmd *mb = (struct mbcmd *)&msg;
 +
 +      if (cmdinfo[mb->cmd_h] == NULL) {
 +              printk(KERN_ERR
 +                     "invalid message (%08x) for mbcmd_receiver().\n",
 +                     (mbox_msg_t)msg);
 +              return -1;
 +      }
 +
 +      (*mbseq_expect)++;
 +
 +      mblog_add(mb, DIR_D2A);
 +
 +      /* call handler for the command */
 +      if (cmdinfo[mb->cmd_h]->handler)
 +              cmdinfo[mb->cmd_h]->handler(mb);
 +      else
 +              printk(KERN_ERR "mbox: %s is not allowed from DSP.\n",
 +                     cmd_name(*mb));
 +      return 0;
 +}
 +
 +static int mbsync_hold_mem_active;
 +
 +void dsp_mbox_start(void)
 +{
 +      omap_mbox_init_seq(omap_dsp->mbox);
 +      mbseq_expect_tmp = 0;
 +}
 +
 +void dsp_mbox_stop(void)
 +{
 +      mbseq = NULL;
 +      mbseq_expect = &mbseq_expect_tmp;
 +}
 +
 +int dsp_mbox_config(void *p)
 +{
 +      unsigned long flags;
 +
 +      if (dsp_address_validate(p, sizeof(struct sync_seq), "mbseq") < 0)
 +              return -1;
 +      if (dsp_mem_type(p, sizeof(struct sync_seq)) != MEM_TYPE_EXTERN) {
 +              printk(KERN_WARNING
 +                     "omapdsp: mbseq is placed in DSP internal memory.\n"
 +                     "         It will prevent DSP from idling.\n");
 +              mbsync_hold_mem_active = 1;
 +              /*
 +               * dsp_mem_enable() never fails because
 +               * it has been already enabled in dspcfg process and
 +               * this will just increment the usecount.
 +               */
 +              dsp_mem_enable((void *)daram_base);
 +      }
 +
 +      local_irq_save(flags);
 +      mbseq = p;
 +      mbseq->da_arm = mbseq_expect_tmp;
 +      mbseq_expect = &mbseq->da_arm;
 +      local_irq_restore(flags);
 +
 +      return 0;
 +}
 +
 +static int __init dsp_mbox_init(void)
 +{
 +      omap_dsp->mbox = omap_mbox_get("dsp");
 +      if (IS_ERR(omap_dsp->mbox)) {
 +              printk(KERN_ERR "failed to get mailbox handler for DSP.\n");
 +              return -ENODEV;
 +      }
 +
 +      omap_dsp->mbox->rxq->callback = mbcmd_receiver;
 +      omap_dsp->mbox->txq->callback = mbcmd_sender_prepare;
 +
 +      return 0;
 +}
 +
 +static void dsp_mbox_exit(void)
 +{
 +      omap_dsp->mbox->txq->callback = NULL;
 +      omap_dsp->mbox->rxq->callback = NULL;
 +
 +      omap_mbox_put(omap_dsp->mbox);
 +
 +      if (mbsync_hold_mem_active) {
 +              dsp_mem_disable((void *)daram_base);
 +              mbsync_hold_mem_active = 0;
 +      }
 +}
 +
 +/*
 + * kernel function dispatcher
 + */
 +extern void mbox_fbctl_upd(void);
 +extern void mbox_fbctl_disable(struct mbcmd *mb);
 +
 +static void mbox_kfunc_fbctl(struct mbcmd *mb)
 +{
 +      switch (mb->data) {
 +      case FBCTL_UPD:
 +              mbox_fbctl_upd();
 +              break;
 +      case FBCTL_DISABLE:
 +              mbox_fbctl_disable(mb);
 +              break;
 +      default:
 +              printk(KERN_ERR
 +                     "mbox: Unknown FBCTL from DSP: 0x%04x\n", mb->data);
 +      }
 +}
 +
 +/*
 + * dspgw: KFUNC message handler
 + */
 +static void mbox_kfunc_power(unsigned short data)
 +{
 +      int ret = -1;
 +
 +      switch (data) {
 +      case DVFS_START: /* ACK from DSP */
 +              /* TBD */
 +              break;
 +      case AUDIO_PWR_UP:
 +              ret = dsp_kfunc_enable_devices(omap_dsp,
 +                                             DSP_KFUNC_DEV_TYPE_AUDIO, 0);
 +              if (ret == 0)
 +                      ret++;
 +              break;
 +      case AUDIO_PWR_DOWN: /* == AUDIO_PWR_DOWN1 */
 +              ret = dsp_kfunc_disable_devices(omap_dsp,
 +                                              DSP_KFUNC_DEV_TYPE_AUDIO, 1);
 +              break;
 +      case AUDIO_PWR_DOWN2:
 +              ret = dsp_kfunc_disable_devices(omap_dsp,
 +                                              DSP_KFUNC_DEV_TYPE_AUDIO, 2);
 +              break;
 +      case DSP_PWR_DOWN:
 +              ret = dsp_kfunc_disable_devices(omap_dsp,
 +                                              DSP_KFUNC_DEV_TYPE_COMMON, 0);
 +              if (ret == 0)
 +                      omap_dsp->enabled = 0;
 +              break;
 +      default:
 +              printk(KERN_ERR
 +                     "mailbox: Unknown PWR from DSP: 0x%04x\n", data);
 +              break;
 +      }
 +
 +      if (unlikely(ret < 0)) {
 +              printk(KERN_ERR "mailbox: PWR(0x%04x) failed\n", data);
 +              return;
 +      }
 +
 +      if (likely(ret == 0))
 +              return;
 +
 +      mbcompose_send(KFUNC, KFUNC_POWER, data);
 +}
 +
 +static void mbox_kfunc(struct mbcmd *mb)
 +{
 +      switch (mb->cmd_l) {
 +      case KFUNC_FBCTL:
 +              mbox_kfunc_fbctl(mb);
 +              break;
 +      case KFUNC_POWER:
 +              mbox_kfunc_power(mb->data);
 +              break;
 +      default:
 +              printk(KERN_ERR
 +                     "mbox: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l);
 +      }
 +}
 +
 +#if defined(CONFIG_ARCH_OMAP1)
 +static inline void dsp_clk_enable(void) {}
 +static inline void dsp_clk_disable(void) {}
 +#elif defined(CONFIG_ARCH_OMAP2)
 +static inline void dsp_clk_enable(void)
 +{
 +      clk_enable(dsp_fck_handle);
 +      clk_enable(dsp_ick_handle);
 +      __dsp_per_enable();
 +}
 +static inline void dsp_clk_disable(void)
 +{
 +      __dsp_per_disable();
 +      clk_disable(dsp_ick_handle);
 +      clk_disable(dsp_fck_handle);
 +}
 +#endif
 +
 +int dsp_late_init(void)
 +{
 +      int ret;
 +
 +      dsp_clk_enable();
 +      ret = dsp_mem_late_init();
 +      if (ret)
 +              return ret;
 +      ret = dsp_mbox_init();
 +      if (ret)
 +              goto fail_mbox;
 +#ifdef CONFIG_ARCH_OMAP1
 +      dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
 +#endif
 +      ret = dsp_kfunc_enable_devices(omap_dsp,
 +                                     DSP_KFUNC_DEV_TYPE_COMMON, 0);
 +      if (ret)
 +              goto fail_kfunc;
 +      omap_dsp->enabled = 1;
 +
 +      return 0;
 +
 + fail_kfunc:
 +      dsp_mbox_exit();
 + fail_mbox:
 +      dsp_clk_disable();
 +
 +      return ret;
 +}
 +
 +extern int  dsp_ctl_core_init(void);
 +extern void dsp_ctl_core_exit(void);
 +extern int dsp_ctl_init(void);
 +extern void dsp_ctl_exit(void);
 +extern int  dsp_mem_init(void);
 +extern void dsp_mem_exit(void);
 +extern void mblog_init(void);
 +extern void mblog_exit(void);
 +extern int  dsp_taskmod_init(void);
 +extern void dsp_taskmod_exit(void);
 +
 +/*
 + * driver functions
 + */
 +static int __init dsp_drv_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +      struct omap_dsp *info;
 +      struct dsp_platform_data *pdata = pdev->dev.platform_data;
 +
 +      dev_info(&pdev->dev, "OMAP DSP driver initialization\n");
 +
 +      info = kzalloc(sizeof(struct omap_dsp), GFP_KERNEL);
 +      if (unlikely(info == NULL)) {
 +              dev_dbg(&pdev->dev, "no memory for info\n");
 +              return -ENOMEM;
 +      }
 +      platform_set_drvdata(pdev, info);
 +      omap_dsp = info;
 +
 +      mutex_init(&info->lock);
 +      info->dev = &pdev->dev;
 +      info->kdev_list = &pdata->kdev_list;
 +
 +      ret = dsp_kfunc_probe_devices(info);
 +      if (ret) {
 +              ret = -ENXIO;
 +              goto fail_kfunc;
 +      }
 +
 +      ret = dsp_ctl_core_init();
 +      if (ret)
 +              goto fail_ctl_core;
 +      ret = dsp_mem_init();
 +      if (ret)
 +              goto fail_mem;
 +      ret = dsp_ctl_init();
 +      if (unlikely(ret))
 +              goto fail_ctl_init;
 +      mblog_init();
 +      ret = dsp_taskmod_init();
 +      if (ret)
 +              goto fail_taskmod;
 +
 +      return 0;
 +
 + fail_taskmod:
 +      mblog_exit();
 +      dsp_ctl_exit();
 + fail_ctl_init:
 +      dsp_mem_exit();
 + fail_mem:
 +      dsp_ctl_core_exit();
 + fail_ctl_core:
 +      dsp_kfunc_remove_devices(info);
 + fail_kfunc:
 +      kfree(info);
 +
 +      return ret;
 +}
 +
 +static int dsp_drv_remove(struct platform_device *pdev)
 +{
 +      struct omap_dsp *info = platform_get_drvdata(pdev);
 +
 +      dsp_cpustat_request(CPUSTAT_RESET);
 +
 +      dsp_cfgstat_request(CFGSTAT_CLEAN);
 +      dsp_mbox_exit();
 +      dsp_taskmod_exit();
 +      mblog_exit();
 +      dsp_ctl_exit();
 +      dsp_mem_exit();
 +
 +      dsp_ctl_core_exit();
 +
 +#ifdef CONFIG_ARCH_OMAP2
 +      __dsp_per_disable();
 +      clk_disable(dsp_ick_handle);
 +      clk_disable(dsp_fck_handle);
 +#endif
 +      dsp_kfunc_remove_devices(info);
 +      kfree(info);
 +
 +      return 0;
 +}
 +
 +#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP1)
 +static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      dsp_cfgstat_request(CFGSTAT_SUSPEND);
 +
 +      return 0;
 +}
 +
 +static int dsp_drv_resume(struct platform_device *pdev)
 +{
 +      dsp_cfgstat_request(CFGSTAT_RESUME);
 +
 +      return 0;
 +}
 +#else
 +#define dsp_drv_suspend               NULL
 +#define dsp_drv_resume                NULL
 +#endif /* CONFIG_PM */
 +
 +static struct platform_driver dsp_driver = {
 +      .probe          = dsp_drv_probe,
 +      .remove         = dsp_drv_remove,
 +      .suspend        = dsp_drv_suspend,
 +      .resume         = dsp_drv_resume,
 +      .driver         = {
 +              .name   = "dsp",
 +      },
 +};
 +
 +static int __init omap_dsp_mod_init(void)
 +{
 +      return platform_driver_register(&dsp_driver);
 +}
 +
 +static void __exit omap_dsp_mod_exit(void)
 +{
 +      platform_driver_unregister(&dsp_driver);
 +}
 +
 +/* module dependency: need mailbox module that have mbox_dsp_info */
 +extern struct omap_mbox mbox_dsp_info;
 +struct omap_mbox *mbox_dep = &mbox_dsp_info;
 +
 +module_init(omap_dsp_mod_init);
 +module_exit(omap_dsp_mod_exit);
index 79c1fdf89afaea4ebea537de20a89a834c303cc0,0000000000000000000000000000000000000000..712c3cfad09c087eb4f9a0dc11c3d725ae98eae7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1069 -1,0 +1,1069 @@@
- #include <asm/arch/mailbox.h>
- #include <asm/arch/dsp.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/device.h>
 +#include <linux/init.h>
 +#include <linux/sched.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/mutex.h>
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
 +#include <asm/ioctls.h>
++#include <mach/mailbox.h>
++#include <mach/dsp.h>
 +#include "hardware_dsp.h"
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +
 +enum dsp_space_e {
 +      SPACE_MEM,
 +      SPACE_IO,
 +};
 +
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +static enum fbstat_e {
 +      FBSTAT_DISABLED = 0,
 +      FBSTAT_ENABLED,
 +      FBSTAT_MAX,
 +} fbstat = FBSTAT_ENABLED;
 +#endif
 +
 +static enum cfgstat_e cfgstat;
 +int mbox_revision;
 +static u8 n_stask;
 +
 +static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf);
 +static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
 +                           const char *buf, size_t count);
 +static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
 +                           char *buf);
 +
 +#define __ATTR_RW(_name, _mode) { \
 +      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
 +      .show   = _name##_show,                                 \
 +      .store  = _name##_store,                                        \
 +}
 +
 +static struct device_attribute dev_attr_ifver     = __ATTR_RO(ifver);
 +static struct device_attribute dev_attr_cpustat   = __ATTR_RO(cpustat);
 +static struct device_attribute dev_attr_icrmask   = __ATTR_RW(icrmask, 0644);
 +static struct device_attribute dev_attr_loadinfo  = __ATTR_RO(loadinfo);
 +
 +/*
 + * misc interactive mailbox command operations
 + */
 +static struct misc_mb_wait_struct {
 +      struct mutex lock;
 +      wait_queue_head_t wait_q;
 +      u8 cmd_h;
 +      u8 cmd_l;
 +      u16 *retvp;
 +} misc_mb_wait = {
 +      .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
 +      .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
 +};
 +
 +static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
 +                                        u16 *retvp)
 +{
 +      struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
 +      int ret = 0;
 +
 +      if (mutex_lock_interruptible(&misc_mb_wait.lock))
 +              return -EINTR;
 +
 +      misc_mb_wait.cmd_h = mb.cmd_h;
 +      misc_mb_wait.cmd_l = mb.cmd_l;
 +      misc_mb_wait.retvp = retvp;
 +      dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
 +
 +      if (misc_mb_wait.cmd_h != 0)
 +              ret = -EINVAL;
 +
 +      mutex_unlock(&misc_mb_wait.lock);
 +      return ret;
 +}
 +
 +#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
 +              __misc_mbcompose_send_and_wait(MBOX_CMD_DSP_##cmd_h, (cmd_l), \
 +                                             (data), (retvp));
 +
 +static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
 +{
 +      volatile u16 *buf;
 +      int i;
 +
 +      /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
 +      if (!waitqueue_active(&misc_mb_wait.wait_q) ||
 +          (misc_mb_wait.cmd_h != mb->cmd_h) ||
 +          (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
 +              const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
 +              char cmdstr[32];
 +
 +              if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
 +                      sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
 +              else
 +                      strcpy(cmdstr, ci->name);
 +              printk(KERN_WARNING
 +                     "mbox: unexpected command %s received!\n", cmdstr);
 +              return -1;
 +      }
 +
 +      /*
 +       * if argc == 1, receive data through mbox:data register.
 +       * if argc > 1, receive through ipbuf_sys.
 +       */
 +      if (argc == 1)
 +              misc_mb_wait.retvp[0] = mb->data;
 +      else if (argc > 1) {
 +              if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +                      printk(KERN_ERR "mbox: %s - ipbuf_sys_da read failed!\n",
 +                             cmdinfo[mb->cmd_h]->name);
 +                      return -1;
 +              }
 +              if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
 +                      printk(KERN_ERR "mbox: %s - IPBUF sync failed!\n",
 +                             cmdinfo[mb->cmd_h]->name);
 +                      dsp_mem_disable(ipbuf_sys_da);
 +                      return -1;
 +              }
 +              /* need word access. do not use memcpy. */
 +              buf = ipbuf_sys_da->d;
 +              for (i = 0; i < argc; i++)
 +                      misc_mb_wait.retvp[i] = buf[i];
 +              release_ipbuf_pvt(ipbuf_sys_da);
 +              dsp_mem_disable(ipbuf_sys_da);
 +      }
 +
 +      misc_mb_wait.cmd_h = 0;
 +      wake_up_interruptible(&misc_mb_wait.wait_q);
 +      return 0;
 +}
 +
 +static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
 +{
 +      u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
 +      int ret;
 +
 +      ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
 +      if ((ret < 0) && (ret != -EINTR))
 +              printk(KERN_ERR "omapdsp: register read error!\n");
 +
 +      return ret;
 +}
 +
 +static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
 +{
 +      u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
 +      struct mb_exarg arg = {
 +              .tid  = TID_ANON,
 +              .argc = 1,
 +              .argv = &val,
 +      };
 +
 +      mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
 +      return 0;
 +}
 +
 +static int dsp_getvar(u8 varid, u16 *val)
 +{
 +      int ret;
 +
 +      ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
 +      if ((ret < 0) && (ret != -EINTR))
 +              printk(KERN_ERR "omapdsp: variable read error!\n");
 +
 +      return ret;
 +}
 +
 +static int dsp_setvar(u8 varid, u16 val)
 +{
 +      mbcompose_send(SETVAR, varid, val);
 +      return 0;
 +}
 +
 +/*
 + * dsp_cfg() return value
 + *  = 0: OK
 + *  = 1: failed, but state is clear. (DSPCFG command failed)
 + *  < 0: failed. need cleanup.
 + */
 +static int dsp_cfg(void)
 +{
 +      int ret = 0;
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +      /* for safety */
 +      dsp_mem_usecount_clear();
 +#endif
 +
 +      /*
 +       * DSPCFG command and dsp_mem_start() must be called
 +       * while internal mem is on.
 +       */
 +      dsp_mem_enable((void *)dspmem_base);
 +
 +      dsp_mbox_start();
 +      dsp_twch_start();
 +      dsp_mem_start();
 +      dsp_err_start();
 +
 +      mbox_revision = -1;
 +
 +      ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
 +      if (ret < 0) {
 +              if (ret != -EINTR)
 +                      printk(KERN_ERR "omapdsp: configuration error!\n");
 +              ret = 1;
 +              goto out;
 +      }
 +
 +#if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT)
 +      /*
 +       * MBREV 3.2 or earlier doesn't assume DMA domain is on
 +       * when DSPCFG command is sent
 +       */
 +      if ((mbox_revision == MBREV_3_0) ||
 +          (mbox_revision == MBREV_3_2)) {
 +              if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
 +                      goto out;
 +      }
 +#endif
 +
 +      if ((ret = dsp_task_config_all(n_stask)) < 0)
 +              goto out;
 +
 +      /* initialization */
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +      fbstat = FBSTAT_ENABLED;
 +#endif
 +
 +      /* send parameter */
 +      ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask());
 +      if (ret < 0)
 +              goto out;
 +
 +      /* create runtime sysfs entries */
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_loadinfo);
 +      if (ret)
 +              printk(KERN_ERR "device_create_file failed: %d\n", ret);
 + out:
 +      dsp_mem_disable((void *)dspmem_base);
 +      return ret;
 +}
 +
 +static int dsp_uncfg(void)
 +{
 +      if (dsp_taskmod_busy()) {
 +              printk(KERN_WARNING "omapdsp: tasks are busy.\n");
 +              return -EBUSY;
 +      }
 +
 +      /* FIXME: lock task module */
 +
 +      /* remove runtime sysfs entries */
 +      device_remove_file(omap_dsp->dev, &dev_attr_loadinfo);
 +
 +      dsp_mbox_stop();
 +      dsp_twch_stop();
 +      dsp_mem_stop();
 +      dsp_err_stop();
 +      dsp_dbg_stop();
 +      dsp_task_unconfig_all();
 +      ipbuf_stop();
 +
 +      return 0;
 +}
 +
 +static int dsp_suspend(void)
 +{
 +      int ret;
 +
 +      ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
 +      if (ret < 0) {
 +              if (ret != -EINVAL)
 +                      printk(KERN_ERR "omapdsp: DSP suspend error!\n");
 +              return ret;
 +      }
 +
 +      udelay(100);    /* wait for DSP-side execution */
 +      return 0;
 +}
 +
 +int dsp_cfgstat_request(enum cfgstat_e st_req)
 +{
 +      static DEFINE_MUTEX(cfgstat_lock);
 +      int ret = 0, ret_override = 0;
 +
 +      if (mutex_lock_interruptible(&cfgstat_lock))
 +              return -EINTR;
 +
 +again:
 +      switch (st_req) {
 +
 +      /* cfgstat takes CLEAN, READY or SUSPEND,
 +         while st_req can take SUSPEND in addition. */
 +
 +      case CFGSTAT_CLEAN:
 +              if (cfgstat == CFGSTAT_CLEAN)
 +                      goto up_out;
 +              if ((ret = dsp_uncfg()) < 0)
 +                      goto up_out;
 +              break;
 +
 +      case CFGSTAT_READY:
 +              if (cfgstat != CFGSTAT_CLEAN) {
 +                      printk(KERN_ERR "omapdsp: DSP is ready already!\n");
 +                      ret = -EINVAL;
 +                      goto up_out;
 +              }
 +
 +              ret = dsp_cfg();
 +              if (ret > 0) {  /* failed, but state is clear. */
 +                      ret = -EINVAL;
 +                      goto up_out;
 +              } else if (ret < 0) {   /* failed, need cleanup. */
 +                      st_req = CFGSTAT_CLEAN;
 +                      ret_override = ret;
 +                      goto again;
 +              }
 +              break;
 +
 +      /*
 +       * suspend / resume
 +       * DSP is not reset within this code, but done in omap_pm_suspend.
 +       * so if these functions are called from sysfs,
 +       * DSP should be reset / unreset out of these functions.
 +       */
 +      case CFGSTAT_SUSPEND:
 +              switch (cfgstat) {
 +
 +              case CFGSTAT_CLEAN:
 +                      if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
 +                              printk(KERN_WARNING
 +                                     "omapdsp: illegal operation -- trying "
 +                                     "suspend DSP while it is running but "
 +                                     "not configured.\n"
 +                                     "  Resetting DSP.\n");
 +                              dsp_cpustat_request(CPUSTAT_RESET);
 +                              ret = -EINVAL;
 +                      }
 +                      goto up_out;
 +
 +              case CFGSTAT_READY:
 +                      if ((ret = dsp_suspend()) < 0)
 +                              goto up_out;
 +                      break;
 +
 +              case CFGSTAT_SUSPEND:
 +                      goto up_out;
 +
 +              default:
 +                      BUG();
 +
 +              }
 +
 +              break;
 +
 +      case CFGSTAT_RESUME:
 +              if (cfgstat != CFGSTAT_SUSPEND) {
 +                      printk(KERN_WARNING
 +                             "omapdsp: DSP resume request, but DSP is not in "
 +                             "suspend state.\n");
 +                      ret = -EINVAL;
 +                      goto up_out;
 +              }
 +              st_req = CFGSTAT_READY;
 +              break;
 +
 +      default:
 +              BUG();
 +
 +      }
 +
 +      cfgstat = st_req;
 +up_out:
 +      mutex_unlock(&cfgstat_lock);
 +      return ret_override ? ret_override : ret;
 +}
 +
 +enum cfgstat_e dsp_cfgstat_get_stat(void)
 +{
 +      return cfgstat;
 +}
 +
 +/*
 + * polls all tasks
 + */
 +static int dsp_poll(void)
 +{
 +      int ret;
 +
 +      ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
 +      if ((ret < 0) && (ret != -EINTR))
 +              printk(KERN_ERR "omapdsp: poll error!\n");
 +
 +      return ret;
 +}
 +
 +int dsp_set_runlevel(u8 level)
 +{
 +      if (level == RUNLEVEL_RECOVERY) {
 +              if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
 +                      return -EINVAL;
 +      } else {
 +              if ((level < RUNLEVEL_USER) ||
 +                  (level > RUNLEVEL_SUPER))
 +                      return -EINVAL;
 +              if (mbcompose_send(RUNLEVEL, level, 0) < 0)
 +                      return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +static void dsp_fbctl_enable(void)
 +{
 +      mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
 +}
 +
 +static int dsp_fbctl_disable(void)
 +{
 +      int ret;
 +
 +      ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
 +                                         NULL);
 +      if ((ret < 0) && (ret != -EINTR))
 +              printk(KERN_ERR "omapdsp: fb disable error!\n");
 +
 +      return 0;
 +}
 +
 +static int dsp_fbstat_request(enum fbstat_e st)
 +{
 +      static DEFINE_MUTEX(fbstat_lock);
 +      int ret = 0;
 +
 +      if (mutex_lock_interruptible(&fbstat_lock))
 +              return -EINTR;
 +
 +      if (st == fbstat)
 +              goto up_out;
 +
 +      switch (st) {
 +      case FBSTAT_ENABLED:
 +              dsp_fbctl_enable();
 +              break;
 +      case FBSTAT_DISABLED:
 +              if ((ret = dsp_fbctl_disable()) < 0)
 +                      goto up_out;
 +              break;
 +      default:
 +              BUG();
 +      }
 +
 +      fbstat = st;
 +up_out:
 +      mutex_unlock(&fbstat_lock);
 +      return 0;
 +}
 +#endif /* CONFIG_OMAP_DSP_FBEXPORT */
 +
 +/*
 + * DSP control device file operations
 + */
 +static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
 +                       unsigned int cmd, unsigned long arg)
 +{
 +      int ret = 0;
 +
 +      switch (cmd) {
 +      /*
 +       * command level 1: commands which don't need lock
 +       */
 +      case DSPCTL_IOCTL_RUN:
 +              dsp_cpustat_request(CPUSTAT_RUN);
 +              break;
 +
 +      case DSPCTL_IOCTL_RESET:
 +              dsp_cpustat_request(CPUSTAT_RESET);
 +              break;
 +
 +      case DSPCTL_IOCTL_SETRSTVECT:
 +              ret = dsp_set_rstvect((dsp_long_t)arg);
 +              break;
 +
 +#ifdef CONFIG_ARCH_OMAP1
 +      case DSPCTL_IOCTL_CPU_IDLE:
 +              dsp_cpustat_request(CPUSTAT_CPU_IDLE);
 +              break;
 +
 +      case DSPCTL_IOCTL_GBL_IDLE:
 +              dsp_cpustat_request(CPUSTAT_GBL_IDLE);
 +              break;
 +
 +      case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
 +              mpui_wordswap_on();
 +              break;
 +
 +      case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
 +              mpui_wordswap_off();
 +              break;
 +
 +      case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
 +              mpui_byteswap_on();
 +              break;
 +
 +      case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
 +              mpui_byteswap_off();
 +              break;
 +#endif /* CONFIG_ARCH_OMAP1 */
 +
 +      case DSPCTL_IOCTL_TASKCNT:
 +              ret = dsp_task_count();
 +              break;
 +
 +      case DSPCTL_IOCTL_MBSEND:
 +              {
 +                      struct omap_dsp_mailbox_cmd u_cmd;
 +                      mbox_msg_t msg;
 +                      if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
 +                              return -EFAULT;
 +                      msg = (u_cmd.cmd << 16) | u_cmd.data;
 +                      ret = dsp_mbcmd_send((struct mbcmd *)&msg);
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_SETVAR:
 +              {
 +                      struct omap_dsp_varinfo var;
 +                      if (copy_from_user(&var, (void *)arg, sizeof(var)))
 +                              return -EFAULT;
 +                      ret = dsp_setvar(var.varid, var.val[0]);
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_RUNLEVEL:
 +              ret = dsp_set_runlevel(arg);
 +              break;
 +
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +      case DSPCTL_IOCTL_FBEN:
 +              ret = dsp_fbstat_request(FBSTAT_ENABLED);
 +              break;
 +#endif
 +
 +      /*
 +       * command level 2: commands which need lock
 +       */
 +      case DSPCTL_IOCTL_DSPCFG:
 +              ret = dsp_cfgstat_request(CFGSTAT_READY);
 +              break;
 +
 +      case DSPCTL_IOCTL_DSPUNCFG:
 +              ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
 +              break;
 +
 +      case DSPCTL_IOCTL_POLL:
 +              ret = dsp_poll();
 +              break;
 +
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +      case DSPCTL_IOCTL_FBDIS:
 +              ret = dsp_fbstat_request(FBSTAT_DISABLED);
 +              break;
 +#endif
 +
 +      case DSPCTL_IOCTL_SUSPEND:
 +              if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
 +                      break;
 +              dsp_cpustat_request(CPUSTAT_RESET);
 +              break;
 +
 +      case DSPCTL_IOCTL_RESUME:
 +              if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
 +                      break;
 +              dsp_cpustat_request(CPUSTAT_RUN);
 +              break;
 +
 +      case DSPCTL_IOCTL_REGMEMR:
 +              {
 +                      struct omap_dsp_reginfo *u_reg = (void *)arg;
 +                      u16 adr, val;
 +
 +                      if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
 +                              return -EFAULT;
 +                      if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
 +                              return ret;
 +                      if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
 +                              return -EFAULT;
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_REGMEMW:
 +              {
 +                      struct omap_dsp_reginfo reg;
 +
 +                      if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
 +                              return -EFAULT;
 +                      ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_REGIOR:
 +              {
 +                      struct omap_dsp_reginfo *u_reg = (void *)arg;
 +                      u16 adr, val;
 +
 +                      if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
 +                              return -EFAULT;
 +                      if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
 +                              return ret;
 +                      if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
 +                              return -EFAULT;
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_REGIOW:
 +              {
 +                      struct omap_dsp_reginfo reg;
 +
 +                      if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
 +                              return -EFAULT;
 +                      ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
 +                      break;
 +              }
 +
 +      case DSPCTL_IOCTL_GETVAR:
 +              {
 +                      struct omap_dsp_varinfo *u_var = (void *)arg;
 +                      u8 varid;
 +                      u16 val[5]; /* maximum */
 +                      int argc;
 +
 +                      if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
 +                              return -EFAULT;
 +                      switch (varid) {
 +                      case VARID_ICRMASK:
 +                              argc = 1;
 +                              break;
 +                      case VARID_LOADINFO:
 +                              argc = 5;
 +                              break;
 +                      default:
 +                              return -EINVAL;
 +                      }
 +                      if ((ret = dsp_getvar(varid, val)) < 0)
 +                              return ret;
 +                      if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
 +                              return -EFAULT;
 +                      break;
 +              }
 +
 +      default:
 +              return -ENOIOCTLCMD;
 +      }
 +
 +      return ret;
 +}
 +
 +/*
 + * functions called from mailbox interrupt routine
 + */
 +void mbox_suspend(struct mbcmd *mb)
 +{
 +      misc_mbcmd_response(mb, 0, 0);
 +}
 +
 +void mbox_dspcfg(struct mbcmd *mb)
 +{
 +      u8 last   = mb->cmd_l & 0x80;
 +      u8 cfgcmd = mb->cmd_l & 0x7f;
 +      static dsp_long_t tmp_ipb_adr;
 +
 +      if (!waitqueue_active(&misc_mb_wait.wait_q) ||
 +          (misc_mb_wait.cmd_h != MBOX_CMD_DSP_DSPCFG)) {
 +              printk(KERN_WARNING
 +                     "mbox: DSPCFG command received, "
 +                     "but nobody is waiting for it...\n");
 +              return;
 +      }
 +
 +      /* mailbox protocol check */
 +      if (cfgcmd == DSPCFG_PROTREV) {
 +              mbox_revision = mb->data;
 +              if (mbox_revision == MBPROT_REVISION)
 +                      return;
 +#ifdef OLD_BINARY_SUPPORT
 +              else if ((mbox_revision == MBREV_3_0) ||
 +                       (mbox_revision == MBREV_3_2)) {
 +                      printk(KERN_WARNING
 +                             "mbox: ***** old DSP binary *****\n"
 +                             "  Please update your DSP application.\n");
 +                      return;
 +              }
 +#endif
 +              else {
 +                      printk(KERN_ERR
 +                             "mbox: protocol revision check error!\n"
 +                             "  expected=0x%04x, received=0x%04x\n",
 +                             MBPROT_REVISION, mb->data);
 +                      mbox_revision = -1;
 +                      goto abort1;
 +              }
 +      }
 +
 +      /*
 +       * following commands are accepted only after
 +       * revision check has been passed.
 +       */
 +      if (!mbox_revision < 0) {
 +              pr_info("mbox: DSPCFG command received, "
 +                      "but revision check has not been passed.\n");
 +              return;
 +      }
 +
 +      switch (cfgcmd) {
 +      case DSPCFG_SYSADRH:
 +              tmp_ipb_adr = (u32)mb->data << 16;
 +              break;
 +
 +      case DSPCFG_SYSADRL:
 +              tmp_ipb_adr |= mb->data;
 +              break;
 +
 +      case DSPCFG_ABORT:
 +              goto abort1;
 +
 +      default:
 +              printk(KERN_ERR
 +                     "mbox: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n",
 +                     mb->cmd_l, mb->data);
 +              return;
 +      }
 +
 +      if (last) {
 +              void *badr;
 +              u16 bln;
 +              u16 bsz;
 +              volatile u16 *buf;
 +              void *ipb_sys_da, *ipb_sys_ad;
 +              void *mbseq;     /* FIXME: 3.4 obsolete */
 +              short *dbg_buf;
 +              u16 dbg_buf_sz, dbg_line_sz;
 +              struct mem_sync_struct mem_sync, *mem_syncp;
 +
 +              ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
 +              if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
 +                      goto abort1;
 +
 +              if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +                      printk(KERN_ERR "mbox: DSPCFG - ipbuf_sys_da read failed!\n");
 +                      goto abort1;
 +              }
 +              if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
 +                      printk(KERN_ERR "mbox: DSPCFG - IPBUF sync failed!\n");
 +                      dsp_mem_disable(ipbuf_sys_da);
 +                      goto abort1;
 +              }
 +              /*
 +               * read configuration data on system IPBUF
 +               * we must read with 16bit-access
 +               */
 +#ifdef OLD_BINARY_SUPPORT
 +              if (mbox_revision == MBPROT_REVISION) {
 +#endif
 +                      buf = ipbuf_sys_da->d;
 +                      n_stask        = buf[0];
 +                      bln            = buf[1];
 +                      bsz            = buf[2];
 +                      badr           = MKVIRT(buf[3], buf[4]);
 +                      /* ipb_sys_da     = MKVIRT(buf[5], buf[6]); */
 +                      ipb_sys_ad     = MKVIRT(buf[7], buf[8]);
 +                      mbseq          = MKVIRT(buf[9], buf[10]);
 +                      dbg_buf        = MKVIRT(buf[11], buf[12]);
 +                      dbg_buf_sz     = buf[13];
 +                      dbg_line_sz    = buf[14];
 +                      mem_sync.DARAM = MKVIRT(buf[15], buf[16]);
 +                      mem_sync.SARAM = MKVIRT(buf[17], buf[18]);
 +                      mem_sync.SDRAM = MKVIRT(buf[19], buf[20]);
 +                      mem_syncp = &mem_sync;
 +#ifdef OLD_BINARY_SUPPORT
 +              } else if (mbox_revision == MBREV_3_2) {
 +                      buf = ipbuf_sys_da->d;
 +                      n_stask     = buf[0];
 +                      bln         = buf[1];
 +                      bsz         = buf[2];
 +                      badr        = MKVIRT(buf[3], buf[4]);
 +                      /* ipb_sys_da  = MKVIRT(buf[5], buf[6]); */
 +                      ipb_sys_ad  = MKVIRT(buf[7], buf[8]);
 +                      mbseq       = MKVIRT(buf[9], buf[10]);
 +                      dbg_buf     = NULL;
 +                      dbg_buf_sz  = 0;
 +                      dbg_line_sz = 0;
 +                      mem_syncp   = NULL;
 +              } else if (mbox_revision == MBREV_3_0) {
 +                      buf = ipbuf_sys_da->d;
 +                      n_stask     = buf[0];
 +                      bln         = buf[1];
 +                      bsz         = buf[2];
 +                      badr        = MKVIRT(buf[3], buf[4]);
 +                      /* bkeep       = buf[5]; */
 +                      /* ipb_sys_da  = MKVIRT(buf[6], buf[7]); */
 +                      ipb_sys_ad  = MKVIRT(buf[8], buf[9]);
 +                      mbseq       = MKVIRT(buf[10], buf[11]);
 +                      dbg_buf     = NULL;
 +                      dbg_buf_sz  = 0;
 +                      dbg_line_sz = 0;
 +                      mem_syncp   = NULL;
 +              } else { /* should not occur */
 +                      dsp_mem_disable(ipbuf_sys_da);
 +                      goto abort1;
 +              }
 +#endif /* OLD_BINARY_SUPPORT */
 +
 +              release_ipbuf_pvt(ipbuf_sys_da);
 +              dsp_mem_disable(ipbuf_sys_da);
 +
 +              /*
 +               * following configurations need to be done before
 +               * waking up the dspcfg initiator process.
 +               */
 +              if (ipbuf_sys_config(ipb_sys_ad, DIR_A2D) < 0)
 +                      goto abort1;
 +              if (ipbuf_config(bln, bsz, badr) < 0)
 +                      goto abort1;
 +              if (dsp_mbox_config(mbseq) < 0)
 +                      goto abort2;
 +              if (dsp_dbg_config(dbg_buf, dbg_buf_sz, dbg_line_sz) < 0)
 +                      goto abort2;
 +              if (dsp_mem_sync_config(mem_syncp) < 0)
 +                      goto abort2;
 +
 +              misc_mb_wait.cmd_h = 0;
 +              wake_up_interruptible(&misc_mb_wait.wait_q);
 +      }
 +      return;
 +
 +abort2:
 +      ipbuf_stop();
 +abort1:
 +      wake_up_interruptible(&misc_mb_wait.wait_q);
 +      return;
 +}
 +
 +void mbox_poll(struct mbcmd *mb)
 +{
 +      misc_mbcmd_response(mb, 0, 0);
 +}
 +
 +void mbox_regrw(struct mbcmd *mb)
 +{
 +      switch (mb->cmd_l) {
 +      case REGRW_DATA:
 +              misc_mbcmd_response(mb, 1, 0);
 +              break;
 +      default:
 +              printk(KERN_ERR
 +                     "mbox: Illegal REGRW command: "
 +                     "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
 +              return;
 +      }
 +}
 +
 +void mbox_getvar(struct mbcmd *mb)
 +{
 +      switch (mb->cmd_l) {
 +      case VARID_ICRMASK:
 +              misc_mbcmd_response(mb, 1, 1);
 +              break;
 +      case VARID_LOADINFO:
 +              misc_mbcmd_response(mb, 5, 1);
 +              break;
 +      default:
 +              printk(KERN_ERR
 +                     "mbox: Illegal GETVAR command: "
 +                     "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
 +              return;
 +      }
 +}
 +
 +void mbox_fbctl_disable(struct mbcmd *mb)
 +{
 +      misc_mbcmd_response(mb, 0, 0);
 +}
 +
 +struct file_operations dsp_ctl_fops = {
 +      .owner   = THIS_MODULE,
 +      .ioctl   = dsp_ctl_ioctl,
 +};
 +
 +/*
 + * sysfs files
 + */
 +
 +/* ifver */
 +static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf)
 +{
 +      int len = 0;
 +
 +      /*
 +       * I/F VERSION descriptions:
 +       *
 +       * 3.2: sysfs / udev support
 +       *      KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
 +       * 3.3: added following ioctls
 +       *      DSPCTL_IOCTL_GBL_IDLE
 +       *      DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
 +       *      DSPCTL_IOCTL_POLL
 +       */
 +
 +      /*
 +       * print all supporting I/F VERSIONs, like followings.
 +       *
 +       * len += sprintf(buf, "3.2\n");
 +       * len += sprintf(buf, "3.3\n");
 +       */
 +      len += sprintf(buf + len, "3.2\n");
 +      len += sprintf(buf + len, "3.3\n");
 +
 +      return len;
 +}
 +
 +/* cpustat */
 +static char *cpustat_name[CPUSTAT_MAX] = {
 +      [CPUSTAT_RESET]    = "reset",
 +#ifdef CONFIG_ARCH_OMAP1
 +      [CPUSTAT_GBL_IDLE] = "gbl_idle",
 +      [CPUSTAT_CPU_IDLE] = "cpu_idle",
 +#endif
 +      [CPUSTAT_RUN]      = "run",
 +};
 +
 +static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
 +}
 +
 +/* icrmask */
 +static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      return sprintf(buf, "0x%04x\n", dsp_cpustat_get_icrmask());
 +}
 +
 +static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
 +                           const char *buf, size_t count)
 +{
 +      u16 mask;
 +      int ret;
 +
 +      mask = simple_strtol(buf, NULL, 16);
 +      dsp_cpustat_set_icrmask(mask);
 +
 +      if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
 +              ret = dsp_setvar(VARID_ICRMASK, mask);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
 +      return count;
 +}
 +
 +/* loadinfo */
 +static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      int len;
 +      int ret;
 +      u16 val[5];
 +
 +      if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
 +              return ret;
 +
 +      /*
 +       * load info value range is 0(free) - 10000(busy):
 +       * if CPU load is not measured on DSP, it sets 0xffff at val[0].
 +       */
 +
 +      if (val[0] == 0xffff) {
 +              len = sprintf(buf,
 +                            "currently DSP load info is not available.\n");
 +              goto out;
 +      }
 +
 +      len = sprintf(buf,
 +                    "DSP load info:\n"
 +                    "  10ms average = %3d.%02d%%\n"
 +                    "  1sec average = %3d.%02d%%  busiest 10ms = %3d.%02d%%\n"
 +                    "  1min average = %3d.%02d%%  busiest 1s   = %3d.%02d%%\n",
 +                    val[0]/100, val[0]%100,
 +                    val[1]/100, val[1]%100, val[2]/100, val[2]%100,
 +                    val[3]/100, val[3]%100, val[4]/100, val[4]%100);
 +out:
 +      return len;
 +}
 +
 +int __init dsp_ctl_init(void)
 +{
 +      int ret;
 +
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_ifver);
 +      if (unlikely(ret))
 +              return ret;
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_cpustat);
 +      if (unlikely(ret))
 +              goto fail_create_cpustat;
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_icrmask);
 +      if (unlikely(ret))
 +              goto fail_create_icrmask;
 +
 +      return 0;
 +
 +fail_create_icrmask:
 +      device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
 +fail_create_cpustat:
 +      device_remove_file(omap_dsp->dev, &dev_attr_ifver);
 +
 +      return ret;
 +}
 +
 +void dsp_ctl_exit(void)
 +{
 +      device_remove_file(omap_dsp->dev, &dev_attr_ifver);
 +      device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
 +      device_remove_file(omap_dsp->dev, &dev_attr_icrmask);
 +}
index 6d3148ff142f85bc75b6a653dcbb6b81ba5dec6f,0000000000000000000000000000000000000000..e21bd069619038b40b109edf4288d4578e0f6952
mode 100644,000000..100644
--- /dev/null
@@@ -1,484 -1,0 +1,484 @@@
- #include <asm/arch/tc.h>
- #include <asm/arch/omapfb.h>
- #include <asm/arch/dsp.h>
- #include <asm/arch/mailbox.h>
- #include <asm/arch/mmu.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * Conversion to mempool API and ARM MMU section mapping
 + * by Paul Mundt <paul.mundt@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/fs.h>
 +#include <linux/fb.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/mempool.h>
 +#include <linux/clk.h>
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
 +#include <asm/irq.h>
 +#include <asm/pgalloc.h>
 +#include <asm/pgtable.h>
++#include <mach/tc.h>
++#include <mach/omapfb.h>
++#include <mach/dsp.h>
++#include <mach/mailbox.h>
++#include <mach/mmu.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +
 +#if 0
 +#if defined(CONFIG_ARCH_OMAP1)
 +#include "../../mach-omap1/mmu.h"
 +#elif defined(CONFIG_ARCH_OMAP2)
 +#include "../../mach-omap2/mmu.h"
 +#endif
 +#endif
 +
 +#include "mmu.h"
 +
 +static struct mem_sync_struct mem_sync;
 +
 +int dsp_mem_sync_inc(void)
 +{
 +      if (dsp_mem_enable((void *)dspmem_base) < 0)
 +              return -1;
 +      if (mem_sync.DARAM)
 +              mem_sync.DARAM->ad_arm++;
 +      if (mem_sync.SARAM)
 +              mem_sync.SARAM->ad_arm++;
 +      if (mem_sync.SDRAM)
 +              mem_sync.SDRAM->ad_arm++;
 +      dsp_mem_disable((void *)dspmem_base);
 +
 +      return 0;
 +}
 +
 +/*
 + * dsp_mem_sync_config() is called from mbox1 workqueue
 + */
 +int dsp_mem_sync_config(struct mem_sync_struct *sync)
 +{
 +      size_t sync_seq_sz = sizeof(struct sync_seq);
 +
 +#ifdef OLD_BINARY_SUPPORT
 +      if (sync == NULL) {
 +              memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
 +              return 0;
 +      }
 +#endif
 +      if ((dsp_mem_type(sync->DARAM, sync_seq_sz) != MEM_TYPE_DARAM) ||
 +          (dsp_mem_type(sync->SARAM, sync_seq_sz) != MEM_TYPE_SARAM) ||
 +          (dsp_mem_type(sync->SDRAM, sync_seq_sz) != MEM_TYPE_EXTERN)) {
 +              printk(KERN_ERR
 +                     "omapdsp: mem_sync address validation failure!\n"
 +                     "  mem_sync.DARAM = 0x%p,\n"
 +                     "  mem_sync.SARAM = 0x%p,\n"
 +                     "  mem_sync.SDRAM = 0x%p,\n",
 +                     sync->DARAM, sync->SARAM, sync->SDRAM);
 +              return -1;
 +      }
 +
 +      memcpy(&mem_sync, sync, sizeof(struct mem_sync_struct));
 +
 +      return 0;
 +}
 +
 +
 +enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len)
 +{
 +      void *ds = (void *)daram_base;
 +      void *de = (void *)daram_base + daram_size;
 +      void *ss = (void *)saram_base;
 +      void *se = (void *)saram_base + saram_size;
 +      int ret;
 +
 +      if ((vadr >= ds) && (vadr < de)) {
 +              if (vadr + len > de)
 +                      return MEM_TYPE_CROSSING;
 +              else
 +                      return MEM_TYPE_DARAM;
 +      } else if ((vadr >= ss) && (vadr < se)) {
 +              if (vadr + len > se)
 +                      return MEM_TYPE_CROSSING;
 +              else
 +                      return MEM_TYPE_SARAM;
 +      } else {
 +              down_read(&dsp_mmu.exmap_sem);
 +              if (exmap_valid(&dsp_mmu, vadr, len))
 +                      ret = MEM_TYPE_EXTERN;
 +              else
 +                      ret = MEM_TYPE_NONE;
 +              up_read(&dsp_mmu.exmap_sem);
 +              return ret;
 +      }
 +}
 +
 +int dsp_address_validate(void *p, size_t len, char *fmt, ...)
 +{
 +      char s[64];
 +      va_list args;
 +
 +      if (dsp_mem_type(p, len) > 0)
 +              return 0;
 +
 +      if (fmt == NULL)
 +              goto out;
 +
 +      va_start(args, fmt);
 +      vsprintf(s, fmt, args);
 +      va_end(args);
 +      printk(KERN_ERR
 +             "omapdsp: %s address(0x%p) and size(0x%x) is not valid!\n"
 +             "(crossing different type of memories, or external memory\n"
 +             "space where no actual memory is mapped)\n", s, p, len);
 + out:
 +      return -1;
 +}
 +
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +
 +static inline unsigned long lineup_offset(unsigned long adr,
 +                                        unsigned long ref,
 +                                        unsigned long mask)
 +{
 +      unsigned long newadr;
 +
 +      newadr = (adr & ~mask) | (ref & mask);
 +      if (newadr < adr)
 +              newadr += mask + 1;
 +      return newadr;
 +}
 +
 +/*
 + * fb update functions:
 + * fbupd_response() is executed by the workqueue.
 + * fbupd_cb() is called when fb update is done, in interrupt context.
 + * mbox_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
 + */
 +static void fbupd_response(struct work_struct *unused)
 +{
 +      int status;
 +
 +      status = mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_UPD);
 +      if (status == 0)
 +              return;
 +
 +      /* FIXME: DSP is busy !! */
 +      printk(KERN_ERR
 +             "omapdsp:"
 +             "DSP is busy when trying to send FBCTL:UPD response!\n");
 +}
 +
 +static DECLARE_WORK(fbupd_response_work, fbupd_response);
 +
 +static void fbupd_cb(void *arg)
 +{
 +      schedule_work(&fbupd_response_work);
 +}
 +
 +void mbox_fbctl_upd(void)
 +{
 +      struct omapfb_update_window win;
 +      volatile unsigned short *buf = ipbuf_sys_da->d;
 +
 +      if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 5000) < 0) {
 +              printk(KERN_ERR "mbox: FBCTL:UPD - IPBUF sync failed!\n");
 +              return;
 +      }
 +      win.x = buf[0];
 +      win.y = buf[1];
 +      win.width = buf[2];
 +      win.height = buf[3];
 +      win.format = buf[4];
 +      release_ipbuf_pvt(ipbuf_sys_da);
 +
 +#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 +      if (!omapfb_ready) {
 +              printk(KERN_WARNING
 +                     "omapdsp: fbupd() called while HWA742 is not ready!\n");
 +              return;
 +      }
 +#endif
 +      omapfb_update_window_async(registered_fb[0], &win, fbupd_cb, NULL);
 +}
 +
 +#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 +static int omapfb_notifier_cb(struct notifier_block *omapfb_nb,
 +                            unsigned long event, void *fbi)
 +{
 +      pr_info("omapfb_notifier_cb(): event = %s\n",
 +              (event == OMAPFB_EVENT_READY)    ? "READY" :
 +              (event == OMAPFB_EVENT_DISABLED) ? "DISABLED" : "Unknown");
 +      if (event == OMAPFB_EVENT_READY)
 +              omapfb_ready = 1;
 +      else if (event == OMAPFB_EVENT_DISABLED)
 +              omapfb_ready = 0;
 +      return 0;
 +}
 +#endif
 +
 +static int dsp_fbexport(dsp_long_t *dspadr)
 +{
 +      dsp_long_t dspadr_actual;
 +      unsigned long padr_sys, padr, fbsz_sys, fbsz;
 +      int cnt;
 +#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 +      int status;
 +#endif
 +
 +      pr_debug( "omapdsp: frame buffer export\n");
 +
 +#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 +      if (omapfb_nb) {
 +              printk(KERN_WARNING
 +                     "omapdsp: frame buffer has been exported already!\n");
 +              return -EBUSY;
 +      }
 +#endif
 +
 +      if (num_registered_fb == 0) {
 +              pr_info("omapdsp: frame buffer not registered.\n");
 +              return -EINVAL;
 +      }
 +      if (num_registered_fb != 1) {
 +              pr_info("omapdsp: %d frame buffers found. we use first one.\n",
 +                      num_registered_fb);
 +      }
 +      padr_sys = registered_fb[0]->fix.smem_start;
 +      fbsz_sys = registered_fb[0]->fix.smem_len;
 +      if (fbsz_sys == 0) {
 +              printk(KERN_ERR
 +                     "omapdsp: framebuffer doesn't seem to be configured "
 +                     "correctly! (size=0)\n");
 +              return -EINVAL;
 +      }
 +
 +      /*
 +       * align padr and fbsz to 4kB boundary
 +       * (should be noted to the user afterwards!)
 +       */
 +      padr = padr_sys & ~(SZ_4K-1);
 +      fbsz = (fbsz_sys + padr_sys - padr + SZ_4K-1) & ~(SZ_4K-1);
 +
 +      /* line up dspadr offset with padr */
 +      dspadr_actual =
 +              (fbsz > SZ_1M) ?  lineup_offset(*dspadr, padr, SZ_1M-1) :
 +              (fbsz > SZ_64K) ? lineup_offset(*dspadr, padr, SZ_64K-1) :
 +              /* (fbsz > SZ_4KB) ? */ *dspadr;
 +      if (dspadr_actual != *dspadr)
 +              pr_debug(
 +                      "omapdsp: actual dspadr for FBEXPORT = %08x\n",
 +                      dspadr_actual);
 +      *dspadr = dspadr_actual;
 +
 +      cnt = omap_mmu_exmap(&dsp_mmu, dspadr_actual, padr, fbsz,
 +                           EXMAP_TYPE_FB);
 +      if (cnt < 0) {
 +              printk(KERN_ERR "omapdsp: exmap failure.\n");
 +              return cnt;
 +      }
 +
 +      if ((padr != padr_sys) || (fbsz != fbsz_sys)) {
 +              printk(KERN_WARNING
 +"  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
 +"  !!  screen base address or size is not aligned in 4kB:           !!\n"
 +"  !!    actual screen  adr = %08lx, size = %08lx                   !!\n"
 +"  !!    exporting      adr = %08lx, size = %08lx                   !!\n"
 +"  !!  Make sure that the framebuffer is allocated with 4kB-order!  !!\n"
 +"  !!  Otherwise DSP can corrupt the kernel memory.                 !!\n"
 +"  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
 +                     padr_sys, fbsz_sys, padr, fbsz);
 +      }
 +
 +      /* increase the DMA priority */
 +      set_emiff_dma_prio(15);
 +
 +#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 +      omapfb_nb = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
 +      if (omapfb_nb == NULL) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to allocate memory for omapfb_nb!\n");
 +              omap_mmu_exunmap(&dsp_mmu, (unsigned long)dspadr);
 +              return -ENOMEM;
 +      }
 +
 +      status = omapfb_register_client(omapfb_nb, omapfb_notifier_cb, NULL);
 +      if (status)
 +              pr_info("omapfb_register_client(): failure(%d)\n", status);
 +#endif
 +
 +      return cnt;
 +}
 +#else
 +void mbox_fbctl_upd(void) { }
 +#endif
 +
 +/* dsp/mem fops: backward compatibility */
 +static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
 +                          loff_t *ppos)
 +{
 +      struct bin_attribute attr;
 +
 +      return __omap_mmu_mem_read(&dsp_mmu, &attr,
 +                                 (char __user *)buf, *ppos, count);
 +}
 +
 +static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
 +                           size_t count, loff_t *ppos)
 +{
 +      struct bin_attribute attr;
 +
 +      return __omap_mmu_mem_write(&dsp_mmu, &attr,
 +                                  (char __user *)buf, *ppos, count);
 +}
 +
 +static int dsp_mem_ioctl(struct inode *inode, struct file *file,
 +                       unsigned int cmd, unsigned long arg)
 +{
 +      struct omap_dsp_mapinfo mapinfo;
 +      __u32 size;
 +
 +      switch (cmd) {
 +      case MEM_IOCTL_MMUINIT:
 +              if (dsp_mmu.exmap_tbl)
 +                      omap_mmu_unregister(&dsp_mmu);
 +              dsp_mem_ipi_init();
 +              return omap_mmu_register(&dsp_mmu);
 +
 +      case MEM_IOCTL_EXMAP:
 +              if (copy_from_user(&mapinfo, (void __user *)arg,
 +                                 sizeof(mapinfo)))
 +                      return -EFAULT;
 +              return omap_mmu_exmap(&dsp_mmu, mapinfo.dspadr,
 +                                    0, mapinfo.size, EXMAP_TYPE_MEM);
 +
 +      case MEM_IOCTL_EXUNMAP:
 +              return omap_mmu_exunmap(&dsp_mmu, (unsigned long)arg);
 +
 +      case MEM_IOCTL_EXMAP_FLUSH:
 +              omap_mmu_exmap_flush(&dsp_mmu);
 +              return 0;
 +#ifdef CONFIG_OMAP_DSP_FBEXPORT
 +      case MEM_IOCTL_FBEXPORT:
 +      {
 +              dsp_long_t dspadr;
 +              int ret;
 +              if (copy_from_user(&dspadr, (void __user *)arg,
 +                                 sizeof(dsp_long_t)))
 +                      return -EFAULT;
 +              ret = dsp_fbexport(&dspadr);
 +              if (copy_to_user((void __user *)arg, &dspadr,
 +                               sizeof(dsp_long_t)))
 +                      return -EFAULT;
 +              return ret;
 +      }
 +#endif
 +      case MEM_IOCTL_MMUITACK:
 +              return dsp_mmu_itack();
 +
 +      case MEM_IOCTL_KMEM_RESERVE:
 +
 +              if (copy_from_user(&size, (void __user *)arg,
 +                                 sizeof(__u32)))
 +                      return -EFAULT;
 +              return omap_mmu_kmem_reserve(&dsp_mmu, size);
 +
 +
 +      case MEM_IOCTL_KMEM_RELEASE:
 +              omap_mmu_kmem_release();
 +              return 0;
 +
 +      default:
 +              return -ENOIOCTLCMD;
 +      }
 +}
 +
 +struct file_operations dsp_mem_fops = {
 +      .owner   = THIS_MODULE,
 +      .read    = dsp_mem_read,
 +      .write   = dsp_mem_write,
 +      .ioctl   = dsp_mem_ioctl,
 +};
 +
 +void dsp_mem_start(void)
 +{
 +      dsp_register_mem_cb(intmem_enable, intmem_disable);
 +}
 +
 +void dsp_mem_stop(void)
 +{
 +      memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
 +      dsp_unregister_mem_cb();
 +}
 +
 +static void dsp_mmu_irq_work(struct work_struct *work)
 +{
 +      struct omap_mmu *mmu = container_of(work, struct omap_mmu, irq_work);
 +
 +      if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
 +              dsp_err_set(ERRCODE_MMU, mmu->fault_address);
 +              return;
 +      }
 +      omap_mmu_itack(mmu);
 +      pr_info("Resetting DSP...\n");
 +      dsp_cpustat_request(CPUSTAT_RESET);
 +      omap_mmu_enable(mmu, 0);
 +}
 +
 +/*
 + * later half of dsp memory initialization
 + */
 +int dsp_mem_late_init(void)
 +{
 +      int ret;
 +
 +      dsp_mem_ipi_init();
 +
 +      INIT_WORK(&dsp_mmu.irq_work, dsp_mmu_irq_work);
 +      ret = omap_mmu_register(&dsp_mmu);
 +      if (ret) {
 +              dsp_reset_idle_boot_base();
 +              goto out;
 +      }
 +      omap_dsp->mmu = &dsp_mmu;
 + out:
 +      return ret;
 +}
 +
 +int __init dsp_mem_init(void)
 +{
 +#ifdef CONFIG_ARCH_OMAP2
 +      dsp_mmu.clk    = dsp_fck_handle;
 +      dsp_mmu.memclk = dsp_ick_handle;
 +#elif defined(CONFIG_ARCH_OMAP1)
 +      dsp_mmu.clk    = dsp_ck_handle;
 +      dsp_mmu.memclk = api_ck_handle;
 +#endif
 +      return 0;
 +}
 +
 +void dsp_mem_exit(void)
 +{
 +      dsp_reset_idle_boot_base();
 +      omap_mmu_unregister(&dsp_mmu);
 +}
index d2276f939190db7997772a4c7368c29ceb092b1a,0000000000000000000000000000000000000000..66d9c8aa51fc7acf80d8a7e8a403da0e87dd3e86
mode 100644,000000..100644
--- /dev/null
@@@ -1,227 -1,0 +1,227 @@@
- #include <asm/arch/mailbox.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/poll.h>
 +#include <linux/sched.h>
 +#include <linux/interrupt.h>
++#include <mach/mailbox.h>
 +#include <asm/uaccess.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +
 +/*
 + * value seen through read()
 + */
 +#define DSP_ERR_WDT   0x00000001
 +#define DSP_ERR_MMU   0x00000002
 +static unsigned long errval;
 +
 +static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
 +static int errcnt;
 +static u16 wdtval;    /* FIXME: read through ioctl */
 +static u32 mmu_fadr;  /* FIXME: read through ioctl */
 +
 +/*
 + * DSP error detection device file operations
 + */
 +static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
 +                          loff_t *ppos)
 +{
 +      unsigned long flags;
 +      int status;
 +      DEFINE_WAIT(wait);
 +
 +      if (count < 4)
 +              return 0;
 +
 +      prepare_to_wait(&err_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (errcnt == 0)
 +              schedule();
 +      finish_wait(&err_wait_q, &wait);
 +      if (signal_pending(current))
 +              return -EINTR;
 +
 +      local_irq_save(flags);
 +      status = copy_to_user(buf, &errval, 4);
 +      if (status) {
 +              local_irq_restore(flags);
 +              return -EFAULT;
 +      }
 +      errcnt = 0;
 +      local_irq_restore(flags);
 +
 +      return 4;
 +}
 +
 +static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
 +{
 +      unsigned int mask = 0;
 +
 +      poll_wait(file, &err_wait_q, wait);
 +      if (errcnt != 0)
 +              mask |= POLLIN | POLLRDNORM;
 +
 +      return mask;
 +}
 +
 +struct file_operations dsp_err_fops = {
 +      .owner = THIS_MODULE,
 +      .poll  = dsp_err_poll,
 +      .read  = dsp_err_read,
 +};
 +
 +/*
 + * set / clear functions
 + */
 +
 +/* DSP MMU */
 +static void dsp_err_mmu_set(unsigned long arg)
 +{
 +      disable_irq(omap_dsp->mmu->irq);
 +      mmu_fadr = (u32)arg;
 +}
 +
 +static void dsp_err_mmu_clr(void)
 +{
 +      enable_irq(omap_dsp->mmu->irq);
 +}
 +
 +/* WDT */
 +static void dsp_err_wdt_set(unsigned long arg)
 +{
 +      wdtval = (u16)arg;
 +}
 +
 +/*
 + * error code handler
 + */
 +static struct {
 +      unsigned long val;
 +      void (*set)(unsigned long arg);
 +      void (*clr)(void);
 +} dsp_err_desc[ERRCODE_MAX] = {
 +      [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
 +      [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
 +};
 +
 +void dsp_err_set(enum errcode_e code, unsigned long arg)
 +{
 +      if (dsp_err_desc[code].set != NULL)
 +              dsp_err_desc[code].set(arg);
 +
 +      errval |= dsp_err_desc[code].val;
 +      errcnt++;
 +      wake_up_interruptible(&err_wait_q);
 +}
 +
 +void dsp_err_clear(enum errcode_e code)
 +{
 +      errval &= ~dsp_err_desc[code].val;
 +
 +      if (dsp_err_desc[code].clr != NULL)
 +              dsp_err_desc[code].clr();
 +}
 +
 +int dsp_err_isset(enum errcode_e code)
 +{
 +      return (errval & dsp_err_desc[code].val) ? 1 : 0;
 +}
 +
 +void dsp_err_notify(void)
 +{
 +      /* new error code should be assigned */
 +      dsp_err_set(DSP_ERR_WDT, 0);
 +}
 +
 +/*
 + * functions called from mailbox interrupt routine
 + */
 +static void mbox_err_wdt(u16 data)
 +{
 +      dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
 +}
 +
 +#ifdef OLD_BINARY_SUPPORT
 +/* v3.3 obsolete */
 +void mbox_wdt(struct mbcmd *mb)
 +{
 +      mbox_err_wdt(mb->data);
 +}
 +#endif
 +
 +extern void mbox_err_ipbfull(void);
 +extern void mbox_err_fatal(u8 tid);
 +
 +void mbox_err(struct mbcmd *mb)
 +{
 +      u8 eid = mb->cmd_l;
 +      char *eidnm = subcmd_name(mb);
 +      u8 tid;
 +
 +      if (eidnm) {
 +              printk(KERN_WARNING
 +                     "mbox: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
 +      } else {
 +              printk(KERN_WARNING
 +                     "mbox: ERR from DSP (unknown EID=%02x): %04x\n",
 +                     eid, mb->data);
 +      }
 +
 +      switch (eid) {
 +      case EID_IPBFULL:
 +              mbox_err_ipbfull();
 +              break;
 +
 +      case EID_FATAL:
 +              tid = mb->data & 0x00ff;
 +              mbox_err_fatal(tid);
 +              break;
 +
 +      case EID_WDT:
 +              mbox_err_wdt(mb->data);
 +              break;
 +      }
 +}
 +
 +/*
 + *
 + */
 +void dsp_err_start(void)
 +{
 +      enum errcode_e i;
 +
 +      for (i = 0; i < ERRCODE_MAX; i++) {
 +              if (dsp_err_isset(i))
 +                      dsp_err_clear(i);
 +      }
 +      omap_dsp->mbox->err_notify = dsp_err_notify;
 +      errcnt = 0;
 +}
 +
 +void dsp_err_stop(void)
 +{
 +      wake_up_interruptible(&err_wait_q);
 +      omap_dsp->mbox->err_notify = NULL;
 +}
index aba8e7422b6de649f3d7cb6e527e7d277b2b2f8d,0000000000000000000000000000000000000000..b05ba070777a80cd2fe379056cf5f46fd03c2df4
mode 100644,000000..100644
--- /dev/null
@@@ -1,353 -1,0 +1,353 @@@
- #include <asm/arch/mailbox.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/device.h>
 +#include <linux/interrupt.h>
++#include <mach/mailbox.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +
 +static struct ipbuf_head *g_ipbuf;
 +struct ipbcfg ipbcfg;
 +struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
 +static struct ipblink ipb_free = IPBLINK_INIT;
 +static int ipbuf_sys_hold_mem_active;
 +
 +static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf);
 +static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
 +
 +void ipbuf_stop(void)
 +{
 +      int i;
 +
 +      device_remove_file(omap_dsp->dev, &dev_attr_ipbuf);
 +
 +      spin_lock(&ipb_free.lock);
 +      RESET_IPBLINK(&ipb_free);
 +      spin_unlock(&ipb_free.lock);
 +
 +      ipbcfg.ln = 0;
 +      if (g_ipbuf) {
 +              kfree(g_ipbuf);
 +              g_ipbuf = NULL;
 +      }
 +      for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
 +              dsp_mem_disable((void *)daram_base);
 +      }
 +      ipbuf_sys_hold_mem_active = 0;
 +}
 +
 +int ipbuf_config(u16 ln, u16 lsz, void *base)
 +{
 +      size_t lsz_byte = ((size_t)lsz) << 1;
 +      size_t size;
 +      int ret = 0;
 +      int i;
 +
 +      /*
 +       * global IPBUF
 +       */
 +      if (((unsigned long)base) & 0x3) {
 +              printk(KERN_ERR
 +                     "omapdsp: global ipbuf address(0x%p) is not "
 +                     "32-bit aligned!\n", base);
 +              return -EINVAL;
 +      }
 +      size = lsz_byte * ln;
 +      if (dsp_address_validate(base, size, "global ipbuf") < 0)
 +              return -EINVAL;
 +
 +      g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL);
 +      if (g_ipbuf == NULL) {
 +              printk(KERN_ERR
 +                     "omapdsp: memory allocation for ipbuf failed.\n");
 +              return -ENOMEM;
 +      }
 +      for (i = 0; i < ln; i++) {
 +              void *top, *btm;
 +
 +              top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
 +              btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
 +              g_ipbuf[i].p = (struct ipbuf *)top;
 +              g_ipbuf[i].bid = i;
 +              if (((unsigned long)top & 0xfffe0000) !=
 +                  ((unsigned long)btm & 0xfffe0000)) {
 +                      /*
 +                       * an ipbuf line should not cross
 +                       * 64k-word boundary.
 +                       */
 +                      printk(KERN_ERR
 +                             "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
 +                             "  @0x%p, size=0x%08x\n", i, top, lsz_byte);
 +                      ret = -EINVAL;
 +                      goto free_out;
 +              }
 +      }
 +      ipbcfg.ln       = ln;
 +      ipbcfg.lsz      = lsz;
 +      ipbcfg.base     = base;
 +      ipbcfg.bsycnt   = ln;   /* DSP holds all ipbufs initially. */
 +      ipbcfg.cnt_full = 0;
 +
 +      pr_info("omapdsp: IPBUF configuration\n"
 +              "           %d words * %d lines at 0x%p.\n",
 +              ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
 +
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_ipbuf);
 +      if (ret)
 +              printk(KERN_ERR "device_create_file failed: %d\n", ret);
 +
 +      return ret;
 +
 + free_out:
 +      kfree(g_ipbuf);
 +      g_ipbuf = NULL;
 +      return ret;
 +}
 +
 +int ipbuf_sys_config(void *p, arm_dsp_dir_t dir)
 +{
 +      char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
 +
 +      if (((unsigned long)p) & 0x3) {
 +              printk(KERN_ERR
 +                     "omapdsp: system ipbuf(%s) address(0x%p) is "
 +                     "not 32-bit aligned!\n", dir_str, p);
 +              return -1;
 +      }
 +      if (dsp_address_validate(p, sizeof(struct ipbuf_sys),
 +                               "system ipbuf(%s)", dir_str) < 0)
 +              return -1;
 +      if (dsp_mem_type(p, sizeof(struct ipbuf_sys)) != MEM_TYPE_EXTERN) {
 +              printk(KERN_WARNING
 +                     "omapdsp: system ipbuf(%s) is placed in"
 +                     " DSP internal memory.\n"
 +                     "         It will prevent DSP from idling.\n", dir_str);
 +              ipbuf_sys_hold_mem_active++;
 +              /*
 +               * dsp_mem_enable() never fails because
 +               * it has been already enabled in dspcfg process and
 +               * this will just increment the usecount.
 +               */
 +              dsp_mem_enable((void *)daram_base);
 +      }
 +
 +      if (dir == DIR_D2A)
 +              ipbuf_sys_da = p;
 +      else
 +              ipbuf_sys_ad = p;
 +
 +      return 0;
 +}
 +
 +int ipbuf_p_validate(void *p, arm_dsp_dir_t dir)
 +{
 +      char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
 +
 +      if (((unsigned long)p) & 0x3) {
 +              printk(KERN_ERR
 +                     "omapdsp: private ipbuf(%s) address(0x%p) is "
 +                     "not 32-bit aligned!\n", dir_str, p);
 +              return -1;
 +      }
 +      return dsp_address_validate(p, sizeof(struct ipbuf_p),
 +                                  "private ipbuf(%s)", dir_str);
 +}
 +
 +/*
 + * Global IPBUF operations
 + */
 +struct ipbuf_head *bid_to_ipbuf(u16 bid)
 +{
 +      return &g_ipbuf[bid];
 +}
 +
 +struct ipbuf_head *get_free_ipbuf(u8 tid)
 +{
 +      struct ipbuf_head *ipb_h;
 +
 +      if (dsp_mem_enable_ipbuf() < 0)
 +              return NULL;
 +
 +      spin_lock(&ipb_free.lock);
 +
 +      if (ipblink_empty(&ipb_free)) {
 +              /* FIXME: wait on queue when not available.  */
 +              ipb_h = NULL;
 +              goto out;
 +      }
 +      ipb_h = &g_ipbuf[ipb_free.top];
 +      ipb_h->p->la = tid;     /* lock */
 +      __ipblink_del_top(&ipb_free);
 +out:
 +      spin_unlock(&ipb_free.lock);
 +      dsp_mem_disable_ipbuf();
 +
 +      return ipb_h;
 +}
 +
 +void release_ipbuf(struct ipbuf_head *ipb_h)
 +{
 +      if (ipb_h->p->la == TID_FREE) {
 +              printk(KERN_WARNING
 +                     "omapdsp: attempt to release unlocked IPBUF[%d].\n",
 +                     ipb_h->bid);
 +              /*
 +               * FIXME: re-calc bsycnt
 +               */
 +              return;
 +      }
 +      ipb_h->p->la = TID_FREE;
 +      ipb_h->p->sa = TID_FREE;
 +      ipblink_add_tail(&ipb_free, ipb_h->bid);
 +}
 +
 +static int try_yld(struct ipbuf_head *ipb_h)
 +{
 +      int status;
 +
 +      ipb_h->p->sa = TID_ANON;
 +      status = mbcompose_send(BKYLD, 0, ipb_h->bid);
 +      if (status < 0) {
 +              /* DSP is busy and ARM keeps this line. */
 +              release_ipbuf(ipb_h);
 +              return status;
 +      }
 +
 +      ipb_bsycnt_inc(&ipbcfg);
 +      return 0;
 +}
 +
 +/*
 + * balancing ipbuf lines with DSP
 + */
 +static void do_balance_ipbuf(struct work_struct *unused)
 +{
 +      while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
 +              struct ipbuf_head *ipb_h;
 +
 +              if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL)
 +                      return;
 +              if (try_yld(ipb_h) < 0)
 +                      return;
 +      }
 +}
 +
 +static DECLARE_WORK(balance_ipbuf_work, do_balance_ipbuf);
 +
 +void balance_ipbuf(void)
 +{
 +      schedule_work(&balance_ipbuf_work);
 +}
 +
 +/* for process context */
 +void unuse_ipbuf(struct ipbuf_head *ipb_h)
 +{
 +      if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
 +              /* we don't have enough IPBUF lines. let's keep it. */
 +              release_ipbuf(ipb_h);
 +      } else {
 +              /* we have enough IPBUF lines. let's return this line to DSP. */
 +              ipb_h->p->la = TID_ANON;
 +              try_yld(ipb_h);
 +              balance_ipbuf();
 +      }
 +}
 +
 +/* for interrupt context */
 +void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h)
 +{
 +      release_ipbuf(ipb_h);
 +      balance_ipbuf();
 +}
 +
 +/*
 + * functions called from mailbox interrupt routine
 + */
 +
 +void mbox_err_ipbfull(void)
 +{
 +      ipbcfg.cnt_full++;
 +}
 +
 +/*
 + * sysfs files
 + */
 +static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf)
 +{
 +      int len = 0;
 +      u16 bid;
 +
 +      for (bid = 0; bid < ipbcfg.ln; bid++) {
 +              struct ipbuf_head *ipb_h = &g_ipbuf[bid];
 +              u16 la = ipb_h->p->la;
 +              u16 ld = ipb_h->p->ld;
 +              u16 c  = ipb_h->p->c;
 +
 +              if (len > PAGE_SIZE - 100) {
 +                      len += sprintf(buf + len, "out of buffer.\n");
 +                      goto finish;
 +              }
 +
 +              len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
 +                             bid, ipb_h->p);
 +              if (la == TID_FREE) {
 +                      len += sprintf(buf + len,
 +                                     "  DSPtask[%d]->Linux "
 +                                     "(already read and now free for Linux)\n",
 +                                     ld);
 +              } else if (ld == TID_FREE) {
 +                      len += sprintf(buf + len,
 +                                     "  Linux->DSPtask[%d] "
 +                                     "(already read and now free for DSP)\n",
 +                                     la);
 +              } else if (ipbuf_is_held(ld, bid)) {
 +                      len += sprintf(buf + len,
 +                                     "  DSPtask[%d]->Linux "
 +                                     "(waiting to be read)\n"
 +                                     "  count = %d\n", ld, c);
 +              } else {
 +                      len += sprintf(buf + len,
 +                                     "  Linux->DSPtask[%d] "
 +                                     "(waiting to be read)\n"
 +                                     "  count = %d\n", la, c);
 +              }
 +      }
 +
 +      len += sprintf(buf + len, "\nFree IPBUF link: ");
 +      spin_lock(&ipb_free.lock);
 +      ipblink_for_each(bid, &ipb_free) {
 +              len += sprintf(buf + len, "%d ", bid);
 +      }
 +      spin_unlock(&ipb_free.lock);
 +      len += sprintf(buf + len, "\n");
 +      len += sprintf(buf + len, "IPBFULL error count: %ld\n",
 +                     ipbcfg.cnt_full);
 +
 +finish:
 +      return len;
 +}
index 2b1e113794c63ca680426823ab2e9410417bd2f9,0000000000000000000000000000000000000000..7e008afb6c90f1c32990457528538eafabe77699
mode 100644,000000..100644
--- /dev/null
@@@ -1,280 -1,0 +1,280 @@@
- #include <asm/arch/mailbox.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/platform_device.h>
 +#include <linux/init.h>
 +#include <linux/jiffies.h>
++#include <mach/mailbox.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +
 +char *subcmd_name(struct mbcmd *mb)
 +{
 +      u8 cmd_h = mb->cmd_h;
 +      u8 cmd_l = mb->cmd_l;
 +      char *s;
 +
 +      switch (cmd_h) {
 +      case MBOX_CMD_DSP_RUNLEVEL:
 +              s = (cmd_l == RUNLEVEL_USER)     ? "USER":
 +                  (cmd_l == RUNLEVEL_SUPER)    ? "SUPER":
 +                  (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
 +                  NULL;
 +              break;
 +      case MBOX_CMD_DSP_PM:
 +              s = (cmd_l == PM_DISABLE) ? "DISABLE":
 +                  (cmd_l == PM_ENABLE)  ? "ENABLE":
 +                  NULL;
 +              break;
 +      case MBOX_CMD_DSP_KFUNC:
 +              s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
 +                      (cmd_l == KFUNC_POWER) ?
 +                      ((mb->data == AUDIO_PWR_UP)     ? "PWR AUD /UP":
 +                       (mb->data == AUDIO_PWR_DOWN)   ? "PWR AUD /DOWN":
 +                       (mb->data == AUDIO_PWR_DOWN2)  ? "PWR AUD /DOWN(2)":
 +                       (mb->data == DSP_PWR_UP)       ? "PWR DSP /UP":
 +                       (mb->data == DSP_PWR_DOWN)     ? "PWR DSP /DOWN":
 +                       (mb->data == DVFS_START)       ? "PWR DVFS/START":
 +                       (mb->data == DVFS_STOP)        ? "PWR DVFS/STOP":
 +                       NULL):
 +
 +                  NULL;
 +              break;
 +      case MBOX_CMD_DSP_DSPCFG:
 +              {
 +                      u8 cfgc = cmd_l & 0x7f;
 +                      s = (cfgc == DSPCFG_REQ)     ? "REQ":
 +                          (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
 +                          (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
 +                          (cfgc == DSPCFG_ABORT)   ? "ABORT":
 +                          (cfgc == DSPCFG_PROTREV) ? "PROTREV":
 +                          NULL;
 +                      break;
 +              }
 +      case MBOX_CMD_DSP_REGRW:
 +              s = (cmd_l == REGRW_MEMR) ? "MEMR":
 +                  (cmd_l == REGRW_MEMW) ? "MEMW":
 +                  (cmd_l == REGRW_IOR)  ? "IOR":
 +                  (cmd_l == REGRW_IOW)  ? "IOW":
 +                  (cmd_l == REGRW_DATA) ? "DATA":
 +                  NULL;
 +              break;
 +      case MBOX_CMD_DSP_GETVAR:
 +      case MBOX_CMD_DSP_SETVAR:
 +              s = (cmd_l == VARID_ICRMASK)  ? "ICRMASK":
 +                  (cmd_l == VARID_LOADINFO) ? "LOADINFO":
 +                  NULL;
 +              break;
 +      case MBOX_CMD_DSP_ERR:
 +              s = (cmd_l == EID_BADTID)     ? "BADTID":
 +                  (cmd_l == EID_BADTCN)     ? "BADTCN":
 +                  (cmd_l == EID_BADBID)     ? "BADBID":
 +                  (cmd_l == EID_BADCNT)     ? "BADCNT":
 +                  (cmd_l == EID_NOTLOCKED)  ? "NOTLOCKED":
 +                  (cmd_l == EID_STVBUF)     ? "STVBUF":
 +                  (cmd_l == EID_BADADR)     ? "BADADR":
 +                  (cmd_l == EID_BADTCTL)    ? "BADTCTL":
 +                  (cmd_l == EID_BADPARAM)   ? "BADPARAM":
 +                  (cmd_l == EID_FATAL)      ? "FATAL":
 +                  (cmd_l == EID_WDT)        ? "WDT":
 +                  (cmd_l == EID_NOMEM)      ? "NOMEM":
 +                  (cmd_l == EID_NORES)      ? "NORES":
 +                  (cmd_l == EID_IPBFULL)    ? "IPBFULL":
 +                  (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
 +                  (cmd_l == EID_TASKBSY)    ? "TASKBSY":
 +                  (cmd_l == EID_TASKERR)    ? "TASKERR":
 +                  (cmd_l == EID_BADCFGTYP)  ? "BADCFGTYP":
 +                  (cmd_l == EID_DEBUG)      ? "DEBUG":
 +                  (cmd_l == EID_BADSEQ)     ? "BADSEQ":
 +                  (cmd_l == EID_BADCMD)     ? "BADCMD":
 +                  NULL;
 +              break;
 +      default:
 +              s = NULL;
 +      }
 +
 +      return s;
 +}
 +
 +/* output of show() method should fit to PAGE_SIZE */
 +#define MBLOG_DEPTH   64
 +
 +struct mblogent {
 +      unsigned long jiffies;
 +      mbox_msg_t msg;
 +      arm_dsp_dir_t dir;
 +};
 +
 +static struct {
 +      spinlock_t lock;
 +      int wp;
 +      unsigned long cnt, cnt_ad, cnt_da;
 +      struct mblogent ent[MBLOG_DEPTH];
 +} mblog = {
 +      .lock = SPIN_LOCK_UNLOCKED,
 +};
 +
 +#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
 +static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
 +{
 +      const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
 +      char *dir_str;
 +      char *subname;
 +
 +      dir_str = (dir == DIR_A2D) ? "sending  " : "receiving";
 +      switch (ci->cmd_l_type) {
 +      case CMD_L_TYPE_SUBCMD:
 +              subname = subcmd_name(mb);
 +              if (unlikely(!subname))
 +                      subname = "Unknown";
 +              pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
 +                       dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
 +                       ci->name, subname, mb->data);
 +              break;
 +      case CMD_L_TYPE_TID:
 +              pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
 +                       dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
 +                       ci->name, mb->cmd_l, mb->data);
 +              break;
 +      case CMD_L_TYPE_NULL:
 +              pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
 +                       dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
 +                       ci->name, mb->data);
 +              break;
 +      }
 +}
 +#else
 +static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
 +#endif
 +
 +void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
 +{
 +      struct mblogent *ent;
 +
 +      spin_lock(&mblog.lock);
 +      ent = &mblog.ent[mblog.wp];
 +      ent->jiffies = jiffies;
 +      ent->msg = *(mbox_msg_t *)mb;
 +      ent->dir = dir;
 +      if (mblog.cnt < 0xffffffff)
 +              mblog.cnt++;
 +      switch (dir) {
 +      case DIR_A2D:
 +              if (mblog.cnt_ad < 0xffffffff)
 +                      mblog.cnt_ad++;
 +              break;
 +      case DIR_D2A:
 +              if (mblog.cnt_da < 0xffffffff)
 +                      mblog.cnt_da++;
 +              break;
 +      }
 +      if (++mblog.wp == MBLOG_DEPTH)
 +              mblog.wp = 0;
 +      spin_unlock(&mblog.lock);
 +
 +      mblog_print_cmd(mb, dir);
 +}
 +
 +/*
 + * sysfs file
 + */
 +static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
 +                        char *buf)
 +{
 +      int len = 0;
 +      int wp;
 +      int i;
 +
 +      spin_lock(&mblog.lock);
 +
 +      wp = mblog.wp;
 +      len += sprintf(buf + len,
 +                     "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
 +                     mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
 +      if (mblog.cnt == 0)
 +              goto done;
 +
 +      len += sprintf(buf + len, "           ARM->DSP   ARM<-DSP\n");
 +      len += sprintf(buf + len, " jiffies  cmd  data  cmd  data\n");
 +      i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
 +      do {
 +              struct mblogent *ent = &mblog.ent[i];
 +              struct mbcmd *mb = (struct mbcmd *)&ent->msg;
 +              char *subname;
 +              struct cmdinfo ci_null = {
 +                      .name = "Unknown",
 +                      .cmd_l_type = CMD_L_TYPE_NULL,
 +              };
 +              const struct cmdinfo *ci;
 +
 +              len += sprintf(buf + len,
 +                             (ent->dir == DIR_A2D) ?
 +                              "%08lx  %04x %04x            ":
 +                              "%08lx             %04x %04x ",
 +                             ent->jiffies,
 +                             (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
 +
 +              if ((ci = cmdinfo[mb->cmd_h]) == NULL)
 +                      ci = &ci_null;
 +
 +              switch (ci->cmd_l_type) {
 +              case CMD_L_TYPE_SUBCMD:
 +                      if ((subname = subcmd_name(mb)) == NULL)
 +                              subname = "Unknown";
 +                      len += sprintf(buf + len, "%s:%s\n",
 +                                     ci->name, subname);
 +                      break;
 +              case CMD_L_TYPE_TID:
 +                      len += sprintf(buf + len, "%s:task %d\n",
 +                                     ci->name, mb->cmd_l);
 +                      break;
 +              case CMD_L_TYPE_NULL:
 +                      len += sprintf(buf + len, "%s\n", ci->name);
 +                      break;
 +              }
 +
 +              if (++i == MBLOG_DEPTH)
 +                      i = 0;
 +      } while (i != wp);
 +
 +done:
 +      spin_unlock(&mblog.lock);
 +
 +      return len;
 +}
 +
 +static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
 +
 +void __init mblog_init(void)
 +{
 +      int ret;
 +
 +      ret = device_create_file(omap_dsp->dev, &dev_attr_mblog);
 +      if (ret)
 +              printk(KERN_ERR "device_create_file failed: %d\n", ret);
 +}
 +
 +void mblog_exit(void)
 +{
 +      device_remove_file(omap_dsp->dev, &dev_attr_mblog);
 +}
index 0dc43f0edcb78d0812c5ac79fb167c63e45552fa,0000000000000000000000000000000000000000..4ac51806eeba36926368c24cd4574cb8bdaeac7c
mode 100644,000000..100644
--- /dev/null
@@@ -1,95 -1,0 +1,95 @@@
- #include <asm/arch/hardware.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#ifndef __OMAP_DSP_OMAP2_DSP_H
 +#define __OMAP_DSP_OMAP2_DSP_H
 +
 +#ifdef CONFIG_ARCH_OMAP24XX
 +#define OMAP24XX_DARAM_BASE   (DSP_MEM_24XX_VIRT + 0x0)
 +#define OMAP24XX_DARAM_SIZE   0x10000
 +#define OMAP24XX_SARAM_BASE   (DSP_MEM_24XX_VIRT + 0x10000)
 +#define OMAP24XX_SARAM_SIZE   0x18000
 +#endif
 +
++#include <mach/hardware.h>
 +
 +/*
 + * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX()
 + */
 +#ifdef CONFIG_ARCH_OMAP24XX
 +#define DSP_IPI_BASE                  DSP_IPI_24XX_VIRT
 +#endif
 +
 +#ifdef CONFIG_ARCH_OMAP34XX
 +#define DSP_IPI_BASE                  DSP_IPI_34XX_VIRT
 +#endif
 +
 +#define DSP_IPI_REVISION              (DSP_IPI_BASE + 0x00)
 +#define DSP_IPI_SYSCONFIG             (DSP_IPI_BASE + 0x10)
 +#define DSP_IPI_INDEX                 (DSP_IPI_BASE + 0x40)
 +#define DSP_IPI_ENTRY                 (DSP_IPI_BASE + 0x44)
 +#define DSP_IPI_ENABLE                        (DSP_IPI_BASE + 0x48)
 +#define DSP_IPI_IOMAP                 (DSP_IPI_BASE + 0x4c)
 +#define DSP_IPI_DSPBOOTCONFIG         (DSP_IPI_BASE + 0x50)
 +
 +#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK       0x00000003
 +#define DSP_IPI_ENTRY_ELMSIZEVALUE_8  0x00000000
 +#define DSP_IPI_ENTRY_ELMSIZEVALUE_16 0x00000001
 +#define DSP_IPI_ENTRY_ELMSIZEVALUE_32 0x00000002
 +
 +#define DSP_BOOT_CONFIG_DIRECT                0x00000000
 +#define DSP_BOOT_CONFIG_PSD_DIRECT    0x00000001
 +#define DSP_BOOT_CONFIG_IDLE          0x00000002
 +#define DSP_BOOT_CONFIG_DL16          0x00000003
 +#define DSP_BOOT_CONFIG_DL32          0x00000004
 +#define DSP_BOOT_CONFIG_API           0x00000005
 +#define DSP_BOOT_CONFIG_INTERNAL      0x00000006
 +
 +/*
 + * DSP boot mode
 + *   direct:        0xffff00
 + *   pseudo direct: 0x080000
 + *   API:           branch 0x010000
 + *   internel:      branch 0x024000
 + */
 +#define DSP_BOOT_ADR_DIRECT           0xffff00
 +#define DSP_BOOT_ADR_PSD_DIRECT               0x080000
 +#define DSP_BOOT_ADR_API              0x010000
 +#define DSP_BOOT_ADR_INTERNAL         0x024000
 +
 +/*
 + * DSP ICR
 + */
 +#define DSPREG_ICR_RESERVED_BITS      0xfc00
 +#define DSPREG_ICR_HWA                        0x0200
 +#define DSPREG_ICR_IPORT              0x0100
 +#define DSPREG_ICR_MPORT              0x0080
 +#define DSPREG_ICR_XPORT              0x0040
 +#define DSPREG_ICR_DPORT              0x0020
 +#define DSPREG_ICR_DPLL                       0x0010
 +#define DSPREG_ICR_PER                        0x0008
 +#define DSPREG_ICR_CACHE              0x0004
 +#define DSPREG_ICR_DMA                        0x0002
 +#define DSPREG_ICR_CPU                        0x0001
 +
 +#endif /* __OMAP_DSP_OMAP2_DSP_H */
index ab189349507d95621151d0ecf19ccfbb5673f535,0000000000000000000000000000000000000000..a371911bffa10cdb0e0388de1d50704208bfc59e
mode 100644,000000..100644
--- /dev/null
@@@ -1,3041 -1,0 +1,3041 @@@
- #include <asm/arch/mailbox.h>
- #include <asm/arch/dsp.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/major.h>
 +#include <linux/fs.h>
 +#include <linux/poll.h>
 +#include <linux/platform_device.h>
 +#include <linux/slab.h>
 +#include <linux/sched.h>
 +#include <linux/mm.h>
 +#include <linux/mutex.h>
 +#include <linux/interrupt.h>
 +#include <linux/kfifo.h>
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
++#include <mach/mailbox.h>
++#include <mach/dsp.h>
 +#include "uaccess_dsp.h"
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +#include "proclist.h"
 +
 +/*
 + * devstate: task device state machine
 + * NOTASK:    task is not attached.
 + * ATTACHED:  task is attached.
 + * GARBAGE:   task is detached. waiting for all processes to close this device.
 + * ADDREQ:    requesting for tadd
 + * DELREQ:    requesting for tdel. no process is opening this device.
 + * FREEZED:   task is attached, but reserved to be killed.
 + * ADDFAIL:   tadd failed.
 + * ADDING:    tadd in process.
 + * DELING:    tdel in process.
 + * KILLING:   tkill in process.
 + */
 +#define TASKDEV_ST_NOTASK     0x00000001
 +#define TASKDEV_ST_ATTACHED   0x00000002
 +#define TASKDEV_ST_GARBAGE    0x00000004
 +#define TASKDEV_ST_INVALID    0x00000008
 +#define TASKDEV_ST_ADDREQ     0x00000100
 +#define TASKDEV_ST_DELREQ     0x00000200
 +#define TASKDEV_ST_FREEZED    0x00000400
 +#define TASKDEV_ST_ADDFAIL    0x00001000
 +#define TASKDEV_ST_ADDING     0x00010000
 +#define TASKDEV_ST_DELING     0x00020000
 +#define TASKDEV_ST_KILLING    0x00040000
 +#define TASKDEV_ST_STATE_MASK 0x7fffffff
 +#define TASKDEV_ST_STALE      0x80000000
 +
 +static struct {
 +      long state;
 +      char *name;
 +} devstate_desc[] = {
 +      { TASKDEV_ST_NOTASK,   "notask" },
 +      { TASKDEV_ST_ATTACHED, "attached" },
 +      { TASKDEV_ST_GARBAGE,  "garbage" },
 +      { TASKDEV_ST_INVALID,  "invalid" },
 +      { TASKDEV_ST_ADDREQ,   "addreq" },
 +      { TASKDEV_ST_DELREQ,   "delreq" },
 +      { TASKDEV_ST_FREEZED,  "freezed" },
 +      { TASKDEV_ST_ADDFAIL,  "addfail" },
 +      { TASKDEV_ST_ADDING,   "adding" },
 +      { TASKDEV_ST_DELING,   "deling" },
 +      { TASKDEV_ST_KILLING,  "killing" },
 +};
 +
 +static char *devstate_name(long state)
 +{
 +      int i;
 +      int max = ARRAY_SIZE(devstate_desc);
 +
 +      for (i = 0; i < max; i++) {
 +              if (state & devstate_desc[i].state)
 +                      return devstate_desc[i].name;
 +      }
 +      return "unknown";
 +}
 +
 +struct rcvdt_bk_struct {
 +      struct ipblink link;
 +      unsigned int rp;
 +};
 +
 +struct taskdev {
 +      struct bus_type *bus;
 +      struct device dev;      /* Generic device interface */
 +
 +      long state;
 +      struct rw_semaphore state_sem;
 +      wait_queue_head_t state_wait_q;
 +      struct mutex usecount_lock;
 +      unsigned int usecount;
 +      char name[TNM_LEN];
 +      struct file_operations fops;
 +      spinlock_t proc_list_lock;
 +      struct list_head proc_list;
 +      struct dsptask *task;
 +
 +      /* read stuff */
 +      wait_queue_head_t read_wait_q;
 +      struct mutex read_mutex;
 +      spinlock_t read_lock;
 +      union {
 +              struct kfifo *fifo;     /* for active word */
 +              struct rcvdt_bk_struct bk;
 +      } rcvdt;
 +
 +      /* write stuff */
 +      wait_queue_head_t write_wait_q;
 +      struct mutex write_mutex;
 +      spinlock_t wsz_lock;
 +      size_t wsz;
 +
 +      /* tctl stuff */
 +      wait_queue_head_t tctl_wait_q;
 +      struct mutex tctl_mutex;
 +      int tctl_stat;
 +      int tctl_ret;   /* return value for tctl_show() */
 +
 +      /* device lock */
 +      struct mutex lock;
 +      pid_t lock_pid;
 +};
 +
 +#define to_taskdev(n) container_of(n, struct taskdev, dev)
 +
 +struct dsptask {
 +      enum {
 +              TASK_ST_ERR = 0,
 +              TASK_ST_READY,
 +              TASK_ST_CFGREQ
 +      } state;
 +      u8 tid;
 +      char name[TNM_LEN];
 +      u16 ttyp;
 +      struct taskdev *dev;
 +
 +      /* read stuff */
 +      struct ipbuf_p *ipbuf_pvt_r;
 +
 +      /* write stuff */
 +      struct ipbuf_p *ipbuf_pvt_w;
 +
 +      /* mmap stuff */
 +      void *map_base;
 +      size_t map_length;
 +};
 +
 +#define sndtyp_acv(ttyp)      ((ttyp) & TTYP_ASND)
 +#define sndtyp_psv(ttyp)      (!((ttyp) & TTYP_ASND))
 +#define sndtyp_bk(ttyp)               ((ttyp) & TTYP_BKDM)
 +#define sndtyp_wd(ttyp)               (!((ttyp) & TTYP_BKDM))
 +#define sndtyp_pvt(ttyp)      ((ttyp) & TTYP_PVDM)
 +#define sndtyp_gbl(ttyp)      (!((ttyp) & TTYP_PVDM))
 +#define rcvtyp_acv(ttyp)      ((ttyp) & TTYP_ARCV)
 +#define rcvtyp_psv(ttyp)      (!((ttyp) & TTYP_ARCV))
 +#define rcvtyp_bk(ttyp)               ((ttyp) & TTYP_BKMD)
 +#define rcvtyp_wd(ttyp)               (!((ttyp) & TTYP_BKMD))
 +#define rcvtyp_pvt(ttyp)      ((ttyp) & TTYP_PVMD)
 +#define rcvtyp_gbl(ttyp)      (!((ttyp) & TTYP_PVMD))
 +
 +static inline int has_taskdev_lock(struct taskdev *dev);
 +static int dsp_rmdev_minor(unsigned char minor);
 +static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
 +static void taskdev_delete(unsigned char minor);
 +static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
 +static int dsp_tdel_bh(struct taskdev *dev, u16 type);
 +
 +static struct bus_type dsptask_bus = {
 +      .name = "dsptask",
 +};
 +
 +static struct class *dsp_task_class;
 +static DEFINE_MUTEX(devmgr_lock);
 +static struct taskdev *taskdev[TASKDEV_MAX];
 +static struct dsptask *dsptask[TASKDEV_MAX];
 +static DEFINE_MUTEX(cfg_lock);
 +static u16 cfg_cmd;
 +static u8 cfg_tid;
 +static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
 +static u8 n_task;     /* static task count */
 +static void *heap;
 +
 +#define is_dynamic_task(tid)  ((tid) >= n_task)
 +
 +#define devstate_read_lock(dev, devstate) \
 +              devstate_read_lock_timeout(dev, devstate, 0)
 +#define devstate_read_unlock(dev)     up_read(&(dev)->state_sem)
 +#define devstate_write_lock(dev, devstate) \
 +              devstate_write_lock_timeout(dev, devstate, 0)
 +#define devstate_write_unlock(dev)    up_write(&(dev)->state_sem)
 +
 +static ssize_t devname_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
 +                           char *buf);
 +static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
 +                            char *buf);
 +static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
 +                           char *buf);
 +static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
 +                       char *buf);
 +static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
 +                         char *buf);
 +static int fifosz_store(struct device *d, struct device_attribute *attr,
 +                      const char *buf, size_t count);
 +static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
 +                      char *buf);
 +static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
 +                       char *buf);
 +
 +#define __ATTR_RW(_name,_mode) { \
 +      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
 +      .show   = _name##_show,                                 \
 +      .store  = _name##_store,                                        \
 +}
 +
 +static struct device_attribute dev_attr_devname   = __ATTR_RO(devname);
 +static struct device_attribute dev_attr_devstate  = __ATTR_RO(devstate);
 +static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
 +static struct device_attribute dev_attr_taskname  = __ATTR_RO(taskname);
 +static struct device_attribute dev_attr_ttyp      = __ATTR_RO(ttyp);
 +static struct device_attribute dev_attr_fifosz    = __ATTR_RW(fifosz, 0666);
 +static struct device_attribute dev_attr_fifocnt   = __ATTR_RO(fifocnt);
 +static struct device_attribute dev_attr_ipblink   = __ATTR_RO(ipblink);
 +static struct device_attribute dev_attr_wsz       = __ATTR_RO(wsz);
 +static struct device_attribute dev_attr_mmap      = __ATTR_RO(mmap);
 +
 +static inline void set_taskdev_state(struct taskdev *dev, int state)
 +{
 +      pr_debug("omapdsp: devstate: CHANGE %s[%d]:\"%s\"->\"%s\"\n",
 +               dev->name,
 +               (dev->task ? dev->task->tid : -1),
 +               devstate_name(dev->state),
 +               devstate_name(state));
 +      dev->state = state;
 +}
 +
 +/*
 + * devstate_read_lock_timeout()
 + * devstate_write_lock_timeout():
 + * timeout != 0: dev->state can be diffeent from what you want.
 + * timeout == 0: no timeout
 + */
 +#define BUILD_DEVSTATE_LOCK_TIMEOUT(rw)                                               \
 +static int devstate_##rw##_lock_timeout(struct taskdev *dev, long devstate,     \
 +                                    int timeout)                              \
 +{                                                                             \
 +      DEFINE_WAIT(wait);                                                      \
 +      down_##rw(&dev->state_sem);                                             \
 +      while (!(dev->state & devstate)) {                                      \
 +              up_##rw(&dev->state_sem);                                       \
 +              prepare_to_wait(&dev->state_wait_q, &wait, TASK_INTERRUPTIBLE); \
 +              if (!timeout)                                                   \
 +                      timeout = MAX_SCHEDULE_TIMEOUT;                         \
 +              timeout = schedule_timeout(timeout);                            \
 +              finish_wait(&dev->state_wait_q, &wait);                         \
 +              if (timeout == 0)                                               \
 +                      return -ETIME;                                          \
 +              if (signal_pending(current))                                    \
 +                      return -EINTR;                                          \
 +              down_##rw(&dev->state_sem);                                     \
 +      }                                                                       \
 +      return 0;                                                               \
 +}
 +BUILD_DEVSTATE_LOCK_TIMEOUT(read)
 +BUILD_DEVSTATE_LOCK_TIMEOUT(write)
 +
 +#define BUILD_DEVSTATE_LOCK_AND_TEST(rw)                                      \
 +static int devstate_##rw##_lock_and_test(struct taskdev *dev, long devstate)  \
 +{                                                                             \
 +      down_##rw(&dev->state_sem);                                             \
 +      if (dev->state & devstate)                                              \
 +              return 1;       /* success */                                   \
 +      /* failure */                                                           \
 +      up_##rw(&dev->state_sem);                                               \
 +      return 0;                                                               \
 +}
 +BUILD_DEVSTATE_LOCK_AND_TEST(read)
 +BUILD_DEVSTATE_LOCK_AND_TEST(write)
 +
 +static int taskdev_lock_interruptible(struct taskdev *dev,
 +                                    struct mutex *lock)
 +{
 +      int ret;
 +
 +      if (has_taskdev_lock(dev))
 +              ret = mutex_lock_interruptible(lock);
 +      else {
 +              if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
 +                      return ret;
 +              ret = mutex_lock_interruptible(lock);
 +              mutex_unlock(&dev->lock);
 +      }
 +
 +      return ret;
 +}
 +
 +static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
 +                                             struct mutex *lock)
 +{
 +      int ret;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      if ((ret = taskdev_lock_interruptible(dev, lock)) != 0)
 +              devstate_read_unlock(dev);
 +
 +      return ret;
 +}
 +
 +static inline void taskdev_unlock_and_stateunlock(struct taskdev *dev,
 +                                                    struct mutex *lock)
 +{
 +      mutex_unlock(lock);
 +      devstate_read_unlock(dev);
 +}
 +
 +/*
 + * taskdev_flush_buf()
 + * must be called under state_lock(ATTACHED) and dev->read_mutex.
 + */
 +static int taskdev_flush_buf(struct taskdev *dev)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      if (sndtyp_wd(ttyp)) {
 +              /* word receiving */
 +              kfifo_reset(dev->rcvdt.fifo);
 +      } else {
 +              /* block receiving */
 +              struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +
 +              if (sndtyp_gbl(ttyp))
 +                      ipblink_flush(&rcvdt->link);
 +              else {
 +                      ipblink_flush_pvt(&rcvdt->link);
 +                      release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +/*
 + * taskdev_set_fifosz()
 + * must be called under dev->read_mutex.
 + */
 +static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
 +              printk(KERN_ERR
 +                     "omapdsp: buffer size can be changed only for "
 +                     "active word sending task.\n");
 +              return -EINVAL;
 +      }
 +      if ((sz == 0) || (sz & 1)) {
 +              printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
 +                              "it must be even and non-zero value.\n", sz);
 +              return -EINVAL;
 +      }
 +
 +      if (kfifo_len(dev->rcvdt.fifo)) {
 +              printk(KERN_ERR "omapdsp: buffer is not empty!\n");
 +              return -EIO;
 +      }
 +
 +      kfifo_free(dev->rcvdt.fifo);
 +      dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock);
 +      if (IS_ERR(dev->rcvdt.fifo)) {
 +              printk(KERN_ERR
 +                     "omapdsp: unable to change receive buffer size. "
 +                     "(%ld bytes for %s)\n", sz, dev->name);
 +              return -ENOMEM;
 +      }
 +
 +      return 0;
 +}
 +
 +static inline int has_taskdev_lock(struct taskdev *dev)
 +{
 +      return (dev->lock_pid == current->pid);
 +}
 +
 +static int taskdev_lock(struct taskdev *dev)
 +{
 +      if (mutex_lock_interruptible(&dev->lock))
 +              return -EINTR;
 +      dev->lock_pid = current->pid;
 +      return 0;
 +}
 +
 +static int taskdev_unlock(struct taskdev *dev)
 +{
 +      if (!has_taskdev_lock(dev)) {
 +              printk(KERN_ERR
 +                     "omapdsp: an illegal process attempted to "
 +                     "unlock the dsptask lock!\n");
 +              return -EINVAL;
 +      }
 +      dev->lock_pid = 0;
 +      mutex_unlock(&dev->lock);
 +      return 0;
 +}
 +
 +static int dsp_task_config(struct dsptask *task, u8 tid)
 +{
 +      u16 ttyp;
 +      int ret;
 +
 +      task->tid = tid;
 +      dsptask[tid] = task;
 +
 +      /* TCFG request */
 +      task->state = TASK_ST_CFGREQ;
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              ret = -EINTR;
 +              goto fail_out;
 +      }
 +      cfg_cmd = MBOX_CMD_DSP_TCFG;
 +      mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (task->state != TASK_ST_READY) {
 +              printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      if (strlen(task->name) <= 1)
 +              sprintf(task->name, "%d", tid);
 +      pr_info("omapdsp: task %d: name %s\n", tid, task->name);
 +
 +      ttyp = task->ttyp;
 +
 +      /*
 +       * task info sanity check
 +       */
 +
 +      /* task type check */
 +      if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
 +              printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n",
 +                     tid, ttyp);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      /* private buffer address check */
 +      if (sndtyp_pvt(ttyp) &&
 +          (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if (rcvtyp_pvt(ttyp) &&
 +          (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) {
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      /* mmap buffer configuration check */
 +      if ((task->map_length > 0) &&
 +          ((!ALIGN((unsigned long)task->map_base, PAGE_SIZE)) ||
 +           (!ALIGN(task->map_length, PAGE_SIZE)) ||
 +           (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) {
 +              printk(KERN_ERR
 +                     "omapdsp: illegal mmap buffer address(0x%p) or "
 +                     "length(0x%x).\n"
 +                     "  It needs to be page-aligned and located at "
 +                     "external memory.\n",
 +                     task->map_base, task->map_length);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      return 0;
 +
 +fail_out:
 +      dsptask[tid] = NULL;
 +      return ret;
 +}
 +
 +static void dsp_task_init(struct dsptask *task)
 +{
 +      mbcompose_send(TCTL, task->tid, TCTL_TINIT);
 +}
 +
 +int dsp_task_config_all(u8 n)
 +{
 +      int i, ret;
 +      struct taskdev *devheap;
 +      struct dsptask *taskheap;
 +      size_t devheapsz, taskheapsz;
 +
 +      pr_info("omapdsp: found %d task(s)\n", n);
 +      if (n == 0)
 +              return 0;
 +
 +      /*
 +       * reducing kmalloc!
 +       */
 +      devheapsz  = sizeof(struct taskdev) * n;
 +      taskheapsz = sizeof(struct dsptask) * n;
 +      heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
 +      if (heap == NULL)
 +              return -ENOMEM;
 +      devheap  = heap;
 +      taskheap = heap + devheapsz;
 +
 +      n_task = n;
 +      for (i = 0; i < n; i++) {
 +              struct taskdev *dev  = &devheap[i];
 +              struct dsptask *task = &taskheap[i];
 +
 +              if ((ret = dsp_task_config(task, i)) < 0)
 +                      return ret;
 +              if ((ret = taskdev_init(dev, task->name, i)) < 0)
 +                      return ret;
 +              if ((ret = taskdev_attach_task(dev, task)) < 0)
 +                      return ret;
 +              dsp_task_init(task);
 +              pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
 +      }
 +
 +      return 0;
 +}
 +
 +static void dsp_task_unconfig(struct dsptask *task)
 +{
 +      dsptask[task->tid] = NULL;
 +}
 +
 +void dsp_task_unconfig_all(void)
 +{
 +      unsigned char minor;
 +      u8 tid;
 +      struct dsptask *task;
 +
 +      for (minor = 0; minor < n_task; minor++) {
 +              /*
 +               * taskdev[minor] can be NULL in case of
 +               * configuration failure
 +               */
 +              if (taskdev[minor])
 +                      taskdev_delete(minor);
 +      }
 +      for (; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor])
 +                      dsp_rmdev_minor(minor);
 +      }
 +
 +      for (tid = 0; tid < n_task; tid++) {
 +              /*
 +               * dsptask[tid] can be NULL in case of
 +               * configuration failure
 +               */
 +              task = dsptask[tid];
 +              if (task)
 +                      dsp_task_unconfig(task);
 +      }
 +      for (; tid < TASKDEV_MAX; tid++) {
 +              task = dsptask[tid];
 +              if (task) {
 +                      /*
 +                       * on-demand tasks should be deleted in
 +                       * rmdev_minor(), but just in case.
 +                       */
 +                      dsp_task_unconfig(task);
 +                      kfree(task);
 +              }
 +      }
 +
 +      if (heap) {
 +              kfree(heap);
 +              heap = NULL;
 +      }
 +
 +      n_task = 0;
 +}
 +
 +static struct device_driver dsptask_driver = {
 +      .name   = "dsptask",
 +      .bus    = &dsptask_bus,
 +};
 +
 +u8 dsp_task_count(void)
 +{
 +      return n_task;
 +}
 +
 +int dsp_taskmod_busy(void)
 +{
 +      struct taskdev *dev;
 +      unsigned char minor;
 +      unsigned int usecount;
 +
 +      for (minor = 0; minor < TASKDEV_MAX; minor++) {
 +              dev = taskdev[minor];
 +              if (dev == NULL)
 +                      continue;
 +              if ((usecount = dev->usecount) > 0) {
 +                      printk("dsp_taskmod_busy(): %s: usecount=%d\n",
 +                             dev->name, usecount);
 +                      return 1;
 +              }
 +/*
 +              if ((dev->state & (TASKDEV_ST_ADDREQ |
 +                                 TASKDEV_ST_DELREQ)) {
 +*/
 +              if (dev->state & TASKDEV_ST_ADDREQ) {
 +                      printk("dsp_taskmod_busy(): %s is in %s\n",
 +                             dev->name, devstate_name(dev->state));
 +                      return 1;
 +              }
 +      }
 +      return 0;
 +}
 +
 +/*
 + * DSP task device file operations
 + */
 +static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +
 +      prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (kfifo_len(dev->rcvdt.fifo) == 0)
 +              schedule();
 +      finish_wait(&dev->read_wait_q, &wait);
 +      if (kfifo_len(dev->rcvdt.fifo) == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +
 +      ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +      ssize_t ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_read().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (ipblink_empty(&rcvdt->link))
 +              schedule();
 +      finish_wait(&dev->read_wait_q, &wait);
 +      if (ipblink_empty(&rcvdt->link)) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      /* copy from delayed IPBUF */
 +      if (sndtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              if (!ipblink_empty(&rcvdt->link)) {
 +                      struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
 +                      unsigned char *base, *src;
 +                      size_t bkcnt;
 +
 +                      if (dsp_mem_enable(ipbp) < 0) {
 +                              ret = -EBUSY;
 +                              goto up_out;
 +                      }
 +                      base = MKVIRT(ipbp->ah, ipbp->al);
 +                      bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
 +                      if (dsp_address_validate(base, bkcnt,
 +                                               "task %s read buffer",
 +                                               dev->task->name) < 0) {
 +                              ret = -EINVAL;
 +                              goto pv_out1;
 +                      }
 +                      if (dsp_mem_enable(base) < 0) {
 +                              ret = -EBUSY;
 +                              goto pv_out1;
 +                      }
 +                      src = base + rcvdt->rp;
 +                      if (bkcnt > count) {
 +                              if (copy_to_user_dsp(buf, src, count)) {
 +                                      ret = -EFAULT;
 +                                      goto pv_out2;
 +                              }
 +                              ret = count;
 +                              rcvdt->rp += count;
 +                      } else {
 +                              if (copy_to_user_dsp(buf, src, bkcnt)) {
 +                                      ret = -EFAULT;
 +                                      goto pv_out2;
 +                              }
 +                              ret = bkcnt;
 +                              ipblink_del_pvt(&rcvdt->link);
 +                              release_ipbuf_pvt(ipbp);
 +                              rcvdt->rp = 0;
 +                      }
 +              pv_out2:
 +                      dsp_mem_disable(src);
 +              pv_out1:
 +                      dsp_mem_disable(ipbp);
 +              }
 +      } else {
 +              /* global */
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              while (!ipblink_empty(&rcvdt->link)) {
 +                      unsigned char *src;
 +                      size_t bkcnt;
 +                      struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
 +
 +                      src = ipb_h->p->d + rcvdt->rp;
 +                      bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
 +                      if (bkcnt > count) {
 +                              if (copy_to_user_dsp(buf, src, count)) {
 +                                      ret = -EFAULT;
 +                                      goto gb_out;
 +                              }
 +                              ret += count;
 +                              rcvdt->rp += count;
 +                              break;
 +                      } else {
 +                              if (copy_to_user_dsp(buf, src, bkcnt)) {
 +                                      ret = -EFAULT;
 +                                      goto gb_out;
 +                              }
 +                              ret += bkcnt;
 +                              buf += bkcnt;
 +                              count -= bkcnt;
 +                              ipblink_del_top(&rcvdt->link);
 +                              unuse_ipbuf(ipb_h);
 +                              rcvdt->rp = 0;
 +                      }
 +              }
 +      gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else {
 +              /* force! */
 +              count = 2;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
 +
 +      if (kfifo_len(dev->rcvdt.fifo) == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 +
 +up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +      int ret = 0;
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_read().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
 +                              &dev->read_wait_q);
 +
 +      if (ipblink_empty(&rcvdt->link)) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      /*
 +       * We will not receive more than requested count.
 +       */
 +      if (sndtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
 +              size_t rcvcnt;
 +              void *src;
 +
 +              if (dsp_mem_enable(ipbp) < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              src = MKVIRT(ipbp->ah, ipbp->al);
 +              rcvcnt = ((unsigned long)ipbp->c) * 2;
 +              if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
 +                                       dev->task->name) < 0) {
 +                      ret = -EINVAL;
 +                      goto pv_out1;
 +              }
 +              if (dsp_mem_enable(src) < 0) {
 +                      ret = -EBUSY;
 +                      goto pv_out1;
 +              }
 +              if (count > rcvcnt)
 +                      count = rcvcnt;
 +              if (copy_to_user_dsp(buf, src, count)) {
 +                      ret = -EFAULT;
 +                      goto pv_out2;
 +              }
 +              ipblink_del_pvt(&rcvdt->link);
 +              release_ipbuf_pvt(ipbp);
 +              ret = count;
 +pv_out2:
 +              dsp_mem_disable(src);
 +pv_out1:
 +              dsp_mem_disable(ipbp);
 +      } else {
 +              /* global */
 +              struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
 +              size_t rcvcnt;
 +
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
 +              if (count > rcvcnt)
 +                      count = rcvcnt;
 +              if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
 +                      ret = -EFAULT;
 +                      goto gb_out;
 +              }
 +              ipblink_del_top(&rcvdt->link);
 +              unuse_ipbuf(ipb_h);
 +              ret = count;
 +gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 +up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
 +                               size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      u16 wd;
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else {
 +              /* force! */
 +              count = 2;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (dev->wsz == 0)
 +              schedule();
 +      finish_wait(&dev->write_wait_q, &wait);
 +      if (dev->wsz == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      if (copy_from_user(&wd, buf, count)) {
 +              ret = -EFAULT;
 +              goto up_out;
 +      }
 +
 +      spin_lock(&dev->wsz_lock);
 +      if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
 +              spin_unlock(&dev->wsz_lock);
 +              goto up_out;
 +      }
 +      ret = count;
 +      if (rcvtyp_acv(dev->task->ttyp))
 +              dev->wsz = 0;
 +      spin_unlock(&dev->wsz_lock);
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
 +                               size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_write().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (dev->wsz == 0)
 +              schedule();
 +      finish_wait(&dev->write_wait_q, &wait);
 +      if (dev->wsz == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      if (count > dev->wsz)
 +              count = dev->wsz;
 +
 +      if (rcvtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
 +              unsigned char *dst;
 +
 +              if (dsp_mem_enable(ipbp) < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              dst = MKVIRT(ipbp->ah, ipbp->al);
 +              if (dsp_address_validate(dst, count, "task %s write buffer",
 +                                       dev->task->name) < 0) {
 +                      ret = -EINVAL;
 +                      goto pv_out1;
 +              }
 +              if (dsp_mem_enable(dst) < 0) {
 +                      ret = -EBUSY;
 +                      goto pv_out1;
 +              }
 +              if (copy_from_user_dsp(dst, buf, count)) {
 +                      ret = -EFAULT;
 +                      goto pv_out2;
 +              }
 +              ipbp->c = count/2;
 +              ipbp->s = dev->task->tid;
 +              spin_lock(&dev->wsz_lock);
 +              if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
 +                      if (rcvtyp_acv(dev->task->ttyp))
 +                              dev->wsz = 0;
 +                      ret = count;
 +              }
 +              spin_unlock(&dev->wsz_lock);
 +      pv_out2:
 +              dsp_mem_disable(dst);
 +      pv_out1:
 +              dsp_mem_disable(ipbp);
 +      } else {
 +              /* global */
 +              struct ipbuf_head *ipb_h;
 +
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
 +                      goto gb_out;
 +              if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
 +                      release_ipbuf(ipb_h);
 +                      ret = -EFAULT;
 +                      goto gb_out;
 +              }
 +              ipb_h->p->c  = count/2;
 +              ipb_h->p->sa = dev->task->tid;
 +              spin_lock(&dev->wsz_lock);
 +              if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
 +                      if (rcvtyp_acv(dev->task->ttyp))
 +                              dev->wsz = 0;
 +                      ret = count;
 +                      ipb_bsycnt_inc(&ipbcfg);
 +              } else
 +                      release_ipbuf(ipb_h);
 +              spin_unlock(&dev->wsz_lock);
 +      gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
 +      return ret;
 +}
 +
 +static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct dsptask *task = dev->task;
 +      unsigned int mask = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return 0;
 +      poll_wait(file, &dev->read_wait_q, wait);
 +      poll_wait(file, &dev->write_wait_q, wait);
 +      if (sndtyp_psv(task->ttyp) ||
 +          (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) ||
 +          (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
 +              mask |= POLLIN | POLLRDNORM;
 +      if (dev->wsz)
 +              mask |= POLLOUT | POLLWRNORM;
 +      devstate_read_unlock(dev);
 +
 +      return mask;
 +}
 +
 +static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
 +{
 +      int tctl_argc;
 +      struct mb_exarg mbarg, *mbargp;
 +      int interactive;
 +      u8 tid;
 +      int ret = 0;
 +
 +      if (cmd < 0x8000) {
 +              /*
 +               * 0x0000 - 0x7fff
 +               * system reserved TCTL commands
 +               */
 +              switch (cmd) {
 +              case TCTL_TEN:
 +              case TCTL_TDIS:
 +                      tctl_argc = 0;
 +                      interactive = 0;
 +                      break;
 +              default:
 +                      return -EINVAL;
 +              }
 +      }
 +      /*
 +       * 0x8000 - 0xffff
 +       * user-defined TCTL commands
 +       */
 +      else if (cmd < 0x8100) {
 +              /* 0x8000-0x80ff: no arg, non-interactive */
 +              tctl_argc = 0;
 +              interactive = 0;
 +      } else if (cmd < 0x8200) {
 +              /* 0x8100-0x81ff: 1 arg, non-interactive */
 +              tctl_argc = 1;
 +              interactive = 0;
 +      } else if (cmd < 0x9000) {
 +              /* 0x8200-0x8fff: reserved */
 +              return -EINVAL;
 +      } else if (cmd < 0x9100) {
 +              /* 0x9000-0x90ff: no arg, interactive */
 +              tctl_argc = 0;
 +              interactive = 1;
 +      } else if (cmd < 0x9200) {
 +              /* 0x9100-0x91ff: 1 arg, interactive */
 +              tctl_argc = 1;
 +              interactive = 1;
 +      } else {
 +              /* 0x9200-0xffff: reserved */
 +              return -EINVAL;
 +      }
 +
 +      /*
 +       * if argc < 0, use tctl_argc as is.
 +       * if argc >= 0, check arg count.
 +       */
 +      if ((argc >= 0) && (argc != tctl_argc))
 +              return -EINVAL;
 +
 +      /*
 +       * issue TCTL
 +       */
 +      if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
 +              return -EINTR;
 +
 +      tid = dev->task->tid;
 +      if (tctl_argc > 0) {
 +              mbarg.argc = tctl_argc;
 +              mbarg.tid  = tid;
 +              mbarg.argv = argv;
 +              mbargp = &mbarg;
 +      } else
 +              mbargp = NULL;
 +
 +      if (interactive) {
 +              dev->tctl_stat = -EINVAL;
 +
 +              mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
 +                                            &dev->tctl_wait_q);
 +              if (signal_pending(current)) {
 +                      ret = -EINTR;
 +                      goto up_out;
 +              }
 +              if ((ret = dev->tctl_stat) < 0) {
 +                      printk(KERN_ERR "omapdsp: TCTL not responding.\n");
 +                      goto up_out;
 +              }
 +      } else
 +              mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
 +
 +up_out:
 +      mutex_unlock(&dev->tctl_mutex);
 +      return ret;
 +}
 +
 +static int dsp_task_ioctl(struct inode *inode, struct file *file,
 +                        unsigned int cmd, unsigned long arg)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret;
 +
 +      if (cmd < 0x10000) {
 +              /* issue TCTL */
 +              u16 mbargv[1];
 +
 +              mbargv[0] = arg & 0xffff;
 +              return dsp_tctl_issue(dev, cmd, -1, mbargv);
 +      }
 +
 +      /* non TCTL ioctls */
 +      switch (cmd) {
 +
 +      case TASK_IOCTL_LOCK:
 +              ret = taskdev_lock(dev);
 +              break;
 +
 +      case TASK_IOCTL_UNLOCK:
 +              ret = taskdev_unlock(dev);
 +              break;
 +
 +      case TASK_IOCTL_BFLSH:
 +              if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +                      return -ENODEV;
 +              ret = taskdev_flush_buf(dev);
 +              taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +              break;
 +
 +      case TASK_IOCTL_SETBSZ:
 +              if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +                      return -ENODEV;
 +              ret = taskdev_set_fifosz(dev, arg);
 +              taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +              break;
 +
 +      case TASK_IOCTL_GETNAME:
 +              ret = 0;
 +              if (copy_to_user((void __user *)arg, dev->name,
 +                               strlen(dev->name) + 1))
 +                      ret = -EFAULT;
 +              break;
 +
 +      default:
 +              ret = -ENOIOCTLCMD;
 +
 +      }
 +
 +      return ret;
 +}
 +
 +static void dsp_task_mmap_open(struct vm_area_struct *vma)
 +{
 +      struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
 +      struct dsptask *task;
 +      size_t len = vma->vm_end - vma->vm_start;
 +
 +      BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
 +      task = dev->task;
 +      omap_mmu_exmap_use(&dsp_mmu, task->map_base, len);
 +}
 +
 +static void dsp_task_mmap_close(struct vm_area_struct *vma)
 +{
 +      struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
 +      struct dsptask *task;
 +      size_t len = vma->vm_end - vma->vm_start;
 +
 +      BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
 +      task = dev->task;
 +      omap_mmu_exmap_unuse(&dsp_mmu, task->map_base, len);
 +}
 +
 +/**
 + * On demand page allocation is not allowed. The mapping area is defined by
 + * corresponding DSP tasks.
 + */
 +static int dsp_task_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 +{
 +      return VM_FAULT_NOPAGE;
 +}
 +
 +static struct vm_operations_struct dsp_task_vm_ops = {
 +      .open = dsp_task_mmap_open,
 +      .close = dsp_task_mmap_close,
 +      .fault = dsp_task_mmap_fault,
 +};
 +
 +static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
 +{
 +      void *tmp_vadr;
 +      unsigned long tmp_padr, tmp_vmadr, off;
 +      size_t req_len, tmp_len;
 +      unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct dsptask *task;
 +      int ret = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +      task = dev->task;
 +
 +      /*
 +       * Don't swap this area out
 +       * Don't dump this area to a core file
 +       */
 +      vma->vm_flags |= VM_RESERVED | VM_IO;
 +
 +      /* Do not cache this area */
 +      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 +
 +      req_len = vma->vm_end - vma->vm_start;
 +      off = vma->vm_pgoff << PAGE_SHIFT;
 +      tmp_vmadr = vma->vm_start;
 +      tmp_vadr = task->map_base + off;
 +      do {
 +              tmp_padr = omap_mmu_virt_to_phys(&dsp_mmu, tmp_vadr, &tmp_len);
 +              if (tmp_padr == 0) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task %s: illegal address "
 +                             "for mmap: %p", task->name, tmp_vadr);
 +                      /* partial mapping will be cleared in upper layer */
 +                      ret = -EINVAL;
 +                      goto unlock_out;
 +              }
 +              if (tmp_len > req_len)
 +                      tmp_len = req_len;
 +
 +              pr_debug("omapdsp: mmap info: "
 +                       "vmadr = %08lx, padr = %08lx, len = %x\n",
 +                       tmp_vmadr, tmp_padr, tmp_len);
 +              if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
 +                                  tmp_len, vma->vm_page_prot) != 0) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task %s: remap_page_range() failed.\n",
 +                             task->name);
 +                      /* partial mapping will be cleared in upper layer */
 +                      ret = -EINVAL;
 +                      goto unlock_out;
 +              }
 +
 +              req_len   -= tmp_len;
 +              tmp_vmadr += tmp_len;
 +              tmp_vadr  += tmp_len;
 +      } while (req_len);
 +
 +      vma->vm_ops = &dsp_task_vm_ops;
 +      vma->vm_private_data = dev;
 +      omap_mmu_exmap_use(&dsp_mmu, task->map_base, vma->vm_end - vma->vm_start);
 +
 +unlock_out:
 +      devstate_read_unlock(dev);
 +      return ret;
 +}
 +
 +static int dsp_task_open(struct inode *inode, struct file *file)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev;
 +      int ret = 0;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
 +              return -ENODEV;
 +
 + restart:
 +      mutex_lock(&dev->usecount_lock);
 +      down_write(&dev->state_sem);
 +
 +      /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +      case TASKDEV_ST_NOTASK:
 +              break;
 +      case TASKDEV_ST_ATTACHED:
 +              goto attached;
 +
 +      case TASKDEV_ST_INVALID:
 +              up_write(&dev->state_sem);
 +              mutex_unlock(&dev->usecount_lock);
 +              return -ENODEV;
 +
 +      case TASKDEV_ST_FREEZED:
 +      case TASKDEV_ST_KILLING:
 +      case TASKDEV_ST_GARBAGE:
 +      case TASKDEV_ST_DELREQ:
 +              /* on the kill process. wait until it becomes NOTASK. */
 +              up_write(&dev->state_sem);
 +              mutex_unlock(&dev->usecount_lock);
 +              if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
 +                      return -EINTR;
 +              devstate_write_unlock(dev);
 +              goto restart;
 +      }
 +
 +      /* NOTASK */
 +      set_taskdev_state(dev, TASKDEV_ST_ADDREQ);
 +      /* wake up twch daemon for tadd */
 +      dsp_twch_touch();
 +      up_write(&dev->state_sem);
 +      if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
 +                              TASKDEV_ST_ADDFAIL) < 0) {
 +              /* cancelled */
 +              if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
 +                      mutex_unlock(&dev->usecount_lock);
 +                      /* out of control ??? */
 +                      return -EINTR;
 +              }
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              ret = -EINTR;
 +              goto change_out;
 +      }
 +      if (dev->state & TASKDEV_ST_ADDFAIL) {
 +              printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
 +                     dev->name);
 +              ret = -EBUSY;
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              goto change_out;
 +      }
 +
 + attached:
 +      ret = proc_list_add(&dev->proc_list_lock,
 +                          &dev->proc_list, current, file);
 +      if (ret)
 +              goto out;
 +
 +      dev->usecount++;
 +      file->f_op = &dev->fops;
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +
 +#ifdef DSP_PTE_FREE   /* not used currently. */
 +      dsp_map_update(current);
 +      dsp_cur_users_add(current);
 +#endif /* DSP_PTE_FREE */
 +      return 0;
 +
 + change_out:
 +      wake_up_interruptible_all(&dev->state_wait_q);
 + out:
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +      return ret;
 +}
 +
 +static int dsp_task_release(struct inode *inode, struct file *file)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +
 +#ifdef DSP_PTE_FREE   /* not used currently. */
 +      dsp_cur_users_del(current);
 +#endif /* DSP_PTE_FREE */
 +
 +      if (has_taskdev_lock(dev))
 +              taskdev_unlock(dev);
 +
 +      proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
 +      mutex_lock(&dev->usecount_lock);
 +      if (--dev->usecount > 0) {
 +              /* other processes are using this device. no state change. */
 +              mutex_unlock(&dev->usecount_lock);
 +              return 0;
 +      }
 +
 +      /* usecount == 0 */
 +      down_write(&dev->state_sem);
 +
 +      /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +
 +      case TASKDEV_ST_KILLING:
 +              break;
 +
 +      case TASKDEV_ST_GARBAGE:
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_ATTACHED:
 +      case TASKDEV_ST_FREEZED:
 +              if (is_dynamic_task(minor)) {
 +                      set_taskdev_state(dev, TASKDEV_ST_DELREQ);
 +                      /* wake up twch daemon for tdel */
 +                      dsp_twch_touch();
 +              }
 +              break;
 +
 +      }
 +
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +      return 0;
 +}
 +
 +/*
 + * mkdev / rmdev
 + */
 +int dsp_mkdev(char *name)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      unsigned char minor;
 +      int ret;
 +
 +      if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
 +              printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      /* naming check */
 +      for (minor = 0; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task device name %s is already "
 +                             "in use.\n", name);
 +                      ret = -EINVAL;
 +                      goto out;
 +              }
 +      }
 +
 +      /* find free minor number */
 +      for (minor = n_task; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] == NULL)
 +                      goto do_make;
 +      }
 +      printk(KERN_ERR "omapdsp: Too many task devices.\n");
 +      ret = -EBUSY;
 +      goto out;
 +
 +do_make:
 +      if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
 +              ret = -ENOMEM;
 +              goto out;
 +      }
 +      if ((status = taskdev_init(dev, name, minor)) < 0) {
 +              kfree(dev);
 +              ret = status;
 +              goto out;
 +      }
 +      ret = minor;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +int dsp_rmdev(char *name)
 +{
 +      unsigned char minor;
 +      int status;
 +      int ret;
 +
 +      if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
 +              printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      /* find in dynamic devices */
 +      for (minor = n_task; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
 +                      goto do_remove;
 +      }
 +
 +      /* find in static devices */
 +      for (minor = 0; minor < n_task; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task device %s is static.\n", name);
 +                      ret = -EINVAL;
 +                      goto out;
 +              }
 +      }
 +
 +      printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
 +      return -EINVAL;
 +
 +do_remove:
 +      ret = minor;
 +      if ((status = dsp_rmdev_minor(minor)) < 0)
 +              ret = status;
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_rmdev_minor(unsigned char minor)
 +{
 +      struct taskdev *dev = taskdev[minor];
 +
 +      while (!down_write_trylock(&dev->state_sem)) {
 +              down_read(&dev->state_sem);
 +              if (dev->state & (TASKDEV_ST_ATTACHED |
 +                                TASKDEV_ST_FREEZED)) {
 +                      /*
 +                       * task is working. kill it.
 +                       * ATTACHED -> FREEZED can be changed under
 +                       * down_read of state_sem..
 +                       */
 +                      set_taskdev_state(dev, TASKDEV_ST_FREEZED);
 +                      wake_up_interruptible_all(&dev->read_wait_q);
 +                      wake_up_interruptible_all(&dev->write_wait_q);
 +                      wake_up_interruptible_all(&dev->tctl_wait_q);
 +              }
 +              up_read(&dev->state_sem);
 +              schedule();
 +      }
 +
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +
 +      case TASKDEV_ST_NOTASK:
 +      case TASKDEV_ST_INVALID:
 +              /* fine */
 +              goto notask;
 +
 +      case TASKDEV_ST_ATTACHED:
 +      case TASKDEV_ST_FREEZED:
 +              /* task is working. kill it. */
 +              set_taskdev_state(dev, TASKDEV_ST_KILLING);
 +              up_write(&dev->state_sem);
 +              dsp_tdel_bh(dev, TDEL_KILL);
 +              goto invalidate;
 +
 +      case TASKDEV_ST_ADDREQ:
 +              /* open() is waiting. drain it. */
 +              set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_DELREQ:
 +              /* nobody is waiting. */
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_ADDING:
 +      case TASKDEV_ST_DELING:
 +      case TASKDEV_ST_KILLING:
 +      case TASKDEV_ST_GARBAGE:
 +      case TASKDEV_ST_ADDFAIL:
 +              /* transient state. wait for a moment. */
 +              break;
 +
 +      }
 +
 +      up_write(&dev->state_sem);
 +
 +invalidate:
 +      /* wait for some time and hope the state is settled */
 +      devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
 +      if (!(dev->state & TASKDEV_ST_NOTASK)) {
 +              printk(KERN_WARNING
 +                     "omapdsp: illegal device state (%s) on rmdev %s.\n",
 +                     devstate_name(dev->state), dev->name);
 +      }
 +notask:
 +      set_taskdev_state(dev, TASKDEV_ST_INVALID);
 +      devstate_read_unlock(dev);
 +
 +      taskdev_delete(minor);
 +      kfree(dev);
 +
 +      return 0;
 +}
 +
 +static struct file_operations dsp_task_fops = {
 +      .owner   = THIS_MODULE,
 +      .poll    = dsp_task_poll,
 +      .ioctl   = dsp_task_ioctl,
 +      .open    = dsp_task_open,
 +      .release = dsp_task_release,
 +};
 +
 +static void dsptask_dev_release(struct device *dev)
 +{
 +}
 +
 +static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
 +{
 +      int ret;
 +      struct device *task_dev;
 +
 +      taskdev[minor] = dev;
 +
 +      spin_lock_init(&dev->proc_list_lock);
 +      INIT_LIST_HEAD(&dev->proc_list);
 +      init_waitqueue_head(&dev->read_wait_q);
 +      init_waitqueue_head(&dev->write_wait_q);
 +      init_waitqueue_head(&dev->tctl_wait_q);
 +      mutex_init(&dev->read_mutex);
 +      mutex_init(&dev->write_mutex);
 +      mutex_init(&dev->tctl_mutex);
 +      mutex_init(&dev->lock);
 +      spin_lock_init(&dev->wsz_lock);
 +      dev->tctl_ret = -EINVAL;
 +      dev->lock_pid = 0;
 +
 +      strncpy(dev->name, name, TNM_LEN);
 +      dev->name[TNM_LEN-1] = '\0';
 +      set_taskdev_state(dev, (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK);
 +      dev->usecount = 0;
 +      mutex_init(&dev->usecount_lock);
 +      memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
 +
 +      dev->dev.parent = omap_dsp->dev;
 +      dev->dev.bus = &dsptask_bus;
 +      sprintf(dev->dev.bus_id, "dsptask%d", minor);
 +      dev->dev.release = dsptask_dev_release;
 +      ret = device_register(&dev->dev);
 +      if (ret) {
 +              printk(KERN_ERR "device_register failed: %d\n", ret);
 +              return ret;
 +      }
 +      ret = device_create_file(&dev->dev, &dev_attr_devname);
 +      if (ret)
 +              goto fail_create_devname;
 +      ret = device_create_file(&dev->dev, &dev_attr_devstate);
 +      if (ret)
 +              goto fail_create_devstate;
 +      ret = device_create_file(&dev->dev, &dev_attr_proc_list);
 +      if (ret)
 +              goto fail_create_proclist;
 +
 +      task_dev = device_create(dsp_task_class, NULL,
 +                               MKDEV(OMAP_DSP_TASK_MAJOR, minor), NULL,
 +                               "dsptask%d", (int)minor);
 +
 +      if (unlikely(IS_ERR(task_dev))) {
 +              ret = -EINVAL;
 +              goto fail_create_taskclass;
 +      }
 +
 +      init_waitqueue_head(&dev->state_wait_q);
 +      init_rwsem(&dev->state_sem);
 +
 +      return 0;
 +
 + fail_create_taskclass:
 +      device_remove_file(&dev->dev, &dev_attr_proc_list);
 + fail_create_proclist:
 +      device_remove_file(&dev->dev, &dev_attr_devstate);
 + fail_create_devstate:
 +      device_remove_file(&dev->dev, &dev_attr_devname);
 + fail_create_devname:
 +      device_unregister(&dev->dev);
 +      return ret;
 +}
 +
 +static void taskdev_delete(unsigned char minor)
 +{
 +      struct taskdev *dev = taskdev[minor];
 +
 +      if (!dev)
 +              return;
 +      device_remove_file(&dev->dev, &dev_attr_devname);
 +      device_remove_file(&dev->dev, &dev_attr_devstate);
 +      device_remove_file(&dev->dev, &dev_attr_proc_list);
 +      device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
 +      device_unregister(&dev->dev);
 +      proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
 +      taskdev[minor] = NULL;
 +}
 +
 +static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
 +{
 +      u16 ttyp = task->ttyp;
 +      int ret;
 +
 +      dev->fops.read =
 +              sndtyp_acv(ttyp) ?
 +              sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
 +              /* sndtyp_bk */   dsp_task_read_bk_acv:
 +              /* sndtyp_psv */
 +              sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
 +              /* sndtyp_bk */   dsp_task_read_bk_psv;
 +      if (sndtyp_wd(ttyp)) {
 +              /* word */
 +              size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */
 +
 +              dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL,
 +                                            &dev->read_lock);
 +              if (IS_ERR(dev->rcvdt.fifo)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: unable to allocate receive buffer. "
 +                             "(%d bytes for %s)\n", fifosz, dev->name);
 +                      return -ENOMEM;
 +              }
 +      } else {
 +              /* block */
 +              INIT_IPBLINK(&dev->rcvdt.bk.link);
 +              dev->rcvdt.bk.rp = 0;
 +      }
 +
 +      dev->fops.write =
 +              rcvtyp_wd(ttyp) ? dsp_task_write_wd:
 +              /* rcvbyp_bk */   dsp_task_write_bk;
 +      dev->wsz = rcvtyp_acv(ttyp) ? 0 :               /* active */
 +              rcvtyp_wd(ttyp)  ? 2 :          /* passive word */
 +              ipbcfg.lsz*2;   /* passive block */
 +
 +      if (task->map_length)
 +              dev->fops.mmap = dsp_task_mmap;
 +
 +      ret = device_create_file(&dev->dev, &dev_attr_taskname);
 +      if (unlikely(ret))
 +              goto fail_create_taskname;
 +      ret = device_create_file(&dev->dev, &dev_attr_ttyp);
 +      if (unlikely(ret))
 +              goto fail_create_ttyp;
 +      ret = device_create_file(&dev->dev, &dev_attr_wsz);
 +      if (unlikely(ret))
 +              goto fail_create_wsz;
 +      if (task->map_length) {
 +              ret = device_create_file(&dev->dev, &dev_attr_mmap);
 +              if (unlikely(ret))
 +                      goto fail_create_mmap;
 +      }
 +      if (sndtyp_wd(ttyp)) {
 +              ret = device_create_file(&dev->dev, &dev_attr_fifosz);
 +              if (unlikely(ret))
 +                      goto fail_create_fifosz;
 +              ret = device_create_file(&dev->dev, &dev_attr_fifocnt);
 +              if (unlikely(ret))
 +                      goto fail_create_fifocnt;
 +      } else {
 +              ret = device_create_file(&dev->dev, &dev_attr_ipblink);
 +              if (unlikely(ret))
 +                      goto fail_create_ipblink;
 +      }
 +
 +      dev->task = task;
 +      task->dev = dev;
 +
 +      return 0;
 +
 + fail_create_fifocnt:
 +      device_remove_file(&dev->dev, &dev_attr_fifosz);
 + fail_create_ipblink:
 + fail_create_fifosz:
 +      if (task->map_length)
 +              device_remove_file(&dev->dev, &dev_attr_mmap);
 + fail_create_mmap:
 +      device_remove_file(&dev->dev, &dev_attr_wsz);
 + fail_create_wsz:
 +      device_remove_file(&dev->dev, &dev_attr_ttyp);
 + fail_create_ttyp:
 +      device_remove_file(&dev->dev, &dev_attr_taskname);
 + fail_create_taskname:
 +      if (task->map_length)
 +              dev->fops.mmap = NULL;
 +
 +      dev->fops.write = NULL;
 +      dev->wsz = 0;
 +
 +      dev->fops.read = NULL;
 +      taskdev_flush_buf(dev);
 +
 +      if (sndtyp_wd(ttyp))
 +              kfifo_free(dev->rcvdt.fifo);
 +
 +      dev->task = NULL;
 +
 +      return ret;
 +}
 +
 +static void taskdev_detach_task(struct taskdev *dev)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      device_remove_file(&dev->dev, &dev_attr_taskname);
 +      device_remove_file(&dev->dev, &dev_attr_ttyp);
 +      if (sndtyp_wd(ttyp)) {
 +              device_remove_file(&dev->dev, &dev_attr_fifosz);
 +              device_remove_file(&dev->dev, &dev_attr_fifocnt);
 +      } else
 +              device_remove_file(&dev->dev, &dev_attr_ipblink);
 +      device_remove_file(&dev->dev, &dev_attr_wsz);
 +      if (dev->task->map_length) {
 +              device_remove_file(&dev->dev, &dev_attr_mmap);
 +              dev->fops.mmap = NULL;
 +      }
 +
 +      dev->fops.read = NULL;
 +      taskdev_flush_buf(dev);
 +      if (sndtyp_wd(ttyp))
 +              kfifo_free(dev->rcvdt.fifo);
 +
 +      dev->fops.write = NULL;
 +      dev->wsz = 0;
 +
 +      pr_info("omapdsp: taskdev %s disabled.\n", dev->name);
 +      dev->task = NULL;
 +}
 +
 +/*
 + * tadd / tdel / tkill
 + */
 +static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
 +{
 +      struct dsptask *task;
 +      struct mb_exarg arg;
 +      u8 tid, tid_response;
 +      u16 argv[2];
 +      int ret = 0;
 +
 +      if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
 +              printk(KERN_ERR
 +                     "omapdsp: taskdev %s is not requesting for tadd. "
 +                     "(state is %s)\n", dev->name, devstate_name(dev->state));
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_ADDING);
 +      devstate_write_unlock(dev);
 +
 +      if (adr == TADD_ABORTADR) {
 +              /* aborting tadd intentionally */
 +              pr_info("omapdsp: tadd address is ABORTADR.\n");
 +              goto fail_out;
 +      }
 +      if (adr >= DSPSPACE_SIZE) {
 +              printk(KERN_ERR
 +                     "omapdsp: illegal address 0x%08x for tadd\n", adr);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      adr >>= 1;      /* word address */
 +      argv[0] = adr >> 16;    /* addrh */
 +      argv[1] = adr & 0xffff; /* addrl */
 +
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              ret = -EINTR;
 +              goto fail_out;
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TADD;
 +      arg.tid  = TID_ANON;
 +      arg.argc = 2;
 +      arg.argv = argv;
 +
 +      if (dsp_mem_sync_inc() < 0) {
 +              printk(KERN_ERR "omapdsp: memory sync failed!\n");
 +              ret = -EBUSY;
 +              goto fail_out;
 +      }
 +      mbcompose_send_and_wait_exarg(TADD, 0, 0, &arg, &cfg_wait_q);
 +
 +      tid = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (tid == TID_ANON) {
 +              printk(KERN_ERR "omapdsp: tadd failed!\n");
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if ((tid < n_task) || dsptask[tid]) {
 +              printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
 +              ret = -ENOMEM;
 +              goto del_out;
 +      }
 +
 +      if ((ret = dsp_task_config(task, tid)) < 0)
 +              goto free_out;
 +
 +      if (strcmp(dev->name, task->name)) {
 +              printk(KERN_ERR
 +                     "omapdsp: task name (%s) doesn't match with "
 +                     "device name (%s).\n", task->name, dev->name);
 +              ret = -EINVAL;
 +              goto free_out;
 +      }
 +
 +      if ((ret = taskdev_attach_task(dev, task)) < 0)
 +              goto free_out;
 +
 +      dsp_task_init(task);
 +      pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
 +      set_taskdev_state(dev, TASKDEV_ST_ATTACHED);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      return 0;
 +
 +free_out:
 +      kfree(task);
 +
 +del_out:
 +      printk(KERN_ERR "omapdsp: deleting the task...\n");
 +
 +      set_taskdev_state(dev, TASKDEV_ST_DELING);
 +
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              printk(KERN_ERR "omapdsp: aborting tdel process. "
 +                              "DSP side could be corrupted.\n");
 +              goto fail_out;
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TDEL;
 +      mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
 +      tid_response = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (tid_response != tid)
 +              printk(KERN_ERR "omapdsp: tdel failed. "
 +                              "DSP side could be corrupted.\n");
 +
 +fail_out:
 +      set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      return ret;
 +}
 +
 +int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +      ret = minor;
 +      if ((status = dsp_tadd(dev, adr)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tdel(struct taskdev *dev)
 +{
 +      if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
 +              printk(KERN_ERR
 +                     "omapdsp: taskdev %s is not requesting for tdel. "
 +                     "(state is %s)\n", dev->name, devstate_name(dev->state));
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_DELING);
 +      devstate_write_unlock(dev);
 +
 +      return dsp_tdel_bh(dev, TDEL_SAFE);
 +}
 +
 +int dsp_tdel_minor(unsigned char minor)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      ret = minor;
 +      if ((status = dsp_tdel(dev)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tkill(struct taskdev *dev)
 +{
 +      while (!down_write_trylock(&dev->state_sem)) {
 +              if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
 +                                                     TASKDEV_ST_FREEZED))) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task has not been attached for "
 +                             "taskdev %s\n", dev->name);
 +                      return -EINVAL;
 +              }
 +              /* ATTACHED -> FREEZED can be changed under read semaphore. */
 +              set_taskdev_state(dev, TASKDEV_ST_FREEZED);
 +              wake_up_interruptible_all(&dev->read_wait_q);
 +              wake_up_interruptible_all(&dev->write_wait_q);
 +              wake_up_interruptible_all(&dev->tctl_wait_q);
 +              devstate_read_unlock(dev);
 +              schedule();
 +      }
 +
 +      if (!(dev->state & (TASKDEV_ST_ATTACHED |
 +                          TASKDEV_ST_FREEZED))) {
 +              printk(KERN_ERR
 +                     "omapdsp: task has not been attached for taskdev %s\n",
 +                     dev->name);
 +              devstate_write_unlock(dev);
 +              return -EINVAL;
 +      }
 +      if (!is_dynamic_task(dev->task->tid)) {
 +              printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
 +                     dev->name);
 +              devstate_write_unlock(dev);
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_KILLING);
 +      devstate_write_unlock(dev);
 +
 +      return dsp_tdel_bh(dev, TDEL_KILL);
 +}
 +
 +int dsp_tkill_minor(unsigned char minor)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      ret = minor;
 +      if ((status = dsp_tkill(dev)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tdel_bh(struct taskdev *dev, u16 type)
 +{
 +      struct dsptask *task;
 +      u8 tid, tid_response;
 +      int ret = 0;
 +
 +      task = dev->task;
 +      tid = task->tid;
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              if (type == TDEL_SAFE) {
 +                      set_taskdev_state(dev, TASKDEV_ST_DELREQ);
 +                      return -EINTR;
 +              } else {
 +                      tid_response = TID_ANON;
 +                      ret = -EINTR;
 +                      goto detach_out;
 +              }
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TDEL;
 +      mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
 +      tid_response = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +detach_out:
 +      taskdev_detach_task(dev);
 +      dsp_task_unconfig(task);
 +      kfree(task);
 +
 +      if (tid_response != tid) {
 +              printk(KERN_ERR "omapdsp: %s failed!\n",
 +                     (type == TDEL_SAFE) ? "tdel" : "tkill");
 +              ret = -EINVAL;
 +      }
 +      down_write(&dev->state_sem);
 +      set_taskdev_state(dev, (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
 +                                         TASKDEV_ST_NOTASK);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      up_write(&dev->state_sem);
 +
 +      return ret;
 +}
 +
 +/*
 + * state inquiry
 + */
 +long taskdev_state_stale(unsigned char minor)
 +{
 +      if (taskdev[minor]) {
 +              long state = taskdev[minor]->state;
 +              taskdev[minor]->state |= TASKDEV_ST_STALE;
 +              return state;
 +      } else
 +              return TASKDEV_ST_NOTASK;
 +}
 +
 +/*
 + * functions called from mailbox interrupt routine
 + */
 +void mbox_wdsnd(struct mbcmd *mb)
 +{
 +      unsigned int n;
 +      u8 tid = mb->cmd_l;
 +      u16 data = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: WDSND with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (sndtyp_bk(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: WDSND from block sending task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (sndtyp_psv(task->ttyp) &&
 +          !waitqueue_active(&task->dev->read_wait_q)) {
 +              printk(KERN_WARNING
 +                     "mbox: WDSND from passive sending task (task%d) "
 +                     "without request!\n", tid);
 +              return;
 +      }
 +
 +      n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data,
 +                    sizeof(data));
 +      if (n != sizeof(data))
 +              printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid);
 +
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +}
 +
 +void mbox_wdreq(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: WDREQ with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: WDREQ from passive receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = 2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_bksnd(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      u16 bid = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +      struct ipbuf_head *ipb_h;
 +      u16 cnt;
 +
 +      if (bid >= ipbcfg.ln) {
 +              printk(KERN_ERR "mbox: BKSND with illegal bid! %d\n", bid);
 +              return;
 +      }
 +      ipb_h = bid_to_ipbuf(bid);
 +      ipb_bsycnt_dec(&ipbcfg);
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKSND with illegal tid! %d\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sndtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSND from word sending task! (task%d)\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sndtyp_pvt(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSND from private sending task! (task%d)\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKSND - IPBUF sync failed!\n");
 +              return;
 +      }
 +
 +      /* should be done in DSP, but just in case. */
 +      ipb_h->p->next = BID_NULL;
 +
 +      cnt = ipb_h->p->c;
 +      if (cnt > ipbcfg.lsz) {
 +              printk(KERN_ERR "mbox: BKSND cnt(%d) > ipbuf line size(%d)!\n",
 +                     cnt, ipbcfg.lsz);
 +              goto unuse_ipbuf_out;
 +      }
 +
 +      if (cnt == 0) {
 +              /* 0-byte send from DSP */
 +              unuse_ipbuf_nowait(ipb_h);
 +              goto done;
 +      }
 +      ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
 +      /* we keep coming bid and return alternative line to DSP. */
 +      balance_ipbuf();
 +
 +done:
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +      return;
 +
 +unuse_ipbuf_out:
 +      unuse_ipbuf_nowait(ipb_h);
 +      return;
 +}
 +
 +void mbox_bkreq(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      u16 cnt = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKREQ with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from word receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_pvt(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from private receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from passive receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = cnt*2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_bkyld(struct mbcmd *mb)
 +{
 +      u16 bid = mb->data;
 +      struct ipbuf_head *ipb_h;
 +
 +      if (bid >= ipbcfg.ln) {
 +              printk(KERN_ERR "mbox: BKYLD with illegal bid! %d\n", bid);
 +              return;
 +      }
 +      ipb_h = bid_to_ipbuf(bid);
 +
 +      /* should be done in DSP, but just in case. */
 +      ipb_h->p->next = BID_NULL;
 +
 +      /* we don't need to sync with DSP */
 +      ipb_bsycnt_dec(&ipbcfg);
 +      release_ipbuf(ipb_h);
 +}
 +
 +void mbox_bksndp(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct ipbuf_p *ipbp;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKSNDP with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (sndtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSNDP from word sending task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (sndtyp_gbl(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSNDP from non-private sending task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      /*
 +       * we should not have delayed block at this point
 +       * because read() routine releases the lock of the buffer and
 +       * until then DSP can't send next data.
 +       */
 +
 +      ipbp = task->ipbuf_pvt_r;
 +      if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKSNDP - IPBUF sync failed!\n");
 +              return;
 +      }
 +      pr_debug("mbox: ipbuf_pvt_r->a = 0x%08lx\n",
 +             MKLONG(ipbp->ah, ipbp->al));
 +      ipblink_add_pvt(&task->dev->rcvdt.bk.link);
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +}
 +
 +void mbox_bkreqp(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +      struct ipbuf_p *ipbp;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKREQP with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from word receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_gbl(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from non-private receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from passive receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +
 +      ipbp = task->ipbuf_pvt_w;
 +      if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKREQP - IPBUF sync failed!\n");
 +              return;
 +      }
 +      pr_debug("mbox: ipbuf_pvt_w->a = 0x%08lx\n",
 +             MKLONG(ipbp->ah, ipbp->al));
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = ipbp->c*2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_tctl(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: TCTL with illegal tid! %d\n", tid);
 +              return;
 +      }
 +
 +      if (!waitqueue_active(&task->dev->tctl_wait_q)) {
 +              printk(KERN_WARNING "mbox: unexpected TCTL from DSP!\n");
 +              return;
 +      }
 +
 +      task->dev->tctl_stat = mb->data;
 +      wake_up_interruptible(&task->dev->tctl_wait_q);
 +}
 +
 +void mbox_tcfg(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      u16 *tnm;
 +      volatile u16 *buf;
 +      int i;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: TCFG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBOX_CMD_DSP_TCFG)) {
 +              printk(KERN_WARNING "mbox: unexpected TCFG from DSP!\n");
 +              return;
 +      }
 +
 +      if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +              printk(KERN_ERR "mbox: TCFG - ipbuf_sys_da read failed!\n");
 +              dsp_mem_disable(ipbuf_sys_da);
 +              goto out;
 +      }
 +      if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: TCFG - IPBUF sync failed!\n");
 +              dsp_mem_disable(ipbuf_sys_da);
 +              goto out;
 +      }
 +
 +      /*
 +       * read configuration data on system IPBUF
 +       */
 +      buf = ipbuf_sys_da->d;
 +      task->ttyp        = buf[0];
 +      task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
 +      task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]);
 +      task->map_base    = MKVIRT(buf[5], buf[6]);
 +      task->map_length  = MKLONG(buf[7], buf[8]) << 1;        /* word -> byte */
 +      tnm               = MKVIRT(buf[9], buf[10]);
 +      release_ipbuf_pvt(ipbuf_sys_da);
 +      dsp_mem_disable(ipbuf_sys_da);
 +
 +      /*
 +       * copy task name string
 +       */
 +      if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
 +              task->name[0] = '\0';
 +              goto out;
 +      }
 +
 +      for (i = 0; i < TNM_LEN-1; i++) {
 +              /* avoiding byte access */
 +              u16 tmp = tnm[i];
 +              task->name[i] = tmp & 0x00ff;
 +              if (!tmp)
 +                      break;
 +      }
 +      task->name[TNM_LEN-1] = '\0';
 +
 +      task->state = TASK_ST_READY;
 +out:
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_tadd(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +
 +      if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TADD)) {
 +              printk(KERN_WARNING "mbox: unexpected TADD from DSP!\n");
 +              return;
 +      }
 +      cfg_tid = tid;
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_tdel(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +
 +      if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TDEL)) {
 +              printk(KERN_WARNING "mbox: unexpected TDEL from DSP!\n");
 +              return;
 +      }
 +      cfg_tid = tid;
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_err_fatal(u8 tid)
 +{
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: FATAL ERR with illegal tid! %d\n", tid);
 +              return;
 +      }
 +
 +      /* wake up waiting processes */
 +      dev = task->dev;
 +      wake_up_interruptible_all(&dev->read_wait_q);
 +      wake_up_interruptible_all(&dev->write_wait_q);
 +      wake_up_interruptible_all(&dev->tctl_wait_q);
 +}
 +
 +static u16 *dbg_buf;
 +static u16 dbg_buf_sz, dbg_line_sz;
 +static int dbg_rp;
 +
 +int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
 +{
 +#ifdef OLD_BINARY_SUPPORT
 +      if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
 +              dbg_buf = NULL;
 +              dbg_buf_sz = 0;
 +              dbg_line_sz = 0;
 +              dbg_rp = 0;
 +              return 0;
 +      }
 +#endif
 +
 +      if (dsp_address_validate(buf, sz, "debug buffer") < 0)
 +              return -1;
 +
 +      if (lsz > sz) {
 +              printk(KERN_ERR
 +                     "omapdsp: dbg_buf lsz (%d) is greater than its "
 +                     "buffer size (%d)\n", lsz, sz);
 +              return -1;
 +      }
 +
 +      dbg_buf = buf;
 +      dbg_buf_sz = sz;
 +      dbg_line_sz = lsz;
 +      dbg_rp = 0;
 +
 +      return 0;
 +}
 +
 +void dsp_dbg_stop(void)
 +{
 +      dbg_buf = NULL;
 +}
 +
 +#ifdef OLD_BINARY_SUPPORT
 +static void mbox_dbg_old(struct mbcmd *mb);
 +#endif
 +
 +void mbox_dbg(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      int cnt = mb->data;
 +      char s[80], *s_end = &s[79], *p;
 +      u16 *src;
 +      int i;
 +
 +#ifdef OLD_BINARY_SUPPORT
 +      if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
 +              mbox_dbg_old(mb);
 +              return;
 +      }
 +#endif
 +
 +      if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
 +          (tid != TID_ANON)) {
 +              printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (dbg_buf == NULL) {
 +              printk(KERN_ERR "mbox: DBG command received, but "
 +                     "dbg_buf has not been configured yet.\n");
 +              return;
 +      }
 +
 +      if (dsp_mem_enable(dbg_buf) < 0)
 +              return;
 +
 +      src = &dbg_buf[dbg_rp];
 +      p = s;
 +      for (i = 0; i < cnt; i++) {
 +              u16 tmp;
 +              /*
 +               * Be carefull that dbg_buf should not be read with
 +               * 1-byte access since it might be placed in DARAM/SARAM
 +               * and it can cause unexpected byteswap.
 +               * For example,
 +               *   *(p++) = *(src++) & 0xff;
 +               * causes 1-byte access!
 +               */
 +              tmp = *src++;
 +              *(p++) = tmp & 0xff;
 +              if (*(p-1) == '\n') {
 +                      *p = '\0';
 +                      pr_info("%s", s);
 +                      p = s;
 +                      continue;
 +              }
 +              if (p == s_end) {
 +                      *p = '\0';
 +                      pr_info("%s\n", s);
 +                      p = s;
 +                      continue;
 +              }
 +      }
 +      if (p > s) {
 +              *p = '\0';
 +              pr_info("%s\n", s);
 +      }
 +      if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz)
 +              dbg_rp = 0;
 +
 +      dsp_mem_disable(dbg_buf);
 +}
 +
 +#ifdef OLD_BINARY_SUPPORT
 +static void mbox_dbg_old(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      char s[80], *s_end = &s[79], *p;
 +      u16 *src;
 +      volatile u16 *buf;
 +      int cnt;
 +      int i;
 +
 +      if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
 +          (tid != TID_ANON)) {
 +              printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +              printk(KERN_ERR "mbox: DBG - ipbuf_sys_da read failed!\n");
 +              return;
 +      }
 +      if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: DBG - IPBUF sync failed!\n");
 +              goto out1;
 +      }
 +      buf = ipbuf_sys_da->d;
 +      cnt = buf[0];
 +      src = MKVIRT(buf[1], buf[2]);
 +      if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
 +              goto out2;
 +
 +      if (dsp_mem_enable(src) < 0)
 +              goto out2;
 +
 +      p = s;
 +      for (i = 0; i < cnt; i++) {
 +              u16 tmp;
 +              /*
 +               * Be carefull that ipbuf should not be read with
 +               * 1-byte access since it might be placed in DARAM/SARAM
 +               * and it can cause unexpected byteswap.
 +               * For example,
 +               *   *(p++) = *(src++) & 0xff;
 +               * causes 1-byte access!
 +               */
 +              tmp = *src++;
 +              *(p++) = tmp & 0xff;
 +              if (*(p-1) == '\n') {
 +                      *p = '\0';
 +                      pr_info("%s", s);
 +                      p = s;
 +                      continue;
 +              }
 +              if (p == s_end) {
 +                      *p = '\0';
 +                      pr_info("%s\n", s);
 +                      p = s;
 +                      continue;
 +              }
 +      }
 +      if (p > s) {
 +              *p = '\0';
 +              pr_info("%s\n", s);
 +      }
 +
 +      dsp_mem_disable(src);
 +out2:
 +      release_ipbuf_pvt(ipbuf_sys_da);
 +out1:
 +      dsp_mem_disable(ipbuf_sys_da);
 +}
 +#endif /* OLD_BINARY_SUPPORT */
 +
 +/*
 + * sysfs files: for each device
 + */
 +
 +/* devname */
 +static ssize_t devname_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      return sprintf(buf, "%s\n", to_taskdev(d)->name);
 +}
 +
 +/* devstate */
 +static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
 +}
 +
 +/* proc_list */
 +static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
 +                            char *buf)
 +{
 +      struct taskdev *dev;
 +      struct proc_list *pl;
 +      int len = 0;
 +
 +      dev = to_taskdev(d);
 +      spin_lock(&dev->proc_list_lock);
 +      list_for_each_entry(pl, &dev->proc_list, list_head) {
 +              /* need to lock tasklist_lock before calling
 +               * find_task_by_pid_type. */
 +              if (find_task_by_pid_type_ns(PIDTYPE_PID, pl->pid, &init_pid_ns) != NULL)
 +                      len += sprintf(buf + len, "%d\n", pl->pid);
 +              read_unlock(&tasklist_lock);
 +      }
 +      spin_unlock(&dev->proc_list_lock);
 +
 +      return len;
 +}
 +
 +/* taskname */
 +static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      int len;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      len = sprintf(buf, "%s\n", dev->task->name);
 +
 +      devstate_read_unlock(dev);
 +      return len;
 +}
 +
 +/* ttyp */
 +static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
 +                       char *buf)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      u16 ttyp;
 +      int len = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      ttyp = dev->task->ttyp;
 +      len += sprintf(buf + len, "0x%04x\n", ttyp);
 +      len += sprintf(buf + len, "%s %s send\n",
 +                      (sndtyp_acv(ttyp)) ? "active" :
 +                                           "passive",
 +                      (sndtyp_wd(ttyp))  ? "word" :
 +                      (sndtyp_pvt(ttyp)) ? "private block" :
 +                                           "global block");
 +      len += sprintf(buf + len, "%s %s receive\n",
 +                      (rcvtyp_acv(ttyp)) ? "active" :
 +                                           "passive",
 +                      (rcvtyp_wd(ttyp))  ? "word" :
 +                      (rcvtyp_pvt(ttyp)) ? "private block" :
 +                                           "global block");
 +
 +      devstate_read_unlock(dev);
 +      return len;
 +}
 +
 +/* fifosz */
 +static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
 +                         char *buf)
 +{
 +      struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
 +      return sprintf(buf, "%d\n", fifo->size);
 +}
 +
 +static int fifosz_store(struct device *d, struct device_attribute *attr,
 +                      const char *buf, size_t count)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      unsigned long fifosz;
 +      int ret;
 +
 +      fifosz = simple_strtol(buf, NULL, 10);
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +      ret = taskdev_set_fifosz(dev, fifosz);
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +
 +      return (ret < 0) ? ret : strlen(buf);
 +}
 +
 +/* fifocnt */
 +static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
 +      return sprintf(buf, "%d\n", fifo->size);
 +}
 +
 +/* ipblink */
 +static inline char *bid_name(u16 bid)
 +{
 +      static char s[6];
 +
 +      switch (bid) {
 +      case BID_NULL:
 +              return "NULL";
 +      case BID_PVT:
 +              return "PRIVATE";
 +      default:
 +              sprintf(s, "%d", bid);
 +              return s;
 +      }
 +}
 +
 +static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
 +      int len;
 +
 +      spin_lock(&rcvdt->link.lock);
 +      len = sprintf(buf, "top  %s\ntail %s\n",
 +                    bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
 +      spin_unlock(&rcvdt->link.lock);
 +
 +      return len;
 +}
 +
 +/* wsz */
 +static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
 +                      char *buf)
 +{
 +      return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
 +}
 +
 +/* mmap */
 +static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
 +                       char *buf)
 +{
 +      struct dsptask *task = to_taskdev(d)->task;
 +      return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
 +}
 +
 +/*
 + * called from ipbuf_show()
 + */
 +int ipbuf_is_held(u8 tid, u16 bid)
 +{
 +      struct dsptask *task = dsptask[tid];
 +      struct ipblink *link;
 +      u16 b;
 +      int ret = 0;
 +
 +      if (task == NULL)
 +              return 0;
 +
 +      link = &task->dev->rcvdt.bk.link;
 +      spin_lock(&link->lock);
 +      ipblink_for_each(b, link) {
 +              if (b == bid) { /* found */
 +                      ret = 1;
 +                      break;
 +              }
 +      }
 +      spin_unlock(&link->lock);
 +
 +      return ret;
 +}
 +
 +int __init dsp_taskmod_init(void)
 +{
 +      int retval;
 +
 +      memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
 +      memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
 +
 +      retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
 +                               &dsp_task_fops);
 +      if (retval < 0) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register task device: %d\n", retval);
 +              return retval;
 +      }
 +
 +      retval = bus_register(&dsptask_bus);
 +      if (retval) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register DSP task bus: %d\n",
 +                     retval);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +      retval = driver_register(&dsptask_driver);
 +      if (retval) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register DSP task driver: %d\n",
 +                     retval);
 +              bus_unregister(&dsptask_bus);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +      dsp_task_class = class_create(THIS_MODULE, "dsptask");
 +      if (IS_ERR(dsp_task_class)) {
 +              printk(KERN_ERR "omapdsp: failed to create DSP task class\n");
 +              driver_unregister(&dsptask_driver);
 +              bus_unregister(&dsptask_bus);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +void dsp_taskmod_exit(void)
 +{
 +      class_destroy(dsp_task_class);
 +      driver_unregister(&dsptask_driver);
 +      bus_unregister(&dsptask_bus);
 +      unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +}
index 0fab20e8b6d087d78e8835a40bcb5b4735672347,0000000000000000000000000000000000000000..a5fea3df1a16a0047966561e71d67f35378ef30e
mode 100644,000000..100644
--- /dev/null
@@@ -1,164 -1,0 +1,164 @@@
- #include <asm/arch/dsp.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/poll.h>
 +#include <linux/sched.h>
 +#include <asm/uaccess.h>
++#include <mach/dsp.h>
 +#include <asm/io.h>
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +
 +static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
 +static unsigned int change_cnt;
 +
 +void dsp_twch_touch(void)
 +{
 +      change_cnt++;
 +      wake_up_interruptible(&read_wait_q);
 +}
 +
 +/*
 + * @count: represents the device counts of the user's interst
 + */
 +static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
 +                           loff_t *ppos)
 +{
 +      long taskstat[TASKDEV_MAX];
 +      int devcount = count / sizeof(long);
 +      int i;
 +      DEFINE_WAIT(wait);
 +
 +      if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
 +              printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
 +              return -EINVAL;
 +      }
 +
 +      prepare_to_wait(&read_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (change_cnt == 0)    /* last check */
 +              schedule();
 +      finish_wait(&read_wait_q, &wait);
 +
 +      /* unconfigured while waiting ;-( */
 +      if ((change_cnt == 0) && (dsp_cfgstat_get_stat() != CFGSTAT_READY))
 +              return -EINVAL;
 +
 +      if (devcount > TASKDEV_MAX)
 +              devcount = TASKDEV_MAX;
 +
 +      count = devcount * sizeof(long);
 +      change_cnt = 0;
 +      for (i = 0; i < devcount; i++) {
 +              /*
 +               * once the device state is read, the 'STALE' bit will be set
 +               * so that the Dynamic Loader can distinguish the new request
 +               * from the old one.
 +               */
 +              taskstat[i] = taskdev_state_stale(i);
 +      }
 +
 +      if (copy_to_user(buf, taskstat, count))
 +              return -EFAULT;
 +
 +      return count;
 +}
 +
 +static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
 +{
 +      unsigned int mask = 0;
 +
 +      poll_wait(file, &read_wait_q, wait);
 +      if (change_cnt)
 +              mask |= POLLIN | POLLRDNORM;
 +
 +      return mask;
 +}
 +
 +static int dsp_twch_ioctl(struct inode *inode, struct file *file,
 +                        unsigned int cmd, unsigned long arg)
 +{
 +      int ret;
 +
 +      switch (cmd) {
 +      case TWCH_IOCTL_MKDEV:
 +              {
 +                      char name[TNM_LEN];
 +                      if (copy_from_user(name, (void __user *)arg, TNM_LEN))
 +                              return -EFAULT;
 +                      name[TNM_LEN-1] = '\0';
 +                      ret = dsp_mkdev(name);
 +                      break;
 +              }
 +
 +      case TWCH_IOCTL_RMDEV:
 +              {
 +                      char name[TNM_LEN];
 +                      if (copy_from_user(name, (void __user *)arg, TNM_LEN))
 +                              return -EFAULT;
 +                      name[TNM_LEN-1] = '\0';
 +                      ret = dsp_rmdev(name);
 +                      break;
 +              }
 +
 +      case TWCH_IOCTL_TADD:
 +              {
 +                      struct omap_dsp_taddinfo ti;
 +                      if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
 +                              return -EFAULT;
 +                      ret = dsp_tadd_minor(ti.minor, ti.taskadr);
 +                      break;
 +              }
 +
 +      case TWCH_IOCTL_TDEL:
 +              ret = dsp_tdel_minor(arg);
 +              break;
 +
 +      case TWCH_IOCTL_TKILL:
 +              ret = dsp_tkill_minor(arg);
 +              break;
 +
 +      default:
 +              return -ENOIOCTLCMD;
 +      }
 +
 +      return ret;
 +}
 +
 +struct file_operations dsp_twch_fops = {
 +      .owner = THIS_MODULE,
 +      .read  = dsp_twch_read,
 +      .poll  = dsp_twch_poll,
 +      .ioctl = dsp_twch_ioctl,
 +};
 +
 +void dsp_twch_start(void)
 +{
 +      change_cnt = 1;         /* first read will not wait */
 +}
 +
 +void dsp_twch_stop(void)
 +{
 +      wake_up_interruptible(&read_wait_q);
 +}
index 028814ffbe94edc40d4c99ab83e1ae9bc50c397c,0000000000000000000000000000000000000000..839a51aa07108c4821ddcec08b8ee762694ae609
mode 100644,000000..100644
--- /dev/null
@@@ -1,176 -1,0 +1,176 @@@
- #include <asm/arch/dsp_common.h>
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#ifndef _OMAP_DSP_UACCESS_DSP_H
 +#define _OMAP_DSP_UACCESS_DSP_H
 +
 +#include <asm/uaccess.h>
++#include <mach/dsp_common.h>
 +#include "dsp.h"
 +
 +#define HAVE_ASM_COPY_FROM_USER_DSP_2B
 +
 +#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +extern unsigned long __copy_from_user_dsp_2b(void *to,
 +                                                const void __user *from);
 +extern unsigned long __copy_to_user_dsp_2b(void __user *to,
 +                                              const void *from);
 +#endif
 +
 +#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +static inline unsigned long copy_from_user_dsp_2b(void *to,
 +                                                    const void *from)
 +{
 +      unsigned short tmp;
 +
 +      if (__copy_from_user(&tmp, from, 2))
 +              return 2;
 +      /* expecting compiler to generate "strh" instruction */
 +      *((unsigned short *)to) = tmp;
 +      return 0;
 +}
 +#endif
 +
 +/*
 + * @n must be multiple of 2
 + */
 +static inline unsigned long copy_from_user_dsp(void *to, const void *from,
 +                                                 unsigned long n)
 +{
 +      if (access_ok(VERIFY_READ, from, n)) {
 +              if ((is_dsp_internal_mem(to)) &&
 +                  (((unsigned long)to & 2) || (n & 2))) {
 +                      /*
 +                       * DARAM/SARAM with odd word alignment
 +                       */
 +                      unsigned long n4;
 +                      unsigned long last_n;
 +
 +                      /* dest not aligned -- copy 2 bytes */
 +                      if (((unsigned long)to & 2) && (n >= 2)) {
 +#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +                              if (__copy_from_user_dsp_2b(to, from))
 +#else
 +                              if (copy_from_user_dsp_2b(to, from))
 +#endif
 +                                      return n;
 +                              to += 2;
 +                              from += 2;
 +                              n -= 2;
 +                      }
 +                      /* middle 4*n bytes */
 +                      last_n = n & 2;
 +                      n4 = n - last_n;
 +                      if ((n = __copy_from_user(to, from, n4)) != 0)
 +                              return n + last_n;
 +                      /* last 2 bytes */
 +                      if (last_n) {
 +                              to += n4;
 +                              from += n4;
 +#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +                              if (__copy_from_user_dsp_2b(to, from))
 +#else
 +                              if (copy_from_user_dsp_2b(to, from))
 +#endif
 +                                      return 2;
 +                              n = 0;
 +                      }
 +              } else {
 +                      /*
 +                       * DARAM/SARAM with 4-byte alignment or
 +                       * external memory
 +                       */
 +                      n = __copy_from_user(to, from, n);
 +              }
 +      }
 +      else    /* security hole - plug it */
 +              memzero(to, n);
 +      return n;
 +}
 +
 +#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +static inline unsigned long copy_to_user_dsp_2b(void *to, const void *from)
 +{
 +      /* expecting compiler to generate "strh" instruction */
 +      unsigned short tmp = *(unsigned short *)from;
 +
 +      return __copy_to_user(to, &tmp, 2);
 +}
 +#endif
 +
 +/*
 + * @n must be multiple of 2
 + */
 +static inline unsigned long copy_to_user_dsp(void *to, const void *from,
 +                                               unsigned long n)
 +{
 +      if (access_ok(VERIFY_WRITE, to, n)) {
 +              if ((is_dsp_internal_mem(from)) &&
 +                  (((unsigned long)to & 2) || (n & 2))) {
 +                      /*
 +                       * DARAM/SARAM with odd word alignment
 +                       */
 +                      unsigned long n4;
 +                      unsigned long last_n;
 +
 +                      /* dest not aligned -- copy 2 bytes */
 +                      if (((unsigned long)to & 2) && (n >= 2)) {
 +#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +                              if (__copy_to_user_dsp_2b(to, from))
 +#else
 +                              if (copy_to_user_dsp_2b(to, from))
 +#endif
 +                                      return n;
 +                              to += 2;
 +                              from += 2;
 +                              n -= 2;
 +                      }
 +                      /* middle 4*n bytes */
 +                      last_n = n & 2;
 +                      n4 = n - last_n;
 +                      if ((n = __copy_to_user(to, from, n4)) != 0)
 +                              return n + last_n;
 +                      /* last 2 bytes */
 +                      if (last_n) {
 +                              to += n4;
 +                              from += n4;
 +#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
 +                              if (__copy_to_user_dsp_2b(to, from))
 +#else
 +                              if (copy_to_user_dsp_2b(to, from))
 +#endif
 +                                      return 2;
 +                              n = 0;
 +                      }
 +              } else {
 +                      /*
 +                       * DARAM/SARAM with 4-byte alignment or
 +                       * external memory
 +                       */
 +                      n = __copy_to_user(to, from, n);
 +              }
 +      }
 +      return n;
 +}
 +
 +#endif /* _OMAP_DSP_UACCESS_DSP_H */
Simple merge
Simple merge
index bcb3c9ae15364b2c0d07d962bbf07e91a695daa6,0000000000000000000000000000000000000000..18e07643165fef430b7631ad053a9011b44efb5f
mode 100644,000000..100644
--- /dev/null
@@@ -1,268 -1,0 +1,268 @@@
- #include <asm/arch/omap34xx.h>
- #include <asm/arch/control.h>
 +/*
 + * omap34xx_temp.c - Linux kernel module for OMAP34xx hardware monitoring
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Written by Peter De Schrijver <peter.de-schrijver@nokia.com>
 + *
 + * Inspired by k8temp.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.
 + *
 + * 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/clk.h>
 +#include <linux/hrtimer.h>
 +#include <linux/module.h>
 +#include <linux/hwmon.h>
 +#include <linux/hwmon-sysfs.h>
 +#include <linux/err.h>
 +#include <linux/platform_device.h>
 +#include <linux/io.h>
++#include <mach/omap34xx.h>
++#include <mach/control.h>
 +
 +#define TEMP_SENSOR_SOC BIT(8)
 +#define TEMP_SENSOR_EOCZ BIT(7)
 +
 +/* minimum delay for EOCZ rise after SOC rise is
 + * 11 cycles of the 32.768Khz clock */
 +#define EOCZ_MIN_RISING_DELAY (11 * 30518)
 +
 +/* maximum delay for EOCZ rise after SOC rise is
 + * 14 cycles of the 32.768Khz clock */
 +#define EOCZ_MAX_RISING_DELAY (14 * 30518)
 +
 +/* minimum delay for EOCZ falling is
 + * 36 cycles of the 32.768Khz clock */
 +#define EOCZ_MIN_FALLING_DELAY (36 * 30518)
 +
 +/* maximum delay for EOCZ falling is
 + * 40 cycles of the 32.768Khz clock */
 +#define EOCZ_MAX_FALLING_DELAY (40 * 30518)
 +
 +struct omap34xx_data {
 +      struct device *hwmon_dev;
 +      struct clk *clk_32k;
 +      struct mutex update_lock;
 +      const char *name;
 +      char valid;
 +      unsigned long last_updated;
 +      u32 temp;
 +};
 +
 +static struct platform_device omap34xx_temp_device = {
 +      .name   = "omap34xx_temp",
 +      .id     = -1,
 +};
 +
 +static int adc_to_temp[] = {
 +      -40, -40, -40, -40, -40, -39, -38, -36, -34, -32, -31, -29, -28, -26,
 +      -25, -24, -22, -21, -19, -18, -17, -15, -14, -12, -11, -9, -8, -7, -5,
 +      -4, -2, -1, 0, 1, 3, 4, 5, 7, 8, 10, 11, 13, 14, 15, 17, 18, 20, 21,
 +      22, 24, 25, 27, 28, 30, 31, 32, 34, 35, 37, 38, 39, 41, 42, 44, 45,
 +      47, 48, 49, 51, 52, 53, 55, 56, 58, 59, 60, 62, 63, 65, 66, 67, 69,
 +      70, 72, 73, 74, 76, 77, 79, 80, 81, 83, 84, 85, 87, 88, 89, 91, 92,
 +      94, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 111, 113,
 +      114, 116, 117, 118, 120, 121, 122, 124, 124, 125, 125, 125, 125, 125};
 +
 +static inline u32 wait_for_eocz(int min_delay, int max_delay, u32 level)
 +{
 +      struct timespec timeout;
 +      ktime_t expire;
 +      u32 temp_sensor_reg;
 +
 +      level &= 1;
 +      level *= TEMP_SENSOR_EOCZ;
 +
 +      expire = ktime_add_ns(ktime_get(), max_delay);
 +      timeout = ns_to_timespec(min_delay);
 +      hrtimer_nanosleep(&timeout, NULL, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 +      do {
 +              temp_sensor_reg = omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR);
 +              if ((temp_sensor_reg & TEMP_SENSOR_EOCZ) == level)
 +                      break;
 +      } while (ktime_us_delta(expire, ktime_get()) > 0);
 +
 +      return (temp_sensor_reg & TEMP_SENSOR_EOCZ) == level;
 +}
 +
 +static void omap34xx_update(struct omap34xx_data *data)
 +{
 +      u32 temp_sensor_reg;
 +
 +      mutex_lock(&data->update_lock);
 +
 +      if (!data->valid
 +          || time_after(jiffies, data->last_updated + HZ)) {
 +
 +              clk_enable(data->clk_32k);
 +
 +              temp_sensor_reg = omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR);
 +              temp_sensor_reg |= TEMP_SENSOR_SOC;
 +              omap_ctrl_writel(temp_sensor_reg, OMAP343X_CONTROL_TEMP_SENSOR);
 +
 +              if (!wait_for_eocz(EOCZ_MIN_RISING_DELAY,
 +                                      EOCZ_MAX_RISING_DELAY, 1))
 +                      goto err;
 +
 +              temp_sensor_reg = omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR);
 +              temp_sensor_reg &= ~TEMP_SENSOR_SOC;
 +              omap_ctrl_writel(temp_sensor_reg, OMAP343X_CONTROL_TEMP_SENSOR);
 +
 +              if (!wait_for_eocz(EOCZ_MIN_FALLING_DELAY,
 +                                      EOCZ_MAX_FALLING_DELAY, 0))
 +                      goto err;
 +
 +              data->temp = omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR) &
 +                                              ((1<<7) - 1);
 +              data->last_updated = jiffies;
 +              data->valid = 1;
 +
 +err:
 +              clk_disable(data->clk_32k);
 +      }
 +
 +      mutex_unlock(&data->update_lock);
 +}
 +
 +static ssize_t show_name(struct device *dev,
 +                      struct device_attribute *devattr, char *buf)
 +{
 +      struct omap34xx_data *data = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%s\n", data->name);
 +}
 +
 +static ssize_t show_temp_raw(struct device *dev,
 +                       struct device_attribute *devattr, char *buf)
 +{
 +      struct omap34xx_data *data = dev_get_drvdata(dev);
 +
 +      omap34xx_update(data);
 +
 +      return sprintf(buf, "%d\n", data->temp);
 +}
 +
 +static ssize_t show_temp(struct device *dev,
 +                       struct device_attribute *devattr, char *buf)
 +{
 +      struct omap34xx_data *data = dev_get_drvdata(dev);
 +
 +      omap34xx_update(data);
 +
 +      return sprintf(buf, "%d\n", adc_to_temp[data->temp]);
 +}
 +
 +static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
 +static SENSOR_DEVICE_ATTR_2(temp1_input_raw, S_IRUGO, show_temp_raw,
 +                              NULL, 0, 0);
 +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 +
 +static int __devinit omap34xx_temp_probe(void)
 +{
 +      int err;
 +      struct omap34xx_data *data;
 +
 +      err = platform_device_register(&omap34xx_temp_device);
 +      if (err) {
 +              printk(KERN_ERR
 +                      "Unable to register omap34xx temperature device\n");
 +              goto exit;
 +      }
 +
 +      data = kzalloc(sizeof(struct omap34xx_data), GFP_KERNEL);
 +      if (!data) {
 +              err = -ENOMEM;
 +              goto exit_platform;
 +      }
 +
 +      dev_set_drvdata(&omap34xx_temp_device.dev, data);
 +      mutex_init(&data->update_lock);
 +      data->name = "omap34xx_temp";
 +
 +      data->clk_32k = clk_get(&omap34xx_temp_device.dev, "ts_fck");
 +      if (IS_ERR(data->clk_32k)) {
 +              err = PTR_ERR(data->clk_32k);
 +              goto exit_free;
 +      }
 +
 +      err = device_create_file(&omap34xx_temp_device.dev,
 +                               &sensor_dev_attr_temp1_input.dev_attr);
 +      if (err)
 +              goto clock_free;
 +
 +      err = device_create_file(&omap34xx_temp_device.dev,
 +                               &sensor_dev_attr_temp1_input_raw.dev_attr);
 +      if (err)
 +              goto exit_remove;
 +
 +      err = device_create_file(&omap34xx_temp_device.dev, &dev_attr_name);
 +      if (err)
 +              goto exit_remove_raw;
 +
 +      data->hwmon_dev = hwmon_device_register(&omap34xx_temp_device.dev);
 +
 +      if (IS_ERR(data->hwmon_dev)) {
 +              err = PTR_ERR(data->hwmon_dev);
 +              goto exit_remove_all;
 +      }
 +
 +      return 0;
 +
 +exit_remove_all:
 +      device_remove_file(&omap34xx_temp_device.dev,
 +                         &dev_attr_name);
 +exit_remove_raw:
 +      device_remove_file(&omap34xx_temp_device.dev,
 +                         &sensor_dev_attr_temp1_input_raw.dev_attr);
 +exit_remove:
 +      device_remove_file(&omap34xx_temp_device.dev,
 +                         &sensor_dev_attr_temp1_input.dev_attr);
 +clock_free:
 +      clk_put(data->clk_32k);
 +
 +exit_free:
 +      kfree(data);
 +exit_platform:
 +      platform_device_unregister(&omap34xx_temp_device);
 +exit:
 +      return err;
 +}
 +
 +static int __init omap34xx_temp_init(void)
 +{
 +      return omap34xx_temp_probe();
 +}
 +
 +static void __exit omap34xx_temp_exit(void)
 +{
 +      struct omap34xx_data *data =
 +                      dev_get_drvdata(&omap34xx_temp_device.dev);
 +
 +      clk_put(data->clk_32k);
 +      hwmon_device_unregister(data->hwmon_dev);
 +      device_remove_file(&omap34xx_temp_device.dev,
 +                         &sensor_dev_attr_temp1_input.dev_attr);
 +      device_remove_file(&omap34xx_temp_device.dev, &dev_attr_name);
 +      kfree(data);
 +      platform_device_unregister(&omap34xx_temp_device);
 +}
 +
 +MODULE_AUTHOR("Peter De Schrijver");
 +MODULE_DESCRIPTION("Omap34xx temperature sensor");
 +MODULE_LICENSE("GPL");
 +
 +module_init(omap34xx_temp_init)
 +module_exit(omap34xx_temp_exit)
 +
Simple merge
Simple merge
index 32664c0e1842f658951d609ffda2b25275d61ff5,0000000000000000000000000000000000000000..c0862d9f2690f0f0daa38f21659aed7011dff175
mode 100644,000000..100644
--- /dev/null
@@@ -1,585 -1,0 +1,585 @@@
- #include <asm/arch/gpio.h>
 +/*
 + * drivers/i2c/chips/lp5521.c
 + *
 + * Copyright (C) 2007 Nokia Corporation
 + *
 + * Written by Mathias Nyman <mathias.nyman@nokia.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/i2c.h>
 +#include <linux/mutex.h>
++#include <mach/gpio.h>
 +
 +#define LP5521_DRIVER_NAME            "lp5521"
 +
 +#ifdef LED_CONNECTED_WRONG
 +#define LP5521_REG_R_PWM              0x04
 +#define LP5521_REG_B_PWM              0x02
 +#else
 +#define LP5521_REG_R_PWM              0x02
 +#define LP5521_REG_B_PWM              0x04
 +#endif
 +#define LP5521_REG_ENABLE             0x00
 +#define LP5521_REG_OP_MODE            0x01
 +#define LP5521_REG_G_PWM              0x03
 +#define LP5521_REG_R_CNTRL            0x05
 +#define LP5521_REG_G_CNTRL            0x06
 +#define LP5521_REG_B_CNTRL            0x07
 +#define LP5521_REG_MISC                       0x08
 +#define LP5521_REG_R_CHANNEL_PC               0x09
 +#define LP5521_REG_G_CHANNEL_PC               0x0a
 +#define LP5521_REG_B_CHANNEL_PC               0x0b
 +#define LP5521_REG_STATUS             0x0c
 +#define LP5521_REG_RESET              0x0d
 +#define LP5521_REG_GPO                        0x0e
 +#define LP5521_REG_R_PROG_MEM         0x10
 +#define LP5521_REG_G_PROG_MEM         0x30
 +#define LP5521_REG_B_PROG_MEM         0x50
 +
 +#define LP5521_MODE_LOAD              "load"
 +#define LP5521_MODE_RUN                       "run"
 +#define LP5521_MODE_DIRECT_CONTROL    "direct"
 +
 +#define LP5521_CURRENT_1m5            0x0f
 +#define LP5521_CURRENT_3m1            0x1f
 +#define LP5521_CURRENT_4m7            0x2f
 +#define LP5521_CURRENT_6m3            0x3f
 +#define LP5521_CURRENT_7m9            0x4f
 +#define LP5521_CURRENT_9m5            0x5f
 +#define LP5521_CURRENT_11m1           0x6f
 +#define LP5521_CURRENT_12m7           0x7f
 +#define LP5521_CURRENT_14m3           0x8f
 +#define LP5521_CURRENT_15m9           0x9f
 +#define LP5521_CURRENT_17m5           0xaf
 +#define LP5521_CURRENT_19m1           0xbf
 +#define LP5521_CURRENT_20m7           0xcf
 +#define LP5521_CURRENT_22m3           0xdf
 +#define LP5521_CURRENT_23m9           0xef
 +#define LP5521_CURRENT_25m5           0xff
 +
 +#define LP5521_PROGRAM_LENGTH         32      /* in bytes */
 +
 +struct lp5521_chip {
 +      struct mutex            lock;
 +      struct i2c_client       *client;
 +      char                    *mode;
 +      int                     red;
 +      int                     green;
 +      int                     blue;
 +};
 +
 +static int lp5521_set_mode(struct lp5521_chip *chip, char *mode);
 +
 +static int lp5521_write(struct i2c_client *client, u8 reg, u8 value)
 +{
 +      return i2c_smbus_write_byte_data(client, reg, value);
 +}
 +
 +static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
 +{
 +      s32 ret = i2c_smbus_read_byte_data(client, reg);
 +
 +      if (ret < 0)
 +              return -EIO;
 +
 +      *buf = ret;
 +      return 0;
 +}
 +
 +static int lp5521_configure(struct i2c_client *client)
 +{
 +      int ret = 0;
 +
 +      /* Enable chip and set light to logarithmic mode*/
 +      ret |= lp5521_write(client, LP5521_REG_ENABLE, 0xc0);
 +
 +      /* setting all color pwms to direct control mode */
 +      ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3f);
 +
 +      /* setting current to 4.7 mA for all channels */
 +      ret |= lp5521_write(client, LP5521_REG_R_CNTRL, LP5521_CURRENT_4m7);
 +      ret |= lp5521_write(client, LP5521_REG_G_CNTRL, LP5521_CURRENT_4m7);
 +      ret |= lp5521_write(client, LP5521_REG_B_CNTRL, LP5521_CURRENT_4m7);
 +
 +      /* Enable auto-powersave, set charge pump to auto, red to battery */
 +      ret |= lp5521_write(client, LP5521_REG_MISC, 0x3c);
 +
 +      /* initialize all channels pwm to zero */
 +      ret |= lp5521_write(client, LP5521_REG_R_PWM, 0);
 +      ret |= lp5521_write(client, LP5521_REG_G_PWM, 0);
 +      ret |= lp5521_write(client, LP5521_REG_B_PWM, 0);
 +
 +      /* Not much can be done about errors at this point */
 +      return ret;
 +}
 +
 +static int lp5521_load_program(struct lp5521_chip *chip, u8 *pattern)
 +{
 +      struct i2c_client *client = chip->client;
 +      int ret = 0;
 +
 +      /* Enter load program mode for all led channels */
 +      ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15); /* 0001 0101 */
 +      if (ret)
 +              return ret;
 +
 +      if (chip->red)
 +              ret |= i2c_smbus_write_i2c_block_data(client,
 +                                                    LP5521_REG_R_PROG_MEM,
 +                                                    LP5521_PROGRAM_LENGTH,
 +                                                    pattern);
 +      if (chip->green)
 +              ret |= i2c_smbus_write_i2c_block_data(client,
 +                                                    LP5521_REG_G_PROG_MEM,
 +                                                    LP5521_PROGRAM_LENGTH,
 +                                                    pattern);
 +      if (chip->blue)
 +              ret |= i2c_smbus_write_i2c_block_data(client,
 +                                                    LP5521_REG_B_PROG_MEM,
 +                                                    LP5521_PROGRAM_LENGTH,
 +                                                    pattern);
 +
 +      return ret;
 +}
 +
 +static int lp5521_run_program(struct lp5521_chip *chip)
 +{
 +      struct i2c_client *client = chip->client;
 +      int ret;
 +      u8 mask = 0xc0;
 +      u8 exec_state = 0;
 +      u8 enable_reg;
 +
 +      ret = lp5521_read(client, LP5521_REG_ENABLE, &enable_reg);
 +      if (ret)
 +              goto fail;
 +
 +      enable_reg &= mask;
 +
 +      /* set all active channels exec state to countinous run*/
 +      exec_state |= (chip->red   << 5);
 +      exec_state |= (chip->green << 3);
 +      exec_state |= (chip->blue  << 1);
 +
 +      enable_reg |= exec_state;
 +
 +      ret |= lp5521_write(client, LP5521_REG_ENABLE, enable_reg);
 +
 +      /* set op-mode to run for active channels, disabled for others */
 +      ret |= lp5521_write(client, LP5521_REG_OP_MODE, exec_state);
 +
 +fail:
 +      return ret;
 +}
 +
 +/*--------------------------------------------------------------*/
 +/*                    Sysfs interface                         */
 +/*--------------------------------------------------------------*/
 +
 +static ssize_t show_active_channels(struct device *dev,
 +                          struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +      char channels[4];
 +      int pos = 0;
 +
 +#ifdef LED_CONNECTED_WRONG
 +      if (chip->blue)
 +              pos += sprintf(channels + pos, "r");
 +      if (chip->green)
 +              pos += sprintf(channels + pos, "g");
 +      if (chip->red)
 +              pos += sprintf(channels + pos, "b");
 +
 +#else
 +      if (chip->red)
 +              pos += sprintf(channels + pos, "r");
 +      if (chip->green)
 +              pos += sprintf(channels + pos, "g");
 +      if (chip->blue)
 +              pos += sprintf(channels + pos, "b");
 +#endif
 +
 +      channels[pos] = '\0';
 +
 +      return sprintf(buf, "%s\n", channels);
 +}
 +
 +static ssize_t store_active_channels(struct device *dev,
 +                           struct device_attribute *attr,
 +                           const char *buf, size_t len)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +
 +      chip->red = 0;
 +      chip->green = 0;
 +      chip->blue = 0;
 +
 +#ifdef LED_CONNECTED_WRONG
 +      if (strchr(buf, 'r') != NULL)
 +              chip->blue = 1;
 +      if (strchr(buf, 'b') != NULL)
 +              chip->red = 1;
 +#else
 +      if (strchr(buf, 'r') != NULL)
 +              chip->red = 1;
 +      if (strchr(buf, 'b') != NULL)
 +              chip->blue = 1;
 +#endif
 +      if (strchr(buf, 'g') != NULL)
 +              chip->green = 1;
 +
 +      return len;
 +}
 +
 +static ssize_t show_color(struct device *dev,
 +                          struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct i2c_client *client = to_i2c_client(dev);
 +      int ret = 0;
 +      u8 r, g, b;
 +
 +      ret |= lp5521_read(client, LP5521_REG_R_PWM, &r);
 +      ret |= lp5521_read(client, LP5521_REG_G_PWM, &g);
 +      ret |= lp5521_read(client, LP5521_REG_B_PWM, &b);
 +
 +      if (ret)
 +              return ret;
 +
 +      return sprintf(buf, "%.2x:%.2x:%.2x\n", r, g, b);
 +}
 +
 +static ssize_t store_color(struct device *dev,
 +                           struct device_attribute *attr,
 +                           const char *buf, size_t len)
 +{
 +      struct i2c_client *client = to_i2c_client(dev);
 +      struct lp5521_chip *chip = i2c_get_clientdata(client);
 +      int ret;
 +      unsigned r, g, b;
 +
 +
 +      ret = sscanf(buf, "%2x:%2x:%2x", &r, &g, &b);
 +      if (ret != 3)
 +              return  -EINVAL;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = lp5521_write(client, LP5521_REG_R_PWM, (u8)r);
 +      ret = lp5521_write(client, LP5521_REG_G_PWM, (u8)g);
 +      ret = lp5521_write(client, LP5521_REG_B_PWM, (u8)b);
 +
 +      mutex_unlock(&chip->lock);
 +
 +      return len;
 +}
 +
 +static ssize_t store_load(struct device *dev,
 +                           struct device_attribute *attr,
 +                           const char *buf, size_t len)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +      int  ret, nrchars, offset = 0, i = 0;
 +      char c[3];
 +      unsigned cmd;
 +      u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
 +
 +      while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
 +
 +              /* separate sscanfs because length is working only for %s */
 +              ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
 +              ret = sscanf(c, "%2x", &cmd);
 +              if (ret != 1)
 +                      goto fail;
 +              pattern[i] = (u8)cmd;
 +
 +              offset += nrchars;
 +              i++;
 +      }
 +
 +      /* pattern commands are always two bytes long */
 +      if (i % 2)
 +              goto fail;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = lp5521_load_program(chip, pattern);
 +      mutex_unlock(&chip->lock);
 +
 +      if (ret) {
 +              dev_err(dev, "lp5521 failed loading pattern\n");
 +              return ret;
 +      }
 +
 +      return len;
 +fail:
 +      dev_err(dev, "lp5521 wrong pattern format\n");
 +      return -EINVAL;
 +}
 +
 +static ssize_t show_mode(struct device *dev,
 +                       struct device_attribute *attr,
 +                       char *buf)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%s\n", chip->mode);
 +}
 +
 +static ssize_t store_mode(struct device *dev,
 +                        struct device_attribute *attr,
 +                        const char *buf, size_t len)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +
 +      mutex_lock(&chip->lock);
 +
 +      if (!strncmp(buf, "run", 3))
 +              lp5521_set_mode(chip, LP5521_MODE_RUN);
 +      else if (!strncmp(buf, "load", 4))
 +              lp5521_set_mode(chip, LP5521_MODE_LOAD);
 +      else if (!strncmp(buf, "direct", 6))
 +              lp5521_set_mode(chip, LP5521_MODE_DIRECT_CONTROL);
 +
 +      mutex_unlock(&chip->lock);
 +
 +      return len;
 +}
 +
 +static ssize_t show_current(struct device *dev,
 +                          struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct i2c_client *client = to_i2c_client(dev);
 +      int ret = 0;
 +      u8 r_curr, g_curr, b_curr;
 +
 +      ret |= lp5521_read(client, LP5521_REG_R_CNTRL, &r_curr);
 +      ret |= lp5521_read(client, LP5521_REG_G_CNTRL, &g_curr);
 +      ret |= lp5521_read(client, LP5521_REG_B_CNTRL, &b_curr);
 +
 +      if (ret)
 +              return ret;
 +
 +      r_curr = r_curr >> 4;
 +      g_curr = g_curr >> 4;
 +      b_curr = b_curr >> 4;
 +
 +      if (r_curr == g_curr && g_curr == b_curr)
 +              return sprintf(buf, "%x\n", r_curr);
 +      else
 +              return sprintf(buf, "%x %x %x\n", r_curr, g_curr, b_curr);
 +}
 +
 +static ssize_t store_current(struct device *dev,
 +                           struct device_attribute *attr,
 +                           const char *buf, size_t len)
 +{
 +      struct lp5521_chip *chip = dev_get_drvdata(dev);
 +      struct i2c_client *client = chip->client;
 +      int ret;
 +      unsigned curr;
 +
 +      ret = sscanf(buf, "%1x", &curr);
 +      if (ret != 1)
 +              return  -EINVAL;
 +
 +      /* current level is determined by the 4 upper bits, rest is ones */
 +      curr = (curr << 4) | 0x0f;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret |= lp5521_write(client, LP5521_REG_R_CNTRL, (u8)curr);
 +      ret |= lp5521_write(client, LP5521_REG_G_CNTRL, (u8)curr);
 +      ret |= lp5521_write(client, LP5521_REG_B_CNTRL, (u8)curr);
 +
 +      mutex_unlock(&chip->lock);
 +
 +      return len;
 +}
 +
 +static DEVICE_ATTR(color, S_IRUGO | S_IWUGO, show_color, store_color);
 +static DEVICE_ATTR(load, S_IWUGO, NULL, store_load);
 +static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, store_mode);
 +static DEVICE_ATTR(active_channels, S_IRUGO | S_IWUGO,
 +                 show_active_channels, store_active_channels);
 +static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
 +
 +static int lp5521_register_sysfs(struct i2c_client *client)
 +{
 +      struct device *dev = &client->dev;
 +      int ret;
 +
 +      ret = device_create_file(dev, &dev_attr_color);
 +      if (ret)
 +              goto fail1;
 +      ret = device_create_file(dev, &dev_attr_load);
 +      if (ret)
 +              goto fail2;
 +      ret = device_create_file(dev, &dev_attr_active_channels);
 +      if (ret)
 +              goto fail3;
 +      ret = device_create_file(dev, &dev_attr_mode);
 +      if (ret)
 +              goto fail4;
 +      ret = device_create_file(dev, &dev_attr_led_current);
 +      if (ret)
 +              goto fail5;
 +      return 0;
 +
 +fail5:
 +      device_remove_file(dev, &dev_attr_mode);
 +fail4:
 +      device_remove_file(dev, &dev_attr_active_channels);
 +fail3:
 +      device_remove_file(dev, &dev_attr_load);
 +fail2:
 +      device_remove_file(dev, &dev_attr_color);
 +fail1:
 +      return ret;
 +}
 +
 +static void lp5521_unregister_sysfs(struct i2c_client *client)
 +{
 +      struct lp5521_chip *chip = i2c_get_clientdata(client);
 +      struct device *dev = &client->dev;
 +
 +      device_remove_file(dev, &dev_attr_led_current);
 +      device_remove_file(dev, &dev_attr_mode);
 +      device_remove_file(dev, &dev_attr_active_channels);
 +      device_remove_file(dev, &dev_attr_color);
 +
 +      if (!strcmp(chip->mode, LP5521_MODE_LOAD))
 +              device_remove_file(dev, &dev_attr_load);
 +}
 +
 +/*--------------------------------------------------------------*/
 +/*                    Set chip operating mode                 */
 +/*--------------------------------------------------------------*/
 +
 +static int lp5521_set_mode(struct lp5521_chip *chip, char *mode)
 +{
 +      struct i2c_client *client = chip->client ;
 +      int ret = 0;
 +
 +      /* if in that mode already do nothing, except for run */
 +      if (!strcmp(mode, chip->mode) && strcmp(mode, LP5521_MODE_RUN))
 +              return 0;
 +
 +      if (!strcmp(mode, LP5521_MODE_RUN))
 +              ret = lp5521_run_program(chip);
 +
 +      if (!strcmp(mode, LP5521_MODE_LOAD))
 +              ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15);
 +
 +      if (!strcmp(mode, LP5521_MODE_DIRECT_CONTROL))
 +              ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
 +
 +      chip->mode = mode;
 +
 +      return ret;
 +}
 +
 +/*--------------------------------------------------------------*/
 +/*                    Probe, Attach, Remove                   */
 +/*--------------------------------------------------------------*/
 +static struct i2c_driver lp5521_driver;
 +
 +static int lp5521_probe(struct i2c_client *client,
 +              const struct i2c_device_id *id)
 +{
 +      struct lp5521_chip *chip;
 +      int ret = 0;
 +
 +      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 +      if (!chip)
 +              return -ENOMEM;
 +
 +      chip->client    = client;
 +      strncpy(client->name, LP5521_DRIVER_NAME, I2C_NAME_SIZE);
 +      i2c_set_clientdata(client, chip);
 +
 +      mutex_init(&chip->lock);
 +
 +      ret = lp5521_configure(client);
 +      if (ret < 0) {
 +              dev_err(&client->dev, "lp5521 error configuring chip \n");
 +              goto fail1;
 +      }
 +
 +      /* Set default values */
 +      chip->mode      = LP5521_MODE_DIRECT_CONTROL;
 +      chip->red       = 1;
 +      chip->green     = 1;
 +      chip->blue      = 1;
 +
 +      ret = lp5521_register_sysfs(client);
 +      if (ret)
 +              dev_err(&client->dev, "lp5521 registering sysfs failed \n");
 +
 +      return ret;
 +
 +fail1:
 +      kfree(chip);
 +      return ret;
 +}
 +
 +static int lp5521_remove(struct i2c_client *client)
 +{
 +      struct lp5521_chip *chip = i2c_get_clientdata(client);
 +
 +      lp5521_unregister_sysfs(client);
 +      kfree(chip);
 +
 +      return 0;
 +}
 +
 +static const struct i2c_device_id lp5521_id[] = {
 +      { LP5521_DRIVER_NAME, 0},
 +      { },
 +};
 +MODULE_DEVICE_TABLE(i2c, lp5521_id);
 +
 +static struct i2c_driver lp5521_driver = {
 +      .driver = {
 +              .name   = LP5521_DRIVER_NAME,
 +      },
 +      .probe          = lp5521_probe,
 +      .remove         = __devexit_p(lp5521_remove),
 +      .id_table       = lp5521_id,
 +};
 +
 +static int __init lp5521_init(void)
 +{
 +      return i2c_add_driver(&lp5521_driver);
 +}
 +
 +static void __exit lp5521_exit(void)
 +{
 +      i2c_del_driver(&lp5521_driver);
 +}
 +
 +MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
 +MODULE_DESCRIPTION("lp5521 LED driver");
 +MODULE_LICENSE("GPL");
 +
 +module_init(lp5521_init);
 +module_exit(lp5521_exit);
index 40eb14af7e0e2b263589d498317078ce1ba1f122,176126d3a01d3054318347cff48dfce8dc2805a1..3e6e2ade92c2041039f16fa49a0332106288cf91
  #include <linux/delay.h>
  #include <linux/rtc.h>
  #include <linux/bcd.h>
 +#include <linux/i2c/menelaus.h>
  
 +#include <asm/mach-types.h>
  #include <asm/mach/irq.h>
  
- #include <asm/arch/gpio.h>
+ #include <mach/gpio.h>
 -#include <mach/menelaus.h>
  
  #define DRIVER_NAME                   "menelaus"
  
index 544cc28fb2371a78f426020c642f818d7aa7b857,0000000000000000000000000000000000000000..10671e803e45cf59f1ca2da0b03e2ad82a08b35f
mode 100644,000000..100644
--- /dev/null
@@@ -1,675 -1,0 +1,675 @@@
- #include <asm/arch/aic23.h>
- #include <asm/arch/mcbsp.h>
 +/*
 + *   Texas Instrumens TLV320AIC23 audio codec's i2c interface.
 + *
 + *   Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
 + *   Copyright (c) by Jussi Laako <jussi.laako@nokia.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/i2c.h>
 +#include <linux/slab.h>
 +#include <linux/device.h>
 +#include <linux/platform_device.h>
 +#include <asm/io.h>
++#include <mach/aic23.h>
++#include <mach/mcbsp.h>
 +
 +#define TLV320AIC23_VERSION   "1.8"
 +#define TLV320AIC23_DATE      "10-Feb-2006"
 +#define MAX_VOL                       100
 +#define MIN_VOL                       0
 +#define MAX_GAIN              100
 +#define MIN_GAIN              0
 +#define OUTPUT_VOLUME_MIN       LHV_MIN
 +#define OUTPUT_VOLUME_MAX       LHV_MAX
 +#define OUTPUT_VOLUME_RANGE     (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
 +#define INPUT_VOLUME_MIN      LIV_MIN
 +#define INPUT_VOLUME_MAX      LIV_MAX
 +#define INPUT_VOLUME_RANGE    (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
 +
 +/* I2C Addresses to scan */
 +static unsigned short normal_i2c[] = { TLV320AIC23ID1, TLV320AIC23ID2, \
 +                                     I2C_CLIENT_END };
 +/*static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };*/
 +
 +/* This makes all addr_data:s */
 +I2C_CLIENT_INSMOD;
 +
 +static struct i2c_driver aic23_driver;
 +static struct i2c_client *new_client;
 +static int selftest;
 +static struct platform_device audio_i2c_device;
 +
 +static struct aic23_info {
 +      u16 volume_reg_left;
 +      u16 volume_reg_right;
 +      u16 input_gain_reg_left;
 +      u16 input_gain_reg_right;
 +      u16 power;                      /* For POWER_DOWN_CONTROL_ADDR */
 +      u16 mask;                       /* For ANALOG_AUDIO_CONTROL_ADDR */
 +      int mic_loopback;
 +      int mic_enable;
 +      int sta;
 +      int power_down;
 +      int initialized;
 +} aic23_info_l;
 +
 +static int _aic23_write_value(struct i2c_client *client, u8 reg, u16 value)
 +{
 +      u8 val, wreg;
 +
 +      /* TLV320AIC23 has 7 bit address and 9 bits of data
 +       * so we need to switch one data bit into reg and rest
 +       * of data into val
 +       */
 +
 +      wreg = (reg << 1);
 +      val = (0x01 & (value >> 8));
 +      wreg = (wreg | val);
 +      val = (0x00ff & value);
 +
 +      return i2c_smbus_write_byte_data(client, wreg, val);
 +}
 +
 +int aic23_write_value(u8 reg, u16 value)
 +{
 +      static struct i2c_client *client;
 +      client = new_client;
 +      _aic23_write_value(client, reg, value);
 +
 +      return 0;
 +}
 +
 +/*
 + * Configures the McBSP3 which is used to send clock to the AIC23 codec.
 + * The input clock rate from DSP is 12MHz.
 + * The DSP clock must be on before this is called.
 + */
 +static int omap_mcbsp3_aic23_clock_init(void)
 +{
 +      u16 w;
 +
 +      /* enable 12MHz clock to mcbsp 1 & 3 */
 +      __raw_writew(__raw_readw(DSP_IDLECT2) | (1<<1), DSP_IDLECT2);
 +      __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1<<1, DSP_RSTCT2);
 +
 +      /* disable sample rate generator */
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, SPCR1, 0x0000);
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, SPCR2, 0x0000);
 +
 +      /* pin control register */
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, PCR0,(CLKXM | CLKXP | CLKRP));
 +
 +      /* configure srg to send 12MHz pulse from dsp peripheral clock */
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, SRGR1, 0x0000);
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, SRGR2, CLKSM);
 +
 +      /* enable sample rate generator */
 +      w = OMAP_MCBSP_READ(OMAP1610_MCBSP3_BASE, SPCR2);
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP3_BASE, SPCR2, (w | FREE | GRST));
 +      printk("Clock enabled to MCBSP1 & 3 \n");
 +
 +      return 0;
 +}
 +
 +static int aic23_detect_client(struct i2c_adapter *adapter, int address,
 +                                   int kind)
 +{
 +      int err = 0;
 +      const char *client_name = "TLV320AIC23 Audio Codec";
 +
 +      if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA |
 +                                   I2C_FUNC_SMBUS_WRITE_BYTE)) {
 +              printk(KERN_WARNING "%s functionality check failed\n",
 +                     client_name);
 +              return err;
 +      }
 +
 +      if (!(new_client = kmalloc(sizeof(struct i2c_client),
 +                                 GFP_KERNEL))) {
 +              err = -ENOMEM;
 +              printk(KERN_WARNING "Couldn't allocate memory for %s\n",
 +                     client_name);
 +              return err;
 +      }
 +
 +      memset(new_client, 0x00, sizeof(struct i2c_client));
 +      new_client->addr = address;
 +      new_client->adapter = adapter;
 +      new_client->driver = &aic23_driver;
 +      new_client->flags = 0;
 +      strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
 +
 +      if ((err = i2c_attach_client(new_client))) {
 +              printk(KERN_WARNING "Couldn't attach %s\n", client_name);
 +              kfree(new_client);
 +              return err;
 +      }
 +
 +      if (platform_device_register(&audio_i2c_device)) {
 +              printk(KERN_WARNING "Failed to register audio i2c device\n");
 +              selftest = -ENODEV;
 +              return selftest;
 +      }
 +      /* FIXME: Do in board-specific file */
 +      omap_mcbsp3_aic23_clock_init();
 +
 +      if (!aic23_info_l.power_down)
 +              aic23_power_up();
 +      aic23_info_l.initialized = 1;
 +
 +      return 0;
 +}
 +
 +static int aic23_detach_client(struct i2c_client *client)
 +{
 +      int err;
 +
 +      platform_device_unregister(&audio_i2c_device);
 +
 +      if ((err = i2c_detach_client(client))) {
 +              printk("aic23.o: Client deregistration failed, \
 +                     client not detached.\n");
 +              return err;
 +      }
 +      kfree(client);
 +      return 0;
 +}
 +
 +static int aic23_attach_adapter(struct i2c_adapter *adapter)
 +{
 +      int res;
 +
 +      res = i2c_probe(adapter, &addr_data, &aic23_detect_client);
 +      return res;
 +}
 +
 +static struct i2c_driver aic23_driver = {
 +      .driver = {
 +              .name   = "OMAP+TLV320AIC23 codec",
 +              /*.flags        = I2C_DF_NOTIFY,*/
 +      },
 +      .id             = I2C_DRIVERID_MISC, /* Experimental ID */
 +      .attach_adapter = aic23_attach_adapter,
 +      .detach_client  = aic23_detach_client,
 +};
 +
 +static void update_volume_left(int volume)
 +{
 +      u16 val = 0;
 +      val = ((volume * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
 +      aic23_write_value(LEFT_CHANNEL_VOLUME_ADDR, val);
 +      aic23_info_l.volume_reg_left = volume;
 +}
 +
 +static void update_volume_right(int volume)
 +{
 +      u16 val = 0;
 +      val = ((volume * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
 +      aic23_write_value(RIGHT_CHANNEL_VOLUME_ADDR, val);
 +      aic23_info_l.volume_reg_right = volume;
 +}
 +
 +static void set_mic(int mic_en)
 +{
 +      u16 dg_ctrl;
 +
 +      if (mic_en) {
 +              aic23_info_l.power = OSC_OFF | LINE_OFF;
 +              dg_ctrl = ADCHP_ON;
 +              aic23_info_l.mask &= ~MICM_MUTED;
 +              aic23_info_l.mask |= MICB_20DB; /* STE_ENABLED */
 +      } else {
 +              aic23_info_l.power =
 +                      OSC_OFF | ADC_OFF | MIC_OFF | LINE_OFF;
 +              dg_ctrl = 0x00;
 +              aic23_info_l.mask =
 +                      DAC_SELECTED | INSEL_MIC | MICM_MUTED;
 +      }
 +      aic23_write_value(POWER_DOWN_CONTROL_ADDR,
 +                              aic23_info_l.power);
 +      aic23_write_value(DIGITAL_AUDIO_CONTROL_ADDR, dg_ctrl);
 +      aic23_write_value(ANALOG_AUDIO_CONTROL_ADDR,
 +                              aic23_info_l.mask);
 +      aic23_info_l.mic_enable = mic_en;
 +
 +      printk(KERN_INFO "aic23 mic state: %i\n", mic_en);
 +}
 +
 +static void aic23_init_power(void)
 +{
 +      aic23_write_value(RESET_CONTROL_ADDR, 0x00);
 +
 +      if (aic23_info_l.initialized == 0) {
 +              aic23_write_value(LEFT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +              aic23_write_value(RIGHT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +      }
 +      else {
 +              update_volume_left(aic23_info_l.volume_reg_left);
 +              update_volume_right(aic23_info_l.volume_reg_right);
 +      }
 +
 +      aic23_info_l.mask = DAC_SELECTED | INSEL_MIC | MICM_MUTED;
 +      aic23_write_value(ANALOG_AUDIO_CONTROL_ADDR,
 +                              aic23_info_l.mask);
 +      aic23_write_value(DIGITAL_AUDIO_CONTROL_ADDR, 0x00);
 +      aic23_write_value(DIGITAL_AUDIO_FORMAT_ADDR, LRP_ON | FOR_DSP);
 +      aic23_write_value(SAMPLE_RATE_CONTROL_ADDR, USB_CLK_ON);
 +      aic23_write_value(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
 +      aic23_info_l.power = OSC_OFF | ADC_OFF | MIC_OFF | LINE_OFF;
 +      aic23_write_value(POWER_DOWN_CONTROL_ADDR,
 +                              aic23_info_l.power);
 +
 +      /* enable mic input */
 +      if (aic23_info_l.mic_enable)
 +              set_mic(aic23_info_l.mic_enable);
 +
 +      printk(KERN_INFO "aic23_init_power() done\n");
 +}
 +
 +void aic23_power_down(void)
 +{
 +      if (aic23_info_l.initialized) {
 +              printk("aic23 powering down\n");
 +              aic23_write_value(POWER_DOWN_CONTROL_ADDR, 0xff);
 +      }
 +      aic23_info_l.power_down = 1;
 +}
 +
 +void aic23_power_up(void)
 +{
 +      if (aic23_info_l.initialized) {
 +              printk("aic23 powering up\n");
 +              aic23_init_power();
 +      }
 +      aic23_info_l.power_down = 0;
 +}
 +
 +/*----------------------------------------------------------------------*/
 +/*                    sysfs initializations                           */
 +/*----------------------------------------------------------------------*/
 +
 +static ssize_t store_volume_left(struct device *dev,
 +                               struct device_attribute *attr,
 +                               const char *buf, size_t count)
 +{
 +      signed volume;
 +
 +      sscanf(buf, "%i", &volume);
 +
 +      if (volume < MIN_VOL) {
 +              aic23_power_down();
 +              return count;
 +      } else if (volume > MIN_VOL && aic23_info_l.power_down) {
 +              aic23_info_l.volume_reg_left = volume;
 +              aic23_power_up();
 +              return count;
 +      }
 +      if (volume > MAX_VOL)
 +              volume = MAX_VOL;
 +
 +      update_volume_left(volume);
 +      return count;
 +}
 +
 +static ssize_t show_volume_left(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%u\n", aic23_info_l.volume_reg_left);
 +}
 +
 +static DEVICE_ATTR(volume_left, S_IRUGO | S_IWUGO,
 +                 show_volume_left, store_volume_left);
 +
 +static ssize_t store_volume_right(struct device *dev,
 +                                struct device_attribute *attr,
 +                                const char *buf, size_t count)
 +{
 +      signed volume;
 +
 +      sscanf(buf, "%i", &volume);
 +      if (volume < MIN_VOL) {
 +              aic23_power_down();
 +              return count;
 +      } else if (volume > MIN_VOL && aic23_info_l.power_down) {
 +              aic23_info_l.volume_reg_right = volume;
 +              aic23_power_up();
 +              return count;
 +      }
 +      if (volume > MAX_VOL)
 +              volume = MAX_VOL;
 +
 +      update_volume_right(volume);
 +      return count;
 +}
 +
 +static ssize_t show_volume_right(struct device *dev,
 +                               struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%u\n", aic23_info_l.volume_reg_right);
 +}
 +
 +static DEVICE_ATTR(volume_right, S_IRUGO | S_IWUGO,
 +                 show_volume_right, store_volume_right);
 +
 +static ssize_t store_gain_left(struct device *dev,
 +                             struct device_attribute *attr,
 +                             const char *buf, size_t count)
 +{
 +      u16 val = 0;
 +      unsigned gain;
 +
 +      sscanf(buf, "%u", &gain);
 +      if (gain > MAX_VOL)
 +              gain = MAX_VOL;
 +
 +      val = ((gain * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
 +      aic23_write_value(LEFT_LINE_VOLUME_ADDR, val);
 +      aic23_info_l.input_gain_reg_left = gain;
 +
 +      return count;
 +}
 +
 +static ssize_t show_gain_left(struct device *dev,
 +                            struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%u\n", aic23_info_l.input_gain_reg_left);
 +}
 +
 +static DEVICE_ATTR(gain_left, S_IRUGO | S_IWUSR, show_gain_left,
 +                 store_gain_left);
 +
 +static ssize_t store_gain_right(struct device *dev,
 +                              struct device_attribute *attr,
 +                              const char *buf, size_t count)
 +{
 +      u16 val = 0;
 +      unsigned gain;
 +
 +      sscanf(buf, "%u", &gain);
 +      if (gain > MAX_VOL)
 +              gain = MAX_VOL;
 +
 +      val = ((gain * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
 +      aic23_write_value(RIGHT_LINE_VOLUME_ADDR, val);
 +      aic23_info_l.input_gain_reg_right = gain;
 +
 +      return count;
 +}
 +
 +static ssize_t show_gain_right(struct device *dev,
 +                             struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%u\n", aic23_info_l.input_gain_reg_right);
 +}
 +
 +static DEVICE_ATTR(gain_right, S_IRUGO | S_IWUSR, show_gain_right,
 +                 store_gain_right);
 +
 +static ssize_t store_mic_loopback(struct device *dev,
 +                                struct device_attribute *attr,
 +                                const char *buf, size_t count)
 +{
 +      int mic;
 +
 +      sscanf(buf, "%i", &mic);
 +      if (mic > 0) {
 +              aic23_write_value(POWER_DOWN_CONTROL_ADDR, \
 +                                      OSC_OFF | ADC_OFF | LINE_OFF);
 +              aic23_info_l.mask = STE_ENABLED | DAC_SELECTED \
 +                                        | INSEL_MIC | MICB_20DB;
 +              aic23_write_value(ANALOG_AUDIO_CONTROL_ADDR,
 +                                      aic23_info_l.mask);
 +              mic = 1;
 +      }
 +      else {
 +              aic23_write_value(POWER_DOWN_CONTROL_ADDR, \
 +                                      OSC_OFF | ADC_OFF | MIC_OFF | LINE_OFF);
 +              mic = 0;
 +      }
 +      aic23_info_l.mic_loopback = mic;
 +
 +      return count;
 +}
 +
 +static ssize_t show_mic_loopback(struct device *dev,
 +                               struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%i\n", aic23_info_l.mic_loopback);
 +}
 +
 +static DEVICE_ATTR(mic_loopback, S_IRUGO | S_IWUSR,
 +                 show_mic_loopback, store_mic_loopback);
 +
 +static ssize_t store_st_attenuation(struct device *dev,
 +                                  struct device_attribute *attr,
 +                                  const char *buf, size_t count)
 +{
 +      unsigned sta;
 +      u16 tmp;
 +
 +      sscanf(buf, "%u", &sta);
 +      if (sta > 3)
 +              sta = 3;
 +
 +      tmp = aic23_info_l.mask;
 +      tmp &= 0x3f;
 +
 +      aic23_info_l.mask =  tmp | STA_REG(sta);
 +      aic23_write_value(ANALOG_AUDIO_CONTROL_ADDR,
 +                              aic23_info_l.mask);
 +      aic23_info_l.sta = sta;
 +
 +      return count;
 +}
 +
 +static ssize_t show_st_attenuation(struct device *dev,
 +                                 struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%i\n", aic23_info_l.sta);
 +}
 +
 +static DEVICE_ATTR(st_attenuation, S_IRUGO | S_IWUSR,
 +                 show_st_attenuation, store_st_attenuation);
 +
 +static ssize_t store_mic_enable(struct device *dev,
 +                              struct device_attribute *attr,
 +                              const char *buf, size_t count)
 +{
 +      int mic;
 +
 +      sscanf(buf, "%i", &mic);
 +      set_mic(mic);
 +
 +      return count;
 +}
 +
 +static ssize_t show_mic_enable(struct device *dev,
 +                             struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%i\n", aic23_info_l.mic_enable);
 +}
 +
 +static DEVICE_ATTR(mic_enable, S_IRUGO | S_IWUSR,
 +      show_mic_enable, store_mic_enable);
 +
 +static ssize_t show_audio_selftest(struct device *dev,
 +                                 struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "%i\n", selftest);
 +}
 +
 +static DEVICE_ATTR(audio_selftest, S_IRUGO | S_IWUSR,
 +              show_audio_selftest, NULL);
 +
 +static int audio_i2c_probe(struct platform_device *dev)
 +{
 +      int r;
 +
 +      if ((r = device_create_file(&dev->dev, &dev_attr_volume_left)) != 0)
 +              return r;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_volume_right)) != 0)
 +              goto err_volume_left;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_gain_right)) != 0)
 +              goto err_volume_right;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_gain_left)) != 0)
 +              goto err_gain_right;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_mic_loopback)) != 0)
 +              goto err_gain_left;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_mic_enable)) != 0)
 +              goto err_mic_loopback;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_st_attenuation)) != 0)
 +              goto err_mic_enable;
 +      else if ((r = device_create_file(&dev->dev,
 +              &dev_attr_audio_selftest)) != 0)
 +              goto err_st_attenuation;
 +      else
 +              return r;
 +
 +err_st_attenuation:
 +      device_remove_file(&dev->dev, &dev_attr_st_attenuation);
 +err_mic_enable:
 +      device_remove_file(&dev->dev, &dev_attr_mic_enable);
 +err_mic_loopback:
 +      device_remove_file(&dev->dev, &dev_attr_mic_loopback);
 +err_gain_left:
 +      device_remove_file(&dev->dev, &dev_attr_gain_left);
 +err_gain_right:
 +      device_remove_file(&dev->dev, &dev_attr_gain_right);
 +err_volume_right:
 +      device_remove_file(&dev->dev, &dev_attr_volume_right);
 +err_volume_left:
 +      device_remove_file(&dev->dev, &dev_attr_volume_left);
 +
 +      return r;
 +}
 +
 +static int audio_i2c_remove(struct platform_device *dev)
 +{
 +      device_remove_file(&dev->dev, &dev_attr_st_attenuation);
 +      device_remove_file(&dev->dev, &dev_attr_mic_enable);
 +      device_remove_file(&dev->dev, &dev_attr_mic_loopback);
 +      device_remove_file(&dev->dev, &dev_attr_gain_left);
 +      device_remove_file(&dev->dev, &dev_attr_gain_right);
 +      device_remove_file(&dev->dev, &dev_attr_volume_right);
 +      device_remove_file(&dev->dev, &dev_attr_volume_left);
 +
 +      return 0;
 +}
 +
 +/*----------------------------------------------------------------*/
 +/*                    PM functions                              */
 +/*----------------------------------------------------------------*/
 +
 +static void audio_i2c_shutdown(struct platform_device *dev)
 +{
 +      /* Let's mute the codec before powering off to prevent
 +      * glitch in the sound
 +      */
 +      aic23_write_value(LEFT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +      aic23_write_value(RIGHT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +      aic23_power_down();
 +}
 +
 +static int audio_i2c_suspend(struct platform_device *dev, pm_message_t state)
 +{
 +      /* Let's mute the codec before powering off to prevent
 +       * glitch in the sound
 +       */
 +      aic23_write_value(LEFT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +      aic23_write_value(RIGHT_CHANNEL_VOLUME_ADDR, LHV_MIN);
 +      aic23_power_down();
 +
 +      return 0;
 +}
 +
 +static int audio_i2c_resume(struct platform_device *dev)
 +{
 +      aic23_power_up();
 +
 +      return 0;
 +}
 +
 +static struct platform_driver audio_i2c_driver = {
 +      .driver = {
 +              .owner  = THIS_MODULE,
 +              .name   = "audio-i2c",
 +      },
 +      .shutdown       = audio_i2c_shutdown,
 +      .probe          = audio_i2c_probe,
 +      .remove         = audio_i2c_remove,
 +      .suspend        = audio_i2c_suspend,
 +      .resume         = audio_i2c_resume,
 +};
 +
 +static struct platform_device audio_i2c_device = {
 +      .name           = "audio-i2c",
 +      .id             = -1,
 +};
 +
 +/*----------------------------------------------------------------*/
 +
 +static int __init aic23_init(void)
 +{
 +      selftest =  0;
 +      aic23_info_l.initialized = 0;
 +
 +      if (i2c_add_driver(&aic23_driver)) {
 +              printk("aic23 i2c: Driver registration failed, \
 +                    module not inserted.\n");
 +              selftest = -ENODEV;
 +              return selftest;
 +      }
 +
 +      if (platform_driver_register(&audio_i2c_driver)) {
 +              printk(KERN_WARNING "Failed to register audio i2c driver\n");
 +              selftest = -ENODEV;
 +              return selftest;
 +      }
 +
 +      printk("TLV320AIC23 I2C version %s (%s)\n",
 +             TLV320AIC23_VERSION, TLV320AIC23_DATE);
 +
 +      return selftest;
 +}
 +
 +static void __exit aic23_exit(void)
 +{
 +      aic23_power_down();
 +      i2c_del_driver(&aic23_driver);
 +
 +      platform_driver_unregister(&audio_i2c_driver);
 +}
 +
 +MODULE_AUTHOR("Kai Svahn <kai.svahn@nokia.com>");
 +MODULE_DESCRIPTION("I2C interface for TLV320AIC23 codec.");
 +MODULE_LICENSE("GPL");
 +
 +module_init(aic23_init)
 +module_exit(aic23_exit)
 +
 +EXPORT_SYMBOL(aic23_write_value);
 +EXPORT_SYMBOL(aic23_power_up);
 +EXPORT_SYMBOL(aic23_power_down);
index ddca5e30d041f248f143dcbbde89d51ccc2a91d7,0000000000000000000000000000000000000000..e05b88007b1d695fe0e3425165361249403a1992
mode 100644,000000..100644
--- /dev/null
@@@ -1,739 -1,0 +1,739 @@@
- #include <asm/arch/board.h>
 +/*
 + * drivers/i2c/chips/tsl2563.c
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Written by Timo O. Karjalainen <timo.o.karjalainen@nokia.com>
 + * Contact: Mathias Nyman <mathias.nyman@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + */
 +
 +#include <linux/module.h>
 +#include <linux/i2c.h>
 +#include <linux/interrupt.h>
 +#include <linux/sched.h>
 +#include <linux/mutex.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/pm.h>
 +#include <linux/hwmon.h>
 +#include <linux/err.h>
++#include <mach/board.h>
 +
 +#define DRIVER_NAME  "tsl2563"
 +
 +/* Use this many bits for fraction part. */
 +#define ADC_FRAC_BITS         (14)
 +
 +/* Given number of 1/10000's in ADC_FRAC_BITS precision. */
 +#define FRAC10K(f)            (((f) * (1L << (ADC_FRAC_BITS))) / (10000))
 +
 +/* Bits used for fraction in calibration coefficients.*/
 +#define CALIB_FRAC_BITS               (10)
 +/* 0.5 in CALIB_FRAC_BITS precision */
 +#define CALIB_FRAC_HALF               (1 << (CALIB_FRAC_BITS - 1))
 +/* Make a fraction from a number n that was multiplied with b. */
 +#define CALIB_FRAC(n, b)      (((n) << CALIB_FRAC_BITS) / (b))
 +/* Decimal 10^(digits in sysfs presentation) */
 +#define CALIB_BASE_SYSFS      (1000)
 +
 +#define TSL2563_CMD           (0x80)
 +#define TSL2563_CLEARINT      (0x40)
 +
 +#define TSL2563_REG_CTRL      (0x00)
 +#define TSL2563_REG_TIMING    (0x01)
 +#define TSL2563_REG_LOWLOW    (0x02) /* data0 low threshold, 2 bytes */
 +#define TSL2563_REG_LOWHIGH   (0x03)
 +#define TSL2563_REG_HIGHLOW   (0x04) /* data0 high threshold, 2 bytes */
 +#define TSL2563_REG_HIGHHIGH  (0x05)
 +#define TSL2563_REG_INT               (0x06)
 +#define TSL2563_REG_ID                (0x0a)
 +#define TSL2563_REG_DATA0LOW  (0x0c) /* broadband sensor value, 2 bytes */
 +#define TSL2563_REG_DATA0HIGH (0x0d)
 +#define TSL2563_REG_DATA1LOW  (0x0e) /* infrared sensor value, 2 bytes */
 +#define TSL2563_REG_DATA1HIGH (0x0f)
 +
 +#define TSL2563_CMD_POWER_ON  (0x03)
 +#define TSL2563_CMD_POWER_OFF (0x00)
 +#define TSL2563_CTRL_POWER_MASK       (0x03)
 +
 +#define TSL2563_TIMING_13MS   (0x00)
 +#define TSL2563_TIMING_100MS  (0x01)
 +#define TSL2563_TIMING_400MS  (0x02)
 +#define TSL2563_TIMING_MASK   (0x03)
 +#define TSL2563_TIMING_GAIN16 (0x10)
 +#define TSL2563_TIMING_GAIN1  (0x00)
 +
 +#define TSL2563_INT_DISBLED   (0x00)
 +#define TSL2563_INT_LEVEL     (0x10)
 +#define TSL2563_INT_PERSIST(n)        ((n) & 0x0F)
 +
 +struct tsl2563_gainlevel_coeff {
 +      u8 gaintime;
 +      u16 min;
 +      u16 max;
 +};
 +
 +static struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = {
 +      {
 +              .gaintime       = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16,
 +              .min            = 0,
 +              .max            = 65534,
 +      }, {
 +              .gaintime       = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN1,
 +              .min            = 2048,
 +              .max            = 65534,
 +      }, {
 +              .gaintime       = TSL2563_TIMING_100MS | TSL2563_TIMING_GAIN1,
 +              .min            = 4095,
 +              .max            = 37177,
 +      }, {
 +              .gaintime       = TSL2563_TIMING_13MS | TSL2563_TIMING_GAIN1,
 +              .min            = 3000,
 +              .max            = 65535,
 +      },
 +};
 +
 +struct tsl2563_chip {
 +      struct mutex            lock;
 +      struct i2c_client       *client;
 +      struct device           *hwmon_dev;
 +
 +      /* Remember state for suspend and resume functions */
 +      pm_message_t            state;
 +
 +      struct tsl2563_gainlevel_coeff *gainlevel;
 +
 +      /* Thresholds are in lux */
 +      u16                     low_thres;
 +      u16                     high_thres;
 +      u8                      intr;
 +
 +      /* Calibration coefficients */
 +      u32                     calib0;
 +      u32                     calib1;
 +
 +      /* Cache current values, to be returned while suspended */
 +      u32                     data0;
 +      u32                     data1;
 +};
 +
 +static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value)
 +{
 +      int ret;
 +      u8 buf[2];
 +
 +      buf[0] = TSL2563_CMD | reg;
 +      buf[1] = value;
 +
 +      ret = i2c_master_send(client, buf, sizeof(buf));
 +      return (ret == sizeof(buf)) ? 0 : ret;
 +}
 +
 +static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len)
 +{
 +      int ret;
 +      u8 cmd = TSL2563_CMD | reg;
 +
 +      ret = i2c_master_send(client, &cmd, sizeof(cmd));
 +      if (ret != sizeof(cmd))
 +              return ret;
 +
 +      return i2c_master_recv(client, buf, len);
 +}
 +
 +static int tsl2563_set_power(struct tsl2563_chip *chip, int on)
 +{
 +      struct i2c_client *client = chip->client;
 +      u8 cmd;
 +
 +      cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF;
 +      return tsl2563_write(client, TSL2563_REG_CTRL, cmd);
 +}
 +
 +/*
 + * Return value is 0 for off, 1 for on, or a negative error
 + * code if reading failed.
 + */
 +static int tsl2563_get_power(struct tsl2563_chip *chip)
 +{
 +      struct i2c_client *client = chip->client;
 +      int ret;
 +      u8 val;
 +
 +      ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val));
 +      if (ret != sizeof(val))
 +              return ret;
 +
 +      return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
 +}
 +
 +static int tsl2563_configure(struct tsl2563_chip *chip)
 +{
 +      struct i2c_client *client = chip->client;
 +      int ret;
 +
 +      ret = tsl2563_write(client, TSL2563_REG_TIMING,
 +                      chip->gainlevel->gaintime);
 +      if (ret)
 +              goto out;
 +
 +      ret = tsl2563_write(client, TSL2563_REG_INT, chip->intr);
 +
 +out:
 +      return ret;
 +}
 +
 +static int tsl2563_detect(struct tsl2563_chip *chip)
 +{
 +      int ret;
 +
 +      ret = tsl2563_set_power(chip, 1);
 +      if (ret)
 +              return ret;
 +
 +      ret = tsl2563_get_power(chip);
 +      if (ret < 0)
 +              return ret;
 +
 +      return ret ? 0 : -ENODEV;
 +}
 +
 +static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id)
 +{
 +      struct i2c_client *client = chip->client;
 +      int ret;
 +
 +      ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id));
 +      if (ret != sizeof(*id))
 +              return ret;
 +
 +      return 0;
 +}
 +
 +/*
 + * "Normalized" ADC value is one obtained with 400ms of integration time and
 + * 16x gain. This function returns the number of bits of shift needed to
 + * convert between normalized values and HW values obtained using given
 + * timing and gain settings.
 + */
 +static int adc_shiftbits(u8 timing)
 +{
 +      int shift = 0;
 +
 +      switch (timing & TSL2563_TIMING_MASK) {
 +      case TSL2563_TIMING_13MS:
 +              shift += 5;
 +              break;
 +      case TSL2563_TIMING_100MS:
 +              shift += 2;
 +              break;
 +      case TSL2563_TIMING_400MS:
 +              /* no-op */
 +              break;
 +      }
 +
 +      if (!(timing & TSL2563_TIMING_GAIN16))
 +              shift += 4;
 +
 +      return shift;
 +}
 +
 +/* Convert a HW ADC value to normalized scale. */
 +static u32 normalize_adc(u16 adc, u8 timing)
 +{
 +      return adc << adc_shiftbits(timing);
 +}
 +
 +static void tsl2563_wait_adc(struct tsl2563_chip *chip)
 +{
 +      unsigned int delay;
 +
 +      switch (chip->gainlevel->gaintime & TSL2563_TIMING_MASK) {
 +      case TSL2563_TIMING_13MS:
 +              delay = 14;
 +              break;
 +      case TSL2563_TIMING_100MS:
 +              delay = 101;
 +              break;
 +      default:
 +              delay = 402;
 +      }
 +      /*
 +       * TODO: Make sure that we wait at least required delay but why we
 +       * have to extend it one tick more?
 +       */
 +      schedule_timeout_interruptible(msecs_to_jiffies(delay) + 2);
 +}
 +
 +static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
 +{
 +      struct i2c_client *client = chip->client;
 +
 +      if (adc > chip->gainlevel->max || adc < chip->gainlevel->min) {
 +
 +              (adc > chip->gainlevel->max) ?
 +                      chip->gainlevel++ : chip->gainlevel--;
 +
 +              tsl2563_write(client, TSL2563_REG_TIMING,
 +                            chip->gainlevel->gaintime);
 +
 +              tsl2563_wait_adc(chip);
 +              tsl2563_wait_adc(chip);
 +
 +              return 1;
 +      } else
 +              return 0;
 +}
 +
 +static int tsl2563_get_adc(struct tsl2563_chip *chip)
 +{
 +      struct i2c_client *client = chip->client;
 +      u8 buf0[2], buf1[2];
 +      u16 adc0, adc1;
 +      int retry = 1;
 +      int ret = 0;
 +
 +      if (chip->state.event != PM_EVENT_ON)
 +              goto out;
 +
 +      while (retry) {
 +              ret = tsl2563_read(client,
 +                                 TSL2563_REG_DATA0LOW | TSL2563_CLEARINT,
 +                                 buf0, sizeof(buf0));
 +              if (ret != sizeof(buf0))
 +                      goto out;
 +
 +              ret = tsl2563_read(client, TSL2563_REG_DATA1LOW,
 +                                 buf1, sizeof(buf1));
 +              if (ret != sizeof(buf1))
 +                      goto out;
 +
 +              adc0 = (buf0[1] << 8) + buf0[0];
 +              adc1 = (buf1[1] << 8) + buf1[0];
 +
 +              retry = tsl2563_adjust_gainlevel(chip, adc0);
 +      }
 +
 +      chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime);
 +      chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime);
 +
 +      ret = 0;
 +out:
 +      return ret;
 +}
 +
 +static inline int calib_to_sysfs(u32 calib)
 +{
 +      return (int) (((calib * CALIB_BASE_SYSFS) +
 +                     CALIB_FRAC_HALF) >> CALIB_FRAC_BITS);
 +}
 +
 +static inline u32 calib_from_sysfs(int value)
 +{
 +      return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS;
 +}
 +
 +/*
 + * Conversions between lux and ADC values.
 + *
 + * The basic formula is lux = c0 * adc0 - c1 * adc1, where c0 and c1 are
 + * appropriate constants. Different constants are needed for different
 + * kinds of light, determined by the ratio adc1/adc0 (basically the ratio
 + * of the intensities in infrared and visible wavelengths). lux_table below
 + * lists the upper threshold of the adc1/adc0 ratio and the corresponding
 + * constants.
 + */
 +
 +struct tsl2563_lux_coeff {
 +      unsigned long ch_ratio;
 +      unsigned long ch0_coeff;
 +      unsigned long ch1_coeff;
 +};
 +
 +static const struct tsl2563_lux_coeff lux_table[] = {
 +      {
 +              .ch_ratio       = FRAC10K(1300),
 +              .ch0_coeff      = FRAC10K(315),
 +              .ch1_coeff      = FRAC10K(262),
 +      }, {
 +              .ch_ratio       = FRAC10K(2600),
 +              .ch0_coeff      = FRAC10K(337),
 +              .ch1_coeff      = FRAC10K(430),
 +      }, {
 +              .ch_ratio       = FRAC10K(3900),
 +              .ch0_coeff      = FRAC10K(363),
 +              .ch1_coeff      = FRAC10K(529),
 +      }, {
 +              .ch_ratio       = FRAC10K(5200),
 +              .ch0_coeff      = FRAC10K(392),
 +              .ch1_coeff      = FRAC10K(605),
 +      }, {
 +              .ch_ratio       = FRAC10K(6500),
 +              .ch0_coeff      = FRAC10K(229),
 +              .ch1_coeff      = FRAC10K(291),
 +      }, {
 +              .ch_ratio       = FRAC10K(8000),
 +              .ch0_coeff      = FRAC10K(157),
 +              .ch1_coeff      = FRAC10K(180),
 +      }, {
 +              .ch_ratio       = FRAC10K(13000),
 +              .ch0_coeff      = FRAC10K(34),
 +              .ch1_coeff      = FRAC10K(26),
 +      }, {
 +              .ch_ratio       = ULONG_MAX,
 +              .ch0_coeff      = 0,
 +              .ch1_coeff      = 0,
 +      },
 +};
 +
 +/*
 + * Convert normalized, scaled ADC values to lux.
 + */
 +static unsigned int adc_to_lux(u32 adc0, u32 adc1)
 +{
 +      const struct tsl2563_lux_coeff *lp = lux_table;
 +      unsigned long ratio, lux, ch0 = adc0, ch1 = adc1;
 +
 +      ratio = ch0 ? ((ch1 << ADC_FRAC_BITS) / ch0) : ULONG_MAX;
 +
 +      while (lp->ch_ratio < ratio)
 +              lp++;
 +
 +      lux = ch0 * lp->ch0_coeff - ch1 * lp->ch1_coeff;
 +
 +      return (unsigned int) (lux >> ADC_FRAC_BITS);
 +}
 +
 +/*--------------------------------------------------------------*/
 +/*                      Sysfs interface                         */
 +/*--------------------------------------------------------------*/
 +
 +static ssize_t tsl2563_adc0_show(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = tsl2563_get_adc(chip);
 +      if (ret)
 +              return ret;
 +
 +      ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data0);
 +      mutex_unlock(&chip->lock);
 +
 +      return ret;
 +}
 +
 +static ssize_t tsl2563_adc1_show(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = tsl2563_get_adc(chip);
 +      if (ret)
 +              return ret;
 +
 +      ret = snprintf(buf, PAGE_SIZE, "%d\n", chip->data1);
 +      mutex_unlock(&chip->lock);
 +
 +      return ret;
 +}
 +
 +/* Apply calibration coefficient to ADC count. */
 +static u32 calib_adc(u32 adc, u32 calib)
 +{
 +      unsigned long scaled = adc;
 +
 +      scaled *= calib;
 +      scaled >>= CALIB_FRAC_BITS;
 +
 +      return (u32) scaled;
 +}
 +
 +static ssize_t tsl2563_lux_show(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      u32 calib0, calib1;
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = tsl2563_get_adc(chip);
 +      if (ret)
 +              goto out;
 +
 +      calib0 = calib_adc(chip->data0, chip->calib0);
 +      calib1 = calib_adc(chip->data1, chip->calib1);
 +
 +      ret = snprintf(buf, PAGE_SIZE, "%d\n", adc_to_lux(calib0, calib1));
 +
 +out:
 +      mutex_unlock(&chip->lock);
 +      return ret;
 +}
 +
 +static ssize_t format_calib(char *buf, int len, u32 calib)
 +{
 +      return snprintf(buf, PAGE_SIZE, "%d\n", calib_to_sysfs(calib));
 +}
 +
 +static ssize_t tsl2563_calib0_show(struct device *dev,
 +                                 struct device_attribute *attr, char *buf)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +      ret = format_calib(buf, PAGE_SIZE, chip->calib0);
 +      mutex_unlock(&chip->lock);
 +      return ret;
 +}
 +
 +static ssize_t tsl2563_calib1_show(struct device *dev,
 +                                 struct device_attribute *attr, char *buf)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +      ret = format_calib(buf, PAGE_SIZE, chip->calib1);
 +      mutex_unlock(&chip->lock);
 +      return ret;
 +}
 +
 +static int do_calib_store(struct device *dev, const char *buf, size_t len,
 +                        int ch)
 +{
 +      struct tsl2563_chip *chip = dev_get_drvdata(dev);
 +      int value;
 +      u32 calib;
 +
 +      if (1 != sscanf(buf, "%d", &value))
 +              return -EINVAL;
 +
 +      calib = calib_from_sysfs(value);
 +
 +      if (ch)
 +              chip->calib1 = calib;
 +      else
 +              chip->calib0 = calib;
 +
 +      return len;
 +}
 +
 +static ssize_t tsl2563_calib0_store(struct device *dev,
 +                                  struct device_attribute *attr,
 +                                  const char *buf, size_t len)
 +{
 +      return do_calib_store(dev, buf, len, 0);
 +}
 +
 +static ssize_t tsl2563_calib1_store(struct device *dev,
 +                                  struct device_attribute *attr,
 +                                  const char *buf, size_t len)
 +{
 +      return do_calib_store(dev, buf, len, 1);
 +}
 +
 +static DEVICE_ATTR(adc0, S_IRUGO, tsl2563_adc0_show, NULL);
 +static DEVICE_ATTR(adc1, S_IRUGO, tsl2563_adc1_show, NULL);
 +static DEVICE_ATTR(lux, S_IRUGO, tsl2563_lux_show, NULL);
 +static DEVICE_ATTR(calib0, S_IRUGO | S_IWUSR,
 +                 tsl2563_calib0_show, tsl2563_calib0_store);
 +static DEVICE_ATTR(calib1, S_IRUGO | S_IWUSR,
 +                 tsl2563_calib1_show, tsl2563_calib1_store);
 +
 +static struct attribute *tsl2563_attributes[] = {
 +      &dev_attr_adc0.attr,
 +      &dev_attr_adc1.attr,
 +      &dev_attr_lux.attr,
 +      &dev_attr_calib0.attr,
 +      &dev_attr_calib1.attr,
 +      NULL
 +};
 +
 +static const struct attribute_group tsl2563_group = {
 +      .attrs = tsl2563_attributes,
 +};
 +
 +static int tsl2563_register_sysfs(struct i2c_client *client)
 +{
 +      struct device *dev = &client->dev;
 +
 +      return sysfs_create_group(&dev->kobj, &tsl2563_group);
 +}
 +
 +static void tsl2563_unregister_sysfs(struct i2c_client *client)
 +{
 +      struct device *dev = &client->dev;
 +
 +      sysfs_remove_group(&dev->kobj, &tsl2563_group);
 +}
 +
 +/*--------------------------------------------------------------*/
 +/*                      Probe, Attach, Remove                   */
 +/*--------------------------------------------------------------*/
 +static struct i2c_driver tsl2563_i2c_driver;
 +
 +static int tsl2563_probe(struct i2c_client *client,
 +              const struct i2c_device_id *device_id)
 +{
 +      struct tsl2563_chip *chip;
 +      int err = 0;
 +      u8 id;
 +
 +      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 +      if (!chip)
 +              return -ENOMEM;
 +
 +      i2c_set_clientdata(client, chip);
 +      chip->client = client;
 +
 +      err = tsl2563_detect(chip);
 +      if (err) {
 +              dev_err(&client->dev, "device not found, error %d \n", -err);
 +              goto fail1;
 +      }
 +
 +      err = tsl2563_read_id(chip, &id);
 +      if (err)
 +              goto fail1;
 +
 +      mutex_init(&chip->lock);
 +
 +      /* Default values used until userspace says otherwise */
 +      chip->low_thres = 0x0;
 +      chip->high_thres = 0xffff;
 +      chip->gainlevel = tsl2563_gainlevel_table;
 +      chip->intr = TSL2563_INT_PERSIST(4);
 +      chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS);
 +      chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS);
 +
 +      dev_info(&client->dev, "model %d, rev. %d\n", id >> 4, id & 0x0f);
 +
 +      err = tsl2563_configure(chip);
 +      if (err)
 +              goto fail1;
 +
 +      chip->hwmon_dev = hwmon_device_register(&client->dev);
 +      if (IS_ERR(chip->hwmon_dev))
 +              goto fail1;
 +
 +      err = tsl2563_register_sysfs(client);
 +      if (err) {
 +              dev_err(&client->dev, "sysfs registration failed, %d\n", err);
 +              goto fail2;
 +      }
 +
 +      return 0;
 +fail2:
 +      hwmon_device_unregister(chip->hwmon_dev);
 +fail1:
 +      kfree(chip);
 +      return err;
 +}
 +
 +static int tsl2563_remove(struct i2c_client *client)
 +{
 +      struct tsl2563_chip *chip = i2c_get_clientdata(client);
 +
 +      tsl2563_unregister_sysfs(client);
 +      hwmon_device_unregister(chip->hwmon_dev);
 +
 +      kfree(chip);
 +      return 0;
 +}
 +
 +static int tsl2563_suspend(struct i2c_client *client, pm_message_t state)
 +{
 +      struct tsl2563_chip *chip = i2c_get_clientdata(client);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = tsl2563_set_power(chip, 0);
 +      if (ret)
 +              goto out;
 +
 +      chip->state = state;
 +
 +out:
 +      mutex_unlock(&chip->lock);
 +      return ret;
 +}
 +
 +static int tsl2563_resume(struct i2c_client *client)
 +{
 +      struct tsl2563_chip *chip = i2c_get_clientdata(client);
 +      int ret;
 +
 +      mutex_lock(&chip->lock);
 +
 +      ret = tsl2563_set_power(chip, 1);
 +      if (ret)
 +              goto out;
 +
 +      ret = tsl2563_configure(chip);
 +      if (ret)
 +              goto out;
 +
 +      chip->state.event = PM_EVENT_ON;
 +
 +out:
 +      mutex_unlock(&chip->lock);
 +      return ret;
 +}
 +
 +static const struct i2c_device_id tsl2563_id[] = {
 +      { DRIVER_NAME, 0 },
 +      { },
 +};
 +MODULE_DEVICE_TABLE(i2c, tsl2563_id);
 +
 +static struct i2c_driver tsl2563_i2c_driver = {
 +      .driver = {
 +              .name    = DRIVER_NAME,
 +      },
 +      .suspend        = tsl2563_suspend,
 +      .resume         = tsl2563_resume,
 +      .probe          = tsl2563_probe,
 +      .remove         = __devexit_p(tsl2563_remove),
 +      .id_table       = tsl2563_id,
 +};
 +
 +static int __init tsl2563_init(void)
 +{
 +      return i2c_add_driver(&tsl2563_i2c_driver);
 +}
 +
 +static void __exit tsl2563_exit(void)
 +{
 +      i2c_del_driver(&tsl2563_i2c_driver);
 +}
 +
 +MODULE_AUTHOR("Nokia Corporation");
 +MODULE_DESCRIPTION("tsl2563 light sensor driver");
 +MODULE_LICENSE("GPL");
 +
 +module_init(tsl2563_init);
 +module_exit(tsl2563_exit);
index 1a8e4137c058151ef106d57a6f81f4dd9f553dd7,0000000000000000000000000000000000000000..713947d5b184fe45a5a4f679f13be986d319aac2
mode 100644,000000..100644
--- /dev/null
@@@ -1,1006 -1,0 +1,1006 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
 +/*
 + * twl4030_core.c - driver for TWL4030 PM and audio CODEC device
 + *
 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
 + *
 + * Modifications to defer interrupt handling to a kernel thread:
 + * Copyright (C) 2006 MontaVista Software, Inc.
 + *
 + * Based on tlv320aic23.c:
 + * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
 + *
 + * Code cleanup and modifications to IRQ handler.
 + * by syed khasim <x0khasim@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/kernel_stat.h>
 +#include <linux/init.h>
 +#include <linux/time.h>
 +#include <linux/mutex.h>
 +#include <linux/interrupt.h>
 +#include <linux/random.h>
 +#include <linux/syscalls.h>
 +#include <linux/kthread.h>
 +
 +#include <linux/i2c.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/i2c/twl4030-gpio.h>
 +#include <linux/i2c/twl4030-madc.h>
 +#include <linux/i2c/twl4030-pwrirq.h>
 +#include <linux/slab.h>
 +#include <linux/clk.h>
 +#include <linux/device.h>
 +#include <linux/irq.h>
 +
 +#include <asm/mach/irq.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
 +
 +#define DRIVER_NAME                   "twl4030"
 +
 +/* Macro Definitions */
 +#define TWL_CLIENT_STRING             "TWL4030-ID"
 +#define TWL_CLIENT_USED                       1
 +#define TWL_CLIENT_FREE                       0
 +
 +/* IRQ Flags */
 +#define FREE                          0
 +#define USED                          1
 +
 +/* Primary Interrupt Handler on TWL4030 Registers */
 +
 +/* Register Definitions */
 +
 +#define REG_PIH_ISR_P1                        (0x1)
 +#define REG_PIH_ISR_P2                        (0x2)
 +#define REG_PIH_SIR                   (0x3)
 +
 +/* Triton Core internal information (BEGIN) */
 +
 +/* Last - for index max*/
 +#define TWL4030_MODULE_LAST           TWL4030_MODULE_SECURED_REG
 +
 +/* Slave address */
 +#define TWL4030_NUM_SLAVES            0x04
 +#define TWL4030_SLAVENUM_NUM0         0x00
 +#define TWL4030_SLAVENUM_NUM1         0x01
 +#define TWL4030_SLAVENUM_NUM2         0x02
 +#define TWL4030_SLAVENUM_NUM3         0x03
 +#define TWL4030_SLAVEID_ID0           0x48
 +#define TWL4030_SLAVEID_ID1           0x49
 +#define TWL4030_SLAVEID_ID2           0x4A
 +#define TWL4030_SLAVEID_ID3           0x4B
 +
 +/* Base Address defns */
 +/* USB ID */
 +#define TWL4030_BASEADD_USB           0x0000
 +/* AUD ID */
 +#define TWL4030_BASEADD_AUDIO_VOICE   0x0000
 +#define TWL4030_BASEADD_GPIO          0x0098
 +
 +#define TWL4030_BASEADD_INTBR         0x0085
 +#define TWL4030_BASEADD_PIH           0x0080
 +#define TWL4030_BASEADD_TEST          0x004C
 +/* AUX ID */
 +#define TWL4030_BASEADD_INTERRUPTS    0x00B9
 +#define TWL4030_BASEADD_LED           0x00EE
 +#define TWL4030_BASEADD_MADC          0x0000
 +#define TWL4030_BASEADD_MAIN_CHARGE   0x0074
 +#define TWL4030_BASEADD_PRECHARGE     0x00AA
 +#define TWL4030_BASEADD_PWM0          0x00F8
 +#define TWL4030_BASEADD_PWM1          0x00FB
 +#define TWL4030_BASEADD_PWMA          0x00EF
 +#define TWL4030_BASEADD_PWMB          0x00F1
 +#define TWL4030_BASEADD_KEYPAD                0x00D2
 +/* POWER ID */
 +#define TWL4030_BASEADD_BACKUP                0x0014
 +#define TWL4030_BASEADD_INT           0x002E
 +#define TWL4030_BASEADD_PM_MASTER     0x0036
 +#define TWL4030_BASEADD_PM_RECEIVER   0x005B
 +#define TWL4030_BASEADD_RTC           0x001C
 +#define TWL4030_BASEADD_SECURED_REG   0x0000
 +
 +/* TWL4030 BCI registers */
 +#define TWL4030_INTERRUPTS_BCIIMR1A   0x2
 +#define TWL4030_INTERRUPTS_BCIIMR2A   0x3
 +#define TWL4030_INTERRUPTS_BCIIMR1B   0x6
 +#define TWL4030_INTERRUPTS_BCIIMR2B   0x7
 +#define TWL4030_INTERRUPTS_BCIISR1A   0x0
 +#define TWL4030_INTERRUPTS_BCIISR2A   0x1
 +#define TWL4030_INTERRUPTS_BCIISR1B   0x4
 +#define TWL4030_INTERRUPTS_BCIISR2B   0x5
 +
 +/* TWL4030 keypad registers */
 +#define TWL4030_KEYPAD_KEYP_IMR1      0x12
 +#define TWL4030_KEYPAD_KEYP_IMR2      0x14
 +#define TWL4030_KEYPAD_KEYP_ISR1      0x11
 +#define TWL4030_KEYPAD_KEYP_ISR2      0x13
 +
 +
 +/* Triton Core internal information (END) */
 +
 +/* Few power values */
 +#define R_CFG_BOOT                    0x05
 +#define R_PROTECT_KEY                 0x0E
 +
 +/* access control */
 +#define KEY_UNLOCK1                   0xce
 +#define KEY_UNLOCK2                   0xec
 +#define KEY_LOCK                      0x00
 +
 +#define HFCLK_FREQ_19p2_MHZ           (1 << 0)
 +#define HFCLK_FREQ_26_MHZ             (2 << 0)
 +#define HFCLK_FREQ_38p4_MHZ           (3 << 0)
 +#define HIGH_PERF_SQ                  (1 << 3)
 +
 +/* on I2C-1 for 2430SDP */
 +#define CONFIG_I2C_TWL4030_ID         1
 +
 +/* SIH_CTRL registers that aren't defined elsewhere */
 +#define TWL4030_INTERRUPTS_BCISIHCTRL 0x0d
 +#define TWL4030_MADC_MADC_SIH_CTRL    0x67
 +#define TWL4030_KEYPAD_KEYP_SIH_CTRL  0x17
 +
 +#define TWL4030_SIH_CTRL_COR_MASK     (1 << 2)
 +
 +/**
 + * struct twl4030_mod_iregs - TWL module IMR/ISR regs to mask/clear at init
 + * @mod_no: TWL4030 module number (e.g., TWL4030_MODULE_GPIO)
 + * @sih_ctrl: address of module SIH_CTRL register
 + * @reg_cnt: number of IMR/ISR regs
 + * @imrs: pointer to array of TWL module interrupt mask register indices
 + * @isrs: pointer to array of TWL module interrupt status register indices
 + *
 + * Ties together TWL4030 modules and lists of IMR/ISR registers to mask/clear
 + * during twl_init_irq().
 + */
 +struct twl4030_mod_iregs {
 +      const u8 mod_no;
 +      const u8 sih_ctrl;
 +      const u8 reg_cnt;
 +      const u8 *imrs;
 +      const u8 *isrs;
 +};
 +
 +/* TWL4030 INT module interrupt mask registers */
 +static const u8 __initconst twl4030_int_imr_regs[] = {
 +      TWL4030_INT_PWR_IMR1,
 +      TWL4030_INT_PWR_IMR2,
 +};
 +
 +/* TWL4030 INT module interrupt status registers */
 +static const u8 __initconst twl4030_int_isr_regs[] = {
 +      TWL4030_INT_PWR_ISR1,
 +      TWL4030_INT_PWR_ISR2,
 +};
 +
 +/* TWL4030 INTERRUPTS module interrupt mask registers */
 +static const u8 __initconst twl4030_interrupts_imr_regs[] = {
 +      TWL4030_INTERRUPTS_BCIIMR1A,
 +      TWL4030_INTERRUPTS_BCIIMR1B,
 +      TWL4030_INTERRUPTS_BCIIMR2A,
 +      TWL4030_INTERRUPTS_BCIIMR2B,
 +};
 +
 +/* TWL4030 INTERRUPTS module interrupt status registers */
 +static const u8 __initconst twl4030_interrupts_isr_regs[] = {
 +      TWL4030_INTERRUPTS_BCIISR1A,
 +      TWL4030_INTERRUPTS_BCIISR1B,
 +      TWL4030_INTERRUPTS_BCIISR2A,
 +      TWL4030_INTERRUPTS_BCIISR2B,
 +};
 +
 +/* TWL4030 MADC module interrupt mask registers */
 +static const u8 __initconst twl4030_madc_imr_regs[] = {
 +      TWL4030_MADC_IMR1,
 +      TWL4030_MADC_IMR2,
 +};
 +
 +/* TWL4030 MADC module interrupt status registers */
 +static const u8 __initconst twl4030_madc_isr_regs[] = {
 +      TWL4030_MADC_ISR1,
 +      TWL4030_MADC_ISR2,
 +};
 +
 +/* TWL4030 keypad module interrupt mask registers */
 +static const u8 __initconst twl4030_keypad_imr_regs[] = {
 +      TWL4030_KEYPAD_KEYP_IMR1,
 +      TWL4030_KEYPAD_KEYP_IMR2,
 +};
 +
 +/* TWL4030 keypad module interrupt status registers */
 +static const u8 __initconst twl4030_keypad_isr_regs[] = {
 +      TWL4030_KEYPAD_KEYP_ISR1,
 +      TWL4030_KEYPAD_KEYP_ISR2,
 +};
 +
 +/* TWL4030 GPIO module interrupt mask registers */
 +static const u8 __initconst twl4030_gpio_imr_regs[] = {
 +      REG_GPIO_IMR1A,
 +      REG_GPIO_IMR1B,
 +      REG_GPIO_IMR2A,
 +      REG_GPIO_IMR2B,
 +      REG_GPIO_IMR3A,
 +      REG_GPIO_IMR3B,
 +};
 +
 +/* TWL4030 GPIO module interrupt status registers */
 +static const u8 __initconst twl4030_gpio_isr_regs[] = {
 +      REG_GPIO_ISR1A,
 +      REG_GPIO_ISR1B,
 +      REG_GPIO_ISR2A,
 +      REG_GPIO_ISR2B,
 +      REG_GPIO_ISR3A,
 +      REG_GPIO_ISR3B,
 +};
 +
 +/* TWL4030 modules that have IMR/ISR registers that must be masked/cleared */
 +static const struct twl4030_mod_iregs __initconst twl4030_mod_regs[] = {
 +      {
 +              .mod_no   = TWL4030_MODULE_INT,
 +              .sih_ctrl = TWL4030_INT_PWR_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_int_imr_regs),
 +              .imrs     = twl4030_int_imr_regs,
 +              .isrs     = twl4030_int_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_INTERRUPTS,
 +              .sih_ctrl = TWL4030_INTERRUPTS_BCISIHCTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_interrupts_imr_regs),
 +              .imrs     = twl4030_interrupts_imr_regs,
 +              .isrs     = twl4030_interrupts_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_MADC,
 +              .sih_ctrl = TWL4030_MADC_MADC_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_madc_imr_regs),
 +              .imrs     = twl4030_madc_imr_regs,
 +              .isrs     = twl4030_madc_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_KEYPAD,
 +              .sih_ctrl = TWL4030_KEYPAD_KEYP_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_keypad_imr_regs),
 +              .imrs     = twl4030_keypad_imr_regs,
 +              .isrs     = twl4030_keypad_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_GPIO,
 +              .sih_ctrl = REG_GPIO_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_gpio_imr_regs),
 +              .imrs     = twl4030_gpio_imr_regs,
 +              .isrs     = twl4030_gpio_isr_regs,
 +      },
 +};
 +
 +
 +/* Helper functions */
 +static int
 +twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid);
 +static int twl4030_attach_adapter(struct i2c_adapter *adapter);
 +static int twl4030_detach_client(struct i2c_client *client);
 +static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc);
 +
 +static void twl_init_irq(void);
 +
 +/* Data Structures */
 +/* To have info on T2 IRQ substem activated or not */
 +static unsigned char twl_irq_used = FREE;
 +static struct completion irq_event;
 +
 +/* Structure to define on TWL4030 Slave ID */
 +struct twl4030_client {
 +      struct i2c_client client;
 +      const char client_name[sizeof(TWL_CLIENT_STRING) + 1];
 +      const unsigned char address;
 +      const char adapter_index;
 +      unsigned char inuse;
 +
 +      /* max numb of i2c_msg required is for read =2 */
 +      struct i2c_msg xfer_msg[2];
 +
 +      /* To lock access to xfer_msg */
 +      struct mutex xfer_lock;
 +};
 +
 +/* Module Mapping */
 +struct twl4030mapping {
 +      unsigned char sid;      /* Slave ID */
 +      unsigned char base;     /* base address */
 +};
 +
 +/* mapping the module id to slave id and base address */
 +static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
 +      { TWL4030_SLAVENUM_NUM0, TWL4030_BASEADD_USB },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_AUDIO_VOICE },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_GPIO },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_INTBR },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_PIH },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_TEST },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_KEYPAD },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MADC },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_INTERRUPTS },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_LED },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MAIN_CHARGE },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PRECHARGE },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM0 },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM1 },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMA },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMB },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_BACKUP },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_INT },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_MASTER },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECEIVER },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_RTC },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_SECURED_REG },
 +};
 +
 +static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES] = {
 +      {
 +              .address        = TWL4030_SLAVEID_ID0,
 +              .client_name    = TWL_CLIENT_STRING "0",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID1,
 +              .client_name    = TWL_CLIENT_STRING "1",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID2,
 +              .client_name    = TWL_CLIENT_STRING "2",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID3,
 +              .client_name    = TWL_CLIENT_STRING "3",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +};
 +
 +/* One Client Driver , 4 Clients */
 +static struct i2c_driver twl4030_driver = {
 +      .driver = {
 +              .name   = DRIVER_NAME,
 +              .owner  = THIS_MODULE,
 +      },
 +      .attach_adapter = twl4030_attach_adapter,
 +      .detach_client  = twl4030_detach_client,
 +};
 +
 +/*
 + * TWL4030 doesn't have PIH mask, hence dummy function for mask
 + * and unmask.
 + */
 +
 +static void twl4030_i2c_ackirq(unsigned int irq) {}
 +static void twl4030_i2c_disableint(unsigned int irq) {}
 +static void twl4030_i2c_enableint(unsigned int irq) {}
 +
 +/* information for processing in the Work Item */
 +static struct irq_chip twl4030_irq_chip = {
 +      .name   = "twl4030",
 +      .ack    = twl4030_i2c_ackirq,
 +      .mask   = twl4030_i2c_disableint,
 +      .unmask = twl4030_i2c_enableint,
 +};
 +
 +/* Global Functions */
 +
 +/**
 + * twl4030_i2c_write - Writes a n bit register in TWL4030
 + * @mod_no: module number
 + * @value: an array of num_bytes+1 containing data to write
 + * @reg: register address (just offset will do)
 + * @num_bytes: number of bytes to transfer
 + *
 + * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and
 + * valid data starts at Offset 1.
 + *
 + * Returns the result of operation - 0 is success
 + */
 +int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
 +{
 +      int ret;
 +      int sid;
 +      struct twl4030_client *twl;
 +      struct i2c_msg *msg;
 +
 +      if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 +              pr_err("Invalid module Number\n");
 +              return -EPERM;
 +      }
 +      sid = twl4030_map[mod_no].sid;
 +      twl = &twl4030_modules[sid];
 +
 +      if (unlikely(twl->inuse != TWL_CLIENT_USED)) {
 +              pr_err("I2C Client[%d] is not initialized[%d]\n",
 +                     sid, __LINE__);
 +              return -EPERM;
 +      }
 +      mutex_lock(&twl->xfer_lock);
 +      /*
 +       * [MSG1]: fill the register address data
 +       * fill the data Tx buffer
 +       */
 +      msg = &twl->xfer_msg[0];
 +      msg->addr = twl->address;
 +      msg->len = num_bytes + 1;
 +      msg->flags = 0;
 +      msg->buf = value;
 +      /* over write the first byte of buffer with the register address */
 +      *value = twl4030_map[mod_no].base + reg;
 +      ret = i2c_transfer(twl->client.adapter, twl->xfer_msg, 1);
 +      mutex_unlock(&twl->xfer_lock);
 +
 +      /* i2cTransfer returns num messages.translate it pls.. */
 +      if (ret >= 0)
 +              ret = 0;
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_i2c_write);
 +
 +/**
 + * twl4030_i2c_read - Reads a n bit register in TWL4030
 + * @mod_no: module number
 + * @value: an array of num_bytes containing data to be read
 + * @reg: register address (just offset will do)
 + * @num_bytes: number of bytes to transfer
 + *
 + * Returns result of operation - num_bytes is success else failure.
 + */
 +int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
 +{
 +      int ret;
 +      u8 val;
 +      int sid;
 +      struct twl4030_client *twl;
 +      struct i2c_msg *msg;
 +
 +      if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 +              pr_err("Invalid module Number\n");
 +              return -EPERM;
 +      }
 +      sid = twl4030_map[mod_no].sid;
 +      twl = &twl4030_modules[sid];
 +
 +      if (unlikely(twl->inuse != TWL_CLIENT_USED)) {
 +              pr_err("I2C Client[%d] is not initialized[%d]\n", sid,
 +                     __LINE__);
 +              return -EPERM;
 +      }
 +      mutex_lock(&twl->xfer_lock);
 +      /* [MSG1] fill the register address data */
 +      msg = &twl->xfer_msg[0];
 +      msg->addr = twl->address;
 +      msg->len = 1;
 +      msg->flags = 0; /* Read the register value */
 +      val = twl4030_map[mod_no].base + reg;
 +      msg->buf = &val;
 +      /* [MSG2] fill the data rx buffer */
 +      msg = &twl->xfer_msg[1];
 +      msg->addr = twl->address;
 +      msg->flags = I2C_M_RD;  /* Read the register value */
 +      msg->len = num_bytes;   /* only n bytes */
 +      msg->buf = value;
 +      ret = i2c_transfer(twl->client.adapter, twl->xfer_msg, 2);
 +      mutex_unlock(&twl->xfer_lock);
 +
 +      /* i2cTransfer returns num messages.translate it pls.. */
 +      if (ret >= 0)
 +              ret = 0;
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_i2c_read);
 +
 +/**
 + * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
 + * @mod_no: module number
 + * @value: the value to be written 8 bit
 + * @reg: register address (just offset will do)
 + *
 + * Returns result of operation - 0 is success
 + */
 +int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
 +{
 +
 +      /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
 +      u8 temp_buffer[2] = { 0 };
 +      /* offset 1 contains the data */
 +      temp_buffer[1] = value;
 +      return twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
 +}
 +EXPORT_SYMBOL(twl4030_i2c_write_u8);
 +
 +/**
 + * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030
 + * @mod_no: module number
 + * @value: the value read 8 bit
 + * @reg: register address (just offset will do)
 + *
 + * Returns result of operation - 0 is success
 + */
 +int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
 +{
 +      return twl4030_i2c_read(mod_no, value, reg, 1);
 +}
 +EXPORT_SYMBOL(twl4030_i2c_read_u8);
 +
 +/* Helper Functions */
 +
 +/*
 + * do_twl4030_module_irq() is the desc->handle method for each of the twl4030
 + * module interrupts.  It executes in kernel thread context.
 + * On entry, cpu interrupts are disabled.
 + */
 +static void do_twl4030_module_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      struct irqaction *action;
 +      const unsigned int cpu = smp_processor_id();
 +
 +      /*
 +       * Earlier this was desc->triggered = 1;
 +       */
 +      desc->status |= IRQ_LEVEL;
 +
 +      /*
 +       * The desc->handle method would normally call the desc->chip->ack
 +       * method here, but we won't bother since our ack method is NULL.
 +       */
 +
 +      if (!desc->depth) {
 +              kstat_cpu(cpu).irqs[irq]++;
 +
 +              action = desc->action;
 +              if (action) {
 +                      int ret;
 +                      int status = 0;
 +                      int retval = 0;
 +
 +                      local_irq_enable();
 +
 +                      do {
 +                              /* Call the ISR with cpu interrupts enabled */
 +                              ret = action->handler(irq, action->dev_id);
 +                              if (ret == IRQ_HANDLED)
 +                                      status |= action->flags;
 +                              retval |= ret;
 +                              action = action->next;
 +                      } while (action);
 +
 +                      if (status & IRQF_SAMPLE_RANDOM)
 +                              add_interrupt_randomness(irq);
 +
 +                      local_irq_disable();
 +
 +                      if (retval != IRQ_HANDLED)
 +                              printk(KERN_ERR "ISR for TWL4030 module"
 +                                      " irq %d can't handle interrupt\n",
 +                                      irq);
 +
 +                      /*
 +                       * Here is where we should call the unmask method, but
 +                       * again we won't bother since it is NULL.
 +                       */
 +              } else
 +                      printk(KERN_CRIT "TWL4030 module irq %d has no ISR"
 +                                      " but can't be masked!\n", irq);
 +      } else
 +              printk(KERN_CRIT "TWL4030 module irq %d is disabled but can't"
 +                              " be masked!\n", irq);
 +}
 +
 +/*
 + * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030
 + * interrupt controller to see which modules are generating interrupt requests
 + * and then calls the desc->handle method for each module requesting service.
 + */
 +static int twl4030_irq_thread(void *data)
 +{
 +      int irq = (int)data;
 +      irq_desc_t *desc = irq_desc + irq;
 +      static unsigned i2c_errors;
 +      const static unsigned max_i2c_errors = 100;
 +
 +      daemonize("twl4030-irq");
 +      current->flags |= PF_NOFREEZE;
 +
 +      while (!kthread_should_stop()) {
 +              int ret;
 +              int module_irq;
 +              u8 pih_isr;
 +
 +              wait_for_completion_interruptible(&irq_event);
 +
 +              ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
 +                                        REG_PIH_ISR_P1);
 +              if (ret) {
 +                      printk(KERN_WARNING "I2C error %d while reading TWL4030"
 +                                      " PIH ISR register.\n", ret);
 +                      if (++i2c_errors >= max_i2c_errors) {
 +                              printk(KERN_ERR "Maximum I2C error count"
 +                                              " exceeded.  Terminating %s.\n",
 +                                              __func__);
 +                              break;
 +                      }
 +                      continue;
 +              }
 +
 +              for (module_irq = TWL4030_IRQ_BASE; 0 != pih_isr;
 +                       pih_isr >>= 1, module_irq++) {
 +                      if (pih_isr & 0x1) {
 +                              irq_desc_t *d = irq_desc + module_irq;
 +
 +                              local_irq_disable();
 +
 +                              d->handle_irq(module_irq, d);
 +
 +                              local_irq_enable();
 +                      }
 +              }
 +
 +              desc->chip->unmask(irq);
 +      }
 +
 +      return 0;
 +}
 +
 +/*
 + * do_twl4030_irq() is the desc->handle method for the twl4030 interrupt.
 + * This is a chained interrupt, so there is no desc->action method for it.
 + * Now we need to query the interrupt controller in the twl4030 to determine
 + * which module is generating the interrupt request.  However, we can't do i2c
 + * transactions in interrupt context, so we must defer that work to a kernel
 + * thread.  All we do here is acknowledge and mask the interrupt and wakeup
 + * the kernel thread.
 + */
 +static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      const unsigned int cpu = smp_processor_id();
 +
 +      /*
 +       * Earlier this was desc->triggered = 1;
 +       */
 +      desc->status |= IRQ_LEVEL;
 +
 +      /*
 +       * Acknowledge, clear _AND_ disable the interrupt.
 +       */
 +      desc->chip->ack(irq);
 +
 +      if (!desc->depth) {
 +              kstat_cpu(cpu).irqs[irq]++;
 +
 +              complete(&irq_event);
 +      }
 +}
 +
 +/* attach a client to the adapter */
 +static int __init twl4030_detect_client(struct i2c_adapter *adapter,
 +                                      unsigned char sid)
 +{
 +      int err = 0;
 +      struct twl4030_client *twl;
 +
 +      if (unlikely(sid >= TWL4030_NUM_SLAVES)) {
 +              pr_err("sid[%d] > MOD_LAST[%d]\n", sid, TWL4030_NUM_SLAVES);
 +              return -EPERM;
 +      }
 +
 +      /* Check basic functionality */
 +      err = i2c_check_functionality(adapter,
 +                      I2C_FUNC_SMBUS_WORD_DATA
 +                      | I2C_FUNC_SMBUS_WRITE_BYTE);
 +      if (!err) {
 +              pr_err("SlaveID=%d functionality check failed\n", sid);
 +              return err;
 +      }
 +      twl = &twl4030_modules[sid];
 +      if (unlikely(twl->inuse)) {
 +              pr_err("Client %s is already in use\n", twl->client_name);
 +              return -EPERM;
 +      }
 +
 +      memset(&twl->client, 0, sizeof(struct i2c_client));
 +
 +      twl->client.addr        = twl->address;
 +      twl->client.adapter     = adapter;
 +      twl->client.driver      = &twl4030_driver;
 +
 +      memcpy(&twl->client.name, twl->client_name,
 +                      sizeof(TWL_CLIENT_STRING) + 1);
 +
 +      pr_info("TWL4030: TRY attach Slave %s on Adapter %s [%x]\n",
 +                              twl->client_name, adapter->name, err);
 +
 +      err = i2c_attach_client(&twl->client);
 +      if (err) {
 +              pr_err("Couldn't attach Slave %s on Adapter"
 +                     "%s [%x]\n", twl->client_name, adapter->name, err);
 +      } else {
 +              twl->inuse = TWL_CLIENT_USED;
 +              mutex_init(&twl->xfer_lock);
 +      }
 +
 +      return err;
 +}
 +
 +/* adapter callback */
 +static int __init twl4030_attach_adapter(struct i2c_adapter *adapter)
 +{
 +      int i;
 +      int ret = 0;
 +      static int twl_i2c_adapter = 1;
 +
 +      for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
 +              /* Check if I need to hook on to this adapter or not */
 +              if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
 +                      ret = twl4030_detect_client(adapter, i);
 +                      if (ret)
 +                              goto free_client;
 +              }
 +      }
 +      twl_i2c_adapter++;
 +
 +      /*
 +       * Check if the PIH module is initialized, if yes, then init
 +       * the T2 Interrupt subsystem
 +       */
 +      if ((twl4030_modules[twl4030_map[TWL4030_MODULE_PIH].sid].inuse ==
 +              TWL_CLIENT_USED) && (twl_irq_used != USED)) {
 +              twl_init_irq();
 +              twl_irq_used = USED;
 +      }
 +      return 0;
 +
 +free_client:
 +      pr_err("TWL_CLIENT(Idx=%d] registration failed[0x%x]\n", i, ret);
 +
 +      /* ignore current slave..it never got registered */
 +      i--;
 +      while (i >= 0) {
 +              /* now remove all those from the current adapter... */
 +              if (twl4030_modules[i].adapter_index == twl_i2c_adapter)
 +                      (void)twl4030_detach_client(&twl4030_modules[i].client);
 +              i--;
 +      }
 +      return ret;
 +}
 +
 +/* adapter's callback */
 +static int twl4030_detach_client(struct i2c_client *client)
 +{
 +      int err;
 +      err = i2c_detach_client(client);
 +      if (err) {
 +              pr_err("Client detach failed\n");
 +              return err;
 +      }
 +      return 0;
 +}
 +
 +static struct task_struct * __init start_twl4030_irq_thread(int irq)
 +{
 +      struct task_struct *thread;
 +
 +      init_completion(&irq_event);
 +      thread = kthread_run(twl4030_irq_thread, (void *)irq,
 +                           "twl4030 irq %d", irq);
 +      if (!thread)
 +              pr_err("%s: could not create twl4030 irq %d thread!\n",
 +                     __func__, irq);
 +
 +      return thread;
 +}
 +
 +/*
 + * These three functions should be part of Voltage frame work
 + * added here to complete the functionality for now.
 + */
 +static int __init protect_pm_master(void)
 +{
 +      int e = 0;
 +
 +      e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
 +                      R_PROTECT_KEY);
 +      return e;
 +}
 +
 +static int __init unprotect_pm_master(void)
 +{
 +      int e = 0;
 +
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
 +                      R_PROTECT_KEY);
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
 +                      R_PROTECT_KEY);
 +      return e;
 +}
 +
 +static int __init power_companion_init(void)
 +{
 +      struct clk *osc;
 +      u32 rate;
 +      u8 ctrl = HFCLK_FREQ_26_MHZ;
 +      int e = 0;
 +
 +      if (cpu_is_omap2430())
 +              osc = clk_get(NULL, "osc_ck");
 +      else
 +              osc = clk_get(NULL, "osc_sys_ck");
 +      if (IS_ERR(osc)) {
 +              printk(KERN_WARNING "Skipping twl3040 internal clock init and "
 +                              "using bootloader value (unknown osc rate)\n");
 +              return 0;
 +      }
 +
 +      rate = clk_get_rate(osc);
 +      clk_put(osc);
 +
 +      switch (rate) {
 +      case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
 +      case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
 +      case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
 +      }
 +
 +      ctrl |= HIGH_PERF_SQ;
 +      e |= unprotect_pm_master();
 +      /* effect->MADC+USB ck en */
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
 +      e |= protect_pm_master();
 +
 +      return e;
 +}
 +
 +/**
 + * twl4030_i2c_clear_isr - clear TWL4030 SIH ISR regs via read + write
 + * @mod_no: TWL4030 module number
 + * @reg: register index to clear
 + * @cor: value of the <module>_SIH_CTRL.COR bit (1 or 0)
 + *
 + * Either reads (cor == 1) or writes (cor == 0) to a TWL4030 interrupt
 + * status register to ensure that any prior interrupts are cleared.
 + * Returns the status from the I2C read operation.
 + */
 +static int __init twl4030_i2c_clear_isr(u8 mod_no, u8 reg, u8 cor)
 +{
 +      u8 tmp;
 +
 +      return (cor) ? twl4030_i2c_read_u8(mod_no, &tmp, reg) :
 +              twl4030_i2c_write_u8(mod_no, 0xff, reg);
 +}
 +
 +/**
 + * twl4030_read_cor_bit - are TWL module ISRs cleared by reads or writes?
 + * @mod_no: TWL4030 module number
 + * @reg: register index to clear
 + *
 + * Returns 1 if the TWL4030 SIH interrupt status registers (ISRs) for
 + * the specified TWL module are cleared by reads, or 0 if cleared by
 + * writes.
 + */
 +static int twl4030_read_cor_bit(u8 mod_no, u8 reg)
 +{
 +      u8 tmp = 0;
 +
 +      WARN_ON(twl4030_i2c_read_u8(mod_no, &tmp, reg) < 0);
 +
 +      tmp &= TWL4030_SIH_CTRL_COR_MASK;
 +      tmp >>= __ffs(TWL4030_SIH_CTRL_COR_MASK);
 +
 +      return tmp;
 +}
 +
 +/**
 + * twl4030_mask_clear_intrs - mask and clear all TWL4030 interrupts
 + * @t: pointer to twl4030_mod_iregs array
 + * @t_sz: ARRAY_SIZE(t) (starting at 1)
 + *
 + * Mask all TWL4030 interrupt mask registers (IMRs) and clear all
 + * interrupt status registers (ISRs).  No return value, but will WARN if
 + * any I2C operations fail.
 + */
 +static void __init twl4030_mask_clear_intrs(const struct twl4030_mod_iregs *t,
 +                                          const u8 t_sz)
 +{
 +      int i, j;
 +
 +      /*
 +       * N.B. - further efficiency is possible here.  Eight I2C
 +       * operations on BCI and GPIO modules are avoidable if I2C
 +       * burst read/write transactions were implemented.  Would
 +       * probably save about 1ms of boot time and a small amount of
 +       * power.
 +       */
 +      for (i = 0; i < t_sz; i++) {
 +              const struct twl4030_mod_iregs tmr = t[i];
 +              int cor;
 +
 +              /* Are ISRs cleared by reads or writes? */
 +              cor = twl4030_read_cor_bit(tmr.mod_no, tmr.sih_ctrl);
 +              WARN_ON(cor < 0);
 +
 +              for (j = 0; j < tmr.reg_cnt; j++) {
 +
 +                      /* Mask interrupts at the TWL4030 */
 +                      WARN_ON(twl4030_i2c_write_u8(tmr.mod_no, 0xff,
 +                                                   tmr.imrs[j]) < 0);
 +
 +                      /* Clear TWL4030 ISRs */
 +                      WARN_ON(twl4030_i2c_clear_isr(tmr.mod_no,
 +                                                    tmr.isrs[j], cor) < 0);
 +              }
 +      }
 +
 +      return;
 +}
 +
 +
 +static void twl_init_irq(void)
 +{
 +      int     i;
 +      int     res = 0;
 +      char    *msg = "Unable to register interrupt subsystem";
 +      unsigned int irq_num;
 +
 +      /*
 +       * Mask and clear all TWL4030 interrupts since initially we do
 +       * not have any TWL4030 module interrupt handlers present
 +       */
 +      twl4030_mask_clear_intrs(twl4030_mod_regs,
 +                               ARRAY_SIZE(twl4030_mod_regs));
 +
 +      /* install an irq handler for each of the PIH modules */
 +      for (i = TWL4030_IRQ_BASE; i < TWL4030_IRQ_END; i++) {
 +              set_irq_chip(i, &twl4030_irq_chip);
 +              set_irq_handler(i, do_twl4030_module_irq);
 +              set_irq_flags(i, IRQF_VALID);
 +      }
 +
 +      irq_num = (cpu_is_omap2430()) ? INT_24XX_SYS_NIRQ : INT_34XX_SYS_NIRQ;
 +
 +      /* install an irq handler to demultiplex the TWL4030 interrupt */
 +      set_irq_data(irq_num, start_twl4030_irq_thread(irq_num));
 +      set_irq_type(irq_num, IRQ_TYPE_EDGE_FALLING);
 +      set_irq_chained_handler(irq_num, do_twl4030_irq);
 +
 +      res = power_companion_init();
 +      if (res < 0)
 +              pr_err("%s[%d][%d]\n", msg, res, __LINE__);
 +}
 +
 +static int __init twl4030_init(void)
 +{
 +      return i2c_add_driver(&twl4030_driver);
 +}
 +
 +static void __exit twl4030_exit(void)
 +{
 +      i2c_del_driver(&twl4030_driver);
 +      twl_irq_used = FREE;
 +}
 +
 +subsys_initcall(twl4030_init);
 +module_exit(twl4030_exit);
 +
 +MODULE_ALIAS("i2c:" DRIVER_NAME);
 +MODULE_AUTHOR("Texas Instruments, Inc.");
 +MODULE_DESCRIPTION("I2C Core interface for TWL4030");
 +MODULE_LICENSE("GPL");
index 9d17f4574fd72a9b890dafd1a9f23edbc7a3fae3,0000000000000000000000000000000000000000..494124cc43cf4fafd95a13c20b09c4cdd83697f0
mode 100644,000000..100644
--- /dev/null
@@@ -1,787 -1,0 +1,787 @@@
- #include <asm/arch/irqs.h>
 +/*
 + * linux/drivers/i2c/chips/twl4030_gpio.c
 + *
 + * Copyright (C) 2006-2007 Texas Instruments, Inc.
 + * Copyright (C) 2006 MontaVista Software, Inc.
 + *
 + * Code re-arranged and cleaned up by:
 + *    Syed Mohammed Khasim <x0khasim@ti.com>
 + *
 + * Initial Code:
 + *    Andy Lowe / Nishanth Menon
 + *
 + * 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/kernel_stat.h>
 +#include <linux/init.h>
 +#include <linux/time.h>
 +#include <linux/interrupt.h>
 +#include <linux/random.h>
 +#include <linux/syscalls.h>
 +#include <linux/kthread.h>
 +#include <linux/irq.h>
 +
 +#include <linux/i2c.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/i2c/twl4030-gpio.h>
 +#include <linux/slab.h>
 +
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
++#include <mach/irqs.h>
 +#include <asm/mach/irq.h>
++#include <mach/gpio.h>
++#include <mach/mux.h>
 +
 +#include <linux/device.h>
 +
 +/* BitField Definitions */
 +
 +/* Data banks : 3 banks for 8 gpios each */
 +#define DATA_BANK_MAX                         8
 +#define GET_GPIO_DATA_BANK(x)                 ((x)/DATA_BANK_MAX)
 +#define GET_GPIO_DATA_OFF(x)                  ((x)%DATA_BANK_MAX)
 +
 +/* GPIODATADIR Fields each block 0-7 */
 +#define BIT_GPIODATADIR_GPIOxDIR(x)           (x)
 +#define MASK_GPIODATADIR_GPIOxDIR(x)          (0x01 << (x))
 +
 +/* GPIODATAIN Fields each block 0-7 */
 +#define BIT_GPIODATAIN_GPIOxIN(x)             (x)
 +#define MASK_GPIODATAIN_GPIOxIN(x)            (0x01 << (x))
 +
 +/* GPIODATAOUT Fields each block 0-7 */
 +#define BIT_GPIODATAOUT_GPIOxOUT(x)           (x)
 +#define MASK_GPIODATAOUT_GPIOxOUT(x)          (0x01 << (x))
 +
 +/* CLEARGPIODATAOUT Fields */
 +#define BIT_CLEARGPIODATAOUT_GPIOxOUT(x)      (x)
 +#define MASK_CLEARGPIODATAOUT_GPIOxOUT(x)     (0x01 << (x))
 +
 +/* SETGPIODATAOUT Fields */
 +#define BIT_SETGPIODATAOUT_GPIOxOUT(x)                (x)
 +#define MASK_SETGPIODATAOUT_GPIOxOUT(x)               (0x01 << (x))
 +
 +/* GPIO_DEBEN Fields */
 +#define BIT_GPIO_DEBEN_GPIOxDEB(x)            (x)
 +#define MASK_GPIO_DEBEN_GPIOxDEB(x)           (0x01 << (x))
 +
 +/* GPIO_ISR1A Fields */
 +#define BIT_GPIO_ISR_GPIOxISR(x)              (x)
 +#define MASK_GPIO_ISR_GPIOxISR(x)             (0x01 << (x))
 +
 +/* GPIO_IMR1A Fields */
 +#define BIT_GPIO_IMR1A_GPIOxIMR(x)            (x)
 +#define MASK_GPIO_IMR1A_GPIOxIMR(x)           (0x01 << (x))
 +
 +/* GPIO_SIR1 Fields */
 +#define BIT_GPIO_SIR1_GPIOxSIR(x)             (x)
 +#define MASK_GPIO_SIR1_GPIO0SIR                       (0x01 << (x))
 +
 +
 +/* Control banks : 5 banks for 4 gpios each */
 +#define DATA_CTL_MAX                  4
 +#define GET_GPIO_CTL_BANK(x)          ((x)/DATA_CTL_MAX)
 +#define GET_GPIO_CTL_OFF(x)           ((x)%DATA_CTL_MAX)
 +#define GPIO_BANK_MAX                 GET_GPIO_CTL_BANK(TWL4030_GPIO_MAX)
 +
 +/* GPIOPUPDCTRx Fields 5 banks of 4 gpios each */
 +#define BIT_GPIOPUPDCTR1_GPIOxPD(x)   (2 * (x))
 +#define MASK_GPIOPUPDCTR1_GPIOxPD(x)  (0x01 << (2 * (x)))
 +#define BIT_GPIOPUPDCTR1_GPIOxPU(x)   ((x) + 1)
 +#define MASK_GPIOPUPDCTR1_GPIOxPU(x)  (0x01 << (((2 * (x)) + 1)))
 +
 +/* GPIO_EDR1 Fields */
 +#define BIT_GPIO_EDR1_GPIOxFALLING(x) (2 * (x))
 +#define MASK_GPIO_EDR1_GPIOxFALLING(x)        (0x01 << (2 * (x)))
 +#define BIT_GPIO_EDR1_GPIOxRISING(x)  ((x) + 1)
 +#define MASK_GPIO_EDR1_GPIOxRISING(x) (0x01 << (((2 * (x)) + 1)))
 +
 +/* GPIO_SIH_CTRL Fields */
 +#define BIT_GPIO_SIH_CTRL_EXCLEN      (0x000)
 +#define MASK_GPIO_SIH_CTRL_EXCLEN     (0x00000001)
 +#define BIT_GPIO_SIH_CTRL_PENDDIS     (0x001)
 +#define MASK_GPIO_SIH_CTRL_PENDDIS    (0x00000002)
 +#define BIT_GPIO_SIH_CTRL_COR         (0x002)
 +#define MASK_GPIO_SIH_CTRL_COR                (0x00000004)
 +
 +/* GPIO_CTRL Fields */
 +#define BIT_GPIO_CTRL_GPIO0CD1                (0x000)
 +#define MASK_GPIO_CTRL_GPIO0CD1               (0x00000001)
 +#define BIT_GPIO_CTRL_GPIO1CD2                (0x001)
 +#define MASK_GPIO_CTRL_GPIO1CD2               (0x00000002)
 +#define BIT_GPIO_CTRL_GPIO_ON         (0x002)
 +#define MASK_GPIO_CTRL_GPIO_ON                (0x00000004)
 +
 +/* Mask for GPIO registers when aggregated into a 32-bit integer */
 +#define GPIO_32_MASK                  0x0003ffff
 +
 +/* Data structures */
 +static struct semaphore gpio_sem;
 +
 +/* store usage of each GPIO. - each bit represents one GPIO */
 +static unsigned int gpio_usage_count;
 +
 +/* shadow the imr register */
 +static unsigned int gpio_imr_shadow;
 +
 +/* bitmask of pending requests to unmask gpio interrupts */
 +static unsigned int gpio_pending_unmask;
 +
 +/* pointer to gpio unmask thread struct */
 +static struct task_struct *gpio_unmask_thread;
 +
 +/*
 + * Helper functions to read and write the GPIO ISR and IMR registers as
 + * 32-bit integers. Functions return 0 on success, non-zero otherwise.
 + * The caller must hold a lock on gpio_sem.
 + */
 +
 +static int gpio_read_isr(unsigned int *isr)
 +{
 +      int ret;
 +
 +      *isr = 0;
 +      ret = twl4030_i2c_read(TWL4030_MODULE_GPIO, (u8 *) isr,
 +                      REG_GPIO_ISR1A, 3);
 +      le32_to_cpup(isr);
 +      *isr &= GPIO_32_MASK;
 +
 +      return ret;
 +}
 +
 +static int gpio_write_isr(unsigned int isr)
 +{
 +      isr &= GPIO_32_MASK;
 +      /*
 +       * The buffer passed to the twl4030_i2c_write() routine must have an
 +       * extra byte at the beginning reserved for its internal use.
 +       */
 +      isr <<= 8;
 +      isr = cpu_to_le32(isr);
 +      return twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &isr,
 +                              REG_GPIO_ISR1A, 3);
 +}
 +
 +static int gpio_write_imr(unsigned int imr)
 +{
 +      imr &= GPIO_32_MASK;
 +      /*
 +       * The buffer passed to the twl4030_i2c_write() routine must have an
 +       * extra byte at the beginning reserved for its internal use.
 +       */
 +      imr <<= 8;
 +      imr = cpu_to_le32(imr);
 +      return twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &imr,
 +                              REG_GPIO_IMR1A, 3);
 +}
 +
 +/*
 + * These routines are analagous to the irqchip methods, but they are designed
 + * to be called from thread context with cpu interrupts enabled and with no
 + * locked spinlocks.  We call these routines from our custom IRQ handler
 + * instead of the usual irqchip methods.
 + */
 +static void twl4030_gpio_mask_and_ack(unsigned int irq)
 +{
 +      int gpio = irq - TWL4030_GPIO_IRQ_BASE;
 +
 +      down(&gpio_sem);
 +      /* mask */
 +      gpio_imr_shadow |= (1 << gpio);
 +      gpio_write_imr(gpio_imr_shadow);
 +      /* ack */
 +      gpio_write_isr(1 << gpio);
 +      up(&gpio_sem);
 +}
 +
 +static void twl4030_gpio_unmask(unsigned int irq)
 +{
 +      int gpio = irq - TWL4030_GPIO_IRQ_BASE;
 +
 +      down(&gpio_sem);
 +      gpio_imr_shadow &= ~(1 << gpio);
 +      gpio_write_imr(gpio_imr_shadow);
 +      up(&gpio_sem);
 +}
 +
 +/*
 + * These are the irqchip methods for the TWL4030 GPIO interrupts.
 + * Our IRQ handle method doesn't call these, but they will be called by
 + * other routines such as setup_irq() and enable_irq().  They are called
 + * with cpu interrupts disabled and with a lock on the irq_controller_lock
 + * spinlock.  This complicates matters, because accessing the TWL4030 GPIO
 + * interrupt controller requires I2C bus transactions that can't be initiated
 + * in this context.  Our solution is to defer accessing the interrupt
 + * controller to a kernel thread.  We only need to support the unmask method.
 + */
 +
 +static void twl4030_gpio_mask_and_ack_irqchip(unsigned int irq) {}
 +static void twl4030_gpio_mask_irqchip(unsigned int irq) {}
 +
 +static void twl4030_gpio_unmask_irqchip(unsigned int irq)
 +{
 +      int gpio = irq - TWL4030_GPIO_IRQ_BASE;
 +
 +      gpio_pending_unmask |= (1 << gpio);
 +      if (gpio_unmask_thread && gpio_unmask_thread->state != TASK_RUNNING)
 +              wake_up_process(gpio_unmask_thread);
 +}
 +
 +static struct irq_chip twl4030_gpio_irq_chip = {
 +      .name   = "twl4030-gpio",
 +      .ack    = twl4030_gpio_mask_and_ack_irqchip,
 +      .mask   = twl4030_gpio_mask_irqchip,
 +      .unmask = twl4030_gpio_unmask_irqchip,
 +};
 +
 +/*
 + * These are the irqchip methods for the TWL4030 PIH GPIO module interrupt.
 + * The PIH module doesn't have interrupt masking capability, so these
 + * methods are NULL.
 + */
 +static void twl4030_gpio_module_ack(unsigned int irq) {}
 +static void twl4030_gpio_module_mask(unsigned int irq) {}
 +static void twl4030_gpio_module_unmask(unsigned int irq) {}
 +static struct irq_chip twl4030_gpio_module_irq_chip = {
 +      .ack    = twl4030_gpio_module_ack,
 +      .mask   = twl4030_gpio_module_mask,
 +      .unmask = twl4030_gpio_module_unmask,
 +};
 +
 +/*
 + * To configure TWL4030 GPIO module registers
 + */
 +static inline int gpio_twl4030_write(u8 address, u8 data)
 +{
 +      int ret = 0;
 +
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
 +      return ret;
 +}
 +
 +/*
 + * To read a TWL4030 GPIO module register
 + */
 +static inline int gpio_twl4030_read(u8 address)
 +{
 +      u8 data;
 +      int ret = 0;
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
 +      if (ret >= 0)
 +              ret = data;
 +      return ret;
 +}
 +
 +/*
 + * twl4030 GPIO request function
 + */
 +int twl4030_request_gpio(int gpio)
 +{
 +      int ret = 0;
 +
 +      if (unlikely(gpio >= TWL4030_GPIO_MAX))
 +              return -EPERM;
 +
 +      down(&gpio_sem);
 +      if (gpio_usage_count & (0x1 << gpio))
 +              ret = -EBUSY;
 +      else {
 +              u8 clear_pull[6] = { 0, 0, 0, 0, 0, 0 };
 +              /* First time usage? - switch on GPIO module */
 +              if (!gpio_usage_count) {
 +                      ret =
 +                      gpio_twl4030_write(REG_GPIO_CTRL,
 +                                      MASK_GPIO_CTRL_GPIO_ON);
 +                      ret = gpio_twl4030_write(REG_GPIO_SIH_CTRL, 0x00);
 +              }
 +              if (!ret)
 +                      gpio_usage_count |= (0x1 << gpio);
 +
 +              ret =
 +              twl4030_i2c_write(TWL4030_MODULE_GPIO, clear_pull,
 +                              REG_GPIOPUPDCTR1, 5);
 +      }
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_request_gpio);
 +
 +/*
 + * TWL4030 GPIO free module
 + */
 +int twl4030_free_gpio(int gpio)
 +{
 +      int ret = 0;
 +
 +      if (unlikely(gpio >= TWL4030_GPIO_MAX))
 +              return -EPERM;
 +
 +      down(&gpio_sem);
 +
 +      if ((gpio_usage_count & (0x1 << gpio)) == 0)
 +              ret = -EPERM;
 +      else
 +              gpio_usage_count &= ~(0x1 << gpio);
 +
 +      /* Last time usage? - switch off GPIO module */
 +      if (!gpio_usage_count)
 +              ret = gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
 +
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_free_gpio);
 +
 +/*
 + * Set direction for TWL4030 GPIO
 + */
 +int twl4030_set_gpio_direction(int gpio, int is_input)
 +{
 +      u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
 +      u8 d_msk = MASK_GPIODATADIR_GPIOxDIR(GET_GPIO_DATA_OFF(gpio));
 +      u8 reg = 0;
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      base = REG_GPIODATADIR1 + d_bnk;
 +
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(base);
 +      if (ret >= 0) {
 +              if (is_input)
 +                      reg = (u8) ((ret) & ~(d_msk));
 +              else
 +                      reg = (u8) ((ret) | (d_msk));
 +
 +              ret = gpio_twl4030_write(base, reg);
 +      }
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_direction);
 +
 +/*
 + * To enable/disable GPIO pin on TWL4030
 + */
 +int twl4030_set_gpio_dataout(int gpio, int enable)
 +{
 +      u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
 +      u8 d_msk = MASK_GPIODATAOUT_GPIOxOUT(GET_GPIO_DATA_OFF(gpio));
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      if (enable)
 +              base = REG_SETGPIODATAOUT1 + d_bnk;
 +      else
 +              base = REG_CLEARGPIODATAOUT1 + d_bnk;
 +
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_write(base, d_msk);
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_dataout);
 +
 +/*
 + * To get the status of a GPIO pin on TWL4030
 + */
 +int twl4030_get_gpio_datain(int gpio)
 +{
 +      u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
 +      u8 d_off = BIT_GPIODATAIN_GPIOxIN(GET_GPIO_DATA_OFF(gpio));
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      base = REG_GPIODATAIN1 + d_bnk;
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(base);
 +      up(&gpio_sem);
 +      if (ret > 0)
 +              ret = (ret >> d_off) & 0x1;
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_get_gpio_datain);
 +
 +/*
 + * Configure PULL type for a GPIO pin on TWL4030
 + */
 +int twl4030_set_gpio_pull(int gpio, int pull_dircn)
 +{
 +      u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
 +      u8 c_off = GET_GPIO_CTL_OFF(gpio);
 +      u8 c_msk = 0;
 +      u8 reg = 0;
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX) ||
 +              !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      base = REG_GPIOPUPDCTR1 + c_bnk;
 +      if (pull_dircn == TWL4030_GPIO_PULL_DOWN)
 +              c_msk = MASK_GPIOPUPDCTR1_GPIOxPD(c_off);
 +      else if (pull_dircn == TWL4030_GPIO_PULL_UP)
 +              c_msk = MASK_GPIOPUPDCTR1_GPIOxPU(c_off);
 +
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(base);
 +      if (ret >= 0) {
 +              /* clear the previous up/down values */
 +              reg = (u8) (ret);
 +              reg &= ~(MASK_GPIOPUPDCTR1_GPIOxPU(c_off) |
 +                      MASK_GPIOPUPDCTR1_GPIOxPD(c_off));
 +              reg |= c_msk;
 +              ret = gpio_twl4030_write(base, reg);
 +      }
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_pull);
 +
 +/*
 + * Configure Edge control for a GPIO pin on TWL4030
 + */
 +int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
 +{
 +      u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
 +      u8 c_off = GET_GPIO_CTL_OFF(gpio);
 +      u8 c_msk = 0;
 +      u8 reg = 0;
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      base = REG_GPIO_EDR1 + c_bnk;
 +
 +      if (edge & TWL4030_GPIO_EDGE_RISING)
 +              c_msk |= MASK_GPIO_EDR1_GPIOxRISING(c_off);
 +
 +      if (edge & TWL4030_GPIO_EDGE_FALLING)
 +              c_msk |= MASK_GPIO_EDR1_GPIOxFALLING(c_off);
 +
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(base);
 +      if (ret >= 0) {
 +              /* clear the previous rising/falling values */
 +              reg =
 +              (u8) (ret &
 +                      ~(MASK_GPIO_EDR1_GPIOxFALLING(c_off) |
 +                      MASK_GPIO_EDR1_GPIOxRISING(c_off)));
 +              reg |= c_msk;
 +              ret = gpio_twl4030_write(base, reg);
 +      }
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_edge_ctrl);
 +
 +/*
 + * Configure debounce timing value for a GPIO pin on TWL4030
 + */
 +int twl4030_set_gpio_debounce(int gpio, int enable)
 +{
 +      u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
 +      u8 d_msk = MASK_GPIO_DEBEN_GPIOxDEB(GET_GPIO_DATA_OFF(gpio));
 +      u8 reg = 0;
 +      u8 base = 0;
 +      int ret = 0;
 +
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))))
 +              return -EPERM;
 +
 +      base = REG_GPIO_DEBEN1 + d_bnk;
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(base);
 +      if (ret >= 0) {
 +              if (enable)
 +                      reg = (u8) ((ret) | (d_msk));
 +              else
 +                      reg = (u8) ((ret) & ~(d_msk));
 +
 +              ret = gpio_twl4030_write(base, reg);
 +      }
 +      up(&gpio_sem);
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_debounce);
 +
 +/*
 + * Configure Card detect for GPIO pin on TWL4030
 + */
 +int twl4030_set_gpio_card_detect(int gpio, int enable)
 +{
 +      u8 reg = 0;
 +      u8 msk = (1 << gpio);
 +      int ret = 0;
 +
 +      /* Only GPIO 0 or 1 can be used for CD feature.. */
 +      if (unlikely((gpio >= TWL4030_GPIO_MAX)
 +              || !(gpio_usage_count & (0x1 << gpio))
 +              || (gpio >= TWL4030_GPIO_MAX_CD))) {
 +              return -EPERM;
 +      }
 +
 +      down(&gpio_sem);
 +      ret = gpio_twl4030_read(REG_GPIO_CTRL);
 +      if (ret >= 0) {
 +              if (enable)
 +                      reg = (u8) (ret | msk);
 +              else
 +                      reg = (u8) (ret & ~msk);
 +
 +              ret = gpio_twl4030_write(REG_GPIO_CTRL, reg);
 +      }
 +      up(&gpio_sem);
 +      return (ret);
 +}
 +EXPORT_SYMBOL(twl4030_set_gpio_card_detect);
 +
 +/* MODULE FUNCTIONS */
 +
 +/*
 + * gpio_unmask_thread() runs as a kernel thread.  It is awakened by the unmask
 + * method for the GPIO interrupts.  It unmasks all of the GPIO interrupts
 + * specified in the gpio_pending_unmask bitmask.  We have to do the unmasking
 + * in a kernel thread rather than directly in the unmask method because of the
 + * need to access the TWL4030 via the I2C bus.  Note that we don't need to be
 + * concerned about race conditions where the request to unmask a GPIO interrupt
 + * has already been cancelled before this thread does the unmasking.  If a GPIO
 + * interrupt is improperly unmasked, then the IRQ handler for it will mask it
 + * when an interrupt occurs.
 + */
 +static int twl4030_gpio_unmask_thread(void *data)
 +{
 +      current->flags |= PF_NOFREEZE;
 +
 +      while (!kthread_should_stop()) {
 +              int irq;
 +              unsigned int gpio_unmask;
 +
 +              local_irq_disable();
 +              gpio_unmask = gpio_pending_unmask;
 +              gpio_pending_unmask = 0;
 +              local_irq_enable();
 +
 +              for (irq = TWL4030_GPIO_IRQ_BASE; 0 != gpio_unmask;
 +                              gpio_unmask >>= 1, irq++) {
 +                      if (gpio_unmask & 0x1)
 +                              twl4030_gpio_unmask(irq);
 +              }
 +
 +              local_irq_disable();
 +              if (!gpio_pending_unmask)
 +                      set_current_state(TASK_INTERRUPTIBLE);
 +              local_irq_enable();
 +
 +              schedule();
 +      }
 +      set_current_state(TASK_RUNNING);
 +      return 0;
 +}
 +
 +/*
 + * do_twl4030_gpio_irq() is the desc->handle method for each of the twl4030
 + * gpio interrupts.  It executes in kernel thread context.
 + * On entry, cpu interrupts are enabled.
 + */
 +static void do_twl4030_gpio_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      struct irqaction *action;
 +      const unsigned int cpu = smp_processor_id();
 +
 +      desc->status |= IRQ_LEVEL;
 +
 +      /*
 +       * Acknowledge, clear _AND_ disable the interrupt.
 +       */
 +      twl4030_gpio_mask_and_ack(irq);
 +
 +      if (!desc->depth) {
 +              kstat_cpu(cpu).irqs[irq]++;
 +
 +              action = desc->action;
 +              if (action) {
 +                      int ret;
 +                      int status = 0;
 +                      int retval = 0;
 +                      do {
 +                              /* Call the ISR with cpu interrupts enabled. */
 +                              ret = action->handler(irq, action->dev_id);
 +                              if (ret == IRQ_HANDLED)
 +                                      status |= action->flags;
 +                              retval |= ret;
 +                              action = action->next;
 +                      } while (action);
 +
 +                      if (retval != IRQ_HANDLED)
 +                              printk(KERN_ERR "ISR for TWL4030 GPIO"
 +                                      " irq %d can't handle interrupt\n",
 +                                      irq);
 +
 +                      if (!desc->depth)
 +                              twl4030_gpio_unmask(irq);
 +              }
 +      }
 +}
 +
 +/*
 + * do_twl4030_gpio_module_irq() is the desc->handle method for the twl4030 gpio
 + * module interrupt.  It executes in kernel thread context.
 + * This is a chained interrupt, so there is no desc->action method for it.
 + * We query the gpio module interrupt controller in the twl4030 to determine
 + * which gpio lines are generating interrupt requests, and then call the
 + * desc->handle method for each gpio that needs service.
 + * On entry, cpu interrupts are disabled.
 + */
 +static void do_twl4030_gpio_module_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      const unsigned int cpu = smp_processor_id();
 +
 +      desc->status |= IRQ_LEVEL;
 +      /*
 +      * The desc->handle method would normally call the desc->chip->ack
 +      * method here, but we won't bother since our ack method is NULL.
 +      */
 +      if (!desc->depth) {
 +              int gpio_irq;
 +              unsigned int gpio_isr;
 +
 +              kstat_cpu(cpu).irqs[irq]++;
 +              local_irq_enable();
 +
 +              down(&gpio_sem);
 +              if (gpio_read_isr(&gpio_isr))
 +                      gpio_isr = 0;
 +              up(&gpio_sem);
 +
 +              for (gpio_irq = TWL4030_GPIO_IRQ_BASE; 0 != gpio_isr;
 +                      gpio_isr >>= 1, gpio_irq++) {
 +                      if (gpio_isr & 0x1) {
 +                              irq_desc_t *d = irq_desc + gpio_irq;
 +                              d->handle_irq(gpio_irq, d);
 +                      }
 +              }
 +
 +              local_irq_disable();
 +              /*
 +               * Here is where we should call the unmask method, but again we
 +               * won't bother since it is NULL.
 +               */
 +      }
 +}
 +
 +/* TWL4030 Initialization module */
 +static int __init gpio_twl4030_init(void)
 +{
 +      int ret;
 +      int irq = 0;
 +
 +      /* init the global locking sem */
 +      sema_init(&gpio_sem, 1);
 +
 +      /* All GPIO interrupts are initially masked */
 +      gpio_pending_unmask = 0;
 +      gpio_imr_shadow = GPIO_32_MASK;
 +      ret = gpio_write_imr(gpio_imr_shadow);
 +      if (!ret) {
 +              /*
 +               * Create a kernel thread to handle deferred unmasking of gpio
 +               * interrupts.
 +               */
 +              gpio_unmask_thread = kthread_create(twl4030_gpio_unmask_thread,
 +                      NULL, "twl4030 gpio");
 +              if (!gpio_unmask_thread) {
 +                      printk(KERN_ERR
 +                              "%s: could not create twl4030 gpio unmask"
 +                              " thread!\n", __func__);
 +                      ret = -ENOMEM;
 +              }
 +      }
 +
 +      if (!ret) {
 +              /* install an irq handler for each of the gpio interrupts */
 +              for (irq = TWL4030_GPIO_IRQ_BASE; irq < TWL4030_GPIO_IRQ_END;
 +                      irq++) {
 +                      set_irq_chip(irq, &twl4030_gpio_irq_chip);
 +                      set_irq_handler(irq, do_twl4030_gpio_irq);
 +                      set_irq_flags(irq, IRQF_VALID);
 +              }
 +
 +              /*
 +               * Install an irq handler to demultiplex the gpio module
 +               * interrupt.
 +               */
 +              set_irq_chip(TWL4030_MODIRQ_GPIO,
 +                      &twl4030_gpio_module_irq_chip);
 +              set_irq_chained_handler(TWL4030_MODIRQ_GPIO,
 +                      do_twl4030_gpio_module_irq);
 +      }
 +
 +      printk(KERN_INFO "TWL4030 GPIO Demux: IRQ Range %d to %d,"
 +              " Initialization %s\n", TWL4030_GPIO_IRQ_BASE,
 +              TWL4030_GPIO_IRQ_END, (ret) ? "Failed" : "Success");
 +      return ret;
 +}
 +
 +/* TWL GPIO exit module */
 +static void __exit gpio_twl4030_exit(void)
 +{
 +      int irq;
 +
 +      /* uninstall the gpio demultiplexing interrupt handler */
 +      set_irq_handler(TWL4030_MODIRQ_GPIO, NULL);
 +      set_irq_flags(TWL4030_MODIRQ_GPIO, 0);
 +
 +      /* uninstall the irq handler for each of the gpio interrupts */
 +      for (irq = TWL4030_GPIO_IRQ_BASE; irq < TWL4030_GPIO_IRQ_END; irq++) {
 +              set_irq_handler(irq, NULL);
 +              set_irq_flags(irq, 0);
 +      }
 +
 +      /* stop the gpio unmask kernel thread */
 +      if (gpio_unmask_thread) {
 +              kthread_stop(gpio_unmask_thread);
 +              gpio_unmask_thread = NULL;
 +      }
 +}
 +
 +module_init(gpio_twl4030_init);
 +module_exit(gpio_twl4030_exit);
 +
 +MODULE_ALIAS("i2c:twl4030-gpio");
 +MODULE_AUTHOR("Texas Instruments, Inc.");
 +MODULE_DESCRIPTION("GPIO interface for TWL4030");
 +MODULE_LICENSE("GPL");
index d9760e41631fc7cf80a6514ee40bc910fed5778d,0000000000000000000000000000000000000000..2906b82cebbfe9827e3d39f5a69b1839bf455e9c
mode 100644,000000..100644
--- /dev/null
@@@ -1,779 -1,0 +1,779 @@@
- #include <asm/arch/usb.h>
 +/*
 + * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
 + *
 + * Copyright (C) 2004-2007 Texas Instruments
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 + *
 + * Current status:
 + *    - HS USB ULPI mode works.
 + *    - 3-pin mode support may be added in future.
 + */
 +
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/time.h>
 +#include <linux/interrupt.h>
 +#include <linux/io.h>
 +#include <linux/usb.h>
 +#include <linux/usb/ch9.h>
 +#include <linux/usb/gadget.h>
 +#include <linux/usb/otg.h>
 +#include <linux/i2c/twl4030.h>
++#include <mach/usb.h>
 +
 +/* Register defines */
 +
 +#define VENDOR_ID_LO                  0x00
 +#define VENDOR_ID_HI                  0x01
 +#define PRODUCT_ID_LO                 0x02
 +#define PRODUCT_ID_HI                 0x03
 +
 +#define FUNC_CTRL                     0x04
 +#define FUNC_CTRL_SET                 0x05
 +#define FUNC_CTRL_CLR                 0x06
 +#define FUNC_CTRL_SUSPENDM            (1 << 6)
 +#define FUNC_CTRL_RESET                       (1 << 5)
 +#define FUNC_CTRL_OPMODE_MASK         (3 << 3) /* bits 3 and 4 */
 +#define FUNC_CTRL_OPMODE_NORMAL               (0 << 3)
 +#define FUNC_CTRL_OPMODE_NONDRIVING   (1 << 3)
 +#define FUNC_CTRL_OPMODE_DISABLE_BIT_NRZI     (2 << 3)
 +#define FUNC_CTRL_TERMSELECT          (1 << 2)
 +#define FUNC_CTRL_XCVRSELECT_MASK     (3 << 0) /* bits 0 and 1 */
 +#define FUNC_CTRL_XCVRSELECT_HS               (0 << 0)
 +#define FUNC_CTRL_XCVRSELECT_FS               (1 << 0)
 +#define FUNC_CTRL_XCVRSELECT_LS               (2 << 0)
 +#define FUNC_CTRL_XCVRSELECT_FS4LS    (3 << 0)
 +
 +#define IFC_CTRL                      0x07
 +#define IFC_CTRL_SET                  0x08
 +#define IFC_CTRL_CLR                  0x09
 +#define IFC_CTRL_INTERFACE_PROTECT_DISABLE    (1 << 7)
 +#define IFC_CTRL_AUTORESUME           (1 << 4)
 +#define IFC_CTRL_CLOCKSUSPENDM                (1 << 3)
 +#define IFC_CTRL_CARKITMODE           (1 << 2)
 +#define IFC_CTRL_FSLSSERIALMODE_3PIN  (1 << 1)
 +
 +#define TWL4030_OTG_CTRL              0x0A
 +#define TWL4030_OTG_CTRL_SET          0x0B
 +#define TWL4030_OTG_CTRL_CLR          0x0C
 +#define TWL4030_OTG_CTRL_DRVVBUS      (1 << 5)
 +#define TWL4030_OTG_CTRL_CHRGVBUS     (1 << 4)
 +#define TWL4030_OTG_CTRL_DISCHRGVBUS  (1 << 3)
 +#define TWL4030_OTG_CTRL_DMPULLDOWN   (1 << 2)
 +#define TWL4030_OTG_CTRL_DPPULLDOWN   (1 << 1)
 +#define TWL4030_OTG_CTRL_IDPULLUP     (1 << 0)
 +
 +#define USB_INT_EN_RISE                       0x0D
 +#define USB_INT_EN_RISE_SET           0x0E
 +#define USB_INT_EN_RISE_CLR           0x0F
 +#define USB_INT_EN_FALL                       0x10
 +#define USB_INT_EN_FALL_SET           0x11
 +#define USB_INT_EN_FALL_CLR           0x12
 +#define USB_INT_STS                   0x13
 +#define USB_INT_LATCH                 0x14
 +#define USB_INT_IDGND                 (1 << 4)
 +#define USB_INT_SESSEND                       (1 << 3)
 +#define USB_INT_SESSVALID             (1 << 2)
 +#define USB_INT_VBUSVALID             (1 << 1)
 +#define USB_INT_HOSTDISCONNECT                (1 << 0)
 +
 +#define CARKIT_CTRL                   0x19
 +#define CARKIT_CTRL_SET                       0x1A
 +#define CARKIT_CTRL_CLR                       0x1B
 +#define CARKIT_CTRL_MICEN             (1 << 6)
 +#define CARKIT_CTRL_SPKRIGHTEN                (1 << 5)
 +#define CARKIT_CTRL_SPKLEFTEN         (1 << 4)
 +#define CARKIT_CTRL_RXDEN             (1 << 3)
 +#define CARKIT_CTRL_TXDEN             (1 << 2)
 +#define CARKIT_CTRL_IDGNDDRV          (1 << 1)
 +#define CARKIT_CTRL_CARKITPWR         (1 << 0)
 +#define CARKIT_PLS_CTRL                       0x22
 +#define CARKIT_PLS_CTRL_SET           0x23
 +#define CARKIT_PLS_CTRL_CLR           0x24
 +#define CARKIT_PLS_CTRL_SPKRRIGHT_BIASEN      (1 << 3)
 +#define CARKIT_PLS_CTRL_SPKRLEFT_BIASEN       (1 << 2)
 +#define CARKIT_PLS_CTRL_RXPLSEN               (1 << 1)
 +#define CARKIT_PLS_CTRL_TXPLSEN               (1 << 0)
 +
 +#define MCPC_CTRL                     0x30
 +#define MCPC_CTRL_SET                 0x31
 +#define MCPC_CTRL_CLR                 0x32
 +#define MCPC_CTRL_RTSOL                       (1 << 7)
 +#define MCPC_CTRL_EXTSWR              (1 << 6)
 +#define MCPC_CTRL_EXTSWC              (1 << 5)
 +#define MCPC_CTRL_VOICESW             (1 << 4)
 +#define MCPC_CTRL_OUT64K              (1 << 3)
 +#define MCPC_CTRL_RTSCTSSW            (1 << 2)
 +#define MCPC_CTRL_HS_UART             (1 << 0)
 +
 +#define MCPC_IO_CTRL                  0x33
 +#define MCPC_IO_CTRL_SET              0x34
 +#define MCPC_IO_CTRL_CLR              0x35
 +#define MCPC_IO_CTRL_MICBIASEN                (1 << 5)
 +#define MCPC_IO_CTRL_CTS_NPU          (1 << 4)
 +#define MCPC_IO_CTRL_RXD_PU           (1 << 3)
 +#define MCPC_IO_CTRL_TXDTYP           (1 << 2)
 +#define MCPC_IO_CTRL_CTSTYP           (1 << 1)
 +#define MCPC_IO_CTRL_RTSTYP           (1 << 0)
 +
 +#define MCPC_CTRL2                    0x36
 +#define MCPC_CTRL2_SET                        0x37
 +#define MCPC_CTRL2_CLR                        0x38
 +#define MCPC_CTRL2_MCPC_CK_EN         (1 << 0)
 +
 +#define OTHER_FUNC_CTRL                       0x80
 +#define OTHER_FUNC_CTRL_SET           0x81
 +#define OTHER_FUNC_CTRL_CLR           0x82
 +#define OTHER_FUNC_CTRL_BDIS_ACON_EN  (1 << 4)
 +#define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2)
 +
 +#define OTHER_IFC_CTRL                        0x83
 +#define OTHER_IFC_CTRL_SET            0x84
 +#define OTHER_IFC_CTRL_CLR            0x85
 +#define OTHER_IFC_CTRL_OE_INT_EN      (1 << 6)
 +#define OTHER_IFC_CTRL_CEA2011_MODE   (1 << 5)
 +#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN    (1 << 4)
 +#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT     (1 << 3)
 +#define OTHER_IFC_CTRL_HIZ_ULPI               (1 << 2)
 +#define OTHER_IFC_CTRL_ALT_INT_REROUTE        (1 << 0)
 +
 +#define OTHER_INT_EN_RISE             0x86
 +#define OTHER_INT_EN_RISE_SET         0x87
 +#define OTHER_INT_EN_RISE_CLR         0x88
 +#define OTHER_INT_EN_FALL             0x89
 +#define OTHER_INT_EN_FALL_SET         0x8A
 +#define OTHER_INT_EN_FALL_CLR         0x8B
 +#define OTHER_INT_STS                 0x8C
 +#define OTHER_INT_LATCH                       0x8D
 +#define OTHER_INT_VB_SESS_VLD         (1 << 7)
 +#define OTHER_INT_DM_HI                       (1 << 6) /* not valid for "latch" reg */
 +#define OTHER_INT_DP_HI                       (1 << 5) /* not valid for "latch" reg */
 +#define OTHER_INT_BDIS_ACON           (1 << 3) /* not valid for "fall" regs */
 +#define OTHER_INT_MANU                        (1 << 1)
 +#define OTHER_INT_ABNORMAL_STRESS     (1 << 0)
 +
 +#define ID_STATUS                     0x96
 +#define ID_RES_FLOAT                  (1 << 4)
 +#define ID_RES_440K                   (1 << 3)
 +#define ID_RES_200K                   (1 << 2)
 +#define ID_RES_102K                   (1 << 1)
 +#define ID_RES_GND                    (1 << 0)
 +
 +#define POWER_CTRL                    0xAC
 +#define POWER_CTRL_SET                        0xAD
 +#define POWER_CTRL_CLR                        0xAE
 +#define POWER_CTRL_OTG_ENAB           (1 << 5)
 +
 +#define OTHER_IFC_CTRL2                       0xAF
 +#define OTHER_IFC_CTRL2_SET           0xB0
 +#define OTHER_IFC_CTRL2_CLR           0xB1
 +#define OTHER_IFC_CTRL2_ULPI_STP_LOW  (1 << 4)
 +#define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3)
 +#define OTHER_IFC_CTRL2_ULPI_4PIN_2430        (1 << 2)
 +#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK   (3 << 0) /* bits 0 and 1 */
 +#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N  (0 << 0)
 +#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N  (1 << 0)
 +
 +#define REG_CTRL_EN                   0xB2
 +#define REG_CTRL_EN_SET                       0xB3
 +#define REG_CTRL_EN_CLR                       0xB4
 +#define REG_CTRL_ERROR                        0xB5
 +#define ULPI_I2C_CONFLICT_INTEN               (1 << 0)
 +
 +#define OTHER_FUNC_CTRL2              0xB8
 +#define OTHER_FUNC_CTRL2_SET          0xB9
 +#define OTHER_FUNC_CTRL2_CLR          0xBA
 +#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN        (1 << 0)
 +
 +/* following registers do not have separate _clr and _set registers */
 +#define VBUS_DEBOUNCE                 0xC0
 +#define ID_DEBOUNCE                   0xC1
 +#define VBAT_TIMER                    0xD3
 +#define PHY_PWR_CTRL                  0xFD
 +#define PHY_PWR_PHYPWD                        (1 << 0)
 +#define PHY_CLK_CTRL                  0xFE
 +#define PHY_CLK_CTRL_CLOCKGATING_EN   (1 << 2)
 +#define PHY_CLK_CTRL_CLK32K_EN                (1 << 1)
 +#define REQ_PHY_DPLL_CLK              (1 << 0)
 +#define PHY_CLK_CTRL_STS              0xFF
 +#define PHY_DPLL_CLK                  (1 << 0)
 +
 +/* In module TWL4030_MODULE_PM_MASTER */
 +#define PROTECT_KEY                   0x0E
 +
 +/* In module TWL4030_MODULE_PM_RECEIVER */
 +#define VUSB_DEDICATED1                       0x7D
 +#define VUSB_DEDICATED2                       0x7E
 +#define VUSB1V5_DEV_GRP                       0x71
 +#define VUSB1V5_TYPE                  0x72
 +#define VUSB1V5_REMAP                 0x73
 +#define VUSB1V8_DEV_GRP                       0x74
 +#define VUSB1V8_TYPE                  0x75
 +#define VUSB1V8_REMAP                 0x76
 +#define VUSB3V1_DEV_GRP                       0x77
 +#define VUSB3V1_TYPE                  0x78
 +#define VUSB3V1_REMAP                 0x79
 +
 +#define ID_STATUS                     0x96
 +#define ID_RES_FLOAT                  (1 << 4) /* mini-B */
 +#define ID_RES_440K                   (1 << 3) /* type 2 charger */
 +#define ID_RES_200K                   (1 << 2) /* 5-wire carkit or
 +                                                  type 1 charger */
 +#define ID_RES_102K                   (1 << 1) /* phone */
 +#define ID_RES_GND                    (1 << 0) /* mini-A */
 +
 +/* In module TWL4030_MODULE_INTBR */
 +#define PMBR1                         0x0D
 +#define GPIO_USB_4PIN_ULPI_2430C      (3 << 0)
 +
 +/* In module TWL4030_MODULE_INT */
 +#define REG_PWR_ISR1                  0x00
 +#define REG_PWR_IMR1                  0x01
 +#define USB_PRES                      (1 << 2)
 +#define REG_PWR_EDR1                  0x05
 +#define USB_PRES_FALLING              (1 << 4)
 +#define USB_PRES_RISING                       (1 << 5)
 +#define REG_PWR_SIH_CTRL              0x07
 +#define COR                           (1 << 2)
 +
 +/* internal define on top of container_of */
 +#define xceiv_to_twl(x)               container_of((x), struct twl4030_usb, otg);
 +
 +/* bits in OTG_CTRL */
 +
 +#define       OTG_XCEIV_OUTPUTS \
 +      (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
 +#define       OTG_XCEIV_INPUTS \
 +      (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
 +#define       OTG_CTRL_BITS \
 +      (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
 +      /* and OTG_PULLUP is sometimes written */
 +
 +#define       OTG_CTRL_MASK   (OTG_DRIVER_SEL| \
 +      OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
 +      OTG_CTRL_BITS)
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +struct twl4030_usb {
 +      struct otg_transceiver  otg;
 +      int                     irq;
 +      u8                      usb_mode;       /* pin configuration */
 +#define T2_USB_MODE_ULPI              1
 +/* #define T2_USB_MODE_CEA2011_3PIN   2 */
 +      u8                      asleep;
 +};
 +
 +static struct twl4030_usb *the_transceiver;
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static int twl4030_i2c_write_u8_verify(u8 module, u8 data, u8 address)
 +{
 +      u8 check;
 +
 +      if ((twl4030_i2c_write_u8(module, data, address) >= 0) &&
 +          (twl4030_i2c_read_u8(module, &check, address) >= 0) &&
 +                                              (check == data))
 +              return 0;
 +      /* Failed once: Try again */
 +      if ((twl4030_i2c_write_u8(module, data, address) >= 0) &&
 +          (twl4030_i2c_read_u8(module, &check, address) >= 0) &&
 +                                              (check == data))
 +              return 0;
 +      /* Failed again: Return error */
 +      return -EBUSY;
 +}
 +
 +#define twl4030_usb_write_verify(address, data)       \
 +      twl4030_i2c_write_u8_verify(TWL4030_MODULE_USB, (data), (address))
 +
 +static inline int twl4030_usb_write(u8 address, u8 data)
 +{
 +      int ret = 0;
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address);
 +      if (ret >= 0) {
 +#if 0 /* debug */
 +              u8 data1;
 +              if (twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data1,
 +                                      address) < 0)
 +                      printk(KERN_ERR "re-read failed\n");
 +              else
 +                      printk(KERN_INFO
 +                             "Write %s wrote %x read %x from reg %x\n",
 +                             (data1 == data) ? "succeed" : "mismatch",
 +                             data, data1, address);
 +#endif
 +      } else {
 +              printk(KERN_WARNING
 +                      "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
 +      }
 +      return ret;
 +}
 +
 +static inline int twl4030_usb_read(u8 address)
 +{
 +      u8 data;
 +      int ret = 0;
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data, address);
 +      if (ret >= 0) {
 +              ret = data;
 +      } else {
 +              printk(KERN_WARNING
 +                      "TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
 +      }
 +      return ret;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static inline int
 +twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
 +{
 +      return twl4030_usb_write(reg + 1, bits);
 +}
 +
 +static inline int
 +twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
 +{
 +      return twl4030_usb_write(reg + 2, bits);
 +
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
 +{
 +      twl->usb_mode = mode;
 +
 +      switch (mode) {
 +      case T2_USB_MODE_ULPI:
 +              twl4030_usb_clear_bits(twl, IFC_CTRL, IFC_CTRL_CARKITMODE);
 +              twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
 +              twl4030_usb_clear_bits(twl, FUNC_CTRL,
 +                                      FUNC_CTRL_XCVRSELECT_MASK |
 +                                      FUNC_CTRL_OPMODE_MASK);
 +              break;
 +/*
 +      case T2_USB_MODE_CEA2011_3PIN:
 +              twl4030_cea2011_3_pin_FS_setup(twl);
 +              break;
 +*/
 +      default:
 +              /* FIXME: power on defaults */
 +              break;
 +      };
 +}
 +
 +#ifdef CONFIG_TWL4030_USB_HS_ULPI
 +static void hs_usb_init(struct twl4030_usb *twl)
 +{
 +      twl->usb_mode = T2_USB_MODE_ULPI;
 +      return;
 +}
 +
 +#endif
 +
 +static void twl4030_i2c_access(int on)
 +{
 +      unsigned long timeout;
 +      int val = twl4030_usb_read(PHY_CLK_CTRL);
 +
 +      if (val >= 0) {
 +              if (on) {
 +                      /* enable DPLL to access PHY registers over I2C */
 +                      val |= REQ_PHY_DPLL_CLK;
 +                      if (twl4030_usb_write_verify(PHY_CLK_CTRL,
 +                                                              (u8)val) < 0) {
 +                              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                                              " line %d\n", __LINE__);
 +                              return;
 +                      }
 +
 +                      timeout = jiffies + HZ;
 +                      while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
 +                                                      PHY_DPLL_CLK)
 +                              && time_before(jiffies, timeout))
 +                                      udelay(10);
 +                      if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
 +                                                      PHY_DPLL_CLK))
 +                              printk(KERN_ERR "Timeout setting T2 HSUSB "
 +                                              "PHY DPLL clock\n");
 +              } else {
 +                      /* let ULPI control the DPLL clock */
 +                      val &= ~REQ_PHY_DPLL_CLK;
 +                      if (twl4030_usb_write_verify(PHY_CLK_CTRL,
 +                                                              (u8)val) < 0) {
 +                              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                                              " line %d\n", __LINE__);
 +                      }
 +              }
 +      }
 +      return;
 +}
 +
 +static void usb_irq_enable(int rising, int falling)
 +{
 +      u8 val;
 +
 +      /* edge setup */
 +      if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c read failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +      val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
 +      if (rising)
 +              val = val | USB_PRES_RISING;
 +      if (falling)
 +              val = val | USB_PRES_FALLING;
 +      if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
 +                                                      REG_PWR_EDR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +
 +      /* un-mask interrupt */
 +      if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c read failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +      val &= ~USB_PRES;
 +      if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
 +                                                      REG_PWR_IMR1) < 0)
 +              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                              " line %d\n", __LINE__);
 +
 +      return;
 +}
 +
 +static void usb_irq_disable(void)
 +{
 +      u8 val;
 +
 +      /* undo edge setup */
 +      if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c read failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +      val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
 +      if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
 +                                                      REG_PWR_EDR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +
 +      /* mask interrupt */
 +      if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c read failed,"
 +                              " line %d\n", __LINE__);
 +              return;
 +      }
 +      val |= USB_PRES;
 +      if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
 +                                                      REG_PWR_IMR1) < 0)
 +              printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                              " line %d\n", __LINE__);
 +
 +      return;
 +}
 +
 +static void twl4030_phy_power(struct twl4030_usb *twl, int on)
 +{
 +      u8 pwr;
 +
 +      pwr = twl4030_usb_read(PHY_PWR_CTRL);
 +      if (on) {
 +              pwr &= ~PHY_PWR_PHYPWD;
 +              if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
 +                      printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                                      " line %d\n", __LINE__);
 +                      return;
 +              }
 +              twl4030_usb_write(PHY_CLK_CTRL,
 +                                twl4030_usb_read(PHY_CLK_CTRL) |
 +                                      (PHY_CLK_CTRL_CLOCKGATING_EN |
 +                                              PHY_CLK_CTRL_CLK32K_EN));
 +      } else  {
 +              pwr |= PHY_PWR_PHYPWD;
 +              if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
 +                      printk(KERN_ERR "twl4030_usb: i2c write failed,"
 +                                      " line %d\n", __LINE__);
 +              }
 +      }
 +      return;
 +}
 +
 +static void twl4030_phy_suspend(int controller_off)
 +{
 +      struct twl4030_usb *twl = the_transceiver;
 +
 +      if (controller_off)
 +              usb_irq_disable();
 +
 +      if (twl->asleep)
 +              return;
 +
 +      if (!controller_off)
 +              /* enable rising edge interrupt to detect cable attach */
 +              usb_irq_enable(1, 0);
 +
 +      twl4030_phy_power(twl, 0);
 +      twl->asleep = 1;
 +      return;
 +}
 +
 +static void twl4030_phy_resume(void)
 +{
 +      struct twl4030_usb *twl = the_transceiver;
 +
 +      if (!twl->asleep)
 +              return;
 +
 +      /* enable falling edge interrupt to detect cable detach */
 +      usb_irq_enable(0, 1);
 +
 +      twl4030_phy_power(twl, 1);
 +      twl4030_i2c_access(1);
 +      twl4030_usb_set_mode(twl, twl->usb_mode);
 +      if (twl->usb_mode == T2_USB_MODE_ULPI)
 +              twl4030_i2c_access(0);
 +      twl->asleep = 0;
 +      return;
 +}
 +
 +static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
 +{
 +      /* Enable writing to power configuration registers */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY);
 +
 +      /* put VUSB3V1 LDO in active state */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
 +
 +      /* input to VUSB3V1 LDO is from VBAT, not VBUS */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
 +
 +      /* turn on 3.1V regulator */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
 +
 +      /* turn on 1.5V regulator */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
 +
 +      /* turn on 1.8V regulator */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
 +
 +      /* disable access to power configuration registers */
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
 +}
 +
 +static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 +{
 +      int ret = IRQ_NONE;
 +      u8 val;
 +
 +      /* action based on cable attach or detach */
 +      if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
 +              printk(KERN_ERR "twl4030_usb: i2c read failed,"
 +                              " line %d\n", __LINE__);
 +              goto done;
 +      }
 +
 +      if (val & USB_PRES_RISING) {
 +              twl4030_phy_resume();
 +              twl4030charger_usb_en(1);
 +      } else {
 +              twl4030charger_usb_en(0);
 +              twl4030_phy_suspend(0);
 +      }
 +
 +      ret = IRQ_HANDLED;
 +
 +done:
 +      return ret;
 +}
 +
 +static int twl4030_set_suspend(struct otg_transceiver *x, int suspend)
 +{
 +      if (suspend)
 +              twl4030_phy_suspend(1);
 +      else
 +              twl4030_phy_resume();
 +
 +      return 0;
 +}
 +
 +static int twl4030_set_peripheral(struct otg_transceiver *xceiv,
 +              struct usb_gadget *gadget)
 +{
 +      u32 l;
 +      struct twl4030_usb *twl = xceiv_to_twl(xceiv);
 +
 +      if (!xceiv)
 +              return -ENODEV;
 +
 +      if (!gadget) {
 +              omap_writew(0, OTG_IRQ_EN);
 +              twl4030_phy_suspend(1);
 +              twl->otg.gadget = NULL;
 +
 +              return -ENODEV;
 +      }
 +
 +      twl->otg.gadget = gadget;
 +      twl4030_phy_resume();
 +
 +      l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
 +      l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
 +      l |= OTG_ID;
 +      omap_writel(l, OTG_CTRL);
 +
 +      twl->otg.state = OTG_STATE_B_IDLE;
 +
 +      twl4030_usb_set_bits(twl, USB_INT_EN_RISE,
 +                      USB_INT_SESSVALID | USB_INT_VBUSVALID);
 +      twl4030_usb_set_bits(twl, USB_INT_EN_FALL,
 +                      USB_INT_SESSVALID | USB_INT_VBUSVALID);
 +
 +      return 0;
 +}
 +
 +static int twl4030_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
 +{
 +      struct twl4030_usb *twl = xceiv_to_twl(xceiv);
 +
 +      if (!xceiv)
 +              return -ENODEV;
 +
 +      if (!host) {
 +              omap_writew(0, OTG_IRQ_EN);
 +              twl4030_phy_suspend(1);
 +              twl->otg.host = NULL;
 +
 +              return -ENODEV;
 +      }
 +
 +      twl->otg.host = host;
 +      twl4030_phy_resume();
 +
 +      twl4030_usb_set_bits(twl, TWL4030_OTG_CTRL,
 +                      TWL4030_OTG_CTRL_DMPULLDOWN
 +                              | TWL4030_OTG_CTRL_DPPULLDOWN);
 +      twl4030_usb_set_bits(twl, USB_INT_EN_RISE, USB_INT_IDGND);
 +      twl4030_usb_set_bits(twl, USB_INT_EN_FALL, USB_INT_IDGND);
 +      twl4030_usb_set_bits(twl, FUNC_CTRL, FUNC_CTRL_SUSPENDM);
 +      twl4030_usb_set_bits(twl, TWL4030_OTG_CTRL, TWL4030_OTG_CTRL_DRVVBUS);
 +
 +      return 0;
 +}
 +
 +static int __init twl4030_usb_init(void)
 +{
 +      struct twl4030_usb      *twl;
 +      int status;
 +
 +      if (the_transceiver)
 +              return 0;
 +
 +      twl = kzalloc(sizeof *twl, GFP_KERNEL);
 +      if (!twl)
 +              return 0;
 +
 +      the_transceiver = twl;
 +
 +      twl->irq                = TWL4030_PWRIRQ_USB_PRES;
 +      twl->otg.set_host       = twl4030_set_host;
 +      twl->otg.set_peripheral = twl4030_set_peripheral;
 +      twl->otg.set_suspend    = twl4030_set_suspend;
 +
 +      usb_irq_disable();
 +      status = request_irq(twl->irq, twl4030_usb_irq, 0, "twl4030_usb", twl);
 +      if (status < 0) {
 +              printk(KERN_DEBUG "can't get IRQ %d, err %d\n",
 +                      twl->irq, status);
 +              kfree(twl);
 +              return -ENODEV;
 +      }
 +
 +#if defined(CONFIG_TWL4030_USB_HS_ULPI)
 +      hs_usb_init(twl);
 +#endif
 +      twl4030_usb_ldo_init(twl);
 +      twl4030_phy_power(twl, 1);
 +      twl4030_i2c_access(1);
 +      twl4030_usb_set_mode(twl, twl->usb_mode);
 +      if (twl->usb_mode == T2_USB_MODE_ULPI)
 +              twl4030_i2c_access(0);
 +
 +      twl->asleep = 0;
 +
 +      if (twl->usb_mode == T2_USB_MODE_ULPI)
 +              twl4030_phy_suspend(1);
 +
 +      otg_set_transceiver(&twl->otg);
 +
 +      printk(KERN_INFO "Initialized TWL4030 USB module\n");
 +
 +      return 0;
 +}
 +
 +
 +static void __exit twl4030_usb_exit(void)
 +{
 +      struct twl4030_usb *twl = the_transceiver;
 +      int val;
 +
 +      usb_irq_disable();
 +      free_irq(twl->irq, twl);
 +
 +      /* set transceiver mode to power on defaults */
 +      twl4030_usb_set_mode(twl, -1);
 +
 +      /* autogate 60MHz ULPI clock,
 +       * clear dpll clock request for i2c access,
 +       * disable 32KHz
 +       */
 +      val = twl4030_usb_read(PHY_CLK_CTRL);
 +      if (val >= 0) {
 +              val |= PHY_CLK_CTRL_CLOCKGATING_EN;
 +              val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
 +              twl4030_usb_write(PHY_CLK_CTRL, (u8)val);
 +      }
 +
 +      /* disable complete OTG block */
 +      twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
 +
 +      twl4030_phy_power(twl, 0);
 +
 +      kfree(twl);
 +}
 +
 +subsys_initcall(twl4030_usb_init);
 +module_exit(twl4030_usb_exit);
 +
 +MODULE_ALIAS("i2c:twl4030-usb");
 +MODULE_AUTHOR("Texas Instruments, Inc.");
 +MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
 +MODULE_LICENSE("GPL");
index 90c092f20302664d84a17111b20ad741657939a2,dcea87a0bc5674e16b88502273b903d684800663..38b1a79b4a5f7866ed511797d0dd1701dbda5927
  #include <linux/delay.h>
  #include <linux/platform_device.h>
  #include <linux/mutex.h>
 +#include <linux/spinlock.h>
  #include <linux/errno.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/keypad.h>
 +#include <linux/i2c/menelaus.h>
 -#include <mach/menelaus.h>
+ #include <mach/gpio.h>
+ #include <mach/keypad.h>
  #include <asm/irq.h>
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
  #include <asm/io.h>
- #include <asm/arch/mux.h>
 +#include <asm/mach-types.h>
+ #include <mach/mux.h>
  
  #undef NEW_BOARD_LEARNING_MODE
  
index 68c5b8e5112dc5eed5b5dc873ce30aa60a46e56b,0000000000000000000000000000000000000000..5dbb80f51c41161b3716c9a2134ed48428ddd32c
mode 100644,000000..100644
--- /dev/null
@@@ -1,375 -1,0 +1,375 @@@
- #include <asm/arch/keypad.h>
 +/*
 + * drivers/input/keyboard/omap-twl4030keypad.c
 + *
 + * Copyright (C) 2007 Texas Instruments, Inc.
 + * Copyright (C) 2008 Nokia Corporation
 + *
 + * Code re-written for 2430SDP by:
 + * Syed Mohammed Khasim <x0khasim@ti.com>
 + *
 + * Initial Code:
 + * Manjunatha G K <manjugk@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/types.h>
 +#include <linux/input.h>
 +#include <linux/kernel.h>
 +#include <linux/delay.h>
 +#include <linux/bitops.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/irq.h>
++#include <mach/keypad.h>
 +#include "twl4030-keypad.h"
 +
 +#define PTV_PRESCALER         4
 +
 +#define MAX_ROWS              8 /* TWL4030 hardlimit */
 +#define ROWCOL_MASK           0xFF000000
 +#define KEYNUM_MASK           0x00FFFFFF
 +
 +/* Global variables */
 +static int *keymap;
 +static u16 kp_state[MAX_ROWS];
 +static int n_rows, n_cols;
 +
 +static struct device *dbg_dev;
 +static struct input_dev *omap_twl4030kp;
 +
 +static int twl4030_kpread(u32 module, u8 *data, u32 reg, u8 num_bytes)
 +{
 +      int ret;
 +
 +      ret = twl4030_i2c_read(module, data, reg, num_bytes);
 +      if (ret < 0) {
 +              dev_warn(dbg_dev, "Couldn't read TWL4030: %X - ret %d[%x]\n",
 +                       reg, ret, ret);
 +              return ret;
 +      }
 +      return ret;
 +}
 +
 +static int twl4030_kpwrite_u8(u32 module, u8 data, u32 reg)
 +{
 +      int ret;
 +
 +      ret = twl4030_i2c_write_u8(module, data, reg);
 +      if (ret < 0) {
 +              dev_warn(dbg_dev, "Could not write TWL4030: %X - ret %d[%x]\n",
 +                       reg, ret, ret);
 +              return ret;
 +      }
 +      return ret;
 +}
 +
 +static int omap_kp_find_key(int col, int row)
 +{
 +      int i, rc;
 +
 +      rc = KEY(col, row, 0);
 +      for (i = 0; keymap[i] != 0; i++)
 +              if ((keymap[i] & ROWCOL_MASK) == rc)
 +                      return keymap[i] & KEYNUM_MASK;
 +
 +      return -EINVAL;
 +}
 +
 +static inline u16 omap_kp_col_xlate(u8 col)
 +{
 +      /* If all bits in a row are active for all coloumns then
 +       * we have that row line connected to gnd. Mark this
 +       * key on as if it was on matrix position n_cols (ie
 +       * one higher than the size of the matrix).
 +       */
 +      if (col == 0xFF)
 +              return (1 << n_cols);
 +      else
 +              return col & ((1 << n_cols) - 1);
 +}
 +
 +static int omap_kp_read_kp_matrix_state(u16 *state)
 +{
 +      u8 new_state[MAX_ROWS];
 +      int row;
 +      int ret = twl4030_kpread(TWL4030_MODULE_KEYPAD,
 +                               new_state, KEYP_FULL_CODE_7_0, n_rows);
 +      if (ret >= 0) {
 +              for (row = 0; row < n_rows; row++)
 +                      state[row] = omap_kp_col_xlate(new_state[row]);
 +      }
 +      return ret;
 +}
 +
 +static int omap_kp_is_in_ghost_state(u16 *key_state)
 +{
 +      int i;
 +      u16 check = 0;
 +
 +      for (i = 0; i < n_rows; i++) {
 +              u16 col = key_state[i];
 +
 +              if ((col & check) && hweight16(col) > 1)
 +                      return 1;
 +              check |= col;
 +      }
 +
 +      return 0;
 +}
 +
 +static void twl4030_kp_scan(int release_all)
 +{
 +      u16 new_state[MAX_ROWS];
 +      int col, row;
 +
 +      if (release_all)
 +              memset(new_state, 0, sizeof(new_state));
 +      else {
 +              /* check for any changes */
 +              int ret = omap_kp_read_kp_matrix_state(new_state);
 +              if (ret < 0)    /* panic ... */
 +                      return;
 +
 +              if (omap_kp_is_in_ghost_state(new_state))
 +                      return;
 +      }
 +
 +      /* check for changes and print those */
 +      for (row = 0; row < n_rows; row++) {
 +              int changed = new_state[row] ^ kp_state[row];
 +
 +              if (!changed)
 +                      continue;
 +
 +              for (col = 0; col < n_cols; col++) {
 +                      int key;
 +
 +                      if (!(changed & (1 << col)))
 +                              continue;
 +
 +                      dev_dbg(dbg_dev, "key [%d:%d] %s\n", row, col,
 +                              (new_state[row] & (1 << col)) ?
 +                              "press" : "release");
 +
 +                      key = omap_kp_find_key(col, row);
 +                      if (key < 0)
 +                              dev_warn(dbg_dev, "Spurious key event %d-%d\n",
 +                                       col, row);
 +                      else
 +                              input_report_key(omap_twl4030kp, key,
 +                                               new_state[row] & (1 << col));
 +              }
 +              kp_state[row] = new_state[row];
 +      }
 +}
 +
 +/*
 + * Keypad interrupt handler
 + */
 +static irqreturn_t do_kp_irq(int irq, void *dev_id)
 +{
 +      u8 reg;
 +      int ret;
 +
 +      /* Read & Clear TWL4030 pending interrupt */
 +      ret = twl4030_kpread(TWL4030_MODULE_KEYPAD, &reg, KEYP_ISR1, 1);
 +
 +      /* Release all keys if I2C has gone bad or
 +       * the KEYP has gone to idle state */
 +      if ((ret >= 0) && (reg & KEYP_IMR1_KP))
 +              twl4030_kp_scan(0);
 +      else
 +              twl4030_kp_scan(1);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Registers keypad device with input sub system
 + * and configures TWL4030 keypad registers
 + */
 +static int __init omap_kp_probe(struct platform_device *pdev)
 +{
 +      u8 reg;
 +      int i;
 +      int ret = 0;
 +      struct omap_kp_platform_data *pdata = pdev->dev.platform_data;
 +
 +      /* Get the debug Device */
 +      dbg_dev = &(pdev->dev);
 +
 +      if (!pdata->rows || !pdata->cols || !pdata->keymap) {
 +              dev_err(dbg_dev, "No rows, cols or keymap from pdata\n");
 +              return -EINVAL;
 +      }
 +
 +      omap_twl4030kp = input_allocate_device();
 +      if (omap_twl4030kp == NULL)
 +              return -ENOMEM;
 +
 +      keymap = pdata->keymap;
 +      n_rows = pdata->rows;
 +      n_cols = pdata->cols;
 +
 +      /* setup input device */
 +      set_bit(EV_KEY, omap_twl4030kp->evbit);
 +
 +      /* Enable auto repeat feature of Linux input subsystem */
 +      if (pdata->rep)
 +              set_bit(EV_REP, omap_twl4030kp->evbit);
 +
 +      for (i = 0; keymap[i] != 0; i++)
 +              set_bit(keymap[i] & KEYNUM_MASK, omap_twl4030kp->keybit);
 +
 +      omap_twl4030kp->name            = "omap_twl4030keypad";
 +      omap_twl4030kp->phys            = "omap_twl4030keypad/input0";
 +      omap_twl4030kp->dev.parent      = &pdev->dev;
 +
 +      omap_twl4030kp->id.bustype      = BUS_HOST;
 +      omap_twl4030kp->id.vendor       = 0x0001;
 +      omap_twl4030kp->id.product      = 0x0001;
 +      omap_twl4030kp->id.version      = 0x0003;
 +
 +      omap_twl4030kp->keycode         = keymap;
 +      omap_twl4030kp->keycodesize     = sizeof(unsigned int);
 +      omap_twl4030kp->keycodemax      = pdata->keymapsize;
 +
 +      ret = input_register_device(omap_twl4030kp);
 +      if (ret < 0) {
 +              dev_err(dbg_dev, "Unable to register twl4030 keypad device\n");
 +              goto err2;
 +      }
 +
 +      /* Disable auto-repeat */
 +      reg = KEYP_CTRL_NOAUTORPT;
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, KEYP_CTRL);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /* Enable TO rising and KP rising and falling edge detection */
 +      reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING;
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, KEYP_EDR);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /* Set PTV prescaler Field */
 +      reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT);
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, KEYP_LK_PTV);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /* Set key debounce time to 20 ms */
 +      i = KEYP_PERIOD_US(20000, PTV_PRESCALER);
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, i, KEYP_DEB);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /* Set timeout period to 100 ms */
 +      i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD,
 +                               (i & 0xFF), KEYP_TIMEOUT_L);
 +      if (ret < 0)
 +              goto err3;
 +
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD,
 +                               (i >> 8), KEYP_TIMEOUT_H);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /* Enable Clear-on-Read */
 +      reg = KEYP_SIH_CTRL_COR | KEYP_SIH_CTRL_PEND_DIS;
 +      ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD,
 +                               reg, KEYP_SIH_CTRL);
 +      if (ret < 0)
 +              goto err3;
 +
 +      /*
 +       * This ISR will always execute in kernel thread context because of
 +       * the need to access the TWL4030 over the I2C bus.
 +       */
 +      ret = request_irq(TWL4030_MODIRQ_KEYPAD, do_kp_irq,
 +              IRQF_DISABLED, "TWL4030 Keypad", omap_twl4030kp);
 +      if (ret < 0) {
 +              dev_info(dbg_dev, "request_irq failed for irq no=%d\n",
 +                      TWL4030_MODIRQ_KEYPAD);
 +              goto err3;
 +      } else {
 +              /* Enable KP and TO interrupts now. */
 +              reg = ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
 +              ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD,
 +                                       reg, KEYP_IMR1);
 +              if (ret < 0)
 +                      goto err5;
 +      }
 +
 +      ret = omap_kp_read_kp_matrix_state(kp_state);
 +      if (ret < 0)
 +              goto err4;
 +
 +      return ret;
 +err5:
 +      /* mask all events - we don't care about the result */
 +      (void) twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, 0xff, KEYP_IMR1);
 +err4:
 +      free_irq(TWL4030_MODIRQ_KEYPAD, NULL);
 +err3:
 +      input_unregister_device(omap_twl4030kp);
 +err2:
 +      input_free_device(omap_twl4030kp);
 +      return -ENODEV;
 +}
 +
 +static int omap_kp_remove(struct platform_device *pdev)
 +{
 +      free_irq(TWL4030_MODIRQ_KEYPAD, NULL);
 +
 +      input_unregister_device(omap_twl4030kp);
 +      return 0;
 +}
 +
 +
 +static struct platform_driver omap_kp_driver = {
 +      .probe          = omap_kp_probe,
 +      .remove         = omap_kp_remove,
 +      .driver         = {
 +              .name   = "omap_twl4030keypad",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +/*
 + * OMAP TWL4030 Keypad init
 + */
 +static int __devinit omap_kp_init(void)
 +{
 +      return platform_driver_register(&omap_kp_driver);
 +}
 +
 +static void __exit omap_kp_exit(void)
 +{
 +      platform_driver_unregister(&omap_kp_driver);
 +}
 +
 +module_init(omap_kp_init);
 +module_exit(omap_kp_exit);
 +MODULE_ALIAS("platform:omap_twl4030keypad");
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION("OMAP TWL4030 Keypad Driver");
 +MODULE_LICENSE("GPL");
index 1e4ed3c25db58ff0c8e2b3fd0ac071d29df8781f,0000000000000000000000000000000000000000..7fb107ec69ef305bbba86465bc27d106826ed1e4
mode 100644,000000..100644
--- /dev/null
@@@ -1,736 -1,0 +1,736 @@@
- #include <asm/arch/gpio.h>
 +/*
 + * TSC2005 touchscreen driver
 + *
 + * Copyright (C) 2006-2008 Nokia Corporation
 + *
 + * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
 + * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.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/kernel.h>
 +#include <linux/module.h>
 +#include <linux/input.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/spi/spi.h>
 +
 +#ifdef CONFIG_ARCH_OMAP
++#include <mach/gpio.h>
 +#endif
 +
 +#include <linux/spi/tsc2005.h>
 +
 +/**
 + * The touchscreen interface operates as follows:
 + *
 + * Initialize:
 + *    Request access to GPIO103 (DAV)
 + *    tsc2005_dav_irq_handler will trigger when DAV line goes down
 + *
 + *  1) Pen is pressed against touchscreeen
 + *  2) TSC2005 performs AD conversion
 + *  3) After the conversion is done TSC2005 drives DAV line down
 + *  4) GPIO IRQ is received and tsc2005_dav_irq_handler is called
 + *  5) tsc2005_ts_irq_handler queues up an spi transfer to fetch
 + *     the x, y, z1, z2 values
 + *  6) tsc2005_ts_rx() reports coordinates to input layer and
 + *     sets up tsc2005_ts_timer() to be called after TSC2005_TS_SCAN_TIME
 + *  7)  When the penup_timer expires, there have not been DAV interrupts
 + *     during the last 20ms which means the pen has been lifted.
 + */
 +
 +#define TSC2005_VDD_LOWER_27
 +
 +#ifdef TSC2005_VDD_LOWER_27
 +#define TSC2005_HZ     (10000000)
 +#else
 +#define TSC2005_HZ     (25000000)
 +#endif
 +
 +#define TSC2005_CMD   (0x80)
 +#define TSC2005_REG   (0x00)
 +
 +#define TSC2005_CMD_STOP      (1)
 +#define TSC2005_CMD_10BIT     (0 << 2)
 +#define TSC2005_CMD_12BIT     (1 << 2)
 +
 +#define TSC2005_CMD_SCAN_XYZZ (0 << 3)
 +#define TSC2005_CMD_SCAN_XY   (1 << 3)
 +#define TSC2005_CMD_SCAN_X    (2 << 3)
 +#define TSC2005_CMD_SCAN_Y    (3 << 3)
 +#define TSC2005_CMD_SCAN_ZZ   (4 << 3)
 +#define TSC2005_CMD_AUX_SINGLE        (5 << 3)
 +#define TSC2005_CMD_TEMP1     (6 << 3)
 +#define TSC2005_CMD_TEMP2     (7 << 3)
 +#define TSC2005_CMD_AUX_CONT  (8 << 3)
 +#define TSC2005_CMD_TEST_X_CONN       (9 << 3)
 +#define TSC2005_CMD_TEST_Y_CONN       (10 << 3)
 +/* command 11 reserved */
 +#define TSC2005_CMD_TEST_SHORT        (12 << 3)
 +#define TSC2005_CMD_DRIVE_XX  (13 << 3)
 +#define TSC2005_CMD_DRIVE_YY  (14 << 3)
 +#define TSC2005_CMD_DRIVE_YX  (15 << 3)
 +
 +#define TSC2005_REG_X         (0 << 3)
 +#define TSC2005_REG_Y         (1 << 3)
 +#define TSC2005_REG_Z1                (2 << 3)
 +#define TSC2005_REG_Z2                (3 << 3)
 +#define TSC2005_REG_AUX               (4 << 3)
 +#define TSC2005_REG_TEMP1     (5 << 3)
 +#define TSC2005_REG_TEMP2     (6 << 3)
 +#define TSC2005_REG_STATUS    (7 << 3)
 +#define TSC2005_REG_AUX_HIGH  (8 << 3)
 +#define TSC2005_REG_AUX_LOW   (9 << 3)
 +#define TSC2005_REG_TEMP_HIGH (10 << 3)
 +#define TSC2005_REG_TEMP_LOW  (11 << 3)
 +#define TSC2005_REG_CFR0      (12 << 3)
 +#define TSC2005_REG_CFR1      (13 << 3)
 +#define TSC2005_REG_CFR2      (14 << 3)
 +#define TSC2005_REG_FUNCTION  (15 << 3)
 +
 +#define TSC2005_REG_PND0      (1 << 1)
 +#define TSC2005_REG_READ      (0x01)
 +#define TSC2005_REG_WRITE     (0x00)
 +
 +
 +#define TSC2005_CFR0_LONGSAMPLING     (1)
 +#define TSC2005_CFR0_DETECTINWAIT     (1 << 1)
 +#define TSC2005_CFR0_SENSETIME_32US   (0)
 +#define TSC2005_CFR0_SENSETIME_96US   (1 << 2)
 +#define TSC2005_CFR0_SENSETIME_544US  (1 << 3)
 +#define TSC2005_CFR0_SENSETIME_2080US (1 << 4)
 +#define TSC2005_CFR0_SENSETIME_2656US (0x001C)
 +#define TSC2005_CFR0_PRECHARGE_20US   (0x0000)
 +#define TSC2005_CFR0_PRECHARGE_84US   (0x0020)
 +#define TSC2005_CFR0_PRECHARGE_276US  (0x0040)
 +#define TSC2005_CFR0_PRECHARGE_1044US (0x0080)
 +#define TSC2005_CFR0_PRECHARGE_1364US (0x00E0)
 +#define TSC2005_CFR0_STABTIME_0US     (0x0000)
 +#define TSC2005_CFR0_STABTIME_100US   (0x0100)
 +#define TSC2005_CFR0_STABTIME_500US   (0x0200)
 +#define TSC2005_CFR0_STABTIME_1MS     (0x0300)
 +#define TSC2005_CFR0_STABTIME_5MS     (0x0400)
 +#define TSC2005_CFR0_STABTIME_100MS   (0x0700)
 +#define TSC2005_CFR0_CLOCK_4MHZ               (0x0000)
 +#define TSC2005_CFR0_CLOCK_2MHZ               (0x0800)
 +#define TSC2005_CFR0_CLOCK_1MHZ               (0x1000)
 +#define TSC2005_CFR0_RESOLUTION12     (0x2000)
 +#define TSC2005_CFR0_STATUS           (0x4000)
 +#define TSC2005_CFR0_PENMODE          (0x8000)
 +
 +#define TSC2005_CFR0_INITVALUE        (TSC2005_CFR0_STABTIME_1MS  |   \
 +                               TSC2005_CFR0_CLOCK_1MHZ    |   \
 +                               TSC2005_CFR0_RESOLUTION12  |   \
 +                               TSC2005_CFR0_PRECHARGE_276US | \
 +                               TSC2005_CFR0_PENMODE)
 +
 +#define TSC2005_CFR1_BATCHDELAY_0MS   (0x0000)
 +#define TSC2005_CFR1_BATCHDELAY_1MS   (0x0001)
 +#define TSC2005_CFR1_BATCHDELAY_2MS   (0x0002)
 +#define TSC2005_CFR1_BATCHDELAY_4MS   (0x0003)
 +#define TSC2005_CFR1_BATCHDELAY_10MS  (0x0004)
 +#define TSC2005_CFR1_BATCHDELAY_20MS  (0x0005)
 +#define TSC2005_CFR1_BATCHDELAY_40MS  (0x0006)
 +#define TSC2005_CFR1_BATCHDELAY_100MS (0x0007)
 +
 +#define TSC2005_CFR1_INITVALUE        (TSC2005_CFR1_BATCHDELAY_2MS)
 +
 +#define TSC2005_CFR2_MAVE_TEMP        (0x0001)
 +#define TSC2005_CFR2_MAVE_AUX (0x0002)
 +#define TSC2005_CFR2_MAVE_Z   (0x0004)
 +#define TSC2005_CFR2_MAVE_Y   (0x0008)
 +#define TSC2005_CFR2_MAVE_X   (0x0010)
 +#define TSC2005_CFR2_AVG_1    (0x0000)
 +#define TSC2005_CFR2_AVG_3    (0x0400)
 +#define TSC2005_CFR2_AVG_7    (0x0800)
 +#define TSC2005_CFR2_MEDIUM_1 (0x0000)
 +#define TSC2005_CFR2_MEDIUM_3 (0x1000)
 +#define TSC2005_CFR2_MEDIUM_7 (0x2000)
 +#define TSC2005_CFR2_MEDIUM_15        (0x3000)
 +
 +#define TSC2005_CFR2_IRQ_DAV  (0x4000)
 +#define TSC2005_CFR2_IRQ_PEN  (0x8000)
 +#define TSC2005_CFR2_IRQ_PENDAV       (0x0000)
 +
 +#define TSC2005_CFR2_INITVALUE        (TSC2005_CFR2_IRQ_DAV   |       \
 +                               TSC2005_CFR2_MAVE_X    |       \
 +                               TSC2005_CFR2_MAVE_Y    |       \
 +                               TSC2005_CFR2_MAVE_Z    |       \
 +                               TSC2005_CFR2_MEDIUM_15 |       \
 +                               TSC2005_CFR2_AVG_7)
 +
 +#define MAX_12BIT                                     ((1 << 12) - 1)
 +#define TS_SAMPLES                                    4
 +#define TS_RECT_SIZE                                  8
 +#define TSC2005_TS_PENUP_TIME                         20
 +
 +static const u32 tsc2005_read_reg[] = {
 +      (TSC2005_REG | TSC2005_REG_X | TSC2005_REG_READ) << 16,
 +      (TSC2005_REG | TSC2005_REG_Y | TSC2005_REG_READ) << 16,
 +      (TSC2005_REG | TSC2005_REG_Z1 | TSC2005_REG_READ) << 16,
 +      (TSC2005_REG | TSC2005_REG_Z2 | TSC2005_REG_READ) << 16,
 +};
 +#define NUM_READ_REGS (sizeof(tsc2005_read_reg)/sizeof(tsc2005_read_reg[0]))
 +
 +struct tsc2005 {
 +      struct spi_device       *spi;
 +
 +      struct input_dev        *idev;
 +      char                    phys[32];
 +      struct timer_list       penup_timer;
 +      spinlock_t              lock;
 +      struct mutex            mutex;
 +
 +      struct spi_message      read_msg;
 +      struct spi_transfer     read_xfer[NUM_READ_REGS];
 +      u32                     data[NUM_READ_REGS];
 +
 +      /* previous x,y,z */
 +      int                     x;
 +      int                     y;
 +      int                     p;
 +      /* average accumulators for each component */
 +      int                     sample_cnt;
 +      int                     avg_x;
 +      int                     avg_y;
 +      int                     avg_z1;
 +      int                     avg_z2;
 +      /* configuration */
 +      int                     x_plate_ohm;
 +      int                     hw_avg_max;
 +      int                     stab_time;
 +      int                     p_max;
 +      int                     touch_pressure;
 +      int                     irq;
 +      s16                     dav_gpio;
 +      /* status */
 +      u8                      sample_sent;
 +      u8                      pen_down;
 +      u8                      disabled;
 +      u8                      disable_depth;
 +      u8                      spi_active;
 +};
 +
 +static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
 +{
 +      u16 data = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
 +      struct spi_message msg;
 +      struct spi_transfer xfer = { 0 };
 +
 +      xfer.tx_buf = &data;
 +      xfer.rx_buf = NULL;
 +      xfer.len = 1;
 +      xfer.bits_per_word = 8;
 +
 +      spi_message_init(&msg);
 +      spi_message_add_tail(&xfer, &msg);
 +      spi_sync(ts->spi, &msg);
 +}
 +
 +static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value)
 +{
 +      u32 tx;
 +      struct spi_message msg;
 +      struct spi_transfer xfer = { 0 };
 +
 +      tx = (TSC2005_REG | reg | TSC2005_REG_PND0 |
 +             TSC2005_REG_WRITE) << 16;
 +      tx |= value;
 +
 +      xfer.tx_buf = &tx;
 +      xfer.rx_buf = NULL;
 +      xfer.len = 4;
 +      xfer.bits_per_word = 24;
 +
 +      spi_message_init(&msg);
 +      spi_message_add_tail(&xfer, &msg);
 +      spi_sync(ts->spi, &msg);
 +}
 +
 +static void tsc2005_ts_update_pen_state(struct tsc2005 *ts,
 +                                      int x, int y, int pressure)
 +{
 +      if (pressure) {
 +              input_report_abs(ts->idev, ABS_X, x);
 +              input_report_abs(ts->idev, ABS_Y, y);
 +              input_report_abs(ts->idev, ABS_PRESSURE, pressure);
 +              if (!ts->pen_down) {
 +                      input_report_key(ts->idev, BTN_TOUCH, 1);
 +                      ts->pen_down = 1;
 +              }
 +      } else {
 +              input_report_abs(ts->idev, ABS_PRESSURE, 0);
 +              if (ts->pen_down) {
 +                      input_report_key(ts->idev, BTN_TOUCH, 0);
 +                      ts->pen_down = 0;
 +              }
 +      }
 +
 +      input_sync(ts->idev);
 +}
 +
 +/*
 + * This function is called by the SPI framework after the coordinates
 + * have been read from TSC2005
 + */
 +static void tsc2005_ts_rx(void *arg)
 +{
 +      struct tsc2005 *ts = arg;
 +      unsigned long flags;
 +      int inside_rect, pressure_limit;
 +      int x, y, z1, z2, pressure;
 +
 +      spin_lock_irqsave(&ts->lock, flags);
 +
 +      x = ts->data[0];
 +      y = ts->data[1];
 +      z1 = ts->data[2];
 +      z2 = ts->data[3];
 +
 +      /* validate pressure and position */
 +      if (x > MAX_12BIT || y > MAX_12BIT)
 +              goto out;
 +
 +      /* skip coords if the pressure-components are out of range */
 +      if (z1 < 100 || z2 > 4000)
 +              goto out;
 +
 +      /* don't run average on the "pen down" event */
 +      if (ts->sample_sent) {
 +              ts->avg_x += x;
 +              ts->avg_y += y;
 +              ts->avg_z1 += z1;
 +              ts->avg_z2 += z2;
 +
 +              if (++ts->sample_cnt < TS_SAMPLES)
 +                      goto out;
 +
 +              x = ts->avg_x / TS_SAMPLES;
 +              y = ts->avg_y / TS_SAMPLES;
 +              z1 = ts->avg_z1 / TS_SAMPLES;
 +              z2 = ts->avg_z2 / TS_SAMPLES;
 +      }
 +
 +      ts->sample_cnt = 0;
 +      ts->avg_x = 0;
 +      ts->avg_y = 0;
 +      ts->avg_z1 = 0;
 +      ts->avg_z2 = 0;
 +
 +      if (z1) {
 +              pressure = x * (z2 - z1) / z1;
 +              pressure = pressure * ts->x_plate_ohm / 4096;
 +      } else
 +              goto out;
 +
 +      pressure_limit = ts->sample_sent? ts->p_max: ts->touch_pressure;
 +      if (pressure > pressure_limit)
 +              goto out;
 +
 +      /* discard the event if it still is within the previous rect - unless
 +       * if the pressure is harder, but then use previous x,y position */
 +      inside_rect = (ts->sample_sent &&
 +              x > (int)ts->x - TS_RECT_SIZE &&
 +              x < (int)ts->x + TS_RECT_SIZE &&
 +              y > (int)ts->y - TS_RECT_SIZE &&
 +              y < (int)ts->y + TS_RECT_SIZE);
 +      if (inside_rect)
 +              x = ts->x, y = ts->y;
 +
 +      if (!inside_rect || pressure < ts->p) {
 +              tsc2005_ts_update_pen_state(ts, x, y, pressure);
 +              ts->sample_sent = 1;
 +              ts->x = x;
 +              ts->y = y;
 +              ts->p = pressure;
 +      }
 +out:
 +      ts->spi_active = 0;
 +      spin_unlock_irqrestore(&ts->lock, flags);
 +
 +      /* kick pen up timer - to make sure it expires again(!) */
 +      if (ts->sample_sent)
 +              mod_timer(&ts->penup_timer,
 +                        jiffies + msecs_to_jiffies(TSC2005_TS_PENUP_TIME));
 +}
 +
 +static void tsc2005_ts_penup_timer_handler(unsigned long data)
 +{
 +      struct tsc2005 *ts = (struct tsc2005 *)data;
 +
 +      if (ts->sample_sent) {
 +              tsc2005_ts_update_pen_state(ts, 0, 0, 0);
 +              ts->sample_sent = 0;
 +      }
 +}
 +
 +/*
 + * This interrupt is called when pen is down and coordinates are
 + * available. That is indicated by a falling edge on DAV line.
 + */
 +static irqreturn_t tsc2005_ts_irq_handler(int irq, void *dev_id)
 +{
 +      struct tsc2005 *ts = dev_id;
 +      int r;
 +
 +      if (ts->spi_active)
 +              return IRQ_HANDLED;
 +
 +      ts->spi_active = 1;
 +      r = spi_async(ts->spi, &ts->read_msg);
 +      if (r)
 +              dev_err(&ts->spi->dev, "ts: spi_async() failed");
 +
 +      /* kick pen up timer */
 +      mod_timer(&ts->penup_timer,
 +                jiffies + msecs_to_jiffies(TSC2005_TS_PENUP_TIME));
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static void tsc2005_ts_setup_spi_xfer(struct tsc2005 *ts)
 +{
 +      struct spi_message *m = &ts->read_msg;
 +      struct spi_transfer *x = &ts->read_xfer[0];
 +      int i;
 +
 +      spi_message_init(m);
 +
 +      for (i = 0; i < NUM_READ_REGS; i++, x++) {
 +              x->tx_buf = &tsc2005_read_reg[i];
 +              x->rx_buf = &ts->data[i];
 +              x->len = 4;
 +              x->bits_per_word = 24;
 +              x->cs_change = i < (NUM_READ_REGS - 1);
 +              spi_message_add_tail(x, m);
 +      }
 +
 +      m->complete = tsc2005_ts_rx;
 +      m->context = ts;
 +}
 +
 +static ssize_t tsc2005_ts_pen_down_show(struct device *dev,
 +                                      struct device_attribute *attr,
 +                                      char *buf)
 +{
 +      struct tsc2005 *tsc = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%u\n", tsc->pen_down);
 +}
 +
 +static DEVICE_ATTR(pen_down, S_IRUGO, tsc2005_ts_pen_down_show, NULL);
 +
 +static int tsc2005_configure(struct tsc2005 *tsc, int flags)
 +{
 +      tsc2005_write(tsc, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
 +      tsc2005_write(tsc, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
 +      tsc2005_write(tsc, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
 +      tsc2005_cmd(tsc, flags);
 +
 +      return 0;
 +}
 +
 +static void tsc2005_start_scan(struct tsc2005 *tsc)
 +{
 +      tsc2005_configure(tsc, TSC2005_CMD_SCAN_XYZZ);
 +}
 +
 +static void tsc2005_stop_scan(struct tsc2005 *tsc)
 +{
 +      tsc2005_cmd(tsc, TSC2005_CMD_STOP);
 +}
 +
 +/* Must be called with mutex held */
 +static void tsc2005_disable(struct tsc2005 *ts)
 +{
 +      if (ts->disable_depth++ != 0)
 +              return;
 +
 +      disable_irq(ts->irq);
 +
 +      /* wait until penup timer expire normally */
 +      do {
 +              msleep(4);
 +      } while (ts->sample_sent);
 +
 +      tsc2005_stop_scan(ts);
 +}
 +
 +static void tsc2005_enable(struct tsc2005 *ts)
 +{
 +      if (--ts->disable_depth != 0)
 +              return;
 +
 +      enable_irq(ts->irq);
 +
 +      tsc2005_start_scan(ts);
 +}
 +
 +static ssize_t tsc2005_disable_show(struct device *dev,
 +                                  struct device_attribute *attr, char *buf)
 +{
 +      struct tsc2005 *ts = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%u\n", ts->disabled);
 +}
 +
 +static ssize_t tsc2005_disable_store(struct device *dev,
 +                                   struct device_attribute *attr,
 +                                   const char *buf, size_t count)
 +{
 +      struct tsc2005          *tsc = dev_get_drvdata(dev);
 +      unsigned long res;
 +      int i;
 +
 +      i = strict_strtoul(buf, 10, &res);
 +      i = i ? 1 : 0;
 +
 +      mutex_lock(&tsc->mutex);
 +      if (i == tsc->disabled)
 +              goto out;
 +      tsc->disabled = i;
 +
 +      if (i)
 +              tsc2005_disable(tsc);
 +      else
 +              tsc2005_enable(tsc);
 +out:
 +      mutex_unlock(&tsc->mutex);
 +      return count;
 +}
 +
 +static DEVICE_ATTR(disable_ts, 0664, tsc2005_disable_show,
 +                 tsc2005_disable_store);
 +
 +
 +static int __devinit tsc2005_ts_init(struct tsc2005 *ts,
 +                                   struct tsc2005_platform_data *pdata)
 +{
 +      struct input_dev *idev;
 +      int dav_gpio, r;
 +      int x_max, y_max;
 +      int x_fudge, y_fudge, p_fudge;
 +
 +      if (pdata->dav_gpio < 0) {
 +              dev_err(&ts->spi->dev, "need DAV GPIO");
 +              return -EINVAL;
 +      }
 +      dav_gpio = pdata->dav_gpio;
 +      ts->dav_gpio = dav_gpio;
 +      dev_dbg(&ts->spi->dev, "TSC2005: DAV GPIO = %d\n", dav_gpio);
 +
 +#ifdef CONFIG_ARCH_OMAP
 +      r = omap_request_gpio(dav_gpio);
 +      if (r < 0) {
 +              dev_err(&ts->spi->dev, "unable to get DAV GPIO");
 +              goto err1;
 +      }
 +      omap_set_gpio_direction(dav_gpio, 1);
 +      ts->irq = OMAP_GPIO_IRQ(dav_gpio);
 +      dev_dbg(&ts->spi->dev, "TSC2005: DAV IRQ = %d\n", ts->irq);
 +#endif
 +      init_timer(&ts->penup_timer);
 +      setup_timer(&ts->penup_timer, tsc2005_ts_penup_timer_handler,
 +                      (unsigned long)ts);
 +
 +      spin_lock_init(&ts->lock);
 +      mutex_init(&ts->mutex);
 +
 +      ts->x_plate_ohm         = pdata->ts_x_plate_ohm ? : 280;
 +      ts->hw_avg_max          = pdata->ts_hw_avg;
 +      ts->stab_time           = pdata->ts_stab_time;
 +      x_max                   = pdata->ts_x_max ? : 4096;
 +      x_fudge                 = pdata->ts_x_fudge ? : 4;
 +      y_max                   = pdata->ts_y_max ? : 4096;
 +      y_fudge                 = pdata->ts_y_fudge ? : 8;
 +      ts->p_max               = pdata->ts_pressure_max ? : MAX_12BIT;
 +      ts->touch_pressure      = pdata->ts_touch_pressure ? : ts->p_max;
 +      p_fudge                 = pdata->ts_pressure_fudge ? : 2;
 +
 +      idev = input_allocate_device();
 +      if (idev == NULL) {
 +              r = -ENOMEM;
 +              goto err2;
 +      }
 +
 +      idev->name = "TSC2005 touchscreen";
 +      snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts",
 +               ts->spi->dev.bus_id);
 +      idev->phys = ts->phys;
 +
 +      idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
 +      idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
 +      ts->idev = idev;
 +
 +      tsc2005_ts_setup_spi_xfer(ts);
 +
 +      input_set_abs_params(idev, ABS_X, 0, x_max, x_fudge, 0);
 +      input_set_abs_params(idev, ABS_Y, 0, y_max, y_fudge, 0);
 +      input_set_abs_params(idev, ABS_PRESSURE, 0, ts->p_max, p_fudge, 0);
 +
 +      tsc2005_start_scan(ts);
 +
 +      r = request_irq(ts->irq, tsc2005_ts_irq_handler,
 +                      IRQF_TRIGGER_FALLING | IRQF_DISABLED |
 +                      IRQF_SAMPLE_RANDOM, "tsc2005", ts);
 +      if (r < 0) {
 +              dev_err(&ts->spi->dev, "unable to get DAV IRQ");
 +              goto err3;
 +      }
 +
 +      set_irq_wake(ts->irq, 1);
 +
 +      r = input_register_device(idev);
 +      if (r < 0) {
 +              dev_err(&ts->spi->dev, "can't register touchscreen device\n");
 +              goto err4;
 +      }
 +
 +      /* We can tolerate these failing */
 +      if (device_create_file(&ts->spi->dev, &dev_attr_pen_down));
 +      if (device_create_file(&ts->spi->dev, &dev_attr_disable_ts));
 +
 +      return 0;
 +err4:
 +      free_irq(ts->irq, ts);
 +err3:
 +      tsc2005_stop_scan(ts);
 +      input_free_device(idev);
 +err2:
 +#ifdef CONFIG_ARCH_OMAP
 +      omap_free_gpio(dav_gpio);
 +#endif
 +err1:
 +      return r;
 +}
 +
 +static int __devinit tsc2005_probe(struct spi_device *spi)
 +{
 +      struct tsc2005                  *tsc;
 +      struct tsc2005_platform_data    *pdata = spi->dev.platform_data;
 +      int r;
 +
 +      if (!pdata) {
 +              dev_dbg(&spi->dev, "no platform data?\n");
 +              return -ENODEV;
 +      }
 +
 +      tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
 +      if (tsc == NULL)
 +              return -ENOMEM;
 +
 +      dev_set_drvdata(&spi->dev, tsc);
 +      tsc->spi = spi;
 +      spi->dev.power.power_state = PMSG_ON;
 +
 +      spi->mode = SPI_MODE_0;
 +      spi->bits_per_word = 8;
 +      /* The max speed might've been defined by the board-specific
 +       * struct */
 +      if (!spi->max_speed_hz)
 +              spi->max_speed_hz = TSC2005_HZ;
 +
 +      spi_setup(spi);
 +
 +      r = tsc2005_ts_init(tsc, pdata);
 +      if (r)
 +              goto err1;
 +
 +      return 0;
 +
 +err1:
 +      kfree(tsc);
 +      return r;
 +}
 +
 +static int __devexit tsc2005_remove(struct spi_device *spi)
 +{
 +      struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
 +
 +      mutex_lock(&ts->mutex);
 +      tsc2005_disable(ts);
 +      mutex_unlock(&ts->mutex);
 +
 +      device_remove_file(&ts->spi->dev, &dev_attr_disable_ts);
 +      device_remove_file(&ts->spi->dev, &dev_attr_pen_down);
 +
 +      free_irq(ts->irq, ts);
 +      input_unregister_device(ts->idev);
 +
 +#ifdef CONFIG_ARCH_OMAP
 +      omap_free_gpio(ts->dav_gpio);
 +#endif
 +      kfree(ts);
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg)
 +{
 +      struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
 +
 +      mutex_lock(&ts->mutex);
 +      tsc2005_disable(ts);
 +      mutex_unlock(&ts->mutex);
 +
 +      return 0;
 +}
 +
 +static int tsc2005_resume(struct spi_device *spi)
 +{
 +      struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
 +
 +      mutex_lock(&ts->mutex);
 +      tsc2005_enable(ts);
 +      mutex_unlock(&ts->mutex);
 +
 +      return 0;
 +}
 +#endif
 +
 +static struct spi_driver tsc2005_driver = {
 +      .driver = {
 +              .name = "tsc2005",
 +              .owner = THIS_MODULE,
 +      },
 +#ifdef CONFIG_PM
 +      .suspend = tsc2005_suspend,
 +      .resume = tsc2005_resume,
 +#endif
 +      .probe = tsc2005_probe,
 +      .remove = __devexit_p(tsc2005_remove),
 +};
 +
 +static int __init tsc2005_init(void)
 +{
 +      printk(KERN_INFO "TSC2005 driver initializing\n");
 +
 +      return spi_register_driver(&tsc2005_driver);
 +}
 +module_init(tsc2005_init);
 +
 +static void __exit tsc2005_exit(void)
 +{
 +      spi_unregister_driver(&tsc2005_driver);
 +}
 +module_exit(tsc2005_exit);
 +
 +MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS("platform:tsc2005");
index 1aecd4f1ac643ccaf2084bd8ed2372831a80efd0,0000000000000000000000000000000000000000..57eb38359f3310fa4cd3e89c5503f0bcaec06cf2
mode 100644,000000..100644
--- /dev/null
@@@ -1,376 -1,0 +1,376 @@@
- #include <asm/arch/board.h>
- #include <asm/arch/dmtimer.h>
 +/* drivers/leds/leds-omap_pwm.c
 + *
 + * Driver to blink LEDs using OMAP PWM timers
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Timo Teras
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 +*/
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/err.h>
 +#include <linux/platform_device.h>
 +#include <linux/leds.h>
 +#include <linux/ctype.h>
 +#include <linux/sched.h>
 +#include <asm/delay.h>
++#include <mach/board.h>
++#include <mach/dmtimer.h>
 +
 +struct omap_pwm_led {
 +      struct led_classdev cdev;
 +      struct work_struct work;
 +      struct omap_pwm_led_platform_data *pdata;
 +      struct omap_dm_timer *intensity_timer;
 +      struct omap_dm_timer *blink_timer;
 +      int powered;
 +      unsigned int on_period, off_period;
 +      enum led_brightness brightness;
 +};
 +
 +static inline struct omap_pwm_led *pdev_to_omap_pwm_led(struct platform_device *pdev)
 +{
 +      return platform_get_drvdata(pdev);
 +}
 +
 +static inline struct omap_pwm_led *cdev_to_omap_pwm_led(struct led_classdev *led_cdev)
 +{
 +      return container_of(led_cdev, struct omap_pwm_led, cdev);
 +}
 +
 +static inline struct omap_pwm_led *work_to_omap_pwm_led(struct work_struct *work)
 +{
 +      return container_of(work, struct omap_pwm_led, work);
 +}
 +
 +static void omap_pwm_led_set_blink(struct omap_pwm_led *led)
 +{
 +      if (!led->powered)
 +              return;
 +
 +      if (led->on_period != 0 && led->off_period != 0) {
 +              unsigned long load_reg, cmp_reg;
 +
 +              load_reg = 32768 * (led->on_period + led->off_period) / 1000;
 +              cmp_reg = 32768 * led->on_period / 1000;
 +
 +              omap_dm_timer_stop(led->blink_timer);
 +              omap_dm_timer_set_load(led->blink_timer, 1, -load_reg);
 +              omap_dm_timer_set_match(led->blink_timer, 1, -cmp_reg);
 +              omap_dm_timer_set_pwm(led->blink_timer, 1, 1,
 +                                    OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 +              omap_dm_timer_write_counter(led->blink_timer, -2);
 +              omap_dm_timer_start(led->blink_timer);
 +      } else {
 +              omap_dm_timer_set_pwm(led->blink_timer, 1, 1,
 +                                    OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 +              omap_dm_timer_stop(led->blink_timer);
 +      }
 +}
 +
 +static void omap_pwm_led_power_on(struct omap_pwm_led *led)
 +{
 +      if (led->powered)
 +              return;
 +      led->powered = 1;
 +
 +      /* Select clock */
 +      omap_dm_timer_enable(led->intensity_timer);
 +      omap_dm_timer_set_source(led->intensity_timer, OMAP_TIMER_SRC_32_KHZ);
 +
 +      /* Turn voltage on */
 +      if (led->pdata->set_power != NULL)
 +              led->pdata->set_power(led->pdata, 1);
 +
 +      /* Enable PWM timers */
 +      if (led->blink_timer != NULL) {
 +              omap_dm_timer_enable(led->blink_timer);
 +              omap_dm_timer_set_source(led->blink_timer,
 +                                       OMAP_TIMER_SRC_32_KHZ);
 +              omap_pwm_led_set_blink(led);
 +      }
 +
 +      omap_dm_timer_set_load(led->intensity_timer, 1, 0xffffff00);
 +}
 +
 +static void omap_pwm_led_power_off(struct omap_pwm_led *led)
 +{
 +      if (!led->powered)
 +              return;
 +      led->powered = 0;
 +
 +      /* Everything off */
 +      omap_dm_timer_stop(led->intensity_timer);
 +      omap_dm_timer_disable(led->intensity_timer);
 +
 +      if (led->blink_timer != NULL) {
 +              omap_dm_timer_stop(led->blink_timer);
 +              omap_dm_timer_disable(led->blink_timer);
 +      }
 +
 +      if (led->pdata->set_power != NULL)
 +              led->pdata->set_power(led->pdata, 0);
 +}
 +
 +static void omap_pwm_led_set_pwm_cycle(struct omap_pwm_led *led, int cycle)
 +{
 +      int n;
 +
 +      if (cycle == 0)
 +              n = 0xff;
 +      else    n = cycle - 1;
 +
 +      if (cycle == LED_FULL) {
 +              omap_dm_timer_set_pwm(led->intensity_timer, 1, 1,
 +                                    OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 +              omap_dm_timer_stop(led->intensity_timer);
 +      } else {
 +              omap_dm_timer_set_pwm(led->intensity_timer, 0, 1,
 +                                    OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 +              omap_dm_timer_set_match(led->intensity_timer, 1,
 +                                      (0xffffff00) | cycle);
 +              omap_dm_timer_start(led->intensity_timer);
 +      }
 +}
 +
 +static void omap_pwm_led_set(struct led_classdev *led_cdev,
 +                           enum led_brightness value)
 +{
 +      struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
 +
 +      led->brightness = value;
 +      schedule_work(&led->work);
 +}
 +
 +static void omap_pwm_led_work(struct work_struct *work)
 +{
 +      struct omap_pwm_led *led = work_to_omap_pwm_led(work);
 +
 +      if (led->brightness != LED_OFF) {
 +              omap_pwm_led_power_on(led);
 +              omap_pwm_led_set_pwm_cycle(led, led->brightness);
 +      } else {
 +              omap_pwm_led_power_off(led);
 +      }
 +}
 +
 +static ssize_t omap_pwm_led_on_period_show(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      struct led_classdev *led_cdev = dev_get_drvdata(dev);
 +      struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
 +
 +      return sprintf(buf, "%u\n", led->on_period) + 1;
 +}
 +
 +static ssize_t omap_pwm_led_on_period_store(struct device *dev,
 +                              struct device_attribute *attr,
 +                              const char *buf, size_t size)
 +{
 +      struct led_classdev *led_cdev = dev_get_drvdata(dev);
 +      struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
 +      int ret = -EINVAL;
 +      unsigned long val;
 +      char *after;
 +      size_t count;
 +
 +      val = simple_strtoul(buf, &after, 10);
 +      count = after - buf;
 +      if (*after && isspace(*after))
 +              count++;
 +
 +      if (count == size) {
 +              led->on_period = val;
 +              omap_pwm_led_set_blink(led);
 +              ret = count;
 +      }
 +
 +      return ret;
 +}
 +
 +static ssize_t omap_pwm_led_off_period_show(struct device *dev,
 +                              struct device_attribute *attr, char *buf)
 +{
 +      struct led_classdev *led_cdev = dev_get_drvdata(dev);
 +      struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
 +
 +      return sprintf(buf, "%u\n", led->off_period) + 1;
 +}
 +
 +static ssize_t omap_pwm_led_off_period_store(struct device *dev,
 +                                      struct device_attribute *attr,
 +                                      const char *buf, size_t size)
 +{
 +      struct led_classdev *led_cdev = dev_get_drvdata(dev);
 +      struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
 +      int ret = -EINVAL;
 +      unsigned long val;
 +      char *after;
 +      size_t count;
 +
 +      val = simple_strtoul(buf, &after, 10);
 +      count = after - buf;
 +      if (*after && isspace(*after))
 +              count++;
 +
 +      if (count == size) {
 +              led->off_period = val;
 +              omap_pwm_led_set_blink(led);
 +              ret = count;
 +      }
 +
 +      return ret;
 +}
 +
 +static DEVICE_ATTR(on_period, 0644, omap_pwm_led_on_period_show,
 +                              omap_pwm_led_on_period_store);
 +static DEVICE_ATTR(off_period, 0644, omap_pwm_led_off_period_show,
 +                              omap_pwm_led_off_period_store);
 +
 +static int omap_pwm_led_probe(struct platform_device *pdev)
 +{
 +      struct omap_pwm_led_platform_data *pdata = pdev->dev.platform_data;
 +      struct omap_pwm_led *led;
 +      int ret;
 +
 +      led = kzalloc(sizeof(struct omap_pwm_led), GFP_KERNEL);
 +      if (led == NULL) {
 +              dev_err(&pdev->dev, "No memory for device\n");
 +              return -ENOMEM;
 +      }
 +
 +      platform_set_drvdata(pdev, led);
 +      led->cdev.brightness_set = omap_pwm_led_set;
 +      led->cdev.default_trigger = NULL;
 +      led->cdev.name = pdata->name;
 +      led->pdata = pdata;
 +      led->brightness = LED_OFF;
 +      INIT_WORK(&led->work, omap_pwm_led_work);
 +
 +      dev_info(&pdev->dev, "OMAP PWM LED (%s) at GP timer %d/%d\n",
 +               pdata->name, pdata->intensity_timer, pdata->blink_timer);
 +
 +      /* register our new led device */
 +      ret = led_classdev_register(&pdev->dev, &led->cdev);
 +      if (ret < 0) {
 +              dev_err(&pdev->dev, "led_classdev_register failed\n");
 +              goto error_classdev;
 +      }
 +
 +      /* get related dm timers */
 +      led->intensity_timer = omap_dm_timer_request_specific(pdata->intensity_timer);
 +      if (led->intensity_timer == NULL) {
 +              dev_err(&pdev->dev, "failed to request intensity pwm timer\n");
 +              ret = -ENODEV;
 +              goto error_intensity;
 +      }
 +      omap_dm_timer_disable(led->intensity_timer);
 +
 +      if (pdata->blink_timer != 0) {
 +              led->blink_timer = omap_dm_timer_request_specific(pdata->blink_timer);
 +              if (led->blink_timer == NULL) {
 +                      dev_err(&pdev->dev, "failed to request blinking pwm timer\n");
 +                      ret = -ENODEV;
 +                      goto error_blink1;
 +              }
 +              omap_dm_timer_disable(led->blink_timer);
 +
 +              ret = device_create_file(led->cdev.dev,
 +                                             &dev_attr_on_period);
 +              if(ret)
 +                      goto error_blink2;
 +
 +              ret = device_create_file(led->cdev.dev,
 +                                      &dev_attr_off_period);
 +              if(ret)
 +                      goto error_blink3;
 +
 +      }
 +
 +      return 0;
 +
 +error_blink3:
 +      device_remove_file(led->cdev.dev,
 +                               &dev_attr_on_period);
 +error_blink2:
 +      dev_err(&pdev->dev, "failed to create device file(s)\n");
 +error_blink1:
 +      omap_dm_timer_free(led->intensity_timer);
 +error_intensity:
 +      led_classdev_unregister(&led->cdev);
 +error_classdev:
 +      kfree(led);
 +      return ret;
 +}
 +
 +static int omap_pwm_led_remove(struct platform_device *pdev)
 +{
 +      struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
 +
 +      device_remove_file(led->cdev.dev,
 +                               &dev_attr_on_period);
 +      device_remove_file(led->cdev.dev,
 +                               &dev_attr_off_period);
 +      led_classdev_unregister(&led->cdev);
 +
 +      omap_pwm_led_set(&led->cdev, LED_OFF);
 +      if (led->blink_timer != NULL)
 +              omap_dm_timer_free(led->blink_timer);
 +      omap_dm_timer_free(led->intensity_timer);
 +      kfree(led);
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int omap_pwm_led_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
 +
 +      led_classdev_suspend(&led->cdev);
 +      return 0;
 +}
 +
 +static int omap_pwm_led_resume(struct platform_device *pdev)
 +{
 +      struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
 +
 +      led_classdev_resume(&led->cdev);
 +      return 0;
 +}
 +#else
 +#define omap_pwm_led_suspend NULL
 +#define omap_pwm_led_resume NULL
 +#endif
 +
 +static struct platform_driver omap_pwm_led_driver = {
 +      .probe          = omap_pwm_led_probe,
 +      .remove         = omap_pwm_led_remove,
 +      .suspend        = omap_pwm_led_suspend,
 +      .resume         = omap_pwm_led_resume,
 +      .driver         = {
 +              .name           = "omap_pwm_led",
 +              .owner          = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_pwm_led_init(void)
 +{
 +      return platform_driver_register(&omap_pwm_led_driver);
 +}
 +
 +static void __exit omap_pwm_led_exit(void)
 +{
 +      platform_driver_unregister(&omap_pwm_led_driver);
 +}
 +
 +module_init(omap_pwm_led_init);
 +module_exit(omap_pwm_led_exit);
 +
 +MODULE_AUTHOR("Timo Teras");
 +MODULE_DESCRIPTION("OMAP PWM LED driver");
 +MODULE_LICENSE("GPL");
index 040b7e41d847116400b11d72fd973665905ae5ec,0000000000000000000000000000000000000000..5c14c4b5275250bab543fea2d1d6f000b0038fa5
mode 100644,000000..100644
--- /dev/null
@@@ -1,135 -1,0 +1,135 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/led.h>
 +/* drivers/leds/leds-omap.c
 + *
 + * (C) 2006 Samsung Electronics
 + * Kyungmin Park <kyungmin.park@samsung.com>
 + *
 + * OMAP - LEDs GPIO driver
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 +*/
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/leds.h>
 +
++#include <mach/gpio.h>
++#include <mach/hardware.h>
++#include <mach/led.h>
 +
 +/* our context */
 +
 +static void omap_set_led_gpio(struct led_classdev *led_cdev,
 +                          enum led_brightness value)
 +{
 +      struct omap_led_config *led_dev;
 +
 +      led_dev = container_of(led_cdev, struct omap_led_config, cdev);
 +
 +      if (value)
 +              omap_set_gpio_dataout(led_dev->gpio, 1);
 +      else
 +              omap_set_gpio_dataout(led_dev->gpio, 0);
 +}
 +
 +static void omap_configure_led_gpio(int gpio)
 +{
 +      if (omap_request_gpio(gpio) < 0) {
 +              printk(KERN_ERR "Failed to request GPIO%d for LEDs\n", gpio);
 +              return;
 +      }
 +      omap_set_gpio_direction(gpio, 0);       /* OUT */
 +}
 +
 +static int omap_led_probe(struct platform_device *dev)
 +{
 +      struct omap_led_platform_data *pdata = dev->dev.platform_data;
 +      struct omap_led_config *leds = pdata->leds;
 +      int i, ret = 0;
 +
 +      for (i = 0; ret >= 0 && i < pdata->nr_leds; i++) {
 +              omap_configure_led_gpio(leds[i].gpio);
 +              if (!leds[i].cdev.brightness_set)
 +                      leds[i].cdev.brightness_set = omap_set_led_gpio;
 +
 +              ret = led_classdev_register(&dev->dev, &leds[i].cdev);
 +      }
 +
 +      if (ret < 0 && i > 1) {
 +              for (i = i - 2; i >= 0; i--)
 +                      led_classdev_unregister(&leds[i].cdev);
 +      }
 +
 +      return ret;
 +}
 +
 +static int omap_led_remove(struct platform_device *dev)
 +{
 +      struct omap_led_platform_data *pdata = dev->dev.platform_data;
 +      struct omap_led_config *leds = pdata->leds;
 +      int i;
 +
 +      for (i = 0; i < pdata->nr_leds; i++)
 +              led_classdev_unregister(&leds[i].cdev);
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int omap_led_suspend(struct platform_device *dev, pm_message_t state)
 +{
 +      struct omap_led_platform_data *pdata = dev->dev.platform_data;
 +      struct omap_led_config *leds = pdata->leds;
 +      int i;
 +
 +      for (i = 0; i < pdata->nr_leds; i++)
 +              led_classdev_suspend(&leds[i].cdev);
 +
 +      return 0;
 +}
 +
 +static int omap_led_resume(struct platform_device *dev)
 +{
 +      struct omap_led_platform_data *pdata = dev->dev.platform_data;
 +      struct omap_led_config *leds = pdata->leds;
 +      int i;
 +
 +      for (i = 0; i < pdata->nr_leds; i++)
 +              led_classdev_resume(&leds[i].cdev);
 +
 +      return 0;
 +}
 +#else
 +#define omap_led_suspend      NULL
 +#define omap_led_resume               NULL
 +#endif
 +
 +static struct platform_driver omap_led_driver = {
 +      .probe          = omap_led_probe,
 +      .remove         = omap_led_remove,
 +      .suspend        = omap_led_suspend,
 +      .resume         = omap_led_resume,
 +      .driver         = {
 +              .name           = "omap-led",
 +              .owner          = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_led_init(void)
 +{
 +      return platform_driver_register(&omap_led_driver);
 +}
 +
 +static void __exit omap_led_exit(void)
 +{
 +      platform_driver_unregister(&omap_led_driver);
 +}
 +
 +module_init(omap_led_init);
 +module_exit(omap_led_exit);
 +
 +MODULE_AUTHOR("Kyungmin Park<kyungmin.park@samsung.com>");
 +MODULE_DESCRIPTION("OMAP LED driver");
 +MODULE_LICENSE("GPL");
Simple merge
index 82c006b4c0264dc300080ac388c43387b9e89f38,0000000000000000000000000000000000000000..1615fb7ecebf57d27615340ae14d8133a37bccc9
mode 100644,000000..100644
--- /dev/null
@@@ -1,579 -1,0 +1,579 @@@
- #include <asm/arch/irqs.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/hardware.h>
 +/*
 + * drivers/media/video/omap/omap16xxcam.c
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Video-for-Linux (Version 2) camera capture driver for
 + * the OMAP H2 and H3 camera controller.
 + *
 + * leverage some code from CEE distribution
 + * Copyright (C) 2003-2004 MontaVista Software, Inc.
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + */
 +
 +#include <linux/vmalloc.h>
 +#include <linux/slab.h>
 +#include <linux/proc_fs.h>
 +#include <linux/ctype.h>
 +#include <linux/delay.h>
 +#include <linux/device.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/interrupt.h>
 +#include <linux/clk.h>
 +
++#include <mach/irqs.h>
++#include <mach/dma.h>
++#include <mach/hardware.h>
 +#include <asm/io.h>
 +#include <asm/scatterlist.h>
 +#include <asm/mach-types.h>
 +
 +#include "omap16xxcam.h"
 +#include "camera_hw_if.h"
 +#include "camera_core.h"
 +
 +#define CONF_CAMERAIF_RESET_R 5
 +#define EN_PER          0
 +
 +/* NUM_CAMDMA_CHANNELS is the number of logical channels used for
 + * DMA data transfer.
 + */
 +#define NUM_CAMDMA_CHANNELS 2
 +
 +typedef struct {
 +      unsigned int ctrlclock;         /* 00 */
 +      unsigned int it_status;         /* 04 */
 +      unsigned int mode;              /* 08 */
 +      unsigned int status;            /* 0C */
 +      unsigned int camdata;           /* 10 */
 +      unsigned int gpio;              /* 14 */
 +      unsigned int peak_counter;      /* 18 */
 +} camera_regs_t;
 +
 +struct camdma_state {
 +      dma_callback_t callback;
 +      void *arg1;
 +      void *arg2;
 +};
 +
 +struct omap16xxcam {
 +      camera_regs_t *camera_regs;
 +      unsigned long iobase_phys;
 +
 +      /* Frequency (in Hz) of camera interface functional clock (ocp_clk) */
 +      unsigned long ocp_clk;
 +
 +      struct clk *func_clk;
 +
 +      /* DMA related stuff */
 +      spinlock_t dma_lock;
 +      int free_dmach;
 +      int next_dmach;
 +      struct camdma_state camdma[NUM_CAMDMA_CHANNELS];
 +      int dma_channel_number1;
 +      int dma_channel_number2;
 +
 +      wait_queue_head_t vsync_wait;
 +
 +      int new;
 +};
 +static struct omap16xxcam hardware_data;
 +
 +static int omap16xxcam_set_xclk(int, void *);
 +static void omap16xx_cam_dma_link_callback(int, unsigned short, void *);
 +
 +/* Clears the camera data FIFO by setting RAZ_FIFO bit in MODE configuration
 + * register.
 + */
 +static void omap16xx_cam_clear_fifo(struct omap16xxcam *data)
 +{
 +      data->camera_regs->mode |= RAZ_FIFO;
 +      udelay(10);
 +      data->camera_regs->mode &= ~RAZ_FIFO;
 +}
 +
 +static void omap16xx_cam_reset(struct omap16xxcam *data, int yes)
 +{
 +      if (machine_is_omap_h3())
 +              data->camera_regs->gpio = yes ? 0 : 1;
 +      else
 +              data->camera_regs->gpio = yes ? 1 : 0;
 +}
 +
 +static void omap16xx_cam_init(void)
 +{
 +      /*
 +       * FIXME - Use mux API's instead of directly writing in to MUX registers
 +       */
 +      omap_writel(omap_readl(FUNC_MUX_CTRL_4) & ~(0x1ff << 21),
 +                  FUNC_MUX_CTRL_4);
 +      omap_writel(0, FUNC_MUX_CTRL_5);
 +      omap_writel(omap_readl(PULL_DWN_CTRL_0) & ~(0x1FFF << 17),
 +                  PULL_DWN_CTRL_0);
 +      omap_writel(omap_readl(PU_PD_SEL_0) & ~(0x1FFF << 17), PU_PD_SEL_0);
 +
 +      omap_writel(0xeaef, COMP_MODE_CTRL_0);
 +      omap_writel(omap_readl(OMAP1610_RESET_CONTROL) &
 +                  ~(1 << CONF_CAMERAIF_RESET_R), OMAP1610_RESET_CONTROL);
 +      omap_writel(omap_readl(OMAP1610_RESET_CONTROL) |
 +                  (1 << CONF_CAMERAIF_RESET_R), OMAP1610_RESET_CONTROL);
 +
 +      /* Enable peripheral reset */
 +      omap_writew(omap_readw(ARM_RSTCT2) | (1 << EN_PER), ARM_RSTCT2);
 +
 +      /* Enable peripheral clock */
 +      clk_enable(hardware_data.func_clk);
 +}
 +
 +static void omap16xx_cam_waitfor_syncedge(struct omap16xxcam *data,
 +                                        u32 edge_mask)
 +{
 +      data->camera_regs->mode =
 +          (FIFO_TRIGGER_LVL << THRESHOLD_BIT) | edge_mask;
 +      do {
 +              interruptible_sleep_on(&data->vsync_wait);
 +      } while (signal_pending(current));
 +}
 +
 +static void omap16xx_cam_configure_dma(struct omap16xxcam *data)
 +{
 +
 +      data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT)
 +          | EN_DMA | EN_FIFO_FULL;
 +      data->camera_regs->ctrlclock |= LCLK_EN;
 +}
 +
 +/* Acquire h/w resources DMA */
 +static int omap16xx_cam_link_open(struct omap16xxcam *data)
 +{
 +      int ret;
 +
 +      /* Acquire first DMA channel */
 +      ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX,
 +                             "camera dma 1",
 +                             omap16xx_cam_dma_link_callback,
 +                             (void *)data, &data->dma_channel_number1);
 +      if (ret)
 +              return ret;
 +
 +      /* Acquire second DMA channel */
 +      ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX,
 +                             "camera dma 2",
 +                             omap16xx_cam_dma_link_callback,
 +                             (void *)data, &data->dma_channel_number2);
 +      if (ret) {
 +              printk(KERN_ERR "No DMA available for camera\n");
 +              return ret;
 +      }
 +      data->next_dmach = data->dma_channel_number1;
 +      OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number1) =
 +          data->dma_channel_number2;
 +      OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number2) =
 +          data->dma_channel_number1;
 +
 +      return 0;
 +}
 +
 +/* Free h/w resources, stop i/f */
 +static int omap16xx_cam_link_close(struct omap16xxcam *data)
 +{
 +      /* Free DMA channels */
 +      omap_stop_dma(data->dma_channel_number1);
 +      omap_stop_dma(data->dma_channel_number2);
 +
 +      omap_free_dma(data->dma_channel_number1);
 +      omap_free_dma(data->dma_channel_number2);
 +
 +      return 0;
 +}
 +
 +/* DMA callback routine. */
 +static void omap16xx_cam_dma_link_callback(int lch, unsigned short ch_status,
 +                                         void *data)
 +{
 +      int count;
 +      void *arg1, *arg2;
 +      struct sgdma_state *sgdma = sgdma;
 +      struct omap16xxcam *cam = (struct omap16xxcam *)data;
 +      dma_callback_t callback;
 +
 +      spin_lock(&cam->dma_lock);
 +      if (cam->free_dmach == 2) {
 +              printk(KERN_ERR "callback all CHANNELS WERE IDLE \n");
 +              spin_unlock(&cam->dma_lock);
 +              return;
 +      }
 +      if (cam->free_dmach == 0) {
 +              lch = cam->next_dmach;
 +      } else {
 +              lch = cam->next_dmach == cam->dma_channel_number1 ?
 +                  cam->dma_channel_number2 : cam->dma_channel_number1;
 +      }
 +
 +      while (cam->free_dmach < 2) {
 +              if (OMAP_DMA_CCR_REG(lch) & (1 << 7))
 +                      break;
 +
 +              count = (lch == cam->dma_channel_number2) ? 1 : 0;
 +
 +              callback = cam->camdma[count].callback;
 +              arg1 = cam->camdma[count].arg1;
 +              arg2 = cam->camdma[count].arg2;
 +              cam->free_dmach++;
 +
 +              spin_unlock(&cam->dma_lock);
 +              callback(arg1, arg2);
 +              spin_lock(&cam->dma_lock);
 +
 +              lch =
 +                  (lch ==
 +                   cam->dma_channel_number2) ? cam->
 +                  dma_channel_number1 : cam->dma_channel_number2;
 +      }
 +      spin_unlock(&cam->dma_lock);
 +
 +}
 +
 +static irqreturn_t omap16xx_cam_isr(int irq, void *client_data)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)client_data;
 +      unsigned int itstat = data->camera_regs->it_status;
 +
 +      /* VSYNC UP interrupt, start filling FIFO and enabling DMA */
 +      if (itstat & V_UP) {
 +              data->camera_regs->mode &= ~EN_V_UP;
 +              omap16xx_cam_clear_fifo(data);
 +              omap16xx_cam_configure_dma(data);
 +              omap_start_dma(data->next_dmach);
 +              wake_up_interruptible(&data->vsync_wait);
 +      }
 +
 +      if (itstat & V_DOWN) {
 +              data->camera_regs->mode &= ~EN_V_DOWN;
 +              wake_up_interruptible(&data->vsync_wait);
 +      }
 +
 +      if (itstat & H_UP)
 +              printk(KERN_INFO "H_UP\n");
 +
 +      if (itstat & H_DOWN)
 +              printk(KERN_INFO "H_DOWN\n");
 +
 +      if (itstat & FIFO_FULL) {
 +              omap16xx_cam_clear_fifo(data);
 +              printk(KERN_INFO "FIFO_FULL\n");
 +      }
 +
 +      if (itstat & DATA_XFER)
 +              printk(KERN_INFO "DATA_TRANS\n");
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/* ------------- Below are interface functions -----------------
 + * ------------- These functions are named omap16xxcam_<name> --
 + */
 +static int omap16xxcam_init_dma(void *priv)
 +{
 +      int ch;
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      data->free_dmach = 2;
 +      for (ch = 0; ch < 2; ++ch) {
 +              data->camdma[ch].callback = NULL;
 +              data->camdma[ch].arg1 = NULL;
 +              data->camdma[ch].arg2 = NULL;
 +      }
 +
 +      return 0;
 +}
 +
 +/* Start the DMA of chains */
 +static int omap16xxcam_start_dma(struct sgdma_state *sgdma,
 +                               dma_callback_t callback, void *arg1,
 +                               void *arg2, void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +      struct scatterlist *sglist;
 +      unsigned long irqflags;
 +      int dmach;
 +      int prev_dmach;
 +      int count;
 +
 +      spin_lock_irqsave(&data->dma_lock, irqflags);
 +      sglist = (struct scatterlist *)(sgdma->sglist + sgdma->next_sglist);
 +
 +      if (!data->free_dmach) {
 +              spin_unlock_irqrestore(&data->dma_lock, irqflags);
 +              return -EBUSY;
 +      }
 +      dmach = data->next_dmach;
 +      count = (dmach == data->dma_channel_number2) ? 1 : 0;
 +      data->camdma[count].callback = callback;
 +      data->camdma[count].arg1 = arg1;
 +      data->camdma[count].arg2 = arg2;
 +
 +      if (cpu_is_omap1710())
 +              omap_set_dma_src_params(dmach, OMAP_DMA_PORT_OCP_T1,
 +                                      OMAP_DMA_AMODE_CONSTANT,
 +                                      CAM_CAMDATA_REG, 0, 0);
 +      else
 +              omap_set_dma_src_params(dmach, OMAP_DMA_PORT_TIPB,
 +                                      OMAP_DMA_AMODE_CONSTANT,
 +                                      CAM_CAMDATA_REG, 0, 0);
 +
 +      omap_set_dma_dest_params(dmach, OMAP_DMA_PORT_EMIFF,
 +                               OMAP_DMA_AMODE_POST_INC,
 +                               sg_dma_address(sglist), 0, 0);
 +
 +      omap_set_dma_transfer_params(dmach, OMAP_DMA_DATA_TYPE_S32,
 +                                   FIFO_TRIGGER_LVL,
 +                                   sg_dma_len(sglist) / (4 *
 +                                                         FIFO_TRIGGER_LVL),
 +                                   OMAP_DMA_SYNC_FRAME, 0, 0);
 +
 +      OMAP_DMA_CLNK_CTRL_REG(dmach) &= ~(1 << 15);
 +
 +      prev_dmach = (dmach == data->dma_channel_number2) ?
 +          data->dma_channel_number1 : data->dma_channel_number2;
 +
 +      if (data->new) {
 +              data->new = 0;
 +              omap16xx_cam_waitfor_syncedge(data, EN_V_UP);
 +      } else {
 +              if (OMAP_DMA_CCR_REG(prev_dmach) & (1 << 7))
 +                      OMAP_DMA_CLNK_CTRL_REG(prev_dmach) |= (1 << 15);
 +              else {
 +                      /* No transfer is in progress */
 +                      omap_start_dma(dmach);
 +              }
 +      }
 +
 +      data->next_dmach = prev_dmach;
 +      data->free_dmach--;
 +      spin_unlock_irqrestore(&data->dma_lock, irqflags);
 +      return 0;
 +}
 +
 +int static omap16xxcam_finish_dma(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      while (data->free_dmach < 2)
 +              mdelay(1);
 +
 +      return 0;
 +}
 +
 +/* Enables the camera. Takes camera out of reset. Enables the clocks. */
 +static int omap16xxcam_enable(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      omap16xx_cam_reset(data, 1);
 +
 +      /* Give clock to camera_module */
 +      data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT);
 +      data->camera_regs->ctrlclock = MCLK_EN | CAMEXCLK_EN;
 +
 +      omap16xx_cam_clear_fifo(data);
 +
 +      /* Wait for camera to settle down */
 +      mdelay(5);
 +
 +      return 0;
 +}
 +
 +/* Disables all the camera clocks. Put the camera interface in reset. */
 +static int omap16xxcam_disable(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      omap16xx_cam_clear_fifo(data);
 +
 +      data->camera_regs->ctrlclock = 0x00000000;
 +      data->camera_regs->mode = 0x00000000;
 +
 +      omap16xx_cam_reset(data, 0);
 +
 +      return 0;
 +}
 +
 +/* Abort the data transfer */
 +static int omap16xxcam_abort(void *priv)
 +{
 +      return omap16xxcam_disable(priv);
 +}
 +
 +static int omap16xxcam_set_xclk(int xclk, void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +      int xclk_val;
 +      int divisor = 1;
 +      divisor = data->ocp_clk / xclk;
 +      if (divisor * xclk < data->ocp_clk)
 +              ++divisor;
 +
 +      switch (divisor) {
 +      case 1:
 +      case 2:
 +              xclk_val = FOSCMOD_TC2_CK2;
 +              break;
 +      case 3:
 +              xclk_val = FOSCMOD_TC2_CK3;
 +              break;
 +      case 4:
 +      case 5:
 +      case 6:
 +      case 7:
 +              xclk_val = FOSCMOD_TC2_CK4;
 +              break;
 +      case 8:
 +      case 9:
 +              xclk_val = FOSCMOD_TC2_CK8;
 +              break;
 +      case 10:
 +      case 11:
 +              xclk_val = FOSCMOD_TC2_CK10;
 +              break;
 +      case 12:
 +      case 13:
 +      case 14:
 +      case 15:
 +              xclk_val = FOSCMOD_TC2_CK12;
 +              break;
 +      case 16:
 +              xclk_val = FOSCMOD_TC2_CK16;
 +              break;
 +      default:
 +              xclk_val = FOSCMOD_TC2_CK16;
 +      }
 +
 +      /* Follow the protocol to change the XCLK clock */
 +      data->camera_regs->ctrlclock &= ~CAMEXCLK_EN;
 +      data->camera_regs->ctrlclock |= xclk_val;
 +      data->camera_regs->ctrlclock |= CAMEXCLK_EN;
 +
 +      return (data->ocp_clk / divisor);
 +}
 +
 +static int omap16xxcam_open(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +      int ret;
 +
 +      ret = request_irq(INT_CAMERA, omap16xx_cam_isr, IRQF_DISABLED,
 +                        "camera", data);
 +      if (ret) {
 +              printk(KERN_ERR "FAILED to acquire IRQ\n");
 +              return ret;
 +      }
 +
 +      data->new = 1;
 +      omap16xxcam_enable(data);
 +      omap16xxcam_init_dma(data);
 +
 +      return omap16xx_cam_link_open(data);
 +}
 +
 +static int omap16xxcam_close(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      omap16xxcam_disable(priv);
 +
 +      free_irq(INT_CAMERA, data);
 +
 +      return omap16xx_cam_link_close(data);
 +}
 +
 +static int omap16xxcam_cleanup(void *priv)
 +{
 +      struct omap16xxcam *data = (struct omap16xxcam *)priv;
 +
 +      if (!data->camera_regs)
 +              return -EINVAL;
 +
 +      omap16xxcam_disable(data);
 +      if (cpu_is_omap1710())
 +              iounmap((void *)data->camera_regs);
 +      data->camera_regs = NULL;
 +
 +      if (data->iobase_phys) {
 +              release_mem_region(data->iobase_phys, CAMERA_IOSIZE);
 +              data->iobase_phys = 0;
 +      }
 +
 +      if (hardware_data.func_clk) {
 +              clk_disable(hardware_data.func_clk);
 +              clk_put(hardware_data.func_clk);
 +              hardware_data.func_clk = NULL;
 +      }
 +
 +      return 0;
 +}
 +
 +/* Initialize the OMAP camera interface */
 +static void *omap16xxcam_init(void)
 +{
 +      unsigned long cam_iobase;
 +
 +      if (!request_mem_region(CAMERA_BASE, CAMERA_IOSIZE,
 +                              camera_hardware_if.name)) {
 +              pr_debug("%s is already in use\n", camera_hardware_if.name);
 +              return NULL;
 +      }
 +
 +      if (cpu_is_omap1710()) {
 +              cam_iobase = (unsigned long)ioremap(CAMERA_BASE, CAMERA_IOSIZE);
 +              if (!cam_iobase) {
 +                      printk(KERN_ERR "CANNOT MAP CAMERA REGISTER\n");
 +                      return NULL;
 +              }
 +      } else
 +              cam_iobase = io_p2v(CAMERA_BASE);
 +
 +      /* Set the base address of the camera registers */
 +      hardware_data.camera_regs = (camera_regs_t *) cam_iobase;
 +      hardware_data.iobase_phys = (unsigned long)CAMERA_BASE;
 +
 +      /* Get the input clock value to camera interface and store it */
 +      if (cpu_is_omap1710())
 +              hardware_data.func_clk = clk_get(0, "tc2_ck");
 +      else
 +              hardware_data.func_clk = clk_get(0, "armper_ck");
 +      hardware_data.ocp_clk = clk_get_rate(hardware_data.func_clk);
 +
 +      /* Initialize the camera IF */
 +      omap16xx_cam_init();
 +      /* Enable it. This is needed for sensor detection */
 +      omap16xxcam_enable((void *)&hardware_data);
 +      /* Initialize DMA data */
 +      spin_lock_init(&hardware_data.dma_lock);
 +
 +      init_waitqueue_head(&hardware_data.vsync_wait);
 +      return (void *)&hardware_data;
 +}
 +
 +struct camera_hardware camera_hardware_if = {
 +      .version        = 0x01,
 +      .name           = "OMAP16xx Parallel Camera",
 +      .init           = omap16xxcam_init,
 +      .cleanup        = omap16xxcam_cleanup,
 +      .open           = omap16xxcam_open,
 +      .close          = omap16xxcam_close,
 +      .enable         = omap16xxcam_enable,
 +      .disable        = omap16xxcam_disable,
 +      .abort          = omap16xxcam_abort,
 +      .set_xclk       = omap16xxcam_set_xclk,
 +      .init_dma       = omap16xxcam_init_dma,
 +      .start_dma      = omap16xxcam_start_dma,
 +      .finish_dma     = omap16xxcam_finish_dma,
 +};
Simple merge
index e12fb120bbac4867c17756fd82fe64c6fe927661,0000000000000000000000000000000000000000..c35821d5b4dd75780b8b75bff155f2216fed1642
mode 100644,000000..100644
--- /dev/null
@@@ -1,185 -1,0 +1,185 @@@
- #include <asm/arch/sti.h>
 +/*
 + * Support functions for OMAP3 SDTI (Serial Debug Tracing Interface)
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + * Written by: Roman Tereshonkov <roman.tereshonkov@nokia.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/init.h>
 +#include <linux/err.h>
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/spinlock.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
++#include <mach/sti.h>
 +#include <asm/byteorder.h>
 +#include <asm/io.h>
 +
 +#define SDTI_REVISION         0x000
 +#define SDTI_SYSCONFIG                0x010
 +#define SDTI_SYSSTATUS                0x014
 +#define SDTI_WINCTRL          0x024
 +#define SDTI_SCONFIG          0x028
 +#define SDTI_TESTCTRL         0x02C
 +#define SDTI_LOCK_ACCESS      0xFB0
 +
 +#define CPU1_TRACE_EN         0x01
 +#define CPU2_TRACE_EN         0x02
 +
 +static struct clk *sdti_ck;
 +unsigned long sti_base, sti_channel_base;
 +static DEFINE_SPINLOCK(sdti_lock);
 +
 +void omap_sti_channel_write_trace(int len, int id, void *data,
 +                              unsigned int channel)
 +{
 +      const u8 *tpntr = data;
 +
 +      spin_lock_irq(&sdti_lock);
 +
 +      sti_channel_writeb(id, channel);
 +      while (len--)
 +              sti_channel_writeb(*tpntr++, channel);
 +      sti_channel_flush(channel);
 +
 +      spin_unlock_irq(&sdti_lock);
 +}
 +EXPORT_SYMBOL(omap_sti_channel_write_trace);
 +
 +static void omap_sdti_reset(void)
 +{
 +      int i;
 +
 +      sti_writel(0x02, SDTI_SYSCONFIG);
 +
 +      for (i = 0; i < 10000; i++)
 +              if (sti_readl(SDTI_SYSSTATUS) & 1)
 +                      break;
 +      if (i == 10000)
 +              printk(KERN_WARNING "XTI: no real reset\n");
 +}
 +
 +static int __init omap_sdti_init(void)
 +{
 +      char buf[64];
 +      int i;
 +
 +      sdti_ck = clk_get(NULL, "emu_per_alwon_ck");
 +      if (IS_ERR(sdti_ck)) {
 +              printk(KERN_ERR "Cannot get clk emu_per_alwon_ck\n");
 +              return PTR_ERR(sdti_ck);
 +      }
 +      clk_enable(sdti_ck);
 +
 +      omap_sdti_reset();
 +      sti_writel(0xC5ACCE55, SDTI_LOCK_ACCESS);
 +
 +      /* Claim SDTI */
 +      sti_writel(1 << 30, SDTI_WINCTRL);
 +      i = sti_readl(SDTI_WINCTRL);
 +      if (!(i & (1 << 30)))
 +              printk(KERN_WARNING "SDTI: cannot claim SDTI\n");
 +
 +      /* 4 bits dual, fclk/3 */
 +      sti_writel(0x43, SDTI_SCONFIG);
 +
 +      /* CPU2 trace enable */
 +      sti_writel(i | CPU2_TRACE_EN, SDTI_WINCTRL);
 +      i = sti_readl(SDTI_WINCTRL);
 +
 +      /* Enable SDTI */
 +      sti_writel((1 << 31) | (i & 0x3FFFFFFF), SDTI_WINCTRL);
 +
 +      i = sti_readl(SDTI_REVISION);
 +      snprintf(buf, sizeof(buf), "OMAP SDTI support loaded (HW v%u.%u)\n",
 +              (i >> 4) & 0x0f, i & 0x0f);
 +      printk(KERN_INFO "%s", buf);
 +      omap_sti_channel_write_trace(strlen(buf), 0xc3, buf, 239);
 +
 +      return 0;
 +}
 +
 +static void omap_sdti_exit(void)
 +{
 +      sti_writel(0, SDTI_WINCTRL);
 +      clk_disable(sdti_ck);
 +      clk_put(sdti_ck);
 +}
 +
 +static int __devinit omap_sdti_probe(struct platform_device *pdev)
 +{
 +      struct resource *res, *cres;
 +      unsigned int size;
 +
 +      if (pdev->num_resources != 2) {
 +              dev_err(&pdev->dev, "invalid number of resources: %d\n",
 +                      pdev->num_resources);
 +              return -ENODEV;
 +      }
 +
 +      /* SDTI base */
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (unlikely(!res)) {
 +              dev_err(&pdev->dev, "invalid mem resource\n");
 +              return -ENODEV;
 +      }
 +
 +      /* Channel base */
 +      cres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 +      if (unlikely(!cres)) {
 +              dev_err(&pdev->dev, "invalid channel mem resource\n");
 +              return -ENODEV;
 +      }
 +
 +      size = res->end - res->start;
 +      sti_base = (unsigned long)ioremap(res->start, size);
 +      if (unlikely(!sti_base))
 +              return -ENODEV;
 +
 +      size = cres->end - cres->start;
 +      sti_channel_base = (unsigned long)ioremap(cres->start, size);
 +      if (unlikely(!sti_channel_base)) {
 +              iounmap((void *)sti_base);
 +              return -ENODEV;
 +      }
 +
 +      return omap_sdti_init();
 +}
 +
 +static int __devexit omap_sdti_remove(struct platform_device *pdev)
 +{
 +      iounmap((void *)sti_channel_base);
 +      iounmap((void *)sti_base);
 +      omap_sdti_exit();
 +
 +      return 0;
 +}
 +
 +static struct platform_driver omap_sdti_driver = {
 +      .probe          = omap_sdti_probe,
 +      .remove         = __devexit_p(omap_sdti_remove),
 +      .driver         = {
 +              .name   = "sti",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_sdti_module_init(void)
 +{
 +      return platform_driver_register(&omap_sdti_driver);
 +}
 +
 +static void __exit omap_sdti_module_exit(void)
 +{
 +      platform_driver_unregister(&omap_sdti_driver);
 +}
 +subsys_initcall(omap_sdti_module_init);
 +module_exit(omap_sdti_module_exit);
 +
 +MODULE_AUTHOR("Roman Tereshonkov");
 +MODULE_LICENSE("GPL");
index 451a139d46b90462575463773c1a8eac70df6bfb,0000000000000000000000000000000000000000..2062d23dca010344505edb01b001b307d8510276
mode 100644,000000..100644
--- /dev/null
@@@ -1,189 -1,0 +1,189 @@@
- #include <asm/arch/sti.h>
- #include <asm/arch/board.h>
 +/*
 + * Console support for OMAP STI/XTI
 + *
 + * Copyright (C) 2004, 2005, 2006 Nokia Corporation
 + * Written by: Paul Mundt <paul.mundt@nokia.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/console.h>
 +#include <linux/init.h>
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/tty.h>
 +#include <linux/tty_driver.h>
++#include <mach/sti.h>
++#include <mach/board.h>
 +
 +#define DRV_NAME "sticon"
 +
 +static struct tty_driver *tty_driver;
 +static DEFINE_SPINLOCK(sti_console_lock);
 +static unsigned int sti_console_channel = -1;
 +static int sti_line_done = -1;
 +
 +/*
 + * Write a string to any channel (including terminating NULL)
 + * Returns number of characters written.
 + */
 +static int sti_channel_puts(const char *string, unsigned int channel, int len)
 +{
 +      int count = 0;
 +
 +      /*
 +       * sti_line_done is needed to determine when we have reached the
 +       * end of the line. write() has a tendency to hand us small
 +       * strings which otherwise end up creating newlines.. we need to
 +       * keep the channel open and in append mode until the line has
 +       * been terminated.
 +       */
 +      if (sti_line_done != 0) {
 +#ifdef __LITTLE_ENDIAN
 +              sti_channel_writeb(0xc3, channel);
 +#else
 +              sti_channel_writeb(0xc0, channel);
 +#endif
 +              xchg(&sti_line_done, 0);
 +      }
 +
 +      while (*string && count != len) {
 +              char c = *string++;
 +
 +              count++;
 +
 +              if (c == '\n') {
 +                      xchg(&sti_line_done, 1);
 +                      sti_channel_writeb(0, channel);
 +                      break;
 +              } else
 +                      sti_channel_writeb(c, channel);
 +      }
 +
 +      if (sti_line_done)
 +              sti_channel_flush(channel);
 +
 +      return count;
 +}
 +
 +static int sti_tty_open(struct tty_struct *tty, struct file *filp)
 +{
 +      return 0;
 +}
 +
 +static int sti_tty_write(struct tty_struct *tty,
 +                       const unsigned char *buf, int len)
 +{
 +      unsigned long flags;
 +      int bytes;
 +
 +      spin_lock_irqsave(&sti_console_lock, flags);
 +      bytes = sti_channel_puts(buf, sti_console_channel, len);
 +      spin_unlock_irqrestore(&sti_console_lock, flags);
 +
 +      return bytes;
 +}
 +
 +static int sti_tty_write_room(struct tty_struct *tty)
 +{
 +      return 0x100000;
 +}
 +
 +static int sti_tty_chars_in_buffer(struct tty_struct *tty)
 +{
 +      return 0;
 +}
 +
 +static struct tty_operations sti_tty_ops = {
 +      .open                   = sti_tty_open,
 +      .write                  = sti_tty_write,
 +      .write_room             = sti_tty_write_room,
 +      .chars_in_buffer        = sti_tty_chars_in_buffer,
 +};
 +
 +static void sti_console_write(struct console *c, const char *s, unsigned n)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&sti_console_lock, flags);
 +      sti_channel_puts(s, sti_console_channel, n);
 +      spin_unlock_irqrestore(&sti_console_lock, flags);
 +}
 +
 +static struct tty_driver *sti_console_device(struct console *c, int *index)
 +{
 +      *index = c->index;
 +      return tty_driver;
 +}
 +
 +static int sti_console_setup(struct console *c, char *opts)
 +{
 +      return 0;
 +}
 +
 +static struct console sti_console = {
 +      .name           = DRV_NAME,
 +      .write          = sti_console_write,
 +      .device         = sti_console_device,
 +      .setup          = sti_console_setup,
 +      .flags          = CON_PRINTBUFFER | CON_ENABLED,
 +      .index          = -1,
 +};
 +
 +static int __init sti_console_init(void)
 +{
 +      const struct omap_sti_console_config *info;
 +
 +      info = omap_get_config(OMAP_TAG_STI_CONSOLE,
 +                             struct omap_sti_console_config);
 +      if (info && info->enable) {
 +              add_preferred_console(DRV_NAME, 0, NULL);
 +
 +              sti_console_channel = info->channel;
 +      }
 +
 +      if (unlikely(sti_console_channel == -1))
 +              return -EINVAL;
 +
 +      register_console(&sti_console);
 +
 +      return 0;
 +}
 +__initcall(sti_console_init);
 +
 +static int __init sti_tty_init(void)
 +{
 +      struct tty_driver *tty;
 +      int ret;
 +
 +      tty = alloc_tty_driver(1);
 +      if (!tty)
 +              return -ENOMEM;
 +
 +      tty->name               = DRV_NAME;
 +      tty->driver_name        = DRV_NAME;
 +      tty->major              = 0;    /* dynamic major */
 +      tty->minor_start        = 0;
 +      tty->type               = TTY_DRIVER_TYPE_SYSTEM;
 +      tty->subtype            = SYSTEM_TYPE_SYSCONS;
 +      tty->init_termios       = tty_std_termios;
 +
 +      tty_set_operations(tty, &sti_tty_ops);
 +
 +      ret = tty_register_driver(tty);
 +      if (ret) {
 +              put_tty_driver(tty);
 +              return ret;
 +      }
 +
 +      tty_driver = tty;
 +      return 0;
 +}
 +late_initcall(sti_tty_init);
 +
 +module_param(sti_console_channel, uint, 0);
 +MODULE_PARM_DESC(sti_console_channel, "STI console channel");
 +MODULE_AUTHOR("Paul Mundt");
 +MODULE_DESCRIPTION("OMAP STI console support");
 +MODULE_LICENSE("GPL");
index 4069d9b2d3905a22fb1a3b9ecc3bc1e5786d54ab,0000000000000000000000000000000000000000..1ea5b1896fb29decd1f5f7e1c1d093b6a0949274
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,117 @@@
- #include <asm/arch/sti.h>
 +/*
 + * STI RX FIFO Support
 + *
 + * Copyright (C) 2005, 2006 Nokia Corporation
 + * Written by:  Paul Mundt <paul.mundt@nokia.com> and
 + *            Roman Tereshonkov <roman.tereshonkov@nokia.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/init.h>
 +#include <linux/interrupt.h>
 +#include <linux/err.h>
 +#include <linux/module.h>
++#include <mach/sti.h>
 +
 +#define STI_READ_BUFFER_SIZE  1024
 +#define sti_buf_pos(pos)      ((sti_crb->bufpos + (pos)) % \
 +                               STI_READ_BUFFER_SIZE)
 +
 +static struct sti_cycle_buffer {
 +      int bufpos;
 +      int datalen;
 +      unsigned char *buf;
 +} *sti_crb;
 +
 +/**
 + * sti_read_packet - STI read packet (read an entire STI packet)
 + * @buf: Buffer to store the packet.
 + * @maxsize: Maximum size requested.
 + *
 + * This reads in a single completed STI packet from the RX FIFOs and
 + * places it in @buf for further processing.
 + *
 + * The return value is < 0 on error, and >= 0 for the number of bytes
 + * actually read. As per the STI specification, we require a 0xC1 to
 + * indicate the end of the packet, and we don't return the packet until
 + * we've read the entire thing in.
 + *
 + * Due to the size of the FIFOs, it's unrealistic to constantly drain
 + * this for 1 or 2 bytes at a time, so we assemble it here and return
 + * the whole thing.
 + */
 +int sti_read_packet(unsigned char *buf, int maxsize)
 +{
 +      unsigned int pos;
 +
 +      if (unlikely(!buf))
 +              return -EINVAL;
 +      if (!sti_crb->datalen)
 +              return 0;
 +
 +      pos = sti_buf_pos(sti_crb->datalen - 1);
 +      /* End of packet */
 +      if (sti_crb->buf[pos] == 0xC1) {
 +              int i;
 +
 +              for (i = 0; i < sti_crb->datalen && i < maxsize; i++) {
 +                      pos = sti_buf_pos(i);
 +                      buf[i] = sti_crb->buf[pos];
 +              }
 +
 +              sti_crb->bufpos = sti_buf_pos(i);
 +              sti_crb->datalen -= i;
 +
 +              return i;
 +      }
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(sti_read_packet);
 +
 +static void sti_fifo_irq(unsigned long arg)
 +{
 +      /* If there is data read it */
 +      while (!(sti_readl(STI_RX_STATUS) & STI_RXFIFO_EMPTY)) {
 +              unsigned int pos = sti_buf_pos(sti_crb->datalen);
 +
 +              sti_crb->buf[pos] = sti_readl(STI_RX_DR);
 +              sti_crb->datalen++;
 +      }
 +
 +      sti_ack_irq(STI_RX_INT);
 +}
 +
 +static int __init sti_fifo_init(void)
 +{
 +      unsigned int size;
 +      int ret;
 +
 +      size = sizeof(struct sti_cycle_buffer) + STI_READ_BUFFER_SIZE;
 +      sti_crb = kmalloc(size, GFP_KERNEL);
 +      if (!sti_crb)
 +              return -ENOMEM;
 +
 +      sti_crb->bufpos = sti_crb->datalen = 0;
 +      sti_crb->buf = (unsigned char *)(sti_crb + sizeof(*sti_crb));
 +
 +      ret = sti_request_irq(STI_RX_INT, sti_fifo_irq, 0);
 +      if (ret != 0)
 +              kfree(sti_crb);
 +
 +      return ret;
 +}
 +
 +static void __exit sti_fifo_exit(void)
 +{
 +      sti_free_irq(STI_RX_INT);
 +      kfree(sti_crb);
 +}
 +
 +module_init(sti_fifo_init);
 +module_exit(sti_fifo_exit);
 +
 +MODULE_AUTHOR("Paul Mundt, Roman Tereshonkov");
 +MODULE_LICENSE("GPL");
index ca3533e75190b67c82888516895cc4517efe255e,0000000000000000000000000000000000000000..f1f8a48f4aa3cce73d135a9e57943ddf61725dca
mode 100644,000000..100644
--- /dev/null
@@@ -1,152 -1,0 +1,152 @@@
- #include <asm/arch/sti.h>
 +/*
 + * OMAP STI/XTI communications interface via netlink socket.
 + *
 + * Copyright (C) 2004, 2005, 2006 Nokia Corporation
 + * Written by: Paul Mundt <paul.mundt@nokia.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/init.h>
 +#include <linux/kernel.h>
 +#include <linux/netlink.h>
 +#include <linux/socket.h>
 +#include <linux/skbuff.h>
 +#include <linux/mutex.h>
 +#include <net/sock.h>
++#include <mach/sti.h>
 +
 +static struct sock *sti_sock;
 +static DEFINE_MUTEX(sti_netlink_mutex);
 +
 +enum {
 +      STI_READ,
 +      STI_WRITE,
 +};
 +
 +static int sti_netlink_read(int pid, int seq, void *payload, int size)
 +{
 +      struct sk_buff *skb;
 +      struct nlmsghdr *nlh;
 +      int ret, len = NLMSG_SPACE(size);
 +      unsigned char *tail;
 +
 +      skb = alloc_skb(len, GFP_KERNEL);
 +      if (!skb)
 +              return -ENOMEM;
 +
 +      tail = skb->tail;
 +      nlh = NLMSG_PUT(skb, pid, seq, STI_READ,
 +                      len - (sizeof(struct nlmsghdr)));
 +      nlh->nlmsg_flags = 0;
 +      memcpy(NLMSG_DATA(nlh), payload, size);
 +      nlh->nlmsg_len = skb->tail - tail;
 +
 +      ret = netlink_unicast(sti_sock, skb, pid, MSG_DONTWAIT);
 +      if (ret > 0)
 +              ret = 0;
 +
 +      return ret;
 +
 +nlmsg_failure:
 +      if (skb)
 +              kfree_skb(skb);
 +
 +      return -EINVAL;
 +}
 +
 +/*
 + * We abuse nlmsg_type and nlmsg_flags for our purposes.
 + *
 + * The ID is encoded into the upper 8 bits of the nlmsg_type, while the
 + * channel number is encoded into the upper 8 bits of the nlmsg_flags.
 + */
 +static int sti_netlink_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 +{
 +      void *data;
 +      u8 chan, id;
 +      int size, ret = 0, len = 0;
 +
 +      data    = NLMSG_DATA(nlh);
 +      chan    = (nlh->nlmsg_flags >> 8) & 0xff;
 +      id      = (nlh->nlmsg_type  >> 8) & 0xff;
 +      size    = (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh));
 +
 +      switch (nlh->nlmsg_type & 0xff) {
 +      case STI_WRITE:
 +              sti_channel_write_trace(size, id, data, chan);
 +              break;
 +      case STI_READ:
 +              data = kmalloc(size, GFP_KERNEL);
 +              if (!data)
 +                      return -ENOMEM;
 +              memset(data, 0, size);
 +
 +              len = sti_read_packet(data, size);
 +              ret = sti_netlink_read(NETLINK_CB(skb).pid, nlh->nlmsg_seq,
 +                                     data, len);
 +              kfree(data);
 +              break;
 +      default:
 +              return -ENOTTY;
 +      }
 +
 +      return ret;
 +}
 +
 +static int sti_netlink_receive_skb(struct sk_buff *skb)
 +{
 +      while (skb->len >= NLMSG_SPACE(0)) {
 +              struct nlmsghdr *nlh;
 +              u32 rlen;
 +              int ret;
 +
 +              nlh = (struct nlmsghdr *)skb->data;
 +              if (nlh->nlmsg_len < sizeof(struct nlmsghdr) ||
 +                  skb->len < nlh->nlmsg_len)
 +                      break;
 +
 +              rlen = NLMSG_ALIGN(nlh->nlmsg_len);
 +              if (rlen > skb->len)
 +                      rlen = skb->len;
 +
 +              ret = sti_netlink_receive_msg(skb, nlh);
 +              if (ret)
 +                      netlink_ack(skb, nlh, -ret);
 +              else if (nlh->nlmsg_flags & NLM_F_ACK)
 +                      netlink_ack(skb, nlh, 0);
 +
 +              skb_pull(skb, rlen);
 +      }
 +
 +      return 0;
 +}
 +
 +static void sti_netlink_receive(struct sk_buff *skb)
 +{
 +      if (!mutex_trylock(&sti_netlink_mutex))
 +              return;
 +
 +      sti_netlink_receive_skb(skb);
 +      mutex_unlock(&sti_netlink_mutex);
 +}
 +
 +static int __init sti_netlink_init(void)
 +{
 +      sti_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0,
 +                                       sti_netlink_receive, NULL,
 +                                       THIS_MODULE);
 +      if (!sti_sock) {
 +              printk(KERN_ERR "STI: Failed to create netlink socket\n");
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +module_init(sti_netlink_init);
 +
 +MODULE_AUTHOR("Paul Mundt");
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("STI netlink-driven communications interface");
index 1140fed048fedb9f636f8940a3de4d93d0bbdb08,0000000000000000000000000000000000000000..28fac623313658ce6c42ed131626caa708d99d39
mode 100644,000000..100644
--- /dev/null
@@@ -1,432 -1,0 +1,432 @@@
- #include <asm/arch/sti.h>
 +/*
 + * Support functions for OMAP STI/XTI (Serial Tracing Interface)
 + *
 + * Copyright (C) 2004, 2005, 2006 Nokia Corporation
 + * Written by: Paul Mundt <paul.mundt@nokia.com>
 + *
 + * STI initialization code and channel handling
 + * from Juha Yrjölä <juha.yrjola@nokia.com>.
 + *
 + * XTI initialization
 + * from Roman Tereshonkov <roman.tereshonkov@nokia.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/init.h>
 +#include <linux/err.h>
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/spinlock.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
++#include <mach/sti.h>
 +#include <asm/byteorder.h>
 +
 +static struct clk *sti_ck;
 +unsigned long sti_base, sti_channel_base;
 +static unsigned long sti_kern_mask = STIEn;
 +static unsigned long sti_irq_mask = STI_IRQSTATUS_MASK;
 +static DEFINE_SPINLOCK(sti_lock);
 +
 +static struct sti_irqdesc {
 +      irqreturn_t (*func)(unsigned long);
 +      unsigned long data;
 +} ____cacheline_aligned sti_irq_desc[STI_NR_IRQS];
 +
 +void sti_channel_write_trace(int len, int id, void *data, unsigned int channel)
 +{
 +      const u8 *tpntr = data;
 +
 +      sti_channel_writeb(id, channel);
 +
 +      if (cpu_is_omap16xx())
 +              /* Check u32 boundary */
 +              if (!((u32)data & (STI_PERCHANNEL_SIZE - 1)) &&
 +                   (len >= STI_PERCHANNEL_SIZE)) {
 +                      const u32 *asrc = data;
 +
 +                      do {
 +                              sti_channel_writel(cpu_to_be32(*asrc++),
 +                                                 channel);
 +                              len -= STI_PERCHANNEL_SIZE;
 +                      } while (len >= STI_PERCHANNEL_SIZE);
 +
 +                      tpntr = (const u8 *)asrc;
 +              }
 +
 +      while (len--)
 +              sti_channel_writeb(*tpntr++, channel);
 +
 +      sti_channel_flush(channel);
 +}
 +EXPORT_SYMBOL(sti_channel_write_trace);
 +
 +void sti_enable_irq(unsigned int id)
 +{
 +      spin_lock_irq(&sti_lock);
 +      sti_writel(1 << id, STI_IRQSETEN);
 +      spin_unlock_irq(&sti_lock);
 +}
 +EXPORT_SYMBOL(sti_enable_irq);
 +
 +void sti_disable_irq(unsigned int id)
 +{
 +      spin_lock_irq(&sti_lock);
 +
 +      if (cpu_is_omap16xx())
 +              sti_writel(1 << id, STI_IRQCLREN);
 +      else if (cpu_is_omap24xx())
 +              sti_writel(sti_readl(STI_IRQSETEN) & ~(1 << id), STI_IRQSETEN);
 +      else
 +              BUG();
 +
 +      spin_unlock_irq(&sti_lock);
 +}
 +EXPORT_SYMBOL(sti_disable_irq);
 +
 +void sti_ack_irq(unsigned int id)
 +{
 +      /* Even though the clear state is 0, we have to write 1 to clear */
 +      sti_writel(1 << id, STI_IRQSTATUS);
 +}
 +EXPORT_SYMBOL(sti_ack_irq);
 +
 +int sti_request_irq(unsigned int irq, void *handler, unsigned long arg)
 +{
 +      struct sti_irqdesc *desc;
 +
 +      if (unlikely(!handler || irq > STI_NR_IRQS))
 +              return -EINVAL;
 +
 +      desc = sti_irq_desc + irq;
 +      if (unlikely(desc->func)) {
 +              printk(KERN_WARNING "STI: Attempting to request in-use IRQ "
 +                                  "%d, consider fixing your code..\n", irq);
 +              return -EBUSY;
 +      }
 +
 +      desc->func = handler;
 +      desc->data = arg;
 +
 +      sti_enable_irq(irq);
 +      return 0;
 +}
 +EXPORT_SYMBOL(sti_request_irq);
 +
 +void sti_free_irq(unsigned int irq)
 +{
 +      struct sti_irqdesc *desc = sti_irq_desc + irq;
 +
 +      if (unlikely(irq > STI_NR_IRQS))
 +              return;
 +
 +      sti_disable_irq(irq);
 +
 +      desc->func = NULL;
 +      desc->data = 0;
 +}
 +EXPORT_SYMBOL(sti_free_irq);
 +
 +/*
 + * This is a bit heavy, so normally we would defer this to a tasklet.
 + * Unfortunately tasklets are too slow for the RX FIFO interrupt (and
 + * possibly some others), so we just do the irqdesc walking here.
 + */
 +static irqreturn_t sti_interrupt(int irq, void *dev_id)
 +{
 +      int ret = IRQ_NONE;
 +      u16 status;
 +      int i;
 +
 +      status = sti_readl(STI_IRQSTATUS) & sti_irq_mask;
 +
 +      for (i = 0; status; i++) {
 +              struct sti_irqdesc *desc = sti_irq_desc + i;
 +              u16 id = 1 << i;
 +
 +              if (!(status & id))
 +                      continue;
 +
 +              if (likely(desc && desc->func))
 +                      ret |= desc->func(desc->data);
 +              if (unlikely(ret == IRQ_NONE)) {
 +                      printk("STI: spurious interrupt (id %d)\n", id);
 +                      sti_disable_irq(i);
 +                      sti_ack_irq(i);
 +                      ret = IRQ_HANDLED;
 +              }
 +
 +              status &= ~id;
 +      }
 +
 +      return IRQ_RETVAL(ret);
 +}
 +
 +static void omap_sti_reset(void)
 +{
 +      int i;
 +
 +      /* Reset STI module */
 +      sti_writel(0x02, STI_SYSCONFIG);
 +
 +      /* Wait a while for the STI module to complete its reset */
 +      for (i = 0; i < 10000; i++)
 +              if (sti_readl(STI_SYSSTATUS) & 1)
 +                      break;
 +}
 +
 +static int __init sti_init(void)
 +{
 +      char buf[64];
 +      int i;
 +
 +      if (cpu_is_omap16xx()) {
 +              /* Release ARM Rhea buses peripherals enable */
 +              sti_writel(sti_readl(ARM_RSTCT2) | 0x0001, ARM_RSTCT2);
 +
 +              /* Enable TC1_CK (functional clock) */
 +              sti_ck = clk_get(NULL, "tc1_ck");
 +      } else if (cpu_is_omap24xx())
 +              /* Enable emulation tools clock */
 +              sti_ck = clk_get(NULL, "emul_ck");
 +
 +      if (IS_ERR(sti_ck))
 +              return PTR_ERR(sti_ck);
 +
 +      clk_enable(sti_ck);
 +
 +      /* Reset STI module */
 +      omap_sti_reset();
 +
 +      /* Enable STI */
 +      sti_trace_enable(MPUCmdEn);
 +
 +      /* Change to custom serial protocol */
 +      sti_writel(0x01, STI_SERIAL_CFG);
 +
 +      /* Set STI clock control register to normal mode */
 +      sti_writel(0x00, STI_CLK_CTRL);
 +
 +      i = sti_readl(STI_REVISION);
 +      snprintf(buf, sizeof(buf), "OMAP STI support loaded (HW v%u.%u)\n",
 +              (i >> 4) & 0x0f, i & 0x0f);
 +      printk(KERN_INFO "%s", buf);
 +
 +      sti_channel_write_trace(strlen(buf), 0xc3, buf, 239);
 +
 +      return 0;
 +}
 +
 +static void sti_exit(void)
 +{
 +      u32 tmp;
 +
 +      /*
 +       * This should have already been done by reset, but we switch off
 +       * STI entirely just for added sanity..
 +       */
 +      tmp = sti_readl(STI_ER);
 +      tmp &= ~STIEn;
 +      sti_writel(tmp, STI_ER);
 +
 +      clk_disable(sti_ck);
 +      clk_put(sti_ck);
 +}
 +
 +static void __sti_trace_enable(int event)
 +{
 +      u32 tmp;
 +
 +      tmp = sti_readl(STI_ER);
 +      tmp |= sti_kern_mask | event;
 +      sti_writel(tmp, STI_ER);
 +}
 +
 +int sti_trace_enable(int event)
 +{
 +      spin_lock_irq(&sti_lock);
 +      sti_kern_mask |= event;
 +      __sti_trace_enable(event);
 +      spin_unlock_irq(&sti_lock);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(sti_trace_enable);
 +
 +static void __sti_trace_disable(int event)
 +{
 +      u32 tmp;
 +
 +      tmp = sti_readl(STI_DR);
 +
 +      if (cpu_is_omap16xx()) {
 +              tmp |= event;
 +              tmp &= ~sti_kern_mask;
 +      } else if (cpu_is_omap24xx()) {
 +              tmp &= ~event;
 +              tmp |= sti_kern_mask;
 +      } else
 +              BUG();
 +
 +      sti_writel(tmp, STI_DR);
 +}
 +
 +void sti_trace_disable(int event)
 +{
 +      spin_lock_irq(&sti_lock);
 +      sti_kern_mask &= ~event;
 +      __sti_trace_disable(event);
 +      spin_unlock_irq(&sti_lock);
 +}
 +EXPORT_SYMBOL(sti_trace_disable);
 +
 +static ssize_t
 +sti_trace_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "0x%08lx\n", sti_readl(STI_ER));
 +}
 +
 +static ssize_t
 +sti_trace_store(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t count)
 +{
 +      int evt = simple_strtoul(buf, NULL, 0);
 +      int mask = ~evt;
 +
 +      spin_lock_irq(&sti_lock);
 +      __sti_trace_disable(mask);
 +      __sti_trace_enable(evt);
 +      spin_unlock_irq(&sti_lock);
 +
 +      return count;
 +}
 +static DEVICE_ATTR(trace, S_IRUGO | S_IWUSR, sti_trace_show, sti_trace_store);
 +
 +static ssize_t
 +sti_imask_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +      return sprintf(buf, "0x%04lx\n", sti_irq_mask);
 +}
 +
 +static ssize_t
 +sti_imask_store(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t count)
 +{
 +      spin_lock_irq(&sti_lock);
 +      sti_irq_mask = simple_strtoul(buf, NULL, 0);
 +      spin_unlock_irq(&sti_lock);
 +
 +      return count;
 +}
 +static DEVICE_ATTR(imask, S_IRUGO | S_IWUSR, sti_imask_show, sti_imask_store);
 +
 +static int __devinit sti_probe(struct platform_device *pdev)
 +{
 +      struct resource *res, *cres;
 +      int ret;
 +
 +      if (pdev->num_resources != 3) {
 +              dev_err(&pdev->dev, "invalid number of resources: %d\n",
 +                      pdev->num_resources);
 +              return -ENODEV;
 +      }
 +
 +      /* STI base */
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (unlikely(!res)) {
 +              dev_err(&pdev->dev, "invalid mem resource\n");
 +              return -ENODEV;
 +      }
 +
 +      /* Channel base */
 +      cres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 +      if (unlikely(!cres)) {
 +              dev_err(&pdev->dev, "invalid channel mem resource\n");
 +              return -ENODEV;
 +      }
 +
 +      ret = device_create_file(&pdev->dev, &dev_attr_trace);
 +      if (unlikely(ret != 0))
 +              return ret;
 +
 +      ret = device_create_file(&pdev->dev, &dev_attr_imask);
 +      if (unlikely(ret != 0))
 +              goto err;
 +
 +      sti_base = io_p2v(res->start);
 +
 +      /*
 +       * OMAP 16xx keeps channels in a relatively sane location,
 +       * whereas 24xx maps them much further out, and so they must be
 +       * remapped.
 +       */
 +      if (cpu_is_omap16xx())
 +              sti_channel_base = io_p2v(cres->start);
 +      else if (cpu_is_omap24xx()) {
 +              unsigned int size = cres->end - cres->start;
 +
 +              sti_channel_base = (unsigned long)ioremap(cres->start, size);
 +              if (unlikely(!sti_channel_base)) {
 +                      ret = -ENODEV;
 +                      goto err_badremap;
 +              }
 +      }
 +
 +      ret = request_irq(platform_get_irq(pdev, 0), sti_interrupt,
 +                        IRQF_DISABLED, "sti", NULL);
 +      if (unlikely(ret != 0))
 +              goto err_badirq;
 +
 +      return sti_init();
 +
 +err_badirq:
 +      iounmap((void *)sti_channel_base);
 +err_badremap:
 +      device_remove_file(&pdev->dev, &dev_attr_imask);
 +err:
 +      device_remove_file(&pdev->dev, &dev_attr_trace);
 +
 +      return ret;
 +}
 +
 +static int __devexit sti_remove(struct platform_device *pdev)
 +{
 +      unsigned int irq = platform_get_irq(pdev, 0);
 +
 +      if (cpu_is_omap24xx())
 +              iounmap((void *)sti_channel_base);
 +
 +      device_remove_file(&pdev->dev, &dev_attr_trace);
 +      device_remove_file(&pdev->dev, &dev_attr_imask);
 +      free_irq(irq, NULL);
 +      sti_exit();
 +
 +      return 0;
 +}
 +
 +static struct platform_driver sti_driver = {
 +      .probe          = sti_probe,
 +      .remove         = __devexit_p(sti_remove),
 +      .driver         = {
 +              .name   = "sti",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init sti_module_init(void)
 +{
 +      return platform_driver_register(&sti_driver);
 +}
 +
 +static void __exit sti_module_exit(void)
 +{
 +      platform_driver_unregister(&sti_driver);
 +}
 +subsys_initcall(sti_module_init);
 +module_exit(sti_module_exit);
 +
 +MODULE_AUTHOR("Paul Mundt, Juha Yrjölä, Roman Tereshonkov");
 +MODULE_LICENSE("GPL");
Simple merge
Simple merge
index 7a6586f95076b9fbf953ffb3315e227e3ba38e6d,0000000000000000000000000000000000000000..af3487164a96d1856e1f6c3c56995cfc0f0b2666
mode 100644,000000..100644
--- /dev/null
@@@ -1,1069 -1,0 +1,1069 @@@
- #include <asm/hardware.h>
- #include <asm/arch/board.h>
- #include <asm/arch/mmc.h>
- #include <asm/arch/cpu.h>
 +/*
 + * drivers/mmc/host/omap_hsmmc.c
 + *
 + * Driver for OMAP2430/3430 MMC controller.
 + *
 + * Copyright (C) 2007 Texas Instruments.
 + *
 + * Authors:
 + *    Syed Mohammed Khasim    <x0khasim@ti.com>
 + *    Madhusudhan             <madhu.cr@ti.com>
 + *    Mohit Jalori            <mjalori@ti.com>
 + *
 + * This file is licensed under the terms of the GNU General Public License
 + * version 2. This program is licensed "as is" without any warranty of any
 + * kind, whether express or implied.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/platform_device.h>
 +#include <linux/workqueue.h>
 +#include <linux/timer.h>
 +#include <linux/clk.h>
 +#include <linux/mmc/host.h>
 +#include <linux/io.h>
 +#include <linux/semaphore.h>
 +#include <asm/dma.h>
++#include <mach/hardware.h>
++#include <mach/board.h>
++#include <mach/mmc.h>
++#include <mach/cpu.h>
 +
 +/* OMAP HSMMC Host Controller Registers */
 +#define OMAP_HSMMC_SYSCONFIG  0x0010
 +#define OMAP_HSMMC_CON                0x002C
 +#define OMAP_HSMMC_BLK                0x0104
 +#define OMAP_HSMMC_ARG                0x0108
 +#define OMAP_HSMMC_CMD                0x010C
 +#define OMAP_HSMMC_RSP10      0x0110
 +#define OMAP_HSMMC_RSP32      0x0114
 +#define OMAP_HSMMC_RSP54      0x0118
 +#define OMAP_HSMMC_RSP76      0x011C
 +#define OMAP_HSMMC_DATA               0x0120
 +#define OMAP_HSMMC_HCTL               0x0128
 +#define OMAP_HSMMC_SYSCTL     0x012C
 +#define OMAP_HSMMC_STAT               0x0130
 +#define OMAP_HSMMC_IE         0x0134
 +#define OMAP_HSMMC_ISE                0x0138
 +#define OMAP_HSMMC_CAPA               0x0140
 +
 +#define VS18                  (1<<26)
 +#define VS30                  (1<<25)
 +#define SDVS18                        (0x5<<9)
 +#define SDVS30                        (0x6<<9)
 +#define SDVSCLR                       0xFFFFF1FF
 +#define SDVSDET                       0x00000400
 +#define AUTOIDLE              0x1
 +#define SDBP                  (1<<8)
 +#define DTO                   0xe
 +#define ICE                   0x1
 +#define ICS                   0x2
 +#define CEN                   (1<<2)
 +#define CLKD_MASK             0x0000FFC0
 +#define INT_EN_MASK           0x307F0033
 +#define INIT_STREAM           (1<<1)
 +#define DP_SELECT             (1<<21)
 +#define DDIR                  (1<<4)
 +#define DMA_EN                        0x1
 +#define MSBS                  1<<5
 +#define BCE                   1<<1
 +#define FOUR_BIT              1 << 1
 +#define CC                    0x1
 +#define TC                    0x02
 +#define OD                    0x1
 +#define ERR                   (1 << 15)
 +#define CMD_TIMEOUT           (1 << 16)
 +#define DATA_TIMEOUT          (1 << 20)
 +#define CMD_CRC                       (1 << 17)
 +#define DATA_CRC              (1 << 21)
 +#define CARD_ERR              (1 << 28)
 +#define STAT_CLEAR            0xFFFFFFFF
 +#define INIT_STREAM_CMD               0x00000000
 +#define DUAL_VOLT_OCR_BIT     7
 +#define SRC                   (1 << 25)
 +#define SRD                   (1 << 26)
 +
 +#define OMAP_MMC1_DEVID               1
 +#define OMAP_MMC2_DEVID               2
 +#define OMAP_MMC_DATADIR_NONE 0
 +#define OMAP_MMC_DATADIR_READ 1
 +#define OMAP_MMC_DATADIR_WRITE        2
 +#define MMC_TIMEOUT_MS                20
 +#define OMAP_MMC_MASTER_CLOCK 96000000
 +#define DRIVER_NAME           "mmci-omap"
 +/*
 + * slot_id is device id - 1, device id is a static value
 + * of 1 to represent device 1 etc..
 + */
 +#define mmc_slot(host)                (host->pdata->slots[host->slot_id])
 +
 +/*
 + * MMC Host controller read/write API's
 + */
 +#define OMAP_HSMMC_READ(base, reg)    \
 +      __raw_readl((base) + OMAP_HSMMC_##reg)
 +
 +#define OMAP_HSMMC_WRITE(base, reg, val) \
 +      __raw_writel((val), (base) + OMAP_HSMMC_##reg)
 +
 +struct mmc_omap_host {
 +      struct  device          *dev;
 +      struct  mmc_host        *mmc;
 +      struct  mmc_request     *mrq;
 +      struct  mmc_command     *cmd;
 +      struct  mmc_data        *data;
 +      struct  clk             *fclk;
 +      struct  clk             *iclk;
 +      struct  clk             *dbclk;
 +      struct  semaphore       sem;
 +      struct  work_struct     mmc_carddetect_work;
 +      void    __iomem         *base;
 +      resource_size_t         mapbase;
 +      unsigned int            id;
 +      unsigned int            dma_len;
 +      unsigned int            dma_dir;
 +      unsigned char           bus_mode;
 +      unsigned char           datadir;
 +      u32                     *buffer;
 +      u32                     bytesleft;
 +      int                     suspended;
 +      int                     irq;
 +      int                     carddetect;
 +      int                     use_dma, dma_ch;
 +      int                     initstr;
 +      int                     slot_id;
 +      int                     dbclk_enabled;
 +      struct  omap_mmc_platform_data  *pdata;
 +};
 +
 +/*
 + * Stop clock to the card
 + */
 +static void omap_mmc_stop_clock(struct mmc_omap_host *host)
 +{
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
 +      if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0)
 +              dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
 +}
 +
 +/*
 + * Send init stream sequence to card
 + * before sending IDLE command
 + */
 +static void send_init_stream(struct mmc_omap_host *host)
 +{
 +      int reg = 0;
 +      unsigned long timeout;
 +
 +      disable_irq(host->irq);
 +      OMAP_HSMMC_WRITE(host->base, CON,
 +              OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
 +      OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
 +
 +      timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
 +      while ((reg != CC) && time_before(jiffies, timeout))
 +              reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
 +
 +      OMAP_HSMMC_WRITE(host->base, CON,
 +              OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
 +      enable_irq(host->irq);
 +}
 +
 +/*
 + * Configure the response type and send the cmd.
 + */
 +static void
 +mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 +      struct mmc_data *data)
 +{
 +      int cmdreg = 0, resptype = 0, cmdtype = 0;
 +
 +      dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
 +              mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
 +      host->cmd = cmd;
 +
 +      /*
 +       * Clear status bits and enable interrupts
 +       */
 +      OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 +      OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
 +      OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
 +
 +      if (cmd->flags & MMC_RSP_PRESENT) {
 +              if (cmd->flags & MMC_RSP_136)
 +                      resptype = 1;
 +              else
 +                      resptype = 2;
 +      }
 +
 +      /*
 +       * Unlike OMAP1 controller, the cmdtype does not seem to be based on
 +       * ac, bc, adtc, bcr. Only CMD12 needs a val of 0x3, rest 0x0.
 +       */
 +      if (cmd->opcode == 12)
 +              cmdtype = 0x3;
 +
 +      cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
 +
 +      if (data) {
 +              cmdreg |= DP_SELECT | MSBS | BCE;
 +              if (data->flags & MMC_DATA_READ)
 +                      cmdreg |= DDIR;
 +              else
 +                      cmdreg &= ~(DDIR);
 +      }
 +
 +      if (host->use_dma)
 +              cmdreg |= DMA_EN;
 +
 +      OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
 +      OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
 +}
 +
 +/*
 + * Notify the transfer complete to MMC core
 + */
 +static void
 +mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 +{
 +      host->data = NULL;
 +
 +      if (host->use_dma && host->dma_ch != -1)
 +              dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
 +                      host->dma_dir);
 +
 +      host->datadir = OMAP_MMC_DATADIR_NONE;
 +
 +      if (!data->error)
 +              data->bytes_xfered += data->blocks * (data->blksz);
 +      else
 +              data->bytes_xfered = 0;
 +
 +      if (!data->stop) {
 +              host->mrq = NULL;
 +              mmc_request_done(host->mmc, data->mrq);
 +              return;
 +      }
 +      mmc_omap_start_command(host, data->stop, NULL);
 +}
 +
 +/*
 + * Notify the core about command completion
 + */
 +static void
 +mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 +{
 +      host->cmd = NULL;
 +
 +      if (cmd->flags & MMC_RSP_PRESENT) {
 +              if (cmd->flags & MMC_RSP_136) {
 +                      /* response type 2 */
 +                      cmd->resp[3] = OMAP_HSMMC_READ(host->base, RSP10);
 +                      cmd->resp[2] = OMAP_HSMMC_READ(host->base, RSP32);
 +                      cmd->resp[1] = OMAP_HSMMC_READ(host->base, RSP54);
 +                      cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP76);
 +              } else {
 +                      /* response types 1, 1b, 3, 4, 5, 6 */
 +                      cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
 +              }
 +      }
 +      if (host->data == NULL || cmd->error) {
 +              host->mrq = NULL;
 +              mmc_request_done(host->mmc, cmd->mrq);
 +      }
 +}
 +
 +/*
 + * DMA clean up for command errors
 + */
 +static void mmc_dma_cleanup(struct mmc_omap_host *host)
 +{
 +      host->data->error = -ETIMEDOUT;
 +
 +      if (host->use_dma && host->dma_ch != -1) {
 +              dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
 +                      host->dma_dir);
 +              omap_free_dma(host->dma_ch);
 +              host->dma_ch = -1;
 +              up(&host->sem);
 +      }
 +      host->data = NULL;
 +      host->datadir = OMAP_MMC_DATADIR_NONE;
 +}
 +
 +/*
 + * MMC controller IRQ handler
 + */
 +static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 +{
 +      struct mmc_omap_host *host = dev_id;
 +      struct mmc_data *data;
 +      int end_cmd = 0, end_trans = 0, status;
 +
 +      if (host->cmd == NULL && host->data == NULL) {
 +              OMAP_HSMMC_WRITE(host->base, STAT,
 +                      OMAP_HSMMC_READ(host->base, STAT));
 +              return IRQ_HANDLED;
 +      }
 +
 +      data = host->data;
 +      status = OMAP_HSMMC_READ(host->base, STAT);
 +      dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 +
 +      if (status & ERR) {
 +              if ((status & CMD_TIMEOUT) ||
 +                      (status & CMD_CRC)) {
 +                      if (host->cmd) {
 +                              if (status & CMD_TIMEOUT) {
 +                                      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +                                              OMAP_HSMMC_READ(host->base,
 +                                                              SYSCTL) | SRC);
 +                                      while (OMAP_HSMMC_READ(host->base,
 +                                                              SYSCTL) & SRC) ;
 +                                      host->cmd->error = -ETIMEDOUT;
 +                              } else {
 +                                      host->cmd->error = -EILSEQ;
 +                              }
 +                              end_cmd = 1;
 +                      }
 +                      if (host->data)
 +                              mmc_dma_cleanup(host);
 +              }
 +              if ((status & DATA_TIMEOUT) ||
 +                      (status & DATA_CRC)) {
 +                      if (host->data) {
 +                              if (status & DATA_TIMEOUT)
 +                                      mmc_dma_cleanup(host);
 +                              else
 +                                      host->data->error = -EILSEQ;
 +                              end_trans = 1;
 +                      }
 +              }
 +              if (status & CARD_ERR) {
 +                      dev_dbg(mmc_dev(host->mmc),
 +                              "Ignoring card err CMD%d\n", host->cmd->opcode);
 +                      if (host->cmd)
 +                              end_cmd = 1;
 +                      if (host->data)
 +                              end_trans = 1;
 +              }
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, STAT, status);
 +
 +      if (end_cmd || (status & CC))
 +              mmc_omap_cmd_done(host, host->cmd);
 +      if (end_trans || (status & TC))
 +              mmc_omap_xfer_done(host, data);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Switch MMC operating voltage
 + */
 +static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 +{
 +      u32 reg_val = 0;
 +      int ret;
 +
 +      /* Disable the clocks */
 +      clk_disable(host->fclk);
 +      clk_disable(host->iclk);
 +      clk_disable(host->dbclk);
 +
 +      /* Turn the power off */
 +      ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
 +      if (ret != 0)
 +              goto err;
 +
 +      /* Turn the power ON with given VDD 1.8 or 3.0v */
 +      ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
 +      if (ret != 0)
 +              goto err;
 +
 +      clk_enable(host->fclk);
 +      clk_enable(host->iclk);
 +      clk_enable(host->dbclk);
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +              OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
 +      reg_val = OMAP_HSMMC_READ(host->base, HCTL);
 +      /*
 +       * If a MMC dual voltage card is detected, the set_ios fn calls
 +       * this fn with VDD bit set for 1.8V. Upon card removal from the
 +       * slot, mmc_omap_detect fn sets the VDD back to 3V.
 +       *
 +       * Only MMC1 supports 3.0V.  MMC2 will not function if SDVS30 is
 +       * set in HCTL.
 +       */
 +      if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
 +                              ((1 << vdd) == MMC_VDD_33_34)))
 +              reg_val |= SDVS30;
 +      if ((1 << vdd) == MMC_VDD_165_195)
 +              reg_val |= SDVS18;
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +              OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
 +
 +      return 0;
 +err:
 +      dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
 +      return ret;
 +}
 +
 +/*
 + * Work Item to notify the core about card insertion/removal
 + */
 +static void mmc_omap_detect(struct work_struct *work)
 +{
 +      u16 vdd = 0;
 +      struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
 +                                              mmc_carddetect_work);
 +
 +      if (host->carddetect) {
 +              if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 +                      /*
 +                       * Set the VDD back to 3V when the card is removed
 +                       * before the set_ios fn turns off the power.
 +                       */
 +                      vdd = fls(host->mmc->ocr_avail) - 1;
 +                      if (omap_mmc_switch_opcond(host, vdd) != 0)
 +                              host->mmc->ios.vdd = vdd;
 +              }
 +              mmc_detect_change(host->mmc, (HZ * 200) / 1000);
 +      } else {
 +              OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +                      OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
 +              while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD) ;
 +              mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 +      }
 +}
 +
 +/*
 + * ISR for handling card insertion and removal
 + */
 +static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
 +{
 +      struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
 +
 +      host->carddetect = mmc_slot(host).card_detect(irq);
 +      schedule_work(&host->mmc_carddetect_work);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * DMA call back function
 + */
 +static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      struct mmc_omap_host *host = data;
 +
 +      if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
 +              dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
 +
 +      if (host->dma_ch < 0)
 +              return;
 +
 +      omap_free_dma(host->dma_ch);
 +      host->dma_ch = -1;
 +      /*
 +       * DMA Callback: run in interrupt context.
 +       * mutex_unlock will through a kernel warning if used.
 +       */
 +      up(&host->sem);
 +}
 +
 +/*
 + * Configure dma src and destination parameters
 + */
 +static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
 +                              struct mmc_data *data)
 +{
 +      if (sync_dir == 0) {
 +              omap_set_dma_dest_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_CONSTANT,
 +                      (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
 +              omap_set_dma_src_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_POST_INC,
 +                      sg_dma_address(&data->sg[0]), 0, 0);
 +      } else {
 +              omap_set_dma_src_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_CONSTANT,
 +                      (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
 +              omap_set_dma_dest_params(host->dma_ch, 0,
 +                      OMAP_DMA_AMODE_POST_INC,
 +                      sg_dma_address(&data->sg[0]), 0, 0);
 +      }
 +      return 0;
 +}
 +/*
 + * Routine to configure and start DMA for the MMC card
 + */
 +static int
 +mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 +{
 +      int sync_dev, sync_dir = 0;
 +      int dma_ch = 0, ret = 0, err = 1;
 +      struct mmc_data *data = req->data;
 +
 +      /*
 +       * If for some reason the DMA transfer is still active,
 +       * we wait for timeout period and free the dma
 +       */
 +      if (host->dma_ch != -1) {
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              schedule_timeout(100);
 +              if (down_trylock(&host->sem)) {
 +                      omap_free_dma(host->dma_ch);
 +                      host->dma_ch = -1;
 +                      up(&host->sem);
 +                      return err;
 +              }
 +      } else {
 +              if (down_trylock(&host->sem))
 +                      return err;
 +      }
 +
 +      if (!(data->flags & MMC_DATA_WRITE)) {
 +              host->dma_dir = DMA_FROM_DEVICE;
 +              if (host->id == OMAP_MMC1_DEVID)
 +                      sync_dev = OMAP24XX_DMA_MMC1_RX;
 +              else
 +                      sync_dev = OMAP24XX_DMA_MMC2_RX;
 +      } else {
 +              host->dma_dir = DMA_TO_DEVICE;
 +              if (host->id == OMAP_MMC1_DEVID)
 +                      sync_dev = OMAP24XX_DMA_MMC1_TX;
 +              else
 +                      sync_dev = OMAP24XX_DMA_MMC2_TX;
 +      }
 +
 +      ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
 +                      host, &dma_ch);
 +      if (ret != 0) {
 +              dev_dbg(mmc_dev(host->mmc),
 +                      "%s: omap_request_dma() failed with %d\n",
 +                      mmc_hostname(host->mmc), ret);
 +              return ret;
 +      }
 +
 +      host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
 +                      data->sg_len, host->dma_dir);
 +      host->dma_ch = dma_ch;
 +
 +      if (!(data->flags & MMC_DATA_WRITE))
 +              mmc_omap_config_dma_param(1, host, data);
 +      else
 +              mmc_omap_config_dma_param(0, host, data);
 +
 +      if ((data->blksz % 4) == 0)
 +              omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
 +                      (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
 +                      sync_dev, sync_dir);
 +      else
 +              /* REVISIT: The MMC buffer increments only when MSB is written.
 +               * Return error for blksz which is non multiple of four.
 +               */
 +              return -EINVAL;
 +
 +      omap_start_dma(dma_ch);
 +      return 0;
 +}
 +
 +/*
 + * Configure block length for MMC/SD cards and initiate the transfer.
 + */
 +static int
 +mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 +{
 +      int ret;
 +      host->data = req->data;
 +
 +      if (req->data == NULL) {
 +              host->datadir = OMAP_MMC_DATADIR_NONE;
 +              OMAP_HSMMC_WRITE(host->base, BLK, 0);
 +              return 0;
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
 +                                      | (req->data->blocks << 16));
 +
 +      host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
 +                      OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
 +
 +      if (host->use_dma) {
 +              ret = mmc_omap_start_dma_transfer(host, req);
 +              if (ret != 0) {
 +                      dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
 +                      return ret;
 +              }
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Request function. for read/write operation
 + */
 +static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +
 +      WARN_ON(host->mrq != NULL);
 +      host->mrq = req;
 +      mmc_omap_prepare_data(host, req);
 +      mmc_omap_start_command(host, req->cmd, req->data);
 +}
 +
 +
 +/* Routine to configure clock values. Exposed API to core */
 +static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 +{
 +      struct mmc_omap_host *host = mmc_priv(mmc);
 +      u16 dsor = 0;
 +      unsigned long regval;
 +      unsigned long timeout;
 +
 +      switch (ios->power_mode) {
 +      case MMC_POWER_OFF:
 +              mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
 +              break;
 +      case MMC_POWER_UP:
 +              mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd);
 +              break;
 +      }
 +
 +      switch (mmc->ios.bus_width) {
 +      case MMC_BUS_WIDTH_4:
 +              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
 +              break;
 +      case MMC_BUS_WIDTH_1:
 +              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
 +              break;
 +      }
 +
 +      if (host->id == OMAP_MMC1_DEVID) {
 +              /* Only MMC1 can operate at 3V/1.8V */
 +              if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
 +                      (ios->vdd == DUAL_VOLT_OCR_BIT)) {
 +                              /*
 +                               * The mmc_select_voltage fn of the core does
 +                               * not seem to set the power_mode to
 +                               * MMC_POWER_UP upon recalculating the voltage.
 +                               * vdd 1.8v.
 +                               */
 +                              if (omap_mmc_switch_opcond(host, ios->vdd) != 0)
 +                                      dev_dbg(mmc_dev(host->mmc),
 +                                              "Switch operation failed\n");
 +              }
 +      }
 +
 +      if (ios->clock) {
 +              dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
 +              if (dsor < 1)
 +                      dsor = 1;
 +
 +              if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
 +                      dsor++;
 +
 +              if (dsor > 250)
 +                      dsor = 250;
 +      }
 +      omap_mmc_stop_clock(host);
 +      regval = OMAP_HSMMC_READ(host->base, SYSCTL);
 +      regval = regval & ~(CLKD_MASK);
 +      regval = regval | (dsor << 6) | (DTO << 16);
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
 +
 +      /* Wait till the ICS bit is set */
 +      timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
 +      while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2
 +              && time_before(jiffies, timeout))
 +              msleep(1);
 +
 +      OMAP_HSMMC_WRITE(host->base, SYSCTL,
 +              OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
 +
 +      if (ios->power_mode == MMC_POWER_ON)
 +              send_init_stream(host);
 +
 +      if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 +              OMAP_HSMMC_WRITE(host->base, CON,
 +                              OMAP_HSMMC_READ(host->base, CON) | OD);
 +}
 +/* NOTE: Read only switch not supported yet */
 +static struct mmc_host_ops mmc_omap_ops = {
 +      .request = omap_mmc_request,
 +      .set_ios = omap_mmc_set_ios,
 +};
 +
 +static int __init omap_mmc_probe(struct platform_device *pdev)
 +{
 +      struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
 +      struct mmc_host *mmc;
 +      struct mmc_omap_host *host = NULL;
 +      struct resource *res;
 +      int ret = 0, irq;
 +      u32 hctl, capa;
 +
 +      if (pdata == NULL) {
 +              dev_err(&pdev->dev, "Platform Data is missing\n");
 +              return -ENXIO;
 +      }
 +
 +      if (pdata->nr_slots == 0) {
 +              dev_err(&pdev->dev, "No Slots\n");
 +              return -ENXIO;
 +      }
 +
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      irq = platform_get_irq(pdev, 0);
 +      if (res == NULL || irq < 0)
 +              return -ENXIO;
 +
 +      res = request_mem_region(res->start, res->end - res->start + 1,
 +                                                      pdev->name);
 +      if (res == NULL)
 +              return -EBUSY;
 +
 +      mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
 +      if (!mmc) {
 +              ret = -ENOMEM;
 +              goto err;
 +      }
 +
 +      host            = mmc_priv(mmc);
 +      host->mmc       = mmc;
 +      host->pdata     = pdata;
 +      host->use_dma   = 1;
 +      host->dma_ch    = -1;
 +      host->irq       = irq;
 +      host->id        = pdev->id;
 +      host->slot_id   = 0;
 +      host->mapbase   = res->start;
 +      host->base      = ioremap(host->mapbase, SZ_4K);
 +      mmc->ops        = &mmc_omap_ops;
 +      mmc->f_min      = 400000;
 +      mmc->f_max      = 52000000;
 +
 +      sema_init(&host->sem, 1);
 +
 +      host->iclk = clk_get(&pdev->dev, "mmchs_ick");
 +      if (IS_ERR(host->iclk)) {
 +              ret = PTR_ERR(host->iclk);
 +              host->iclk = NULL;
 +              goto err1;
 +      }
 +      host->fclk = clk_get(&pdev->dev, "mmchs_fck");
 +      if (IS_ERR(host->fclk)) {
 +              ret = PTR_ERR(host->fclk);
 +              host->fclk = NULL;
 +              clk_put(host->iclk);
 +              goto err1;
 +      }
 +
 +      if (clk_enable(host->fclk) != 0) {
 +              clk_put(host->iclk);
 +              clk_put(host->fclk);
 +              goto err1;
 +      }
 +
 +      if (clk_enable(host->iclk) != 0) {
 +              clk_disable(host->fclk);
 +              clk_put(host->iclk);
 +              clk_put(host->fclk);
 +              goto err1;
 +      }
 +
 +      host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
 +      /*
 +       * MMC can still work without debounce clock.
 +       */
 +      if (IS_ERR(host->dbclk))
 +              dev_dbg(mmc_dev(host->mmc), "Failed to get debounce clock\n");
 +      else
 +              if (clk_enable(host->dbclk) != 0)
 +                      dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
 +                                                      " clk failed\n");
 +              else
 +                      host->dbclk_enabled = 1;
 +
 +#ifdef CONFIG_MMC_BLOCK_BOUNCE
 +      mmc->max_phys_segs = 1;
 +      mmc->max_hw_segs = 1;
 +#endif
 +      mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 +      mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 +      mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
 +      mmc->max_seg_size = mmc->max_req_size;
 +
 +      mmc->ocr_avail = mmc_slot(host).ocr_mask;
 +      mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 +
 +      if (pdata->conf.wire4)
 +              mmc->caps |= MMC_CAP_4_BIT_DATA;
 +
 +      /* Only MMC1 supports 3.0V */
 +      if (host->id == OMAP_MMC1_DEVID) {
 +              hctl = SDVS30;
 +              capa = VS30 | VS18;
 +      } else {
 +              hctl = SDVS18;
 +              capa = VS18;
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | hctl);
 +
 +      OMAP_HSMMC_WRITE(host->base, CAPA,
 +                      OMAP_HSMMC_READ(host->base, CAPA) | capa);
 +
 +      /* Set the controller to AUTO IDLE mode */
 +      OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
 +                      OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
 +
 +      /* Set SD bus power bit */
 +      OMAP_HSMMC_WRITE(host->base, HCTL,
 +                      OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
 +
 +      /* Request IRQ for MMC operations */
 +      ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, pdev->name,
 +                       host);
 +      if (ret) {
 +              dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
 +              goto irq_err;
 +      }
 +
 +      /* Request IRQ for card detect */
 +      if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
 +              ret = request_irq(mmc_slot(host).card_detect_irq,
 +                                omap_mmc_cd_handler, IRQF_DISABLED, "MMC CD",
 +                                host);
 +              if (ret) {
 +                      dev_dbg(mmc_dev(host->mmc),
 +                              "Unable to grab MMC CD IRQ");
 +                      free_irq(host->irq, host);
 +                      goto irq_err;
 +              }
 +      }
 +
 +      INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
 +      if (pdata->init != NULL) {
 +              if (pdata->init(&pdev->dev) != 0) {
 +                      free_irq(mmc_slot(host).card_detect_irq, host);
 +                      free_irq(host->irq, host);
 +                      goto irq_err;
 +              }
 +      }
 +
 +      OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
 +      OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
 +
 +      platform_set_drvdata(pdev, host);
 +      mmc_add_host(mmc);
 +
 +      return 0;
 +
 +irq_err:
 +      dev_dbg(mmc_dev(host->mmc), "Unable to configure MMC IRQs\n");
 +      clk_disable(host->fclk);
 +      clk_disable(host->iclk);
 +      clk_put(host->fclk);
 +      clk_put(host->iclk);
 +      if (host->dbclk_enabled) {
 +              clk_disable(host->dbclk);
 +              clk_put(host->dbclk);
 +      }
 +
 +err1:
 +      iounmap(host->base);
 +err:
 +      dev_dbg(mmc_dev(host->mmc), "Probe Failed\n");
 +      release_mem_region(res->start, res->end - res->start + 1);
 +      if (host)
 +              mmc_free_host(mmc);
 +      return ret;
 +}
 +
 +static int omap_mmc_remove(struct platform_device *pdev)
 +{
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +      struct resource *res;
 +      u16 vdd = 0;
 +
 +      if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 +      /*
 +       * Set the vdd back to 3V,
 +       * applicable for dual volt support.
 +       */
 +              vdd = fls(host->mmc->ocr_avail) - 1;
 +              if (omap_mmc_switch_opcond(host, vdd) != 0)
 +                      host->mmc->ios.vdd = vdd;
 +      }
 +
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (res)
 +              release_mem_region(res->start, res->end - res->start + 1);
 +
 +      platform_set_drvdata(pdev, NULL);
 +      if (host) {
 +              mmc_remove_host(host->mmc);
 +              if (host->pdata->cleanup)
 +                      host->pdata->cleanup(&pdev->dev);
 +              free_irq(host->irq, host);
 +              if (mmc_slot(host).card_detect_irq)
 +                      free_irq(mmc_slot(host).card_detect_irq, host);
 +              flush_scheduled_work();
 +
 +              clk_disable(host->fclk);
 +              clk_disable(host->iclk);
 +              clk_put(host->fclk);
 +              clk_put(host->iclk);
 +              if (host->dbclk_enabled) {
 +                      clk_disable(host->dbclk);
 +                      clk_put(host->dbclk);
 +              }
 +
 +              mmc_free_host(host->mmc);
 +              iounmap(host->base);
 +      }
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      int ret = 0;
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +
 +      if (host && host->suspended)
 +              return 0;
 +
 +      if (host) {
 +              ret = mmc_suspend_host(host->mmc, state);
 +              if (ret == 0) {
 +                      host->suspended = 1;
 +
 +                      OMAP_HSMMC_WRITE(host->base, ISE, 0);
 +                      OMAP_HSMMC_WRITE(host->base, IE, 0);
 +
 +                      ret = host->pdata->suspend(&pdev->dev, host->slot_id);
 +                      if (ret)
 +                              dev_dbg(mmc_dev(host->mmc),
 +                                      "Unable to handle MMC board"
 +                                      " level suspend\n");
 +
 +                      if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 +                              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                                      OMAP_HSMMC_READ(host->base, HCTL)
 +                                      & SDVSCLR);
 +                              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                                      OMAP_HSMMC_READ(host->base, HCTL)
 +                                      | SDVS30);
 +                              OMAP_HSMMC_WRITE(host->base, HCTL,
 +                                      OMAP_HSMMC_READ(host->base, HCTL)
 +                                      | SDBP);
 +                      }
 +
 +                      clk_disable(host->fclk);
 +                      clk_disable(host->iclk);
 +                      clk_disable(host->dbclk);
 +              }
 +
 +      }
 +      return ret;
 +}
 +
 +/* Routine to resume the MMC device */
 +static int omap_mmc_resume(struct platform_device *pdev)
 +{
 +      int ret = 0;
 +      struct mmc_omap_host *host = platform_get_drvdata(pdev);
 +
 +      if (host && !host->suspended)
 +              return 0;
 +
 +      if (host) {
 +
 +              ret = clk_enable(host->fclk);
 +              if (ret)
 +                      goto clk_en_err;
 +
 +              ret = clk_enable(host->iclk);
 +              if (ret) {
 +                      clk_disable(host->fclk);
 +                      clk_put(host->fclk);
 +                      goto clk_en_err;
 +              }
 +
 +              if (clk_enable(host->dbclk) != 0)
 +                      dev_dbg(mmc_dev(host->mmc),
 +                                      "Enabling debounce clk failed\n");
 +
 +              ret = host->pdata->resume(&pdev->dev, host->slot_id);
 +              if (ret)
 +                      dev_dbg(mmc_dev(host->mmc),
 +                                      "Unmask interrupt failed\n");
 +
 +              /* Notify the core to resume the host */
 +              ret = mmc_resume_host(host->mmc);
 +              if (ret == 0)
 +                      host->suspended = 0;
 +      }
 +
 +      return ret;
 +
 +clk_en_err:
 +      dev_dbg(mmc_dev(host->mmc),
 +              "Failed to enable MMC clocks during resume\n");
 +      return ret;
 +}
 +
 +#else
 +#define omap_mmc_suspend      NULL
 +#define omap_mmc_resume               NULL
 +#endif
 +
 +static struct platform_driver omap_mmc_driver = {
 +      .probe          = omap_mmc_probe,
 +      .remove         = omap_mmc_remove,
 +      .suspend        = omap_mmc_suspend,
 +      .resume         = omap_mmc_resume,
 +      .driver         = {
 +              .name = DRIVER_NAME,
 +              .owner = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_mmc_init(void)
 +{
 +      /* Register the MMC driver */
 +      return platform_driver_register(&omap_mmc_driver);
 +}
 +
 +static void __exit omap_mmc_cleanup(void)
 +{
 +      /* Unregister MMC driver */
 +      platform_driver_unregister(&omap_mmc_driver);
 +}
 +
 +module_init(omap_mmc_init);
 +module_exit(omap_mmc_cleanup);
 +
 +MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS("platform:" DRIVER_NAME);
 +MODULE_AUTHOR("Texas Instruments Inc");
index 0a60ebbc217591af7c00511ad3096f8d2fa9656d,0a60ebbc217591af7c00511ad3096f8d2fa9656d..2cbd75e1b2df666f9d5685e9c90f50ee012f7574
@@@ -17,7 -17,7 +17,7 @@@
  #include <linux/mtd/map.h>
  #include <linux/mtd/partitions.h>
  
--#include <asm/hardware.h>
++#include <mach/hardware.h>
  #include <asm/io.h>
  
  
Simple merge
Simple merge
Simple merge
index 16029777c88b95bb214f9c3f9d52986599709814,0000000000000000000000000000000000000000..c598d9d58b7951c1292793c579d6f0ee882bc534
mode 100644,000000..100644
--- /dev/null
@@@ -1,860 -1,0 +1,860 @@@
- #include <asm/arch/board.h>
- #include <asm/arch/dma.h>
 +/*
 + *  drivers/mtd/nand/omap-hw.c
 + *
 + *  This is the MTD driver for OMAP1710 internal HW NAND controller.
 + *
 + *  Copyright (C) 2004-2006 Nokia Corporation
 + *
 + *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and
 + *          Juha Yrjölä <juha.yrjola@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License version 2 as published by
 + * the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but WITHOUT
 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 + * more details.
 + *
 + * You should have received a copy of the GNU General Public License along with
 + * this program; see the file COPYING. If not, write to the Free Software
 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
 + */
 +
 +#include <linux/slab.h>
 +#include <linux/init.h>
 +#include <linux/module.h>
 +#include <linux/delay.h>
 +#include <linux/delay.h>
 +#include <linux/errno.h>
 +#include <linux/sched.h>
 +#include <linux/types.h>
 +#include <linux/wait.h>
 +#include <linux/spinlock.h>
 +#include <linux/interrupt.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/nand.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/mtd/nand_ecc.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/clk.h>
 +
 +#include <asm/io.h>
 +
++#include <mach/board.h>
++#include <mach/dma.h>
 +
 +#define NAND_BASE             0xfffbcc00
 +#define NND_REVISION          0x00
 +#define NND_ACCESS            0x04
 +#define NND_ADDR_SRC          0x08
 +#define NND_CTRL              0x10
 +#define NND_MASK              0x14
 +#define NND_STATUS            0x18
 +#define NND_READY             0x1c
 +#define NND_COMMAND           0x20
 +#define NND_COMMAND_SEC               0x24
 +#define NND_ECC_SELECT                0x28
 +#define NND_ECC_START         0x2c
 +#define NND_ECC_9             0x4c
 +#define NND_RESET             0x50
 +#define NND_FIFO              0x54
 +#define NND_FIFOCTRL          0x58
 +#define NND_PSC_CLK           0x5c
 +#define NND_SYSTEST           0x60
 +#define NND_SYSCFG            0x64
 +#define NND_SYSSTATUS         0x68
 +#define NND_FIFOTEST1         0x6c
 +#define NND_FIFOTEST2         0x70
 +#define NND_FIFOTEST3         0x74
 +#define NND_FIFOTEST4         0x78
 +#define NND_PSC1_CLK          0x8c
 +#define NND_PSC2_CLK          0x90
 +
 +
 +#define NND_CMD_READ1_LOWER   0x00
 +#define NND_CMD_WRITE1_LOWER  0x00
 +#define NND_CMD_READ1_UPPER   0x01
 +#define NND_CMD_WRITE1_UPPER  0x01
 +#define NND_CMD_PROGRAM_END   0x10
 +#define NND_CMD_READ2_SPARE   0x50
 +#define NND_CMD_WRITE2_SPARE  0x50
 +#define NND_CMD_ERASE         0x60
 +#define NND_CMD_STATUS                0x70
 +#define NND_CMD_PROGRAM               0x80
 +#define NND_CMD_READ_ID               0x90
 +#define NND_CMD_ERASE_END     0xD0
 +#define NND_CMD_RESET         0xFF
 +
 +
 +#define NAND_Ecc_P1e          (1 << 0)
 +#define NAND_Ecc_P2e          (1 << 1)
 +#define NAND_Ecc_P4e          (1 << 2)
 +#define NAND_Ecc_P8e          (1 << 3)
 +#define NAND_Ecc_P16e         (1 << 4)
 +#define NAND_Ecc_P32e         (1 << 5)
 +#define NAND_Ecc_P64e         (1 << 6)
 +#define NAND_Ecc_P128e                (1 << 7)
 +#define NAND_Ecc_P256e                (1 << 8)
 +#define NAND_Ecc_P512e                (1 << 9)
 +#define NAND_Ecc_P1024e               (1 << 10)
 +#define NAND_Ecc_P2048e               (1 << 11)
 +
 +#define NAND_Ecc_P1o          (1 << 16)
 +#define NAND_Ecc_P2o          (1 << 17)
 +#define NAND_Ecc_P4o          (1 << 18)
 +#define NAND_Ecc_P8o          (1 << 19)
 +#define NAND_Ecc_P16o         (1 << 20)
 +#define NAND_Ecc_P32o         (1 << 21)
 +#define NAND_Ecc_P64o         (1 << 22)
 +#define NAND_Ecc_P128o                (1 << 23)
 +#define NAND_Ecc_P256o                (1 << 24)
 +#define NAND_Ecc_P512o                (1 << 25)
 +#define NAND_Ecc_P1024o               (1 << 26)
 +#define NAND_Ecc_P2048o               (1 << 27)
 +
 +#define TF(value)     (value ? 1 : 0)
 +
 +#define P2048e(a)     (TF(a & NAND_Ecc_P2048e)        << 0 )
 +#define P2048o(a)     (TF(a & NAND_Ecc_P2048o)        << 1 )
 +#define P1e(a)                (TF(a & NAND_Ecc_P1e)           << 2 )
 +#define P1o(a)                (TF(a & NAND_Ecc_P1o)           << 3 )
 +#define P2e(a)                (TF(a & NAND_Ecc_P2e)           << 4 )
 +#define P2o(a)                (TF(a & NAND_Ecc_P2o)           << 5 )
 +#define P4e(a)                (TF(a & NAND_Ecc_P4e)           << 6 )
 +#define P4o(a)                (TF(a & NAND_Ecc_P4o)           << 7 )
 +
 +#define P8e(a)                (TF(a & NAND_Ecc_P8e)           << 0 )
 +#define P8o(a)                (TF(a & NAND_Ecc_P8o)           << 1 )
 +#define P16e(a)               (TF(a & NAND_Ecc_P16e)          << 2 )
 +#define P16o(a)               (TF(a & NAND_Ecc_P16o)          << 3 )
 +#define P32e(a)               (TF(a & NAND_Ecc_P32e)          << 4 )
 +#define P32o(a)               (TF(a & NAND_Ecc_P32o)          << 5 )
 +#define P64e(a)               (TF(a & NAND_Ecc_P64e)          << 6 )
 +#define P64o(a)               (TF(a & NAND_Ecc_P64o)          << 7 )
 +
 +#define P128e(a)      (TF(a & NAND_Ecc_P128e)         << 0 )
 +#define P128o(a)      (TF(a & NAND_Ecc_P128o)         << 1 )
 +#define P256e(a)      (TF(a & NAND_Ecc_P256e)         << 2 )
 +#define P256o(a)      (TF(a & NAND_Ecc_P256o)         << 3 )
 +#define P512e(a)      (TF(a & NAND_Ecc_P512e)         << 4 )
 +#define P512o(a)      (TF(a & NAND_Ecc_P512o)         << 5 )
 +#define P1024e(a)     (TF(a & NAND_Ecc_P1024e)        << 6 )
 +#define P1024o(a)     (TF(a & NAND_Ecc_P1024o)        << 7 )
 +
 +#define P8e_s(a)      (TF(a & NAND_Ecc_P8e)           << 0 )
 +#define P8o_s(a)      (TF(a & NAND_Ecc_P8o)           << 1 )
 +#define P16e_s(a)     (TF(a & NAND_Ecc_P16e)          << 2 )
 +#define P16o_s(a)     (TF(a & NAND_Ecc_P16o)          << 3 )
 +#define P1e_s(a)      (TF(a & NAND_Ecc_P1e)           << 4 )
 +#define P1o_s(a)      (TF(a & NAND_Ecc_P1o)           << 5 )
 +#define P2e_s(a)      (TF(a & NAND_Ecc_P2e)           << 6 )
 +#define P2o_s(a)      (TF(a & NAND_Ecc_P2o)           << 7 )
 +
 +#define P4e_s(a)      (TF(a & NAND_Ecc_P4e)           << 0 )
 +#define P4o_s(a)      (TF(a & NAND_Ecc_P4o)           << 1 )
 +
 +extern struct nand_oobinfo jffs2_oobinfo;
 +
 +/*
 + * MTD structure for OMAP board
 + */
 +static struct mtd_info *omap_mtd;
 +static struct clk *omap_nand_clk;
 +static int omap_nand_dma_ch;
 +static struct completion omap_nand_dma_comp;
 +static unsigned long omap_nand_base = io_p2v(NAND_BASE);
 +
 +static inline u32 nand_read_reg(int idx)
 +{
 +      return __raw_readl(omap_nand_base + idx);
 +}
 +
 +static inline void nand_write_reg(int idx, u32 val)
 +{
 +      __raw_writel(val, omap_nand_base + idx);
 +}
 +
 +static inline u8 nand_read_reg8(int idx)
 +{
 +      return __raw_readb(omap_nand_base + idx);
 +}
 +
 +static inline void nand_write_reg8(int idx, u8 val)
 +{
 +      __raw_writeb(val, omap_nand_base + idx);
 +}
 +
 +static void omap_nand_select_chip(struct mtd_info *mtd, int chip)
 +{
 +      u32 l;
 +
 +      switch(chip) {
 +      case -1:
 +              l = nand_read_reg(NND_CTRL);
 +              l |= (1 << 8) | (1 << 10) | (1 << 12) | (1 << 14);
 +              nand_write_reg(NND_CTRL, l);
 +              break;
 +      case 0:
 +              /* Also CS1, CS2, CS4 would be available */
 +              l = nand_read_reg(NND_CTRL);
 +              l &= ~(1 << 8);
 +              nand_write_reg(NND_CTRL, l);
 +              break;
 +      default:
 +              BUG();
 +      }
 +}
 +
 +static void nand_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      complete((struct completion *) data);
 +}
 +
 +static void omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 +                                         unsigned int u32_count, int is_write)
 +{
 +      const int block_size = 16;
 +      unsigned int block_count, len;
 +      int dma_ch;
 +      unsigned long fifo_reg, timeout, jiffies_before, jiffies_spent;
 +      static unsigned long max_jiffies = 0;
 +
 +      dma_ch = omap_nand_dma_ch;
 +      block_count = u32_count * 4 / block_size;
 +      nand_write_reg(NND_STATUS, 0x0f);
 +      nand_write_reg(NND_FIFOCTRL, (block_size << 24) | block_count);
 +      fifo_reg = NAND_BASE + NND_FIFO;
 +      if (is_write) {
 +              omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB,
 +                                       OMAP_DMA_AMODE_CONSTANT, fifo_reg,
 +                                       0, 0);
 +              omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF,
 +                                      OMAP_DMA_AMODE_POST_INC,
 +                                      virt_to_phys(addr),
 +                                      0, 0);
 +//            omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
 +              /* Set POSTWRITE bit */
 +              nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 16));
 +      } else {
 +              omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB,
 +                                      OMAP_DMA_AMODE_CONSTANT, fifo_reg,
 +                                      0, 0);
 +              omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF,
 +                                       OMAP_DMA_AMODE_POST_INC,
 +                                       virt_to_phys(addr),
 +                                       0, 0);
 +//            omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_8);
 +              /* Set PREFETCH bit */
 +              nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
 +      }
 +      omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, block_size / 4,
 +                                   block_count, OMAP_DMA_SYNC_FRAME,
 +                                   0, 0);
 +      init_completion(&omap_nand_dma_comp);
 +
 +      len = u32_count << 2;
 +      dma_cache_maint(addr, len, DMA_TO_DEVICE);
 +      omap_start_dma(dma_ch);
 +      jiffies_before = jiffies;
 +      timeout = wait_for_completion_timeout(&omap_nand_dma_comp,
 +                                            msecs_to_jiffies(1000));
 +      jiffies_spent = (unsigned long)((long)jiffies - (long)jiffies_before);
 +      if (jiffies_spent > max_jiffies)
 +              max_jiffies = jiffies_spent;
 +
 +      if (timeout == 0) {
 +              printk(KERN_WARNING "omap-hw-nand: DMA timeout after %u ms, max. seen latency %u ms\n",
 +                     jiffies_to_msecs(jiffies_spent),
 +                     jiffies_to_msecs(max_jiffies));
 +      }
 +      if (!is_write)
 +              dma_cache_maint(addr, len, DMA_FROM_DEVICE);
 +
 +      nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~((1 << 16) | (1 << 17)));
 +}
 +
 +static void fifo_read(u32 *out, unsigned int len)
 +{
 +      const int block_size = 16;
 +      unsigned long status_reg, fifo_reg;
 +      int c;
 +
 +      status_reg = omap_nand_base + NND_STATUS;
 +      fifo_reg = omap_nand_base + NND_FIFO;
 +      len = len * 4 / block_size;
 +      nand_write_reg(NND_FIFOCTRL, (block_size << 24) | len);
 +      nand_write_reg(NND_STATUS, 0x0f);
 +      nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
 +      c = block_size / 4;
 +      while (len--) {
 +              int i;
 +
 +              while ((__raw_readl(status_reg) & (1 << 2)) == 0);
 +              __raw_writel(0x0f, status_reg);
 +              for (i = 0; i < c; i++) {
 +                      u32 l = __raw_readl(fifo_reg);
 +                      *out++ = l;
 +              }
 +      }
 +      nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~(1 << 17));
 +      nand_write_reg(NND_STATUS, 0x0f);
 +}
 +
 +static void omap_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 +{
 +      unsigned long access_reg;
 +
 +      if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
 +              int u32_count = len >> 2;
 +              u32 *dest = (u32 *) buf;
 +              /* If the transfer is big enough and the length divisible by
 +               * 16, we try to use DMA transfer, or FIFO copy in case of
 +               * DMA failure (e.g. all channels busy) */
 +              if (u32_count > 64 && (u32_count & 3) == 0) {
 +                      if (omap_nand_dma_ch >= 0) {
 +                              omap_nand_dma_transfer(mtd, buf, u32_count, 0);
 +                              return;
 +                      }
 +                      /* In case of an error, fallback to FIFO copy */
 +                      fifo_read((u32 *) buf, u32_count);
 +                      return;
 +              }
 +              access_reg = omap_nand_base + NND_ACCESS;
 +              /* Small buffers we just read directly */
 +              while (u32_count--)
 +                      *dest++ = __raw_readl(access_reg);
 +      } else {
 +              /* If we're not word-aligned, we use byte copy */
 +              access_reg = omap_nand_base + NND_ACCESS;
 +              while (len--)
 +                      *buf++ = __raw_readb(access_reg);
 +      }
 +}
 +
 +static void omap_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 +{
 +      if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
 +              const u32 *src = (const u32 *) buf;
 +
 +              len >>= 2;
 +#if 0
 +              /* If the transfer is big enough and length divisible by 16,
 +               * we try to use DMA transfer. */
 +              if (len > 256 / 4 && (len & 3) == 0) {
 +                      if (omap_nand_dma_transfer(mtd, (void *) buf, len, 1) == 0)
 +                              return;
 +                      /* In case of an error, fallback to CPU copy */
 +              }
 +#endif
 +              while (len--)
 +                      nand_write_reg(NND_ACCESS, *src++);
 +      } else {
 +              while (len--)
 +                      nand_write_reg8(NND_ACCESS, *buf++);
 +      }
 +}
 +
 +static int omap_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 +{
 +      if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
 +              const u32 *dest = (const u32 *) buf;
 +              len >>= 2;
 +              while (len--)
 +                      if (*dest++ != nand_read_reg(NND_ACCESS))
 +                              return -EFAULT;
 +      } else {
 +              while (len--)
 +                      if (*buf++ != nand_read_reg8(NND_ACCESS))
 +                              return -EFAULT;
 +      }
 +      return 0;
 +}
 +
 +static u_char omap_nand_read_byte(struct mtd_info *mtd)
 +{
 +      return nand_read_reg8(NND_ACCESS);
 +}
 +
 +static int omap_nand_dev_ready(struct mtd_info *mtd)
 +{
 +      u32 l;
 +
 +      l = nand_read_reg(NND_READY);
 +      return l & 0x01;
 +}
 +
 +static int nand_write_command(u8 cmd, u32 addr, int addr_valid)
 +{
 +      if (addr_valid) {
 +              nand_write_reg(NND_ADDR_SRC, addr);
 +              nand_write_reg8(NND_COMMAND, cmd);
 +      } else {
 +              nand_write_reg(NND_ADDR_SRC, 0);
 +              nand_write_reg8(NND_COMMAND_SEC, cmd);
 +      }
 +      while (!omap_nand_dev_ready(NULL));
 +      return 0;
 +}
 +
 +/*
 + * Send command to NAND device
 + */
 +static void omap_nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 +{
 +      struct nand_chip *this = mtd->priv;
 +
 +      /*
 +       * Write out the command to the device.
 +       */
 +      if (command == NAND_CMD_SEQIN) {
 +              int readcmd;
 +
 +              if (column >= mtd->writesize) {
 +                      /* OOB area */
 +                      column -= mtd->writesize;
 +                      readcmd = NAND_CMD_READOOB;
 +              } else if (column < 256) {
 +                      /* First 256 bytes --> READ0 */
 +                      readcmd = NAND_CMD_READ0;
 +              } else {
 +                      column -= 256;
 +                      readcmd = NAND_CMD_READ1;
 +              }
 +              nand_write_command(readcmd, 0, 0);
 +      }
 +      switch (command) {
 +      case NAND_CMD_RESET:
 +      case NAND_CMD_PAGEPROG:
 +      case NAND_CMD_STATUS:
 +      case NAND_CMD_ERASE2:
 +              nand_write_command(command, 0, 0);
 +              break;
 +      case NAND_CMD_ERASE1:
 +              nand_write_command(command, ((page_addr & 0xFFFFFF00) << 1) | (page_addr & 0XFF), 1);
 +              break;
 +      default:
 +              nand_write_command(command, (page_addr << this->page_shift) | column, 1);
 +      }
 +}
 +
 +static void omap_nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 +{
 +      struct nand_chip *this = mtd->priv;
 +
 +      if (command == NAND_CMD_READOOB) {
 +              column += mtd->writesize;
 +              command = NAND_CMD_READ0;
 +      }
 +      switch (command) {
 +      case NAND_CMD_RESET:
 +      case NAND_CMD_PAGEPROG:
 +      case NAND_CMD_STATUS:
 +      case NAND_CMD_ERASE2:           
 +              nand_write_command(command, 0, 0);
 +              break;
 +      case NAND_CMD_ERASE1:
 +              nand_write_command(command, page_addr << this->page_shift >> 11, 1);
 +              break;
 +      default:
 +              nand_write_command(command, (page_addr << 16) | column, 1);
 +      }
 +      if (command == NAND_CMD_READ0)
 +              nand_write_command(NAND_CMD_READSTART, 0, 0);
 +}
 +
 +/*
 + * Generate non-inverted ECC bytes.
 + *
 + * Using noninverted ECC can be considered ugly since writing a blank
 + * page ie. padding will clear the ECC bytes. This is no problem as long
 + * nobody is trying to write data on the seemingly unused page.
 + *
 + * Reading an erased page will produce an ECC mismatch between
 + * generated and read ECC bytes that has to be dealt with separately.
 + */
 +static int omap_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 +{
 +      u32 l;
 +      int reg;
 +      int n;
 +      struct nand_chip *this = mtd->priv;
 +
 +      /* Ex NAND_ECC_HW12_2048 */
 +      if ((this->ecc.mode == NAND_ECC_HW) && (this->ecc.size  == 2048))
 +              n = 4;
 +      else
 +              n = 1;
 +      reg = NND_ECC_START;
 +      while (n--) {
 +              l = nand_read_reg(reg);
 +              *ecc_code++ = l;          // P128e, ..., P1e
 +              *ecc_code++ = l >> 16;    // P128o, ..., P1o
 +              // P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e
 +              *ecc_code++ = ((l >> 8) & 0x0f) | ((l >> 20) & 0xf0);
 +              reg += 4;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * This function will generate true ECC value, which can be used
 + * when correcting data read from NAND flash memory core
 + */
 +static void gen_true_ecc(u8 *ecc_buf)
 +{
 +      u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8);
 +
 +      ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp) );
 +      ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
 +      ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
 +}
 +
 +/*
 + * This function compares two ECC's and indicates if there is an error.
 + * If the error can be corrected it will be corrected to the buffer
 + */
 +static int omap_nand_compare_ecc(u8 *ecc_data1,   /* read from NAND memory */
 +                               u8 *ecc_data2,   /* read from register */
 +                               u8 *page_data)
 +{
 +      uint   i;
 +      u8     tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
 +      u8     comp0_bit[8], comp1_bit[8], comp2_bit[8];
 +      u8     ecc_bit[24];
 +      u8     ecc_sum = 0;
 +      u8     find_bit = 0;
 +      uint   find_byte = 0;
 +      int    isEccFF;
 +
 +      isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF);
 +
 +      gen_true_ecc(ecc_data1);
 +      gen_true_ecc(ecc_data2);
 +
 +      for (i = 0; i <= 2; i++) {
 +              *(ecc_data1 + i) = ~(*(ecc_data1 + i));
 +              *(ecc_data2 + i) = ~(*(ecc_data2 + i));
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp0_bit[i]      = *ecc_data1 % 2;
 +              *ecc_data1       = *ecc_data1 / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp1_bit[i]      = *(ecc_data1 + 1) % 2;
 +              *(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp2_bit[i]      = *(ecc_data1 + 2) % 2;
 +              *(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp0_bit[i]     = *ecc_data2 % 2;
 +              *ecc_data2       = *ecc_data2 / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp1_bit[i]     = *(ecc_data2 + 1) % 2;
 +              *(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp2_bit[i]     = *(ecc_data2 + 2) % 2;
 +              *(ecc_data2 + 2) = *(ecc_data2 + 2) / 2;
 +      }
 +
 +      for (i = 0; i< 6; i++ )
 +              ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
 +
 +      for (i = 0; i < 8; i++)
 +              ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
 +
 +      for (i = 0; i < 8; i++)
 +              ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
 +
 +      ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
 +      ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
 +
 +      for (i = 0; i < 24; i++)
 +              ecc_sum += ecc_bit[i];
 +
 +      switch (ecc_sum) {
 +      case 0:
 +              /* Not reached because this function is not called if
 +                 ECC values are equal */
 +              return 0;
 +
 +      case 1:
 +              /* Uncorrectable error */
 +              DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
 +              return -1;
 +
 +      case 12:
 +              /* Correctable error */
 +              find_byte = (ecc_bit[23] << 8) + 
 +                          (ecc_bit[21] << 7) + 
 +                          (ecc_bit[19] << 6) +
 +                          (ecc_bit[17] << 5) +
 +                          (ecc_bit[15] << 4) +
 +                          (ecc_bit[13] << 3) +
 +                          (ecc_bit[11] << 2) +
 +                          (ecc_bit[9]  << 1) +
 +                          ecc_bit[7];
 +
 +              find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
 +
 +              DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
 +
 +              page_data[find_byte] ^= (1 << find_bit);
 +
 +              return 0;
 +      default:
 +              if (isEccFF) {
 +                      if (ecc_data2[0] == 0 && ecc_data2[1] == 0 && ecc_data2[2] == 0)
 +                              return 0;
 +              } 
 +              DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
 +              return -1;
 +      }
 +}
 +
 +static int omap_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 +{
 +      struct nand_chip *this;
 +      int block_count = 0, i, r;
 +
 +      this = mtd->priv;
 +      /* Ex NAND_ECC_HW12_2048 */
 +      if ((this->ecc.mode == NAND_ECC_HW) && (this->ecc.size  == 2048))
 +              block_count = 4;
 +      else
 +              block_count = 1;
 +      for (i = 0; i < block_count; i++) {
 +              if (memcmp(read_ecc, calc_ecc, 3) != 0) {
 +                      r = omap_nand_compare_ecc(read_ecc, calc_ecc, dat);
 +                      if (r < 0)
 +                              return r;
 +              }
 +              read_ecc += 3;
 +              calc_ecc += 3;
 +              dat += 512;
 +      }
 +      return 0;
 +}
 +
 +static void omap_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 +{
 +      nand_write_reg(NND_RESET, 0x01);
 +}
 +
 +#ifdef CONFIG_MTD_CMDLINE_PARTS
 +
 +extern int mtdpart_setup(char *);
 +
 +static int __init add_dynamic_parts(struct mtd_info *mtd)
 +{
 +      static const char *part_parsers[] = { "cmdlinepart", NULL };
 +      struct mtd_partition *parts;
 +      const struct omap_flash_part_str_config *cfg;
 +      char *part_str = NULL;
 +      size_t part_str_len;
 +      int c;
 +
 +      cfg = omap_get_var_config(OMAP_TAG_FLASH_PART_STR, &part_str_len);
 +      if (cfg != NULL) {
 +              part_str = kmalloc(part_str_len + 1, GFP_KERNEL);
 +              if (part_str == NULL)
 +                      return -ENOMEM;
 +              memcpy(part_str, cfg->part_table, part_str_len);
 +              part_str[part_str_len] = '\0';
 +              mtdpart_setup(part_str);
 +      }
 +      c = parse_mtd_partitions(omap_mtd, part_parsers, &parts, 0);
 +      if (part_str != NULL) {
 +              mtdpart_setup(NULL);
 +              kfree(part_str);
 +      }
 +      if (c <= 0)
 +              return -1;
 +
 +      add_mtd_partitions(mtd, parts, c);
 +
 +      return 0;
 +}
 +
 +#else
 +
 +static inline int add_dynamic_parts(struct mtd_info *mtd)
 +{
 +      return -1;
 +}
 +
 +#endif
 +
 +static inline int calc_psc(int ns, int cycle_ps)
 +{
 +      return (ns * 1000 + (cycle_ps - 1)) / cycle_ps;
 +}
 +
 +static void set_psc_regs(int psc_ns, int psc1_ns, int psc2_ns)
 +{
 +      int psc[3], i;
 +      unsigned long rate, ps;
 +
 +      rate = clk_get_rate(omap_nand_clk);
 +      ps = 1000000000 / (rate / 1000);
 +      psc[0] = calc_psc(psc_ns, ps);
 +      psc[1] = calc_psc(psc1_ns, ps);
 +      psc[2] = calc_psc(psc2_ns, ps);
 +      for (i = 0; i < 3; i++) {
 +              if (psc[i] < 2)
 +                      psc[i] = 2;
 +              else if (psc[i] > 256)
 +                      psc[i] = 256;
 +      }
 +      nand_write_reg(NND_PSC_CLK, psc[0] - 1);
 +      nand_write_reg(NND_PSC1_CLK, psc[1] - 1);
 +      nand_write_reg(NND_PSC2_CLK, psc[2] - 1);
 +      printk(KERN_INFO "omap-hw-nand: using PSC values %d, %d, %d\n", psc[0], psc[1], psc[2]);
 +}
 +
 +/*
 + * Main initialization routine
 + */
 +static int __init omap_nand_init(void)
 +{
 +      struct nand_chip *this;
 +      int err = 0;
 +      u32 l;
 +
 +      omap_nand_clk = clk_get(NULL, "armper_ck");
 +      BUG_ON(omap_nand_clk == NULL);
 +      clk_enable(omap_nand_clk);
 +
 +      l = nand_read_reg(NND_REVISION);        
 +      printk(KERN_INFO "omap-hw-nand: OMAP NAND Controller rev. %d.%d\n", l>>4, l & 0xf);
 +
 +      /* Reset the NAND Controller */
 +      nand_write_reg(NND_SYSCFG, 0x02);
 +      while ((nand_read_reg(NND_SYSSTATUS) & 0x01) == 0);
 +
 +      /* No Prefetch, no postwrite, write prot & enable pairs disabled,
 +         addres counter set to send 4 byte addresses to flash,
 +         A8 is set not to be sent to flash (erase addre needs formatting),
 +         choose little endian, enable 512 byte ECC logic,        
 +       */
 +      nand_write_reg(NND_CTRL, 0xFF01);
 +
 +      /* Allocate memory for MTD device structure and private data */
 +      omap_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 +      if (!omap_mtd) {
 +              printk(KERN_WARNING "omap-hw-nand: Unable to allocate OMAP NAND MTD device structure.\n");
 +              err = -ENOMEM;
 +              goto free_clock;
 +      }
 +#if 1
 +      err = omap_request_dma(OMAP_DMA_NAND, "NAND", nand_dma_cb,
 +                             &omap_nand_dma_comp, &omap_nand_dma_ch);
 +      if (err < 0) {
 +              printk(KERN_WARNING "omap-hw-nand: Unable to reserve DMA channel\n");
 +              omap_nand_dma_ch = -1;
 +      }
 +#else
 +      omap_nand_dma_ch = -1;
 +#endif
 +      /* Get pointer to private data */
 +      this = (struct nand_chip *) (&omap_mtd[1]);
 +
 +      /* Initialize structures */
 +      memset((char *) omap_mtd, 0, sizeof(struct mtd_info));
 +      memset((char *) this, 0, sizeof(struct nand_chip));
 +
 +      /* Link the private data with the MTD structure */
 +      omap_mtd->priv = this;
 +      omap_mtd->name = "omap-nand";
 +
 +      this->options = NAND_SKIP_BBTSCAN;
 +
 +      /* Used from chip select and nand_command() */
 +      this->read_byte = omap_nand_read_byte;
 +
 +      this->select_chip   = omap_nand_select_chip;
 +      this->dev_ready     = omap_nand_dev_ready;
 +      this->chip_delay    = 0;
 +      this->ecc.mode      = NAND_ECC_HW;
 +      this->ecc.bytes     = 3;
 +      this->ecc.size      = 512;
 +      this->cmdfunc       = omap_nand_command;
 +      this->write_buf     = omap_nand_write_buf;
 +      this->read_buf      = omap_nand_read_buf;
 +      this->verify_buf    = omap_nand_verify_buf;
 +      this->ecc.calculate = omap_nand_calculate_ecc;
 +      this->ecc.correct   = omap_nand_correct_data;
 +      this->ecc.hwctl     = omap_nand_enable_hwecc;
 +
 +      nand_write_reg(NND_SYSCFG, 0x1); /* Enable auto idle */
 +      nand_write_reg(NND_PSC_CLK, 10);
 +      /* Scan to find existance of the device */
 +      if (nand_scan(omap_mtd, 1)) {
 +              err = -ENXIO;
 +              goto out_mtd;
 +      }
 +
 +      set_psc_regs(25, 15, 35);
 +      if (this->page_shift == 11) {
 +              this->cmdfunc = omap_nand_command_lp;
 +              l = nand_read_reg(NND_CTRL);
 +              l |= 1 << 4; /* Set the A8 bit in CTRL reg */
 +              nand_write_reg(NND_CTRL, l);
 +              this->ecc.mode = NAND_ECC_HW;
 +              this->ecc.steps = 1;
 +              this->ecc.size = 2048;
 +              this->ecc.bytes = 12;
 +              nand_write_reg(NND_ECC_SELECT, 6);
 +      }
 +
 +      /* We have to do bbt scanning ourselves */
 +      if (this->scan_bbt (omap_mtd)) {
 +              err = -ENXIO;
 +              goto out_mtd;
 +      }
 +
 +      err = add_dynamic_parts(omap_mtd);
 +      if (err < 0) {
 +              printk(KERN_ERR "omap-hw-nand: no partitions defined\n");
 +              err = -ENODEV;
 +              nand_release(omap_mtd);
 +              goto out_mtd;
 +      }
 +      /* init completed */
 +      return 0;
 +out_mtd:
 +      if (omap_nand_dma_ch >= 0)
 +              omap_free_dma(omap_nand_dma_ch);
 +      kfree(omap_mtd);
 +free_clock:
 +      clk_put(omap_nand_clk);
 +      return err;
 +}
 +
 +module_init(omap_nand_init);
 +
 +/*
 + * Clean up routine
 + */
 +static void __exit omap_nand_cleanup (void)
 +{
 +      clk_disable(omap_nand_clk);
 +      clk_put(omap_nand_clk);
 +      nand_release(omap_mtd);
 +      kfree(omap_mtd);
 +}
 +
 +module_exit(omap_nand_cleanup);
 +
index e9663af457c94e15b8092e144e19226cc3f09bd1,0000000000000000000000000000000000000000..63a79682802ab4bd6cf7f1323036e87fb7c32429
mode 100644,000000..100644
--- /dev/null
@@@ -1,186 -1,0 +1,186 @@@
- #include <asm/hardware.h>
 +/*
 + * drivers/mtd/nand/omap-nand-flash.c
 + *
 + * Copyright (c) 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
 + * Copyright (c) 2004 David Brownell
 + *
 + * 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/ioport.h>
 +#include <linux/delay.h>
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/types.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/nand.h>
 +#include <linux/mtd/partitions.h>
 +
 +#include <asm/io.h>
- #include <asm/arch/tc.h>
++#include <mach/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/flash.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/nand.h>
++#include <mach/tc.h>
 +
 +#include <asm/io.h>
++#include <mach/hardware.h>
++#include <mach/nand.h>
 +
 +#define       DRIVER_NAME     "omapnand"
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +static const char *part_probes[] = { "cmdlinepart", NULL };
 +#endif
 +
 +struct omap_nand_info {
 +      struct omap_nand_platform_data *pdata;
 +      struct mtd_partition    *parts;
 +      struct mtd_info         mtd;
 +      struct nand_chip        nand;
 +};
 +
 +/*
 + *    hardware specific access to control-lines
 + *    NOTE:  boards may use different bits for these!!
 + *
 + *    ctrl:
 + *    NAND_NCE: bit 0 - don't care
 + *    NAND_CLE: bit 1 -> bit 1  (0x0002)
 + *    NAND_ALE: bit 2 -> bit 2  (0x0004)
 + */
 +
 +static void omap_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 +{
 +      struct nand_chip *chip = mtd->priv;
 +      unsigned long mask;
 +
 +      if (cmd == NAND_CMD_NONE)
 +              return;
 +
 +      mask = (ctrl & NAND_CLE) ? 0x02 : 0;
 +      if (ctrl & NAND_ALE)
 +              mask |= 0x04;
 +      writeb(cmd, (unsigned long)chip->IO_ADDR_W | mask);
 +}
 +
 +static int omap_nand_dev_ready(struct mtd_info *mtd)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd);
 +
 +      return info->pdata->dev_ready(info->pdata);
 +}
 +
 +static int __devinit omap_nand_probe(struct platform_device *pdev)
 +{
 +      struct omap_nand_info           *info;
 +      struct omap_nand_platform_data  *pdata = pdev->dev.platform_data;
 +      struct resource                 *res = pdev->resource;
 +      unsigned long                   size = res->end - res->start + 1;
 +      int                             err;
 +
 +      info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
 +      if (!info)
 +              return -ENOMEM;
 +
 +      if (!request_mem_region(res->start, size, pdev->dev.driver->name)) {
 +              err = -EBUSY;
 +              goto out_free_info;
 +      }
 +
 +      info->nand.IO_ADDR_R = ioremap(res->start, size);
 +      if (!info->nand.IO_ADDR_R) {
 +              err = -ENOMEM;
 +              goto out_release_mem_region;
 +      }
 +      info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
 +      info->nand.cmd_ctrl = omap_nand_hwcontrol;
 +      info->nand.ecc.mode = NAND_ECC_SOFT;
 +      info->nand.options = pdata->options;
 +      if (pdata->dev_ready)
 +              info->nand.dev_ready = omap_nand_dev_ready;
 +      else
 +              info->nand.chip_delay = 20;
 +
 +      info->mtd.name = pdev->dev.bus_id;
 +      info->mtd.priv = &info->nand;
 +
 +      info->pdata = pdata;
 +
 +      /* DIP switches on H2 and some other boards change between 8 and 16 bit
 +       * bus widths for flash.  Try the other width if the first try fails.
 +       */
 +      if (nand_scan(&info->mtd, 1)) {
 +              info->nand.options ^= NAND_BUSWIDTH_16;
 +              if (nand_scan(&info->mtd, 1)) {
 +                      err = -ENXIO;
 +                      goto out_iounmap;
 +              }
 +      }
 +      info->mtd.owner = THIS_MODULE;
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 +      if (err > 0)
 +              add_mtd_partitions(&info->mtd, info->parts, err);
 +      else if (err < 0 && pdata->parts)
 +              add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
 +      else
 +#endif
 +              add_mtd_device(&info->mtd);
 +
 +      platform_set_drvdata(pdev, info);
 +
 +      return 0;
 +
 +out_iounmap:
 +      iounmap(info->nand.IO_ADDR_R);
 +out_release_mem_region:
 +      release_mem_region(res->start, size);
 +out_free_info:
 +      kfree(info);
 +
 +      return err;
 +}
 +
 +static int omap_nand_remove(struct platform_device *pdev)
 +{
 +      struct omap_nand_info *info = platform_get_drvdata(pdev);
 +
 +      platform_set_drvdata(pdev, NULL);
 +      /* Release NAND device, its internal structures and partitions */
 +      nand_release(&info->mtd);
 +      iounmap(info->nand.IO_ADDR_R);
 +      kfree(info);
 +      return 0;
 +}
 +
 +static struct platform_driver omap_nand_driver = {
 +      .probe          = omap_nand_probe,
 +      .remove         = omap_nand_remove,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +      },
 +};
 +MODULE_ALIAS(DRIVER_NAME);
 +
 +static int __init omap_nand_init(void)
 +{
 +      return platform_driver_register(&omap_nand_driver);
 +}
 +
 +static void __exit omap_nand_exit(void)
 +{
 +      platform_driver_unregister(&omap_nand_driver);
 +}
 +
 +module_init(omap_nand_init);
 +module_exit(omap_nand_exit);
 +
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Jian Zhang <jzhang@ti.com> (and others)");
 +MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
 +
index b4ce8085f27fee987bfa927e4224402fea53aebb,0000000000000000000000000000000000000000..a33944c9d5fa0a36715f2ef582de47a6650c3ae3
mode 100644,000000..100644
--- /dev/null
@@@ -1,757 -1,0 +1,757 @@@
- #include <asm/arch/gpmc.h>
- #include <asm/arch/nand.h>
 +/*
 + * drivers/mtd/nand/omap2.c
 + *
 + * Copyright (c) 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
 + * Copyright (c) 2004 Micron Technology Inc.
 + * Copyright (c) 2004 David Brownell
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/platform_device.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/delay.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/nand.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/io.h>
 +
 +#include <asm/dma.h>
 +
++#include <mach/gpmc.h>
++#include <mach/nand.h>
 +
 +#define GPMC_IRQ_STATUS               0x18
 +#define GPMC_ECC_CONFIG               0x1F4
 +#define GPMC_ECC_CONTROL      0x1F8
 +#define GPMC_ECC_SIZE_CONFIG  0x1FC
 +#define GPMC_ECC1_RESULT      0x200
 +
 +#define       DRIVER_NAME     "omap2-nand"
 +#define       NAND_IO_SIZE    SZ_4K
 +
 +#define       NAND_WP_ON      1
 +#define       NAND_WP_OFF     0
 +#define NAND_WP_BIT   0x00000010
 +#define WR_RD_PIN_MONITORING  0x00600000
 +
 +#define       GPMC_BUF_FULL   0x00000001
 +#define       GPMC_BUF_EMPTY  0x00000000
 +
 +#define NAND_Ecc_P1e          (1 << 0)
 +#define NAND_Ecc_P2e          (1 << 1)
 +#define NAND_Ecc_P4e          (1 << 2)
 +#define NAND_Ecc_P8e          (1 << 3)
 +#define NAND_Ecc_P16e         (1 << 4)
 +#define NAND_Ecc_P32e         (1 << 5)
 +#define NAND_Ecc_P64e         (1 << 6)
 +#define NAND_Ecc_P128e                (1 << 7)
 +#define NAND_Ecc_P256e                (1 << 8)
 +#define NAND_Ecc_P512e                (1 << 9)
 +#define NAND_Ecc_P1024e               (1 << 10)
 +#define NAND_Ecc_P2048e               (1 << 11)
 +
 +#define NAND_Ecc_P1o          (1 << 16)
 +#define NAND_Ecc_P2o          (1 << 17)
 +#define NAND_Ecc_P4o          (1 << 18)
 +#define NAND_Ecc_P8o          (1 << 19)
 +#define NAND_Ecc_P16o         (1 << 20)
 +#define NAND_Ecc_P32o         (1 << 21)
 +#define NAND_Ecc_P64o         (1 << 22)
 +#define NAND_Ecc_P128o                (1 << 23)
 +#define NAND_Ecc_P256o                (1 << 24)
 +#define NAND_Ecc_P512o                (1 << 25)
 +#define NAND_Ecc_P1024o               (1 << 26)
 +#define NAND_Ecc_P2048o               (1 << 27)
 +
 +#define TF(value)     (value ? 1 : 0)
 +
 +#define P2048e(a)     (TF(a & NAND_Ecc_P2048e)        << 0)
 +#define P2048o(a)     (TF(a & NAND_Ecc_P2048o)        << 1)
 +#define P1e(a)                (TF(a & NAND_Ecc_P1e)           << 2)
 +#define P1o(a)                (TF(a & NAND_Ecc_P1o)           << 3)
 +#define P2e(a)                (TF(a & NAND_Ecc_P2e)           << 4)
 +#define P2o(a)                (TF(a & NAND_Ecc_P2o)           << 5)
 +#define P4e(a)                (TF(a & NAND_Ecc_P4e)           << 6)
 +#define P4o(a)                (TF(a & NAND_Ecc_P4o)           << 7)
 +
 +#define P8e(a)                (TF(a & NAND_Ecc_P8e)           << 0)
 +#define P8o(a)                (TF(a & NAND_Ecc_P8o)           << 1)
 +#define P16e(a)               (TF(a & NAND_Ecc_P16e)          << 2)
 +#define P16o(a)               (TF(a & NAND_Ecc_P16o)          << 3)
 +#define P32e(a)               (TF(a & NAND_Ecc_P32e)          << 4)
 +#define P32o(a)               (TF(a & NAND_Ecc_P32o)          << 5)
 +#define P64e(a)               (TF(a & NAND_Ecc_P64e)          << 6)
 +#define P64o(a)               (TF(a & NAND_Ecc_P64o)          << 7)
 +
 +#define P128e(a)      (TF(a & NAND_Ecc_P128e)         << 0)
 +#define P128o(a)      (TF(a & NAND_Ecc_P128o)         << 1)
 +#define P256e(a)      (TF(a & NAND_Ecc_P256e)         << 2)
 +#define P256o(a)      (TF(a & NAND_Ecc_P256o)         << 3)
 +#define P512e(a)      (TF(a & NAND_Ecc_P512e)         << 4)
 +#define P512o(a)      (TF(a & NAND_Ecc_P512o)         << 5)
 +#define P1024e(a)     (TF(a & NAND_Ecc_P1024e)        << 6)
 +#define P1024o(a)     (TF(a & NAND_Ecc_P1024o)        << 7)
 +
 +#define P8e_s(a)      (TF(a & NAND_Ecc_P8e)           << 0)
 +#define P8o_s(a)      (TF(a & NAND_Ecc_P8o)           << 1)
 +#define P16e_s(a)     (TF(a & NAND_Ecc_P16e)          << 2)
 +#define P16o_s(a)     (TF(a & NAND_Ecc_P16o)          << 3)
 +#define P1e_s(a)      (TF(a & NAND_Ecc_P1e)           << 4)
 +#define P1o_s(a)      (TF(a & NAND_Ecc_P1o)           << 5)
 +#define P2e_s(a)      (TF(a & NAND_Ecc_P2e)           << 6)
 +#define P2o_s(a)      (TF(a & NAND_Ecc_P2o)           << 7)
 +
 +#define P4e_s(a)      (TF(a & NAND_Ecc_P4e)           << 0)
 +#define P4o_s(a)      (TF(a & NAND_Ecc_P4o)           << 1)
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +static const char *part_probes[] = { "cmdlinepart", NULL };
 +#endif
 +
 +struct omap_nand_info {
 +      struct nand_hw_control          controller;
 +      struct omap_nand_platform_data  *pdata;
 +      struct mtd_info                 mtd;
 +      struct mtd_partition            *parts;
 +      struct nand_chip                nand;
 +      struct platform_device          *pdev;
 +
 +      int                             gpmc_cs;
 +      unsigned long                   phys_base;
 +      void __iomem                    *gpmc_cs_baseaddr;
 +      void __iomem                    *gpmc_baseaddr;
 +};
 +
 +/*
 + * omap_nand_wp - This function enable or disable the Write Protect feature on
 + * NAND device
 + * @mtd: MTD device structure
 + * @mode: WP ON/OFF
 + */
 +static void omap_nand_wp(struct mtd_info *mtd, int mode)
 +{
 +      struct omap_nand_info *info = container_of(mtd,
 +                                              struct omap_nand_info, mtd);
 +
 +      unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
 +
 +      if (mode)
 +              config &= ~(NAND_WP_BIT);       /* WP is ON */
 +      else
 +              config |= (NAND_WP_BIT);        /* WP is OFF */
 +
 +      __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
 +}
 +
 +/*
 + * hardware specific access to control-lines
 + * NOTE: boards may use different bits for these!!
 + *
 + * ctrl:
 + * NAND_NCE: bit 0 - don't care
 + * NAND_CLE: bit 1 -> Command Latch
 + * NAND_ALE: bit 2 -> Address Latch
 + */
 +static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 +{
 +      struct omap_nand_info *info = container_of(mtd,
 +                                      struct omap_nand_info, mtd);
 +      switch (ctrl) {
 +      case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
 +              info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_COMMAND;
 +              info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_DATA;
 +              break;
 +
 +      case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
 +              info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_ADDRESS;
 +              info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_DATA;
 +              break;
 +
 +      case NAND_CTRL_CHANGE | NAND_NCE:
 +              info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_DATA;
 +              info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_DATA;
 +              break;
 +      }
 +
 +      if (cmd != NAND_CMD_NONE)
 +              __raw_writeb(cmd, info->nand.IO_ADDR_W);
 +}
 +
 +/*
 + * omap_read_buf - read data from NAND controller into buffer
 + * @mtd: MTD device structure
 + * @buf: buffer to store date
 + * @len: number of bytes to read
 + */
 +static void omap_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 +{
 +      struct omap_nand_info *info = container_of(mtd,
 +                                      struct omap_nand_info, mtd);
 +      u16 *p = (u16 *) buf;
 +
 +      len >>= 1;
 +
 +      while (len--)
 +              *p++ = cpu_to_le16(readw(info->nand.IO_ADDR_R));
 +}
 +
 +/*
 + * omap_write_buf - write buffer to NAND controller
 + * @mtd: MTD device structure
 + * @buf: data buffer
 + * @len: number of bytes to write
 + */
 +static void omap_write_buf(struct mtd_info *mtd, const u_char * buf, int len)
 +{
 +      struct omap_nand_info *info = container_of(mtd,
 +                                              struct omap_nand_info, mtd);
 +      u16 *p = (u16 *) buf;
 +
 +      len >>= 1;
 +
 +      while (len--) {
 +              writew(cpu_to_le16(*p++), info->nand.IO_ADDR_W);
 +
 +              while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
 +                                              GPMC_STATUS) & GPMC_BUF_FULL));
 +      }
 +}
 +/*
 + * omap_verify_buf - Verify chip data against buffer
 + * @mtd: MTD device structure
 + * @buf: buffer containing the data to compare
 + * @len: number of bytes to compare
 + */
 +static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      u16 *p = (u16 *) buf;
 +
 +      len >>= 1;
 +
 +      while (len--) {
 +
 +              if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R)))
 +                      return -EFAULT;
 +      }
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
 +/*
 + * omap_hwecc_init-Initialize the Hardware ECC for NAND flash in GPMC controller
 + * @mtd: MTD device structure
 + */
 +static void omap_hwecc_init(struct mtd_info *mtd)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      register struct nand_chip *chip = mtd->priv;
 +      unsigned long val = 0x0;
 +
 +      /* Read from ECC Control Register */
 +      val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
 +      /* Clear all ECC | Enable Reg1 */
 +      val = ((0x00000001<<8) | 0x00000001);
 +      __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
 +
 +      /* Read from ECC Size Config Register */
 +      val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
 +      /* ECCSIZE1=512 | Select eccResultsize[0-3] */
 +      val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
 +      __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
 +}
 +
 +/*
 + * gen_true_ecc - This function will generate true ECC value, which can be used
 + * when correcting data read from NAND flash memory core
 + * @ecc_buf: buffer to store ecc code
 + */
 +static void gen_true_ecc(u8 *ecc_buf)
 +{
 +      u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) |
 +              ((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8);
 +
 +      ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) |
 +                      P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
 +      ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) |
 +                      P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
 +      ecc_buf[2] = ~(P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) |
 +                      P1e(tmp) | P2048o(tmp) | P2048e(tmp));
 +}
 +
 +/*
 + * omap_compare_ecc - This function compares two ECC's and indicates if there
 + * is an error. If the error can be corrected it will be corrected to the
 + * buffer
 + * @ecc_data1:  ecc code from nand spare area
 + * @ecc_data2:  ecc code from hardware register obtained from hardware ecc
 + * @page_data:  page data
 + */
 +static int omap_compare_ecc(u8 *ecc_data1,    /* read from NAND memory */
 +                          u8 *ecc_data2,      /* read from register */
 +                          u8 *page_data)
 +{
 +      uint    i;
 +      u8      tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
 +      u8      comp0_bit[8], comp1_bit[8], comp2_bit[8];
 +      u8      ecc_bit[24];
 +      u8      ecc_sum = 0;
 +      u8      find_bit = 0;
 +      uint    find_byte = 0;
 +      int     isEccFF;
 +
 +      isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF);
 +
 +      gen_true_ecc(ecc_data1);
 +      gen_true_ecc(ecc_data2);
 +
 +      for (i = 0; i <= 2; i++) {
 +              *(ecc_data1 + i) = ~(*(ecc_data1 + i));
 +              *(ecc_data2 + i) = ~(*(ecc_data2 + i));
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp0_bit[i]     = *ecc_data1 % 2;
 +              *ecc_data1      = *ecc_data1 / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp1_bit[i]      = *(ecc_data1 + 1) % 2;
 +              *(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              tmp2_bit[i]      = *(ecc_data1 + 2) % 2;
 +              *(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp0_bit[i]     = *ecc_data2 % 2;
 +              *ecc_data2       = *ecc_data2 / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp1_bit[i]     = *(ecc_data2 + 1) % 2;
 +              *(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
 +      }
 +
 +      for (i = 0; i < 8; i++) {
 +              comp2_bit[i]     = *(ecc_data2 + 2) % 2;
 +              *(ecc_data2 + 2) = *(ecc_data2 + 2) / 2;
 +      }
 +
 +      for (i = 0; i < 6; i++)
 +              ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
 +
 +      for (i = 0; i < 8; i++)
 +              ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
 +
 +      for (i = 0; i < 8; i++)
 +              ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
 +
 +      ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
 +      ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
 +
 +      for (i = 0; i < 24; i++)
 +              ecc_sum += ecc_bit[i];
 +
 +      switch (ecc_sum) {
 +      case 0:
 +              /* Not reached because this function is not called if
 +               *  ECC values are equal
 +               */
 +              return 0;
 +
 +      case 1:
 +              /* Uncorrectable error */
 +              DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
 +              return -1;
 +
 +      case 11:
 +              /* UN-Correctable error */
 +              DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n");
 +              return -1;
 +
 +      case 12:
 +              /* Correctable error */
 +              find_byte = (ecc_bit[23] << 8) +
 +                          (ecc_bit[21] << 7) +
 +                          (ecc_bit[19] << 6) +
 +                          (ecc_bit[17] << 5) +
 +                          (ecc_bit[15] << 4) +
 +                          (ecc_bit[13] << 3) +
 +                          (ecc_bit[11] << 2) +
 +                          (ecc_bit[9]  << 1) +
 +                          ecc_bit[7];
 +
 +              find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
 +
 +              DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at "
 +                              "offset: %d, bit: %d\n", find_byte, find_bit);
 +
 +              page_data[find_byte] ^= (1 << find_bit);
 +
 +              return 0;
 +      default:
 +              if (isEccFF) {
 +                      if (ecc_data2[0] == 0 &&
 +                          ecc_data2[1] == 0 &&
 +                          ecc_data2[2] == 0)
 +                              return 0;
 +              }
 +              DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
 +              return -1;
 +      }
 +}
 +
 +/*
 + * omap_correct_data - Compares the ecc read from nand spare area with ECC
 + * registers values and corrects one bit error if it has occured
 + * @mtd: MTD device structure
 + * @dat: page data
 + * @read_ecc: ecc read from nand flash
 + * @calc_ecc: ecc read from ECC registers
 + */
 +static int omap_correct_data(struct mtd_info *mtd, u_char * dat,
 +                              u_char * read_ecc, u_char * calc_ecc)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      int blockCnt = 0, i = 0, ret = 0;
 +
 +      /* Ex NAND_ECC_HW12_2048 */
 +      if ((info->nand.ecc.mode == NAND_ECC_HW) &&
 +                      (info->nand.ecc.size  == 2048))
 +              blockCnt = 4;
 +      else
 +              blockCnt = 1;
 +
 +      for (i = 0; i < blockCnt; i++) {
 +              if (memcmp(read_ecc, calc_ecc, 3) != 0) {
 +                      ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
 +                      if (ret < 0) return ret;
 +              }
 +              read_ecc += 3;
 +              calc_ecc += 3;
 +              dat      += 512;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * omap_calcuate_ecc - Generate non-inverted ECC bytes.
 + * Using noninverted ECC can be considered ugly since writing a blank
 + * page ie. padding will clear the ECC bytes. This is no problem as long
 + * nobody is trying to write data on the seemingly unused page. Reading
 + * an erased page will produce an ECC mismatch between generated and read
 + * ECC bytes that has to be dealt with separately.
 + * @mtd: MTD device structure
 + * @dat: The pointer to data on which ecc is computed
 + * @ecc_code: The ecc_code buffer
 + */
 +static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 +                              u_char *ecc_code)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      unsigned long val = 0x0;
 +      unsigned long reg;
 +
 +      /* Start Reading from HW ECC1_Result = 0x200 */
 +      reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
 +      val = __raw_readl(reg);
 +      *ecc_code++ = val;          /* P128e, ..., P1e */
 +      *ecc_code++ = val >> 16;    /* P128o, ..., P1o */
 +      /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
 +      *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
 +      reg += 4;
 +
 +      return 0;
 +}
 +
 +/*
 + * omap_enable_hwecc - This function enables the hardware ecc functionality
 + * @mtd: MTD device structure
 + * @mode: Read/Write mode
 + */
 +static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      register struct nand_chip *chip = mtd->priv;
 +      unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
 +      unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
 +
 +      switch (mode) {
 +      case NAND_ECC_READ    :
 +              __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
 +              /* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
 +              val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
 +              break;
 +      case NAND_ECC_READSYN :
 +               __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
 +              /* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
 +              val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
 +              break;
 +      case NAND_ECC_WRITE   :
 +              __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
 +              /* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
 +              val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
 +              break;
 +      default:
 +              DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
 +                                      mode);
 +              break;
 +      }
 +
 +      __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
 +}
 +#endif
 +
 +/*
 + * omap_wait - Wait function is called during Program and erase
 + * operations and the way it is called from MTD layer, we should wait
 + * till the NAND chip is ready after the programming/erase operation
 + * has completed.
 + * @mtd: MTD device structure
 + * @chip: NAND Chip structure
 + */
 +static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 +{
 +      register struct nand_chip *this = mtd->priv;
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      int status = 0;
 +
 +      this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
 +                                              GPMC_CS_NAND_COMMAND;
 +      this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
 +
 +      while (!(status & 0x40)) {
 +               __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
 +              status = __raw_readb(this->IO_ADDR_R);
 +      }
 +      return status;
 +}
 +
 +/*
 + * omap_dev_ready - calls the platform specific dev_ready function
 + * @mtd: MTD device structure
 + */
 +static int omap_dev_ready(struct mtd_info *mtd)
 +{
 +      struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 +                                                      mtd);
 +      unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
 +
 +      if ((val & 0x100) == 0x100) {
 +              /* Clear IRQ Interrupt */
 +              val |= 0x100;
 +              val &= ~(0x0);
 +              __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
 +      } else {
 +              unsigned int cnt = 0;
 +              while (cnt++ < 0x1FF) {
 +                      if  ((val & 0x100) == 0x100)
 +                              return 0;
 +                      val = __raw_readl(info->gpmc_baseaddr +
 +                                                      GPMC_IRQ_STATUS);
 +              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int __devinit omap_nand_probe(struct platform_device *pdev)
 +{
 +      struct omap_nand_info           *info;
 +      struct omap_nand_platform_data  *pdata;
 +      int                             err;
 +      unsigned long                   val;
 +
 +
 +      pdata = pdev->dev.platform_data;
 +      if (pdata == NULL) {
 +              dev_err(&pdev->dev, "platform data missing\n");
 +              return -ENODEV;
 +      }
 +
 +      info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
 +      if (!info) return -ENOMEM;
 +
 +      platform_set_drvdata(pdev, info);
 +
 +      spin_lock_init(&info->controller.lock);
 +      init_waitqueue_head(&info->controller.wq);
 +
 +      info->pdev = pdev;
 +
 +      info->gpmc_cs           = pdata->cs;
 +      info->gpmc_baseaddr     = pdata->gpmc_baseaddr;
 +      info->gpmc_cs_baseaddr  = pdata->gpmc_cs_baseaddr;
 +
 +      info->mtd.priv          = &info->nand;
 +      info->mtd.name          = pdev->dev.bus_id;
 +      info->mtd.owner         = THIS_MODULE;
 +
 +      err = gpmc_cs_request(info->gpmc_cs, NAND_IO_SIZE, &info->phys_base);
 +      if (err < 0) {
 +              dev_err(&pdev->dev, "Cannot request GPMC CS\n");
 +              goto out_free_info;
 +      }
 +
 +      /* Enable RD PIN Monitoring Reg */
 +      if (pdata->dev_ready) {
 +              val  = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1);
 +              val |= WR_RD_PIN_MONITORING;
 +              gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
 +      }
 +
 +      val  = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7);
 +      val &= ~(0xf << 8);
 +      val |=  (0xc & 0xf) << 8;
 +      gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val);
 +
 +      /* NAND write protect off */
 +      omap_nand_wp(&info->mtd, NAND_WP_OFF);
 +
 +      if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
 +                              pdev->dev.driver->name)) {
 +              err = -EBUSY;
 +              goto out_free_cs;
 +      }
 +
 +      info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
 +      if (!info->nand.IO_ADDR_R) {
 +              err = -ENOMEM;
 +              goto out_release_mem_region;
 +      }
 +      info->nand.controller = &info->controller;
 +
 +      info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
 +      info->nand.cmd_ctrl  = omap_hwcontrol;
 +
 +      info->nand.read_buf   = omap_read_buf;
 +      info->nand.write_buf  = omap_write_buf;
 +      info->nand.verify_buf = omap_verify_buf;
 +
 +      /*
 +      * If RDY/BSY line is connected to OMAP then use the omap ready funcrtion
 +      * and the generic nand_wait function which reads the status register
 +      * after monitoring the RDY/BSY line.Otherwise use a standard chip delay
 +      * which is slightly more than tR (AC Timing) of the NAND device and read
 +      * status register until you get a failure or success
 +      */
 +      if (pdata->dev_ready) {
 +              info->nand.dev_ready = omap_dev_ready;
 +              info->nand.chip_delay = 0;
 +      } else {
 +              info->nand.waitfunc = omap_wait;
 +              info->nand.chip_delay = 50;
 +      }
 +
 +      info->nand.options  |= NAND_SKIP_BBTSCAN;
 +      if ((gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1) & 0x3000)
 +                                                              == 0x1000)
 +              info->nand.options  |= NAND_BUSWIDTH_16;
 +
 +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
 +      info->nand.ecc.bytes            = 3;
 +      info->nand.ecc.size             = 512;
 +      info->nand.ecc.calculate        = omap_calculate_ecc;
 +      info->nand.ecc.hwctl            = omap_enable_hwecc;
 +      info->nand.ecc.correct          = omap_correct_data;
 +      info->nand.ecc.mode             = NAND_ECC_HW;
 +
 +      /* init HW ECC */
 +      omap_hwecc_init(&info->mtd);
 +#else
 +      info->nand.ecc.mode = NAND_ECC_SOFT;
 +#endif
 +
 +      /* DIP switches on some boards change between 8 and 16 bit
 +       * bus widths for flash.  Try the other width if the first try fails.
 +       */
 +      if (nand_scan(&info->mtd, 1)) {
 +              info->nand.options ^= NAND_BUSWIDTH_16;
 +              if (nand_scan(&info->mtd, 1)) {
 +                      err = -ENXIO;
 +                      goto out_release_mem_region;
 +              }
 +      }
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 +      if (err > 0)
 +              add_mtd_partitions(&info->mtd, info->parts, err);
 +      else if (pdata->parts)
 +              add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
 +      else
 +#endif
 +              add_mtd_device(&info->mtd);
 +
 +      platform_set_drvdata(pdev, &info->mtd);
 +
 +      return 0;
 +
 +out_release_mem_region:
 +      release_mem_region(info->phys_base, NAND_IO_SIZE);
 +out_free_cs:
 +      gpmc_cs_free(info->gpmc_cs);
 +out_free_info:
 +      kfree(info);
 +
 +      return err;
 +}
 +
 +static int omap_nand_remove(struct platform_device *pdev)
 +{
 +      struct mtd_info *mtd = platform_get_drvdata(pdev);
 +      struct omap_nand_info *info = mtd->priv;
 +
 +      platform_set_drvdata(pdev, NULL);
 +      /* Release NAND device, its internal structures and partitions */
 +      nand_release(&info->mtd);
 +      iounmap(info->nand.IO_ADDR_R);
 +      kfree(&info->mtd);
 +      return 0;
 +}
 +
 +static struct platform_driver omap_nand_driver = {
 +      .probe          = omap_nand_probe,
 +      .remove         = omap_nand_remove,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +MODULE_ALIAS(DRIVER_NAME);
 +
 +static int __init omap_nand_init(void)
 +{
 +      printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
 +      return platform_driver_register(&omap_nand_driver);
 +}
 +
 +static void __exit omap_nand_exit(void)
 +{
 +      platform_driver_unregister(&omap_nand_driver);
 +}
 +
 +module_init(omap_nand_init);
 +module_exit(omap_nand_exit);
 +
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
index f279d896eedfac76a875e24c56d5053fa851d93d,0000000000000000000000000000000000000000..d265215e862da41a7779cc70495e1249ec0a34b0
mode 100644,000000..100644
--- /dev/null
@@@ -1,777 -1,0 +1,777 @@@
- #include <asm/arch/gpmc.h>
- #include <asm/arch/onenand.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/gpmc.h>
- #include <asm/arch/pm.h>
 +/*
 + *  linux/drivers/mtd/onenand/omap2.c
 + *
 + *  OneNAND driver for OMAP2 / OMAP3
 + *
 + *  Copyright (C) 2005-2006 Nokia Corporation
 + *
 + *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjola
 + *  IRQ and DMA support written by Timo Teras
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License version 2 as published by
 + * the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but WITHOUT
 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 + * more details.
 + *
 + * You should have received a copy of the GNU General Public License along with
 + * this program; see the file COPYING. If not, write to the Free Software
 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
 + */
 +
 +#include <linux/device.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/onenand.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/platform_device.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +
 +#include <asm/io.h>
 +#include <asm/mach/flash.h>
- #include <asm/arch/dma.h>
++#include <mach/gpmc.h>
++#include <mach/onenand.h>
++#include <mach/gpio.h>
++#include <mach/gpmc.h>
++#include <mach/pm.h>
 +
 +#include <linux/dma-mapping.h>
 +#include <asm/dma-mapping.h>
- #include <asm/arch/board.h>
++#include <mach/dma.h>
 +
++#include <mach/board.h>
 +
 +#define DRIVER_NAME "omap2-onenand"
 +
 +#define ONENAND_IO_SIZE               SZ_128K
 +#define ONENAND_BUFRAM_SIZE   (1024 * 5)
 +
 +struct omap2_onenand {
 +      struct platform_device *pdev;
 +      int gpmc_cs;
 +      unsigned long phys_base;
 +      int gpio_irq;
 +      struct mtd_info mtd;
 +      struct mtd_partition *parts;
 +      struct onenand_chip onenand;
 +      struct completion irq_done;
 +      struct completion dma_done;
 +      int dma_channel;
 +      int freq;
 +      int (*setup)(void __iomem *base, int freq);
 +};
 +
 +static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      struct omap2_onenand *c = data;
 +
 +      complete(&c->dma_done);
 +}
 +
 +static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
 +{
 +      struct omap2_onenand *c = dev_id;
 +
 +      complete(&c->irq_done);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static inline unsigned short read_reg(struct omap2_onenand *c, int reg)
 +{
 +      return readw(c->onenand.base + reg);
 +}
 +
 +static inline void write_reg(struct omap2_onenand *c, unsigned short value,
 +                           int reg)
 +{
 +      writew(value, c->onenand.base + reg);
 +}
 +
 +static void wait_err(char *msg, int state, unsigned int ctrl, unsigned int intr)
 +{
 +      printk(KERN_ERR "onenand_wait: %s! state %d ctrl 0x%04x intr 0x%04x\n",
 +             msg, state, ctrl, intr);
 +}
 +
 +static void wait_warn(char *msg, int state, unsigned int ctrl,
 +                    unsigned int intr)
 +{
 +      printk(KERN_WARNING "onenand_wait: %s! state %d ctrl 0x%04x "
 +             "intr 0x%04x\n", msg, state, ctrl, intr);
 +}
 +
 +static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      unsigned int intr = 0;
 +      unsigned int ctrl;
 +      unsigned long timeout;
 +      u32 syscfg;
 +
 +      if (state == FL_RESETING) {
 +              int i;
 +
 +              for (i = 0; i < 20; i++) {
 +                      udelay(1);
 +                      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                      if (intr & ONENAND_INT_MASTER)
 +                              break;
 +              }
 +              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +              if (ctrl & ONENAND_CTRL_ERROR) {
 +                      wait_err("controller error", state, ctrl, intr);
 +                      return -EIO;
 +              }
 +              if (!(intr & ONENAND_INT_RESET)) {
 +                      wait_err("timeout", state, ctrl, intr);
 +                      return -EIO;
 +              }
 +              return 0;
 +      }
 +
 +      if (state != FL_READING) {
 +              int result;
 +
 +              /* Turn interrupts on */
 +              syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 +              syscfg |= ONENAND_SYS_CFG1_IOBE;
 +              write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 +
 +              INIT_COMPLETION(c->irq_done);
 +              if (c->gpio_irq) {
 +                      result = omap_get_gpio_datain(c->gpio_irq);
 +                      if (result == -1) {
 +                              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +                              intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                              wait_err("gpio error", state, ctrl, intr);
 +                              return -EIO;
 +                      }
 +              } else
 +                      result = 0;
 +              if (result == 0) {
 +                      int retry_cnt = 0;
 +retry:
 +                      result = wait_for_completion_timeout(&c->irq_done,
 +                                                  msecs_to_jiffies(20));
 +                      if (result == 0) {
 +                              /* Timeout after 20ms */
 +                              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +                              if (ctrl & ONENAND_CTRL_ONGO) {
 +                                      /*
 +                                       * The operation seems to be still going
 +                                       * so give it some more time.
 +                                       */
 +                                      retry_cnt += 1;
 +                                      if (retry_cnt < 3)
 +                                              goto retry;
 +                                      intr = read_reg(c,
 +                                                      ONENAND_REG_INTERRUPT);
 +                                      wait_err("timeout", state, ctrl, intr);
 +                                      return -EIO;
 +                              }
 +                              intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                              if ((intr & ONENAND_INT_MASTER) == 0)
 +                                      wait_warn("timeout", state, ctrl, intr);
 +                      }
 +              }
 +      } else {
 +              /* Turn interrupts off */
 +              syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 +              syscfg &= ~ONENAND_SYS_CFG1_IOBE;
 +              write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 +
 +              timeout = jiffies + msecs_to_jiffies(20);
 +              while (time_before(jiffies, timeout)) {
 +                      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                      if (intr & ONENAND_INT_MASTER)
 +                              break;
 +              }
 +      }
 +
 +      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +      ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +
 +      if (intr & ONENAND_INT_READ) {
 +              int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);
 +
 +              if (ecc) {
 +                      unsigned int addr1, addr8;
 +
 +                      addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
 +                      addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
 +                      if (ecc & ONENAND_ECC_2BIT_ALL) {
 +                              printk(KERN_ERR "onenand_wait: ECC error = "
 +                                     "0x%04x, addr1 %#x, addr8 %#x\n",
 +                                     ecc, addr1, addr8);
 +                              mtd->ecc_stats.failed++;
 +                              return -EBADMSG;
 +                      } else if (ecc & ONENAND_ECC_1BIT_ALL) {
 +                              printk(KERN_NOTICE "onenand_wait: correctable "
 +                                     "ECC error = 0x%04x, addr1 %#x, "
 +                                     "addr8 %#x\n", ecc, addr1, addr8);
 +                              mtd->ecc_stats.corrected++;
 +                      }
 +              }
 +      } else if (state == FL_READING) {
 +              wait_err("timeout", state, ctrl, intr);
 +              return -EIO;
 +      }
 +
 +      if (ctrl & ONENAND_CTRL_ERROR) {
 +              wait_err("controller error", state, ctrl, intr);
 +              if (ctrl & ONENAND_CTRL_LOCK)
 +                      printk(KERN_ERR "onenand_wait: "
 +                                      "Device is write protected!!!\n");
 +              return -EIO;
 +      }
 +
 +      if (ctrl & 0xFE9F)
 +              wait_warn("unexpected controller status", state, ctrl, intr);
 +
 +      return 0;
 +}
 +
 +static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
 +{
 +      struct onenand_chip *this = mtd->priv;
 +
 +      if (ONENAND_CURRENT_BUFFERRAM(this)) {
 +              if (area == ONENAND_DATARAM)
 +                      return mtd->writesize;
 +              if (area == ONENAND_SPARERAM)
 +                      return mtd->oobsize;
 +      }
 +
 +      return 0;
 +}
 +
 +#if defined(CONFIG_ARCH_OMAP3) || defined(MULTI_OMAP2)
 +
 +static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +      unsigned long timeout;
 +      void *buf = (void *)buffer;
 +      size_t xtra;
 +      volatile unsigned *done;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
 +              goto out_copy;
 +
 +      if (buf >= high_memory) {
 +              struct page *p1;
 +
 +              if (((size_t)buf & PAGE_MASK) !=
 +                  ((size_t)(buf + count - 1) & PAGE_MASK))
 +                      goto out_copy;
 +              p1 = vmalloc_to_page(buf);
 +              if (!p1)
 +                      goto out_copy;
 +              buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
 +      }
 +
 +      xtra = count & 3;
 +      if (xtra) {
 +              count -= xtra;
 +              memcpy(buf + count, this->base + bram_offset + count, xtra);
 +      }
 +
 +      dma_src = c->phys_base + bram_offset;
 +      dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
 +      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              goto out_copy;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count >> 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +
 +      timeout = jiffies + msecs_to_jiffies(20);
 +      done = &c->dma_done.done;
 +      while (time_before(jiffies, timeout))
 +              if (*done)
 +                      break;
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
 +
 +      if (!*done) {
 +              dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
 +              goto out_copy;
 +      }
 +
 +      return 0;
 +
 +out_copy:
 +      memcpy(buf, this->base + bram_offset, count);
 +      return 0;
 +}
 +
 +static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +      unsigned long timeout;
 +      void *buf = (void *)buffer;
 +      volatile unsigned *done;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
 +              goto out_copy;
 +
 +      /* panic_write() may be in an interrupt context */
 +      if (in_interrupt())
 +              goto out_copy;
 +
 +      if (buf >= high_memory) {
 +              struct page *p1;
 +
 +              if (((size_t)buf & PAGE_MASK) !=
 +                  ((size_t)(buf + count - 1) & PAGE_MASK))
 +                      goto out_copy;
 +              p1 = vmalloc_to_page(buf);
 +              if (!p1)
 +                      goto out_copy;
 +              buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
 +      }
 +
 +      dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
 +      dma_dst = c->phys_base + bram_offset;
 +      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count >> 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +
 +      timeout = jiffies + msecs_to_jiffies(20);
 +      done = &c->dma_done.done;
 +      while (time_before(jiffies, timeout))
 +              if (*done)
 +                      break;
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
 +
 +      if (!*done) {
 +              dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
 +              goto out_copy;
 +      }
 +
 +      return 0;
 +
 +out_copy:
 +      memcpy(this->base + bram_offset, buf, count);
 +      return 0;
 +}
 +
 +#else
 +
 +int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                               unsigned char *buffer, int offset,
 +                               size_t count);
 +
 +int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                const unsigned char *buffer,
 +                                int offset, size_t count);
 +
 +#endif
 +
 +#if defined(CONFIG_ARCH_OMAP2) || defined(MULTI_OMAP2)
 +
 +static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      /* DMA is not used.  Revisit PM requirements before enabling it. */
 +      if (1 || (c->dma_channel < 0) ||
 +          ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
 +          (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
 +              memcpy(buffer, (__force void *)(this->base + bram_offset),
 +                     count);
 +              return 0;
 +      }
 +
 +      dma_src = c->phys_base + bram_offset;
 +      dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
 +                               DMA_FROM_DEVICE);
 +      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count / 4, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +      wait_for_completion(&c->dma_done);
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
 +
 +      return 0;
 +}
 +
 +static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      /* DMA is not used.  Revisit PM requirements before enabling it. */
 +      if (1 || (c->dma_channel < 0) ||
 +          ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
 +          (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
 +              memcpy((__force void *)(this->base + bram_offset), buffer,
 +                     count);
 +              return 0;
 +      }
 +
 +      dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
 +                               DMA_TO_DEVICE);
 +      dma_dst = c->phys_base + bram_offset;
 +      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16,
 +                                   count / 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +      wait_for_completion(&c->dma_done);
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
 +
 +      return 0;
 +}
 +
 +#else
 +
 +int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                               unsigned char *buffer, int offset,
 +                               size_t count);
 +
 +int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                const unsigned char *buffer,
 +                                int offset, size_t count);
 +
 +#endif
 +
 +static struct platform_driver omap2_onenand_driver;
 +
 +static int __adjust_timing(struct device *dev, void *data)
 +{
 +      int ret = 0;
 +      struct omap2_onenand *c;
 +
 +      c = dev_get_drvdata(dev);
 +
 +      BUG_ON(c->setup == NULL);
 +
 +      /* DMA is not in use so this is all that is needed */
 +      /* Revisit for OMAP3! */
 +      ret = c->setup(c->onenand.base, c->freq);
 +
 +      return ret;
 +}
 +
 +int omap2_onenand_rephase(void)
 +{
 +      return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
 +                                    NULL, __adjust_timing);
 +}
 +
 +static void __devexit omap2_onenand_shutdown(struct platform_device *pdev)
 +{
 +      struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 +
 +      /* With certain content in the buffer RAM, the OMAP boot ROM code
 +       * can recognize the flash chip incorrectly. Zero it out before
 +       * soft reset.
 +       */
 +      memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
 +}
 +
 +static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 +{
 +      struct omap_onenand_platform_data *pdata;
 +      struct omap2_onenand *c;
 +      int r;
 +
 +      pdata = pdev->dev.platform_data;
 +      if (pdata == NULL) {
 +              dev_err(&pdev->dev, "platform data missing\n");
 +              return -ENODEV;
 +      }
 +
 +      c = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
 +      if (!c)
 +              return -ENOMEM;
 +
 +      init_completion(&c->irq_done);
 +      init_completion(&c->dma_done);
 +      c->gpmc_cs = pdata->cs;
 +      c->gpio_irq = pdata->gpio_irq;
 +      c->dma_channel = pdata->dma_channel;
 +      if (c->dma_channel < 0) {
 +              /* if -1, don't use DMA */
 +              c->gpio_irq = 0;
 +      }
 +
 +      r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
 +      if (r < 0) {
 +              dev_err(&pdev->dev, "Cannot request GPMC CS\n");
 +              goto err_kfree;
 +      }
 +
 +      if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
 +                             pdev->dev.driver->name) == NULL) {
 +              dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
 +                      "size: 0x%x\n", c->phys_base, ONENAND_IO_SIZE);
 +              r = -EBUSY;
 +              goto err_free_cs;
 +      }
 +      c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
 +      if (c->onenand.base == NULL) {
 +              r = -ENOMEM;
 +              goto err_release_mem_region;
 +      }
 +
 +      if (pdata->onenand_setup != NULL) {
 +              r = pdata->onenand_setup(c->onenand.base, c->freq);
 +              if (r < 0) {
 +                      dev_err(&pdev->dev, "Onenand platform setup failed: "
 +                              "%d\n", r);
 +                      goto err_iounmap;
 +              }
 +              c->setup = pdata->onenand_setup;
 +      }
 +
 +      if (c->gpio_irq) {
 +              if ((r = omap_request_gpio(c->gpio_irq)) < 0) {
 +                      dev_err(&pdev->dev,  "Failed to request GPIO%d for "
 +                              "OneNAND\n", c->gpio_irq);
 +                      goto err_iounmap;
 +      }
 +      omap_set_gpio_direction(c->gpio_irq, 1);
 +
 +      if ((r = request_irq(OMAP_GPIO_IRQ(c->gpio_irq),
 +                           omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
 +                           pdev->dev.driver->name, c)) < 0)
 +              goto err_release_gpio;
 +      }
 +
 +      if (c->dma_channel >= 0) {
 +              r = omap_request_dma(0, pdev->dev.driver->name,
 +                                   omap2_onenand_dma_cb, (void *) c,
 +                                   &c->dma_channel);
 +              if (r == 0) {
 +                      omap_set_dma_write_mode(c->dma_channel,
 +                                              OMAP_DMA_WRITE_NON_POSTED);
 +                      omap_set_dma_src_data_pack(c->dma_channel, 1);
 +                      omap_set_dma_src_burst_mode(c->dma_channel,
 +                                                  OMAP_DMA_DATA_BURST_8);
 +                      omap_set_dma_dest_data_pack(c->dma_channel, 1);
 +                      omap_set_dma_dest_burst_mode(c->dma_channel,
 +                                                   OMAP_DMA_DATA_BURST_8);
 +              } else {
 +                      dev_info(&pdev->dev,
 +                               "failed to allocate DMA for OneNAND, "
 +                               "using PIO instead\n");
 +                      c->dma_channel = -1;
 +              }
 +      }
 +
 +      dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
 +               "base %p\n", c->gpmc_cs, c->phys_base,
 +               c->onenand.base);
 +
 +      c->pdev = pdev;
 +      c->mtd.name = pdev->dev.bus_id;
 +      c->mtd.priv = &c->onenand;
 +      c->mtd.owner = THIS_MODULE;
 +
 +      if (c->dma_channel >= 0) {
 +              struct onenand_chip *this = &c->onenand;
 +
 +              this->wait = omap2_onenand_wait;
 +              if (cpu_is_omap34xx()) {
 +                      this->read_bufferram = omap3_onenand_read_bufferram;
 +                      this->write_bufferram = omap3_onenand_write_bufferram;
 +              } else {
 +                      this->read_bufferram = omap2_onenand_read_bufferram;
 +                      this->write_bufferram = omap2_onenand_write_bufferram;
 +              }
 +      }
 +
 +      if ((r = onenand_scan(&c->mtd, 1)) < 0)
 +              goto err_release_dma;
 +
 +      switch ((c->onenand.version_id >> 4) & 0xf) {
 +      case 0:
 +              c->freq = 40;
 +              break;
 +      case 1:
 +              c->freq = 54;
 +              break;
 +      case 2:
 +              c->freq = 66;
 +              break;
 +      case 3:
 +              c->freq = 83;
 +              break;
 +      }
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      if (pdata->parts != NULL)
 +              r = add_mtd_partitions(&c->mtd, pdata->parts,
 +                                     pdata->nr_parts);
 +      else
 +#endif
 +              r = add_mtd_device(&c->mtd);
 +      if (r < 0)
 +              goto err_release_onenand;
 +
 +      platform_set_drvdata(pdev, c);
 +
 +      return 0;
 +
 +err_release_onenand:
 +      onenand_release(&c->mtd);
 +err_release_dma:
 +      if (c->dma_channel != -1)
 +              omap_free_dma(c->dma_channel);
 +      if (c->gpio_irq)
 +              free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
 +err_release_gpio:
 +      if (c->gpio_irq)
 +              omap_free_gpio(c->gpio_irq);
 +err_iounmap:
 +      iounmap(c->onenand.base);
 +err_release_mem_region:
 +      release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 +err_free_cs:
 +      gpmc_cs_free(c->gpmc_cs);
 +err_kfree:
 +      kfree(c);
 +
 +      return r;
 +}
 +
 +static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 +{
 +      struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 +
 +      BUG_ON(c == NULL);
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      if (c->parts)
 +              del_mtd_partitions(&c->mtd);
 +      else
 +              del_mtd_device(&c->mtd);
 +#else
 +      del_mtd_device(&c->mtd);
 +#endif
 +
 +      onenand_release(&c->mtd);
 +      if (c->dma_channel != -1)
 +              omap_free_dma(c->dma_channel);
 +      omap2_onenand_shutdown(pdev);
 +      platform_set_drvdata(pdev, NULL);
 +      if (c->gpio_irq) {
 +              free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
 +              omap_free_gpio(c->gpio_irq);
 +      }
 +      iounmap(c->onenand.base);
 +      release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 +      kfree(c);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver omap2_onenand_driver = {
 +      .probe          = omap2_onenand_probe,
 +      .remove         = omap2_onenand_remove,
 +      .shutdown       = omap2_onenand_shutdown,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap2_onenand_init(void)
 +{
 +      printk(KERN_INFO "OneNAND driver initializing\n");
 +      return platform_driver_register(&omap2_onenand_driver);
 +}
 +
 +static void __exit omap2_onenand_exit(void)
 +{
 +      platform_driver_unregister(&omap2_onenand_driver);
 +}
 +
 +module_init(omap2_onenand_init);
 +module_exit(omap2_onenand_exit);
 +
 +MODULE_ALIAS(DRIVER_NAME);
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
 +MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
Simple merge
index 7e2f74e9160aafdd8a15bb7a15f93dc429fbbe43,0000000000000000000000000000000000000000..b706253aae0ca7e2acb629e43ceb7f454b87fcf2
mode 100644,000000..100644
--- /dev/null
@@@ -1,901 -1,0 +1,901 @@@
- #include <asm/hardware.h>
 +/*
 + * BRIEF MODULE DESCRIPTION
 + *
 + *    Infra-red driver for the OMAP1610-H2 and OMAP1710-H3 and H4 Platforms
 + *      (SIR/MIR/FIR modes)
 + *      (based on omap-sir.c)
 + *
 + * Copyright 2003 MontaVista Software Inc.
 + * Author: MontaVista Software, Inc.
 + *       source@mvista.com
 + *
 + * Copyright 2004 Texas Instruments.
 + *
 + *  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  SOFTWARE  IS PROVIDED         ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 + *  WARRANTIES,         INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 + *  NO        EVENT  SHALL   THE 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.
 + *
 + *  You should have received a copy of the  GNU General Public License along
 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
 + *  675 Mass Ave, Cambridge, MA 02139, USA.
 + *
 + Modifications:
 + Feb 2004, Texas Instruments
 + - Ported to 2.6 kernel (Feb 2004).
 + *
 + Apr 2004, Texas Instruments
 + - Added support for H3 (Apr 2004).
 + Nov 2004, Texas Instruments
 + - Added support for Power Management.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/types.h>
 +#include <linux/init.h>
 +#include <linux/errno.h>
 +#include <linux/netdevice.h>
 +#include <linux/slab.h>
 +#include <linux/rtnetlink.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +#include <linux/ioport.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c.h>
 +#include <linux/workqueue.h>
 +
 +#include <net/irda/irda.h>
 +#include <net/irda/irmod.h>
 +#include <net/irda/wrapper.h>
 +#include <net/irda/irda_device.h>
 +
 +#include <asm/irq.h>
 +#include <asm/io.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/irda.h>
++#include <mach/hardware.h>
 +#include <asm/serial.h>
 +#include <asm/mach-types.h>
 +#include <asm/dma.h>
++#include <mach/mux.h>
++#include <mach/gpio.h>
++#include <mach/irda.h>
 +
 +#define UART3_EFR_EN                  (1 << 4)
 +#define UART3_MCR_EN_TCR_TLR          (1 << 6)
 +
 +#define UART3_LCR_WL_8                        (3 << 0)
 +#define UART3_LCR_SP2                 (1 << 2)
 +#define UART3_LCR_DIVEN                       (1 << 7)
 +
 +#define UART3_FCR_FIFO_EN             (1 << 0)
 +#define UART3_FCR_FIFO_RX             (1 << 1)
 +#define UART3_FCR_FIFO_TX             (1 << 2)
 +#define UART3_FCR_FIFO_DMA1           (1 << 3)
 +#define UART3_FCR_FIFO_TX_TRIG16      (1 << 4)
 +#define UART3_FCR_FIFO_RX_TRIG16      (1 << 6)
 +#define UART3_FCR_CONFIG      (\
 +              UART3_FCR_FIFO_EN | UART3_FCR_FIFO_RX   |\
 +              UART3_FCR_FIFO_TX | UART3_FCR_FIFO_DMA1 |\
 +              UART3_FCR_FIFO_TX_TRIG16                |\
 +              UART3_FCR_FIFO_RX_TRIG16)
 +
 +#define UART3_SCR_TX_TRIG1            (1 << 6)
 +#define UART3_SCR_RX_TRIG1            (1 << 7)
 +
 +#define UART3_MDR1_RESET              (0x07)
 +#define UART3_MDR1_SIR                        (1 << 0)
 +#define UART3_MDR1_MIR                        (4 << 0)
 +#define UART3_MDR1_FIR                        (5 << 0)
 +#define UART3_MDR1_SIP_AUTO           (1 << 6)
 +
 +#define UART3_MDR2_TRIG1              (0 << 1)
 +#define UART3_MDR2_IRTX_UNDERRUN      (1 << 0)
 +
 +#define UART3_ACERG_TX_UNDERRUN_DIS   (1 << 4)
 +#define UART3_ACERG_SD_MODE_LOW               (1 << 6)
 +#define UART3_ACERG_DIS_IR_RX         (1 << 5)
 +
 +#define UART3_IER_EOF                 (1 << 5)
 +#define UART3_IER_CTS                 (1 << 7)
 +
 +#define UART3_IIR_TX_STATUS           (1 << 5)
 +#define UART3_IIR_EOF                 (0x80)
 +
 +#define IS_FIR(omap_ir)               ((omap_ir)->speed >= 4000000)
 +
 +struct omap_irda {
 +      unsigned char open;
 +      int speed;              /* Current IrDA speed */
 +      int newspeed;
 +
 +      struct net_device_stats stats;
 +      struct irlap_cb *irlap;
 +      struct qos_info qos;
 +
 +      int rx_dma_channel;
 +      int tx_dma_channel;
 +
 +      dma_addr_t rx_buf_dma_phys;     /* Physical address of RX DMA buffer */
 +      dma_addr_t tx_buf_dma_phys;     /* Physical address of TX DMA buffer */
 +
 +      void *rx_buf_dma_virt;          /* Virtual address of RX DMA buffer */
 +      void *tx_buf_dma_virt;          /* Virtual address of TX DMA buffer */
 +
 +      struct device *dev;
 +      struct omap_irda_config *pdata;
 +};
 +
 +static void inline uart_reg_out(int idx, u8 val)
 +{
 +      omap_writeb(val, idx);
 +}
 +
 +static u8 inline uart_reg_in(int idx)
 +{
 +      u8 b = omap_readb(idx);
 +      return b;
 +}
 +
 +/* forward declarations */
 +extern void omap_stop_dma(int lch);
 +static int omap_irda_set_speed(struct net_device *dev, int speed);
 +
 +static void omap_irda_start_rx_dma(struct omap_irda *omap_ir)
 +{
 +      /* Configure DMA */
 +      omap_set_dma_src_params(omap_ir->rx_dma_channel, 0x3, 0x0,
 +                              omap_ir->pdata->src_start,
 +                              0, 0);
 +
 +      omap_enable_dma_irq(omap_ir->rx_dma_channel, 0x01);
 +
 +      omap_set_dma_dest_params(omap_ir->rx_dma_channel, 0x0, 0x1,
 +                              omap_ir->rx_buf_dma_phys,
 +                              0, 0);
 +
 +      omap_set_dma_transfer_params(omap_ir->rx_dma_channel, 0x0,
 +                              IRDA_SKB_MAX_MTU, 0x1,
 +                              0x0, omap_ir->pdata->rx_trigger, 0);
 +
 +      omap_start_dma(omap_ir->rx_dma_channel);
 +}
 +
 +static void omap_start_tx_dma(struct omap_irda *omap_ir, int size)
 +{
 +      /* Configure DMA */
 +      omap_set_dma_dest_params(omap_ir->tx_dma_channel, 0x03, 0x0,
 +                              omap_ir->pdata->dest_start, 0, 0);
 +
 +      omap_enable_dma_irq(omap_ir->tx_dma_channel, 0x01);
 +
 +      omap_set_dma_src_params(omap_ir->tx_dma_channel, 0x0, 0x1,
 +                              omap_ir->tx_buf_dma_phys,
 +                              0, 0);
 +
 +      omap_set_dma_transfer_params(omap_ir->tx_dma_channel, 0x0, size, 0x1,
 +                              0x0, omap_ir->pdata->tx_trigger, 0);
 +
 +      /* Start DMA */
 +      omap_start_dma(omap_ir->tx_dma_channel);
 +}
 +
 +/* DMA RX callback - normally, we should not go here,
 + * it calls only if something is going wrong
 + */
 +static void omap_irda_rx_dma_callback(int lch, u16 ch_status, void *data)
 +{
 +      struct net_device *dev = data;
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +
 +      printk(KERN_ERR "RX Transfer error or very big frame\n");
 +
 +      /* Clear interrupts */
 +      uart_reg_in(UART3_IIR);
 +
 +      omap_ir->stats.rx_frame_errors++;
 +
 +      uart_reg_in(UART3_RESUME);
 +
 +      /* Re-init RX DMA */
 +      omap_irda_start_rx_dma(omap_ir);
 +}
 +
 +/* DMA TX callback - calling when frame transfer has been finished */
 +static void omap_irda_tx_dma_callback(int lch, u16 ch_status, void *data)
 +{
 +      struct net_device *dev = data;
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +
 +      /*Stop DMA controller */
 +      omap_stop_dma(omap_ir->tx_dma_channel);
 +}
 +
 +/*
 + * Set the IrDA communications speed.
 + * Interrupt have to be disabled here.
 + */
 +static int omap_irda_startup(struct net_device *dev)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +
 +      /* FIXME: use clk_* apis for UART3 clock*/
 +      /* Enable UART3 clock and set UART3 to IrDA mode */
 +      if (machine_is_omap_h2() || machine_is_omap_h3())
 +              omap_writel(omap_readl(MOD_CONF_CTRL_0) | (1 << 31) | (1 << 15),
 +                              MOD_CONF_CTRL_0);
 +
 +      /* Only for H2?
 +       */
 +      if (omap_ir->pdata->transceiver_mode && machine_is_omap_h2()) {
 +              /* Is it select_irda on H2 ? */
 +              omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7,
 +                                      FUNC_MUX_CTRL_A);
 +              omap_ir->pdata->transceiver_mode(omap_ir->dev, IR_SIRMODE);
 +      }
 +
 +      uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);     /* Reset mode */
 +
 +      /* Clear DLH and DLL */
 +      uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
 +
 +      uart_reg_out(UART3_DLL, 0);
 +      uart_reg_out(UART3_DLH, 0);
 +      uart_reg_out(UART3_LCR, 0xbf);  /* FIXME: Add #define */
 +
 +      uart_reg_out(UART3_EFR, UART3_EFR_EN);
 +      uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
 +
 +      /* Enable access to UART3_TLR and UART3_TCR registers */
 +      uart_reg_out(UART3_MCR, UART3_MCR_EN_TCR_TLR);
 +
 +      uart_reg_out(UART3_SCR, 0);
 +      /* Set Rx trigger to 1 and Tx trigger to 1 */
 +      uart_reg_out(UART3_TLR, 0);
 +
 +      /* Set LCR to 8 bits and 1 stop bit */
 +      uart_reg_out(UART3_LCR, 0x03);
 +
 +      /* Clear RX and TX FIFO and enable FIFO */
 +      /* Use DMA Req for transfers */
 +      uart_reg_out(UART3_FCR, UART3_FCR_CONFIG);
 +
 +      uart_reg_out(UART3_MCR, 0);
 +
 +      uart_reg_out(UART3_SCR, UART3_SCR_TX_TRIG1 |
 +                      UART3_SCR_RX_TRIG1);
 +
 +      /* Enable UART3 SIR Mode,(Frame-length method to end frames) */
 +      uart_reg_out(UART3_MDR1, UART3_MDR1_SIR);
 +
 +      /* Set Status FIFO trig to 1 */
 +      uart_reg_out(UART3_MDR2, 0);
 +
 +      /* Enables RXIR input */
 +      /* and disable TX underrun */
 +      /* SEND_SIP pulse */
 +      uart_reg_out(UART3_ACREG, UART3_ACERG_SD_MODE_LOW |
 +                      UART3_ACERG_TX_UNDERRUN_DIS);
 +
 +      /* Enable EOF Interrupt only */
 +      uart_reg_out(UART3_IER, UART3_IER_CTS | UART3_IER_EOF);
 +
 +      /* Set Maximum Received Frame size to 2048 bytes */
 +      uart_reg_out(UART3_RXFLL, 0x00);
 +      uart_reg_out(UART3_RXFLH, 0x08);
 +
 +      uart_reg_in(UART3_RESUME);
 +
 +      return 0;
 +}
 +
 +static int omap_irda_shutdown(struct omap_irda *omap_ir)
 +{
 +      unsigned long flags;
 +
 +      local_irq_save(flags);
 +
 +      /* Disable all UART3 Interrupts */
 +      uart_reg_out(UART3_IER, 0);
 +
 +      /* Disable UART3 and disable baud rate generator */
 +      uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);
 +
 +      /* set SD_MODE pin to high and Disable RX IR */
 +      uart_reg_out(UART3_ACREG, (UART3_ACERG_DIS_IR_RX |
 +                      ~(UART3_ACERG_SD_MODE_LOW)));
 +
 +      /* Clear DLH and DLL */
 +      uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
 +      uart_reg_out(UART3_DLL, 0);
 +      uart_reg_out(UART3_DLH, 0);
 +
 +      local_irq_restore(flags);
 +
 +      return 0;
 +}
 +
 +static irqreturn_t
 +omap_irda_irq(int irq, void *dev_id)
 +{
 +      struct net_device *dev = dev_id;
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      struct sk_buff *skb;
 +
 +      u8 status;
 +      int w = 0;
 +
 +      /* Clear EOF interrupt */
 +      status = uart_reg_in(UART3_IIR);
 +
 +      if (status & UART3_IIR_TX_STATUS) {
 +              u8 mdr2 = uart_reg_in(UART3_MDR2);
 +              if (mdr2 & UART3_MDR2_IRTX_UNDERRUN)
 +                      printk(KERN_ERR "IrDA Buffer underrun error\n");
 +
 +              omap_ir->stats.tx_packets++;
 +
 +              if (omap_ir->newspeed) {
 +                      omap_irda_set_speed(dev, omap_ir->newspeed);
 +                      omap_ir->newspeed = 0;
 +              }
 +
 +              netif_wake_queue(dev);
 +              if (!(status & UART3_IIR_EOF))
 +                      return IRQ_HANDLED;
 +      }
 +
 +      /* Stop DMA and if there are no errors, send frame to upper layer */
 +      omap_stop_dma(omap_ir->rx_dma_channel);
 +
 +      status = uart_reg_in(UART3_SFLSR);      /* Take a frame status */
 +
 +      if (status != 0) {      /* Bad frame? */
 +              omap_ir->stats.rx_frame_errors++;
 +              uart_reg_in(UART3_RESUME);
 +      } else {
 +              /* We got a frame! */
 +              skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
 +
 +              if (!skb) {
 +                      printk(KERN_ERR "omap_sir: out of memory for RX SKB\n");
 +                      return IRQ_HANDLED;
 +              }
 +              /*
 +               * Align any IP headers that may be contained
 +               * within the frame.
 +               */
 +
 +              skb_reserve(skb, 1);
 +
 +              w = omap_get_dma_dst_pos(omap_ir->rx_dma_channel) -
 +                                              omap_ir->rx_buf_dma_phys;
 +
 +              if (!IS_FIR(omap_ir))
 +                      /* Copy DMA buffer to skb */
 +                      memcpy(skb_put(skb, w - 2), omap_ir->rx_buf_dma_virt,
 +                                      w - 2);
 +              else
 +                      /* Copy DMA buffer to skb */
 +                      memcpy(skb_put(skb, w - 4), omap_ir->rx_buf_dma_virt,
 +                                      w - 4);
 +
 +              skb->dev = dev;
 +              skb_reset_mac_header(skb);
 +              skb->protocol = htons(ETH_P_IRDA);
 +              omap_ir->stats.rx_packets++;
 +              omap_ir->stats.rx_bytes += skb->len;
 +              netif_receive_skb(skb); /* Send data to upper level */
 +      }
 +
 +      /* Re-init RX DMA */
 +      omap_irda_start_rx_dma(omap_ir);
 +
 +      dev->last_rx = jiffies;
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static int omap_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      int speed = irda_get_next_speed(skb);
 +      int mtt = irda_get_mtt(skb);
 +      int xbofs = irda_get_next_xbofs(skb);
 +
 +
 +      /*
 +       * Does this packet contain a request to change the interface
 +       * speed?  If so, remember it until we complete the transmission
 +       * of this frame.
 +       */
 +      if (speed != omap_ir->speed && speed != -1)
 +              omap_ir->newspeed = speed;
 +
 +      if (xbofs) /* Set number of addtional BOFS */
 +              uart_reg_out(UART3_EBLR, xbofs + 1);
 +
 +      /*
 +       * If this is an empty frame, we can bypass a lot.
 +       */
 +      if (skb->len == 0) {
 +              if (omap_ir->newspeed) {
 +                      omap_ir->newspeed = 0;
 +                      omap_irda_set_speed(dev, speed);
 +              }
 +              dev_kfree_skb(skb);
 +              return 0;
 +      }
 +
 +      netif_stop_queue(dev);
 +
 +      /* Copy skb data to DMA buffer */
 +      skb_copy_from_linear_data(skb, omap_ir->tx_buf_dma_virt, skb->len);
 +
 +      /* Copy skb data to DMA buffer */
 +      omap_ir->stats.tx_bytes += skb->len;
 +
 +      /* Set frame length */
 +      uart_reg_out(UART3_TXFLL, (skb->len & 0xff));
 +      uart_reg_out(UART3_TXFLH, (skb->len >> 8));
 +
 +      if (mtt > 1000)
 +              mdelay(mtt / 1000);
 +      else
 +              udelay(mtt);
 +
 +      /* Start TX DMA transfer */
 +      omap_start_tx_dma(omap_ir, skb->len);
 +
 +      /* We can free skb now because it's already in DMA buffer */
 +      dev_kfree_skb(skb);
 +
 +      dev->trans_start = jiffies;
 +
 +      return 0;
 +}
 +
 +static int
 +omap_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
 +{
 +      struct if_irda_req *rq = (struct if_irda_req *)ifreq;
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      int ret = -EOPNOTSUPP;
 +
 +
 +      switch (cmd) {
 +      case SIOCSBANDWIDTH:
 +              if (capable(CAP_NET_ADMIN)) {
 +                      /*
 +                       * We are unable to set the speed if the
 +                       * device is not running.
 +                       */
 +                      if (omap_ir->open)
 +                              ret = omap_irda_set_speed(dev,
 +                                              rq->ifr_baudrate);
 +                      else {
 +                              printk(KERN_ERR "omap_ir: SIOCSBANDWIDTH:"
 +                                              " !netif_running\n");
 +                              ret = 0;
 +                      }
 +              }
 +              break;
 +
 +      case SIOCSMEDIABUSY:
 +              ret = -EPERM;
 +              if (capable(CAP_NET_ADMIN)) {
 +                      irda_device_set_media_busy(dev, TRUE);
 +                      ret = 0;
 +              }
 +              break;
 +
 +      case SIOCGRECEIVING:
 +              rq->ifr_receiving = 0;
 +              break;
 +
 +      default:
 +              break;
 +      }
 +
 +      return ret;
 +}
 +
 +static struct net_device_stats *omap_irda_stats(struct net_device *dev)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      return &omap_ir->stats;
 +}
 +
 +static int omap_irda_start(struct net_device *dev)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      int err;
 +
 +      omap_ir->speed = 9600;
 +
 +      err = request_irq(dev->irq, omap_irda_irq, 0, dev->name, dev);
 +      if (err)
 +              goto err_irq;
 +
 +      /*
 +       * The interrupt must remain disabled for now.
 +       */
 +      disable_irq(dev->irq);
 +
 +      /*  Request DMA channels for IrDA hardware */
 +      if (omap_request_dma(omap_ir->pdata->rx_channel, "IrDA Rx DMA",
 +                      (void *)omap_irda_rx_dma_callback,
 +                      dev, &(omap_ir->rx_dma_channel))) {
 +              printk(KERN_ERR "Failed to request IrDA Rx DMA\n");
 +              goto err_irq;
 +      }
 +
 +      if (omap_request_dma(omap_ir->pdata->tx_channel, "IrDA Tx DMA",
 +                      (void *)omap_irda_tx_dma_callback,
 +                      dev, &(omap_ir->tx_dma_channel))) {
 +              printk(KERN_ERR "Failed to request IrDA Tx DMA\n");
 +              goto err_irq;
 +      }
 +
 +      /* Allocate TX and RX buffers for DMA channels */
 +      omap_ir->rx_buf_dma_virt =
 +              dma_alloc_coherent(NULL, IRDA_SKB_MAX_MTU,
 +                              &(omap_ir->rx_buf_dma_phys),
 +                              GFP_KERNEL);
 +
 +      if (!omap_ir->rx_buf_dma_virt) {
 +              printk(KERN_ERR "Unable to allocate memory for rx_buf_dma\n");
 +              goto err_irq;
 +      }
 +
 +      omap_ir->tx_buf_dma_virt =
 +              dma_alloc_coherent(NULL, IRDA_SIR_MAX_FRAME,
 +                              &(omap_ir->tx_buf_dma_phys),
 +                              GFP_KERNEL);
 +
 +      if (!omap_ir->tx_buf_dma_virt) {
 +              printk(KERN_ERR "Unable to allocate memory for tx_buf_dma\n");
 +              goto err_mem1;
 +      }
 +
 +      /*
 +       * Setup the serial port for the specified config.
 +       */
 +      if (omap_ir->pdata->select_irda)
 +              omap_ir->pdata->select_irda(omap_ir->dev, IR_SEL);
 +
 +      err = omap_irda_startup(dev);
 +
 +      if (err)
 +              goto err_startup;
 +
 +      omap_irda_set_speed(dev, omap_ir->speed = 9600);
 +
 +      /*
 +       * Open a new IrLAP layer instance.
 +       */
 +      omap_ir->irlap = irlap_open(dev, &omap_ir->qos, "omap_sir");
 +
 +      err = -ENOMEM;
 +      if (!omap_ir->irlap)
 +              goto err_irlap;
 +
 +      /* Now enable the interrupt and start the queue */
 +      omap_ir->open = 1;
 +
 +      /* Start RX DMA */
 +      omap_irda_start_rx_dma(omap_ir);
 +
 +      enable_irq(dev->irq);
 +      netif_start_queue(dev);
 +
 +      return 0;
 +
 +err_irlap:
 +      omap_ir->open = 0;
 +      omap_irda_shutdown(omap_ir);
 +err_startup:
 +      dma_free_coherent(NULL, IRDA_SIR_MAX_FRAME,
 +                      omap_ir->tx_buf_dma_virt, omap_ir->tx_buf_dma_phys);
 +err_mem1:
 +      dma_free_coherent(NULL, IRDA_SKB_MAX_MTU,
 +                      omap_ir->rx_buf_dma_virt, omap_ir->rx_buf_dma_phys);
 +err_irq:
 +      free_irq(dev->irq, dev);
 +      return err;
 +}
 +
 +static int omap_irda_stop(struct net_device *dev)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +
 +      disable_irq(dev->irq);
 +
 +      netif_stop_queue(dev);
 +
 +      omap_free_dma(omap_ir->rx_dma_channel);
 +      omap_free_dma(omap_ir->tx_dma_channel);
 +
 +      if (omap_ir->rx_buf_dma_virt)
 +              dma_free_coherent(NULL, IRDA_SKB_MAX_MTU,
 +                              omap_ir->rx_buf_dma_virt,
 +                              omap_ir->rx_buf_dma_phys);
 +      if (omap_ir->tx_buf_dma_virt)
 +              dma_free_coherent(NULL, IRDA_SIR_MAX_FRAME,
 +                              omap_ir->tx_buf_dma_virt,
 +                              omap_ir->tx_buf_dma_phys);
 +
 +      omap_irda_shutdown(omap_ir);
 +
 +      /* Stop IrLAP */
 +      if (omap_ir->irlap) {
 +              irlap_close(omap_ir->irlap);
 +              omap_ir->irlap = NULL;
 +      }
 +
 +      omap_ir->open = 0;
 +
 +      /*
 +       * Free resources
 +       */
 +      free_irq(dev->irq, dev);
 +
 +      return 0;
 +}
 +
 +static int omap_irda_set_speed(struct net_device *dev, int speed)
 +{
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +      int divisor;
 +      unsigned long flags;
 +
 +      /* Set IrDA speed */
 +      if (speed <= 115200) {
 +
 +              local_irq_save(flags);
 +
 +              /* SIR mode */
 +              if (omap_ir->pdata->transceiver_mode)
 +                      omap_ir->pdata->transceiver_mode(omap_ir->dev,
 +                                                      IR_SIRMODE);
 +
 +              /* Set SIR mode */
 +              uart_reg_out(UART3_MDR1, 1);
 +              uart_reg_out(UART3_EBLR, 1);
 +
 +              divisor = 48000000 / (16 * speed);      /* Base clock 48 MHz */
 +
 +              uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
 +              uart_reg_out(UART3_DLL, (divisor & 0xff));
 +              uart_reg_out(UART3_DLH, (divisor >> 8));
 +              uart_reg_out(UART3_LCR, 0x03);
 +
 +              uart_reg_out(UART3_MCR, 0);
 +
 +              local_irq_restore(flags);
 +      } else if (speed <= 1152000) {
 +
 +              local_irq_save(flags);
 +
 +              /* Set MIR mode, auto SIP */
 +              uart_reg_out(UART3_MDR1, UART3_MDR1_MIR |
 +                              UART3_MDR1_SIP_AUTO);
 +
 +              uart_reg_out(UART3_EBLR, 2);
 +
 +              divisor = 48000000 / (41 * speed);      /* Base clock 48 MHz */
 +
 +              uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
 +              uart_reg_out(UART3_DLL, (divisor & 0xff));
 +              uart_reg_out(UART3_DLH, (divisor >> 8));
 +              uart_reg_out(UART3_LCR, 0x03);
 +
 +              if (omap_ir->pdata->transceiver_mode)
 +                      omap_ir->pdata->transceiver_mode(omap_ir->dev,
 +                                                      IR_MIRMODE);
 +
 +              local_irq_restore(flags);
 +      } else {
 +              local_irq_save(flags);
 +
 +              /* FIR mode */
 +              uart_reg_out(UART3_MDR1, UART3_MDR1_FIR |
 +                              UART3_MDR1_SIP_AUTO);
 +
 +              if (omap_ir->pdata->transceiver_mode)
 +                      omap_ir->pdata->transceiver_mode(omap_ir->dev,
 +                                                      IR_FIRMODE);
 +
 +              local_irq_restore(flags);
 +      }
 +
 +      omap_ir->speed = speed;
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +/*
 + * Suspend the IrDA interface.
 + */
 +static int omap_irda_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct net_device *dev = platform_get_drvdata(pdev);
 +      struct omap_irda *omap_ir = netdev_priv(dev);
 +
 +      if (!dev)
 +              return 0;
 +
 +      if (omap_ir->open) {
 +              /*
 +               * Stop the transmit queue
 +               */
 +              netif_device_detach(dev);
 +              disable_irq(dev->irq);
 +              omap_irda_shutdown(omap_ir);
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Resume the IrDA interface.
 + */
 +static int omap_irda_resume(struct platform_device *pdev)
 +{
 +      struct net_device *dev = platform_get_drvdata(pdev);
 +      struct omap_irda *omap_ir= netdev_priv(dev);
 +
 +      if (!dev)
 +              return 0;
 +
 +      if (omap_ir->open) {
 +              /*
 +               * If we missed a speed change, initialise at the new speed
 +               * directly.  It is debatable whether this is actually
 +               * required, but in the interests of continuing from where
 +               * we left off it is desireable.  The converse argument is
 +               * that we should re-negotiate at 9600 baud again.
 +               */
 +              if (omap_ir->newspeed) {
 +                      omap_ir->speed = omap_ir->newspeed;
 +                      omap_ir->newspeed = 0;
 +              }
 +
 +              omap_irda_startup(dev);
 +              omap_irda_set_speed(dev, omap_ir->speed);
 +              enable_irq(dev->irq);
 +
 +              /*
 +               * This automatically wakes up the queue
 +               */
 +              netif_device_attach(dev);
 +      }
 +
 +      return 0;
 +}
 +#else
 +#define omap_irda_suspend     NULL
 +#define omap_irda_resume      NULL
 +#endif
 +
 +static int omap_irda_probe(struct platform_device *pdev)
 +{
 +      struct net_device *dev;
 +      struct omap_irda *omap_ir;
 +      struct omap_irda_config *pdata = pdev->dev.platform_data;
 +      unsigned int baudrate_mask;
 +      int err = 0;
 +      int irq = NO_IRQ;
 +
 +      if (!pdata) {
 +              printk(KERN_ERR "IrDA Platform data not supplied\n");
 +              return -ENOENT;
 +      }
 +
 +      if (!pdata->rx_channel || !pdata->tx_channel) {
 +              printk(KERN_ERR "IrDA invalid rx/tx channel value\n");
 +              return -ENOENT;
 +      }
 +
 +      irq = platform_get_irq(pdev, 0);
 +      if (irq <= 0) {
 +              printk(KERN_WARNING "no irq for IrDA\n");
 +              return -ENOENT;
 +      }
 +
 +      dev = alloc_irdadev(sizeof(struct omap_irda));
 +      if (!dev)
 +              goto err_mem_1;
 +
 +
 +      omap_ir = netdev_priv(dev);
 +      omap_ir->dev = &pdev->dev;
 +      omap_ir->pdata = pdata;
 +
 +      dev->hard_start_xmit    = omap_irda_hard_xmit;
 +      dev->open               = omap_irda_start;
 +      dev->stop               = omap_irda_stop;
 +      dev->do_ioctl           = omap_irda_ioctl;
 +      dev->get_stats          = omap_irda_stats;
 +      dev->irq                = irq;
 +
 +      irda_init_max_qos_capabilies(&omap_ir->qos);
 +
 +      baudrate_mask = 0;
 +      if (omap_ir->pdata->transceiver_cap & IR_SIRMODE)
 +              baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 +      if (omap_ir->pdata->transceiver_cap & IR_MIRMODE)
 +              baudrate_mask |= IR_57600 | IR_1152000;
 +      if (omap_ir->pdata->transceiver_cap & IR_FIRMODE)
 +              baudrate_mask |= IR_4000000 << 8;
 +
 +      omap_ir->qos.baud_rate.bits &= baudrate_mask;
 +      omap_ir->qos.min_turn_time.bits = 7;
 +
 +      irda_qos_bits_to_value(&omap_ir->qos);
 +
 +      /* Any better way to avoid this? No. */
 +      if (machine_is_omap_h3() || machine_is_omap_h4())
 +              INIT_DELAYED_WORK(&omap_ir->pdata->gpio_expa, NULL);
 +
 +      err = register_netdev(dev);
 +      if (!err)
 +              platform_set_drvdata(pdev, dev);
 +      else
 +              free_netdev(dev);
 +
 +err_mem_1:
 +      return err;
 +}
 +
 +static int omap_irda_remove(struct platform_device *pdev)
 +{
 +      struct net_device *dev = platform_get_drvdata(pdev);
 +
 +      if (pdev) {
 +              unregister_netdev(dev);
 +              free_netdev(dev);
 +      }
 +      return 0;
 +}
 +
 +static struct platform_driver omapir_driver = {
 +      .probe          = omap_irda_probe,
 +      .remove         = omap_irda_remove,
 +      .suspend        = omap_irda_suspend,
 +      .resume         = omap_irda_resume,
 +      .driver         = {
 +              .name   = "omapirda",
 +      },
 +};
 +
 +static char __initdata banner[] = KERN_INFO "OMAP IrDA driver initializing\n";
 +
 +static int __init omap_irda_init(void)
 +{
 +      printk(banner);
 +      return platform_driver_register(&omapir_driver);
 +}
 +
 +static void __exit omap_irda_exit(void)
 +{
 +      platform_driver_unregister(&omapir_driver);
 +}
 +
 +module_init(omap_irda_init);
 +module_exit(omap_irda_exit);
 +
 +MODULE_AUTHOR("MontaVista");
 +MODULE_DESCRIPTION("OMAP IrDA Driver");
 +MODULE_LICENSE("GPL");
 +
Simple merge
index 269ff615c0fdf88fe626c9f93499ac4f63a297a2,0000000000000000000000000000000000000000..bfcf51511419f29c6e3a8d33da4fcd0052491fa2
mode 100644,000000..100644
--- /dev/null
@@@ -1,655 -1,0 +1,655 @@@
- #include <asm/hardware.h>
 +/*
 + * drivers/rtc/rtc-twl4030.c
 + *
 + * TWL4030 Real Time Clock interface
 + *
 + * Copyright (C) 2007 MontaVista Software, Inc
 + * Author: Alexandre Rusev <source@mvista.com>
 + *
 + * Based on original TI driver twl4030-rtc.c
 + *   Copyright (C) 2006 Texas Instruments, Inc.
 + *
 + * Based on rtc-omap.c
 + *   Copyright (C) 2003 MontaVista Software, Inc.
 + *   Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
 + *
 + *   Copyright (C) 2006 David Brownell
 + *
 + * 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/init.h>
 +#include <linux/module.h>
 +#include <linux/ioport.h>
 +#include <linux/delay.h>
 +#include <linux/types.h>
 +#include <linux/rtc.h>
 +#include <linux/bcd.h>
 +#include <linux/platform_device.h>
 +#include <linux/spinlock.h>
 +#include <linux/interrupt.h>
 +#include <linux/device.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/i2c/twl4030-rtc.h>
 +#include <linux/io.h>
 +#include <linux/irq.h>
 +
 +#include <asm/mach/time.h>
 +#include <asm/system.h>
++#include <mach/hardware.h>
 +
 +#define ALL_TIME_REGS         6
 +
 +/*
 + * If this driver ever becomes modularised, it will be really nice
 + * to make the epoch retain its value across module reload...
 + */
 +static int epoch = 1900;      /* year corresponding to 0x00   */
 +
 +/*
 + * Supports 1 byte read from TWL4030 RTC register.
 + */
 +static int twl4030_rtc_read_u8(u8 *data, u8 reg)
 +{
 +      int ret;
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg);
 +      if (ret < 0) {
 +              printk(KERN_WARNING "twl4030_rtc: Could not read TWL4030"
 +                     "register %X - returned %d[%x]\n", reg, ret, ret);
 +      }
 +      return ret;
 +}
 +
 +/*
 + * Supports 1 byte write to TWL4030 RTC registers.
 + */
 +static int twl4030_rtc_write_u8(u8 data, u8 reg)
 +{
 +      int ret;
 +
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg);
 +      if (ret < 0) {
 +              printk(KERN_WARNING "twl4030_rtc: Could not write TWL4030"
 +                     "register %X - returned %d[%x]\n", reg, ret, ret);
 +      }
 +      return ret;
 +}
 +
 +/*
 + * Enables timer or alarm interrupts.
 + */
 +static int set_rtc_irq_bit(unsigned char bit)
 +{
 +      unsigned char val;
 +      int ret;
 +
 +      ret = twl4030_rtc_read_u8(&val, REG_RTC_INTERRUPTS_REG);
 +      if (ret < 0)
 +              goto set_irq_out;
 +
 +      val |= bit;
 +      ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
 +
 +set_irq_out:
 +      return ret;
 +}
 +
 +#ifdef CONFIG_PM
 +/*
 + * Read timer or alarm interrupts register.
 + */
 +static int get_rtc_irq_bit(unsigned char *val)
 +{
 +      int ret;
 +
 +      ret = twl4030_rtc_read_u8(val, REG_RTC_INTERRUPTS_REG);
 +      return ret;
 +}
 +#endif
 +/*
 + * Disables timer or alarm interrupts.
 + */
 +static int mask_rtc_irq_bit(unsigned char bit)
 +{
 +      unsigned char val;
 +      int ret;
 +
 +      ret = twl4030_rtc_read_u8(&val, REG_RTC_INTERRUPTS_REG);
 +      if (ret < 0)
 +              goto mask_irq_out;
 +
 +      val &= ~bit;
 +      ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
 +
 +mask_irq_out:
 +      return ret;
 +}
 +
 +static int twl4030_rtc_alarm_irq_set_state(struct device *dev, int enabled)
 +{
 +      int ret;
 +
 +      /* Allow ints for RTC ALARM updates.  */
 +      if (enabled)
 +              ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 +      else
 +              ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 +
 +      return ret;
 +}
 +
 +/*
 + * Gets current TWL4030 RTC time and date parameters.
 + */
 +static int get_rtc_time(struct rtc_time *rtc_tm)
 +{
 +      unsigned char rtc_data[ALL_TIME_REGS + 1];
 +      int ret;
 +      u8 save_control;
 +
 +      ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
 +      if (ret < 0)
 +              return ret;
 +
 +      save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
 +
 +      ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
 +      if (ret < 0)
 +              return ret;
 +
 +      ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
 +                             REG_SECONDS_REG, ALL_TIME_REGS);
 +
 +      if (ret < 0) {
 +              printk(KERN_ERR "twl4030_rtc: twl4030_i2c_read error.\n");
 +              return ret;
 +      }
 +
 +      rtc_tm->tm_sec = BCD2BIN(rtc_data[0]);
 +      rtc_tm->tm_min = BCD2BIN(rtc_data[1]);
 +      rtc_tm->tm_hour = BCD2BIN(rtc_data[2]);
 +      rtc_tm->tm_mday = BCD2BIN(rtc_data[3]);
 +      rtc_tm->tm_mon = BCD2BIN(rtc_data[4]);
 +      rtc_tm->tm_year = BCD2BIN(rtc_data[5]);
 +
 +      /*
 +       * Account for differences between how the RTC uses the values
 +       * and how they are defined in a struct rtc_time;
 +       */
 +      rtc_tm->tm_year += (epoch - 1900);
 +      if (rtc_tm->tm_year <= 69)
 +              rtc_tm->tm_year += 100;
 +
 +      rtc_tm->tm_mon--;
 +
 +      return ret;
 +}
 +
 +static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
 +{
 +      unsigned char save_control;
 +      unsigned char rtc_data[ALL_TIME_REGS + 1];
 +      int ret;
 +
 +      /* Month range is 01..12 */
 +      tm->tm_mon++;
 +
 +      rtc_data[1] = BIN2BCD(tm->tm_sec);
 +      rtc_data[2] = BIN2BCD(tm->tm_min);
 +      rtc_data[3] = BIN2BCD(tm->tm_hour);
 +      rtc_data[4] = BIN2BCD(tm->tm_mday);
 +      rtc_data[5] = BIN2BCD(tm->tm_mon);
 +      rtc_data[6] = BIN2BCD(tm->tm_year);
 +
 +      /* Stop RTC while updating the TC registers */
 +      ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
 +      if (ret < 0)
 +              goto out;
 +
 +      save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
 +      twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
 +      if (ret < 0)
 +              goto out;
 +
 +      /* update all the alarm registers in one shot */
 +      ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data,
 +                      REG_SECONDS_REG, ALL_TIME_REGS);
 +      if (ret < 0) {
 +              printk(KERN_ERR "twl4030: twl4030_i2c_write error.\n");
 +              goto out;
 +      }
 +
 +      /* Start back RTC */
 +      save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
 +      ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
 +
 +out:
 +      return ret;
 +}
 +
 +/*
 + * Gets current TWL4030 RTC alarm time.
 + */
 +static int get_rtc_alm_time(struct rtc_time *alm_tm)
 +{
 +      unsigned char rtc_data[ALL_TIME_REGS + 1];
 +      int ret;
 +
 +      ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
 +                             REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
 +      if (ret < 0) {
 +              printk(KERN_ERR "twl4030_rtc: twl4030_i2c_read error.\n");
 +              return ret;
 +      }
 +
 +      alm_tm->tm_sec = BCD2BIN(rtc_data[0]);
 +      alm_tm->tm_min = BCD2BIN(rtc_data[1]);
 +      alm_tm->tm_hour = BCD2BIN(rtc_data[2]);
 +      alm_tm->tm_mday = BCD2BIN(rtc_data[3]);
 +      alm_tm->tm_mon = BCD2BIN(rtc_data[4]);
 +      alm_tm->tm_year = BCD2BIN(rtc_data[5]);
 +
 +      /*
 +       * Account for differences between how the RTC uses the values
 +       * and how they are defined in a struct rtc_time;
 +       */
 +      alm_tm->tm_year += (epoch - 1900);
 +      if (alm_tm->tm_year <= 69)
 +              alm_tm->tm_year += 100;
 +
 +      alm_tm->tm_mon--;
 +
 +      return ret;
 +}
 +
 +static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm)
 +{
 +      int ret;
 +
 +      memset(tm, 0, sizeof(struct rtc_time));
 +      ret = get_rtc_time(tm);
 +
 +      return ret;
 +}
 +
 +/*
 + * Gets current TWL4030 RTC alarm time.
 + */
 +static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 +{
 +      int ret;
 +      u8 rtc_interrupts_reg = 0;
 +
 +      /*
 +       * This returns a struct rtc_time. Reading >= 0xc0
 +       * means "don't care" or "match all". Only the tm_hour,
 +       * tm_min, and tm_sec values are filled in.
 +       */
 +      memset(&alm->time, 0, sizeof(struct rtc_time));
 +      ret = get_rtc_alm_time(&alm->time);
 +
 +      if (ret)
 +              goto out;
 +
 +      /* Check alarm enabled flag state */
 +      ret =
 +          ret | twl4030_i2c_read_u8(TWL4030_MODULE_RTC, &rtc_interrupts_reg,
 +                                    REG_RTC_INTERRUPTS_REG);
 +
 +      if (ret)
 +              goto out;
 +
 +      if ((rtc_interrupts_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) != 0)
 +              alm->enabled = 1;
 +      else
 +              alm->enabled = 0;
 +
 +out:
 +      return ret;
 +}
 +
 +static int twl4030_rtc_irq_set_state(struct device *dev, int enabled)
 +{
 +      int ret;
 +
 +      /* Allow ints for RTC updates.  */
 +      if (enabled)
 +              ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 +      else
 +              ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 +
 +      return ret;
 +}
 +
 +static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 +{
 +      unsigned char alarm_data[ALL_TIME_REGS + 1];
 +      int ret;
 +
 +      /* Month range is 01..12 */
 +      alm->time.tm_mon++;
 +
 +      alarm_data[1] = BIN2BCD(alm->time.tm_sec);
 +      alarm_data[2] = BIN2BCD(alm->time.tm_min);
 +      alarm_data[3] = BIN2BCD(alm->time.tm_hour);
 +      alarm_data[4] = BIN2BCD(alm->time.tm_mday);
 +      alarm_data[5] = BIN2BCD(alm->time.tm_mon);
 +      alarm_data[6] = BIN2BCD(alm->time.tm_year);
 +
 +      /* update all the alarm registers in one shot */
 +      ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data,
 +                      REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
 +      if (ret) {
 +              printk(KERN_ERR "twl4030: twl4030_i2c_write error.\n");
 +              goto out;
 +      }
 +
 +      ret = twl4030_rtc_alarm_irq_set_state(dev, alm->enabled);
 +out:
 +      return ret;
 +}
 +
 +/*
 + * We will just handle setting the frequency and make use the framework for
 + * reading the periodic interupts.
 + * @freq: Current periodic IRQ freq
 + */
 +static int twl4030_rtc_irq_set_freq(struct device *dev, int freq)
 +{
 +      struct rtc_device *rtc = dev_get_drvdata(dev);
 +
 +      if (freq < 0 || freq > 3)
 +              return -EINVAL;
 +
 +      rtc->irq_freq = freq;
 +
 +      /* set rtc irq freq to user defined value */
 +      set_rtc_irq_bit(freq);
 +
 +      return 0;
 +}
 +
 +#ifdef        CONFIG_RTC_INTF_DEV
 +
 +static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd,
 +                           unsigned long arg)
 +{
 +
 +      switch (cmd) {
 +      case RTC_AIE_OFF:
 +              return twl4030_rtc_alarm_irq_set_state(dev, 0);
 +      case RTC_AIE_ON:
 +              return twl4030_rtc_alarm_irq_set_state(dev, 1);
 +
 +      case RTC_UIE_OFF:
 +              /* Fall Through */
 +      case RTC_PIE_OFF:
 +              /* Mask ints from RTC updates.  */
 +              return twl4030_rtc_irq_set_state(dev, 0);
 +      case RTC_UIE_ON:
 +              /* Fall Through */
 +      case RTC_PIE_ON:
 +              /* Allow ints for RTC updates.  */
 +              return twl4030_rtc_irq_set_state(dev, 1);
 +
 +      case RTC_EPOCH_READ:
 +              return put_user(epoch, (unsigned long *)arg);
 +      case RTC_EPOCH_SET:
 +              /*
 +               * There were no RTC clocks before 1900.
 +               */
 +              if (arg < 1900)
 +                      return -EINVAL;
 +
 +              if (!capable(CAP_SYS_TIME))
 +                      return -EACCES;
 +
 +              epoch = arg;
 +              return 0;
 +      default:
 +              return -ENOIOCTLCMD;
 +      }
 +}
 +
 +#else
 +#define       omap_rtc_ioctl  NULL
 +#endif
 +
 +static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
 +{
 +      unsigned long events = 0;
 +      int ret = IRQ_NONE;
 +      int res;
 +      u8 rd_reg;
 +
 +      res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
 +      if (res)
 +              goto out;
 +      /*
 +       * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
 +       * only one (ALARM or RTC) interrupt source may be enabled
 +       * at time, we also could check our results
 +       * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
 +       */
 +      if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
 +              events |= RTC_IRQF | RTC_AF;
 +      else
 +              events |= RTC_IRQF | RTC_UF;
 +
 +      res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
 +                                 REG_RTC_STATUS_REG);
 +      if (res)
 +              goto out;
 +      /*
 +       * Workaround for strange behaviour with T2. Need to write into ISR
 +       * register one more time to clear the interrupt. Otherwise, the same
 +       * RTC event generates 2 interrupts in a row.
 +       * (no errata document available)
 +       */
 +      res = twl4030_i2c_write_u8(TWL4030_MODULE_INT,
 +                      PWR_RTC_INT_CLR, REG_PWR_ISR1);
 +      if (res)
 +              goto out;
 +
 +      /* Notify RTC core on event */
 +      rtc_update_irq(rtc, 1, events);
 +
 +      ret = IRQ_HANDLED;
 +out:
 +      return ret;
 +}
 +
 +static struct rtc_class_ops twl4030_rtc_ops = {
 +      .ioctl          = twl4030_rtc_ioctl,
 +      .read_time      = twl4030_rtc_read_time,
 +      .set_time       = twl4030_rtc_set_time,
 +      .read_alarm     = twl4030_rtc_read_alarm,
 +      .set_alarm      = twl4030_rtc_set_alarm,
 +      .irq_set_freq   = twl4030_rtc_irq_set_freq,
 +};
 +
 +static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
 +{
 +      struct twl4030rtc_platform_data *pdata = pdev->dev.platform_data;
 +      struct rtc_device *rtc;
 +      int ret = 0;
 +      u8 rd_reg;
 +
 +      if (pdata != NULL && pdata->init != NULL) {
 +              ret = pdata->init();
 +              if (ret < 0)
 +                      goto out;
 +      }
 +
 +      rtc = rtc_device_register(pdev->name,
 +                                &pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
 +      if (IS_ERR(rtc)) {
 +              ret = -EINVAL;
 +              dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
 +                      PTR_ERR(rtc));
 +              goto out0;
 +
 +      }
 +
 +      /* Set the irq freq to every second */
 +      rtc->irq_freq = 0;
 +
 +      platform_set_drvdata(pdev, rtc);
 +
 +      ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
 +
 +      if (ret < 0)
 +              goto out1;
 +
 +      if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M)
 +              dev_warn(&pdev->dev, "Power up reset detected.\n");
 +
 +      if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
 +              dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
 +
 +      /* Clear RTC Power up reset and pending alarm interrupts */
 +      ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
 +      if (ret < 0)
 +              goto out1;
 +
 +      ret = request_irq(TWL4030_PWRIRQ_RTC, twl4030_rtc_interrupt,
 +                              0, rtc->dev.bus_id, rtc);
 +      if (ret < 0) {
 +              dev_err(&pdev->dev, "IRQ is not free.\n");
 +              goto out1;
 +      }
 +
 +      /* Check RTC module status, Enable if it is off */
 +      ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
 +      if (ret < 0)
 +              goto out2;
 +
 +      if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
 +              dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n");
 +              rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
 +              ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
 +              if (ret < 0)
 +                      goto out2;
 +      }
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_IMR1);
 +      if (ret < 0)
 +              goto out2;
 +
 +      rd_reg &= PWR_RTC_IT_UNMASK;
 +      /* MASK PWR - we will need this */
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_IMR1);
 +      if (ret < 0)
 +              goto out2;
 +
 +      ret = twl4030_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, REG_PWR_EDR1);
 +      if (ret < 0)
 +              goto out2;
 +
 +      /* Rising edge detection enabled, needed for RTC alarm */
 +      rd_reg |= 0x80;
 +      ret = twl4030_i2c_write_u8(TWL4030_MODULE_INT, rd_reg, REG_PWR_EDR1);
 +      if (ret < 0)
 +              goto out2;
 +
 +      return ret;
 +
 +
 +out2:
 +      free_irq(TWL4030_MODIRQ_PWR, rtc);
 +out1:
 +      rtc_device_unregister(rtc);
 +out0:
 +      if (pdata != NULL && pdata->exit != NULL)
 +              pdata->exit();
 +out:
 +      return ret;
 +}
 +
 +/*
 + * Disable all TWL4030 RTC module interrupts.
 + * Sets status flag to free.
 + */
 +static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
 +{
 +      /* leave rtc running, but disable irqs */
 +      struct twl4030rtc_platform_data *pdata = pdev->dev.platform_data;
 +      struct rtc_device *rtc = platform_get_drvdata(pdev);
 +
 +      mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 +      mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 +
 +      free_irq(TWL4030_MODIRQ_PWR, rtc);
 +
 +      if (pdata != NULL && pdata->exit != NULL)
 +              pdata->exit();
 +
 +      rtc_device_unregister(rtc);
 +      platform_set_drvdata(pdev, NULL);
 +      return 0;
 +}
 +
 +static void twl4030_rtc_shutdown(struct platform_device *pdev)
 +{
 +      twl4030_rtc_alarm_irq_set_state(&pdev->dev, 0);
 +      twl4030_rtc_irq_set_state(&pdev->dev, 0);
 +}
 +
 +#ifdef CONFIG_PM
 +
 +static unsigned char irqstat;
 +
 +static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      get_rtc_irq_bit(&irqstat);
 +
 +      mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M |
 +                       BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 +      return 0;
 +}
 +
 +static int twl4030_rtc_resume(struct platform_device *pdev)
 +{
 +      set_rtc_irq_bit(irqstat);
 +      return 0;
 +}
 +#else
 +#define twl4030_rtc_suspend NULL
 +#define twl4030_rtc_resume  NULL
 +#endif
 +
 +MODULE_ALIAS("platform:twl4030_rtc");
 +static struct platform_driver twl4030rtc_driver = {
 +      .probe          = twl4030_rtc_probe,
 +      .remove         = __devexit_p(twl4030_rtc_remove),
 +      .shutdown       = twl4030_rtc_shutdown,
 +      .suspend        = twl4030_rtc_suspend,
 +      .resume         = twl4030_rtc_resume,
 +      .driver         = {
 +              .owner  = THIS_MODULE,
 +              .name   = "twl4030_rtc",
 +      },
 +};
 +
 +static int __init twl4030_rtc_init(void)
 +{
 +      return platform_driver_register(&twl4030rtc_driver);
 +}
 +
 +static void __exit twl4030_rtc_exit(void)
 +{
 +      platform_driver_unregister(&twl4030rtc_driver);
 +}
 +
 +MODULE_ALIAS("platform:twl4030_rtc");
 +MODULE_AUTHOR("Texas Instruments, MontaVista Software");
 +MODULE_LICENSE("GPL");;
 +
 +module_init(twl4030_rtc_init);
 +module_exit(twl4030_rtc_exit);
index 3980943e27e4ec06d4ef417cacc24a23826647b7,0000000000000000000000000000000000000000..939bc48c2b5e8d38468fdfa9682837e851dae5f0
mode 100644,000000..100644
--- /dev/null
@@@ -1,301 -1,0 +1,301 @@@
- #include <asm/arch/gpio.h>
 +/*
 + * TSC2301 driver
 + *
 + * Copyright (C) 2005, 2006 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 + *
 + */
 +
 +#include <linux/module.h>
 +#include <linux/device.h>
 +#include <linux/delay.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc2301.h>
 +
 +#ifdef CONFIG_ARCH_OMAP
++#include <mach/gpio.h>
 +#endif
 +
 +u16 tsc2301_read_reg(struct tsc2301 *tsc, int reg)
 +{
 +      struct spi_transfer t[2];
 +      struct spi_message m;
 +      u16 data = 0, cmd;
 +
 +      cmd = reg;
 +      cmd |= 0x8000;
 +
 +      memset(t, 0, sizeof(t));
 +      spi_message_init(&m);
 +      m.spi = tsc->spi;
 +
 +      t[0].tx_buf = &cmd;
 +      t[0].rx_buf = NULL;
 +      t[0].len = 2;
 +      spi_message_add_tail(&t[0], &m);
 +
 +      t[1].tx_buf = NULL;
 +      t[1].rx_buf = &data;
 +      t[1].len = 2;
 +      spi_message_add_tail(&t[1], &m);
 +
 +      spi_sync(m.spi, &m);
 +
 +      return data;
 +}
 +
 +void tsc2301_write_reg(struct tsc2301 *tsc, int reg, u16 val)
 +{
 +      struct spi_transfer t;
 +      struct spi_message m;
 +      u16 data[2];
 +
 +      /* Now we prepare the command for transferring */
 +      data[0] = reg;
 +      data[1] = val;
 +
 +      spi_message_init(&m);
 +      m.spi = tsc->spi;
 +
 +      memset(&t, 0, sizeof(t));
 +      t.tx_buf = data;
 +      t.rx_buf = NULL;
 +      t.len = 4;
 +      spi_message_add_tail(&t, &m);
 +
 +      spi_sync(m.spi, &m);
 +}
 +
 +void tsc2301_write_kbc(struct tsc2301 *tsc, int val)
 +{
 +      u16 w;
 +
 +      w = tsc->config2_shadow;
 +      w &= ~(0x03 << 14);
 +      w |= (val & 0x03) << 14;
 +      tsc2301_write_reg(tsc, TSC2301_REG_CONFIG2, w);
 +      tsc->config2_shadow = w;
 +}
 +
 +void tsc2301_write_pll(struct tsc2301 *tsc,
 +                     int pll_n, int pll_a, int pll_pdc, int pct_e, int pll_o)
 +{
 +      u16 w;
 +
 +      w = tsc->config2_shadow;
 +      w &= ~0x3fff;
 +      w |= (pll_n & 0x0f) | ((pll_a & 0x0f) << 4) | ((pll_pdc & 0x0f) << 8);
 +      w |= pct_e ? (1 << 12) : 0;
 +      w |= pll_o ? (1 << 13) : 0;
 +      tsc2301_write_reg(tsc, TSC2301_REG_CONFIG2, w);
 +      tsc->config2_shadow = w;
 +}
 +
 +void tsc2301_read_buf(struct tsc2301 *tsc, int reg, u16 *rx_buf, int len)
 +{
 +      struct spi_transfer t[2];
 +      struct spi_message m;
 +      u16 cmd, i;
 +
 +      cmd = reg;
 +      cmd |= 0x8000;
 +
 +      spi_message_init(&m);
 +      m.spi = tsc->spi;
 +
 +      memset(t, 0, sizeof(t));
 +      t[0].tx_buf = &cmd;
 +      t[0].rx_buf = NULL;
 +      t[0].len = 2;
 +      spi_message_add_tail(&t[0], &m);
 +
 +      t[1].tx_buf = NULL;
 +      t[1].rx_buf = rx_buf;
 +      t[1].len = 2 * len;
 +      spi_message_add_tail(&t[1], &m);
 +
 +      spi_sync(m.spi, &m);
 +
 +      for (i = 0; i < len; i++)
 +              printk(KERN_DEBUG "rx_buf[%d]: %04x\n", i, rx_buf[i]);
 +}
 +
 +static int __devinit tsc2301_probe(struct spi_device *spi)
 +{
 +      struct tsc2301                  *tsc;
 +      struct tsc2301_platform_data    *pdata = spi->dev.platform_data;
 +      int r;
 +      u16 w;
 +
 +      if (!pdata) {
 +              dev_dbg(&spi->dev, "no platform data?\n");
 +              return -ENODEV;
 +      }
 +
 +      tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
 +      if (tsc == NULL)
 +              return -ENOMEM;
 +
 +      dev_set_drvdata(&spi->dev, tsc);
 +      tsc->spi = spi;
 +
 +      tsc->enable_clock = pdata->enable_clock;
 +      tsc->disable_clock = pdata->disable_clock;
 +
 +      if (pdata->reset_gpio >= 0) {
 +              tsc->reset_gpio = pdata->reset_gpio;
 +#ifdef CONFIG_ARCH_OMAP
 +              r = omap_request_gpio(tsc->reset_gpio);
 +              if (r < 0)
 +                      goto err1;
 +              omap_set_gpio_dataout(tsc->reset_gpio, 1);
 +              omap_set_gpio_direction(tsc->reset_gpio, 0);
 +              mdelay(1);
 +              omap_set_gpio_dataout(tsc->reset_gpio, 0);
 +#endif
 +      } else
 +              tsc->reset_gpio = -1;
 +
 +      spi->mode = SPI_MODE_1;
 +      spi->bits_per_word = 16;
 +      /* The max speed might've been defined by the board-specific
 +       * struct */
 +      if (!spi->max_speed_hz)
 +              spi->max_speed_hz = TSC2301_HZ;
 +      spi_setup(spi);
 +
 +      /* Soft reset */
 +      tsc2301_write_reg(tsc, TSC2301_REG_RESET, 0xbb00);
 +      msleep(1);
 +
 +      w = tsc2301_read_reg(tsc, TSC2301_REG_ADC);
 +      if (!(w & (1 << 14))) {
 +              dev_err(&spi->dev, "invalid ADC reg value: %04x\n", w);
 +              r = -ENODEV;
 +              goto err1;
 +      }
 +
 +      w = tsc2301_read_reg(tsc, TSC2301_REG_DAC);
 +      if (!(w & (1 << 15))) {
 +              dev_err(&spi->dev, "invalid DAC reg value: %04x\n", w);
 +              r = -ENODEV;
 +              goto err1;
 +      }
 +
 +      /* Stop keypad scanning */
 +      tsc2301_write_reg(tsc, TSC2301_REG_KEY, 0x4000);
 +
 +      /* We have to cache this for read-modify-write, since we can't
 +       * read back BIT15 */
 +      w = tsc2301_read_reg(tsc, TSC2301_REG_CONFIG2);
 +      /* By default BIT15 is set */
 +      w |= 1 << 15;
 +      tsc->config2_shadow = w;
 +
 +      r = tsc2301_kp_init(tsc, pdata);
 +      if (r)
 +              goto err1;
 +      r = tsc2301_ts_init(tsc, pdata);
 +      if (r)
 +              goto err2;
 +      r = tsc2301_mixer_init(tsc, pdata);
 +      if (r)
 +              goto err3;
 +      return 0;
 +
 +err3:
 +      tsc2301_ts_exit(tsc);
 +err2:
 +      tsc2301_kp_exit(tsc);
 +err1:
 +      kfree(tsc);
 +      return r;
 +}
 +
 +static int __devexit tsc2301_remove(struct spi_device *spi)
 +{
 +      struct tsc2301 *tsc = dev_get_drvdata(&spi->dev);
 +
 +      tsc2301_mixer_exit(tsc);
 +        tsc2301_ts_exit(tsc);
 +        tsc2301_kp_exit(tsc);
 +      kfree(tsc);
 +
 +      return 0;
 +}
 +
 +#ifdef CONFIG_PM
 +static int tsc2301_suspend(struct spi_device *spi, pm_message_t mesg)
 +{
 +      struct tsc2301 *tsc = dev_get_drvdata(&spi->dev);
 +      int r;
 +
 +      if ((r = tsc2301_mixer_suspend(tsc)) < 0)
 +              return r;
 +      if ((r = tsc2301_kp_suspend(tsc)) < 0)
 +              goto err1;
 +      if ((r = tsc2301_ts_suspend(tsc)) < 0)
 +              goto err2;
 +
 +      return 0;
 +err2:
 +      tsc2301_kp_resume(tsc);
 +err1:
 +      tsc2301_mixer_resume(tsc);
 +      return r;
 +}
 +
 +static int tsc2301_resume(struct spi_device *spi)
 +{
 +      struct tsc2301 *tsc = dev_get_drvdata(&spi->dev);
 +
 +      tsc2301_ts_resume(tsc);
 +      tsc2301_kp_resume(tsc);
 +      tsc2301_mixer_resume(tsc);
 +      return 0;
 +}
 +#endif
 +
 +static struct spi_driver tsc2301_driver = {
 +      .driver = {
 +                 .name = "tsc2301",
 +                 .bus = &spi_bus_type,
 +                 .owner = THIS_MODULE,
 +      },
 +#ifdef CONFIG_PM
 +      .suspend = tsc2301_suspend,
 +      .resume = tsc2301_resume,
 +#endif
 +      .probe = tsc2301_probe,
 +      .remove = __devexit_p(tsc2301_remove),
 +};
 +
 +static int __init tsc2301_init(void)
 +{
 +      printk("TSC2301 driver initializing\n");
 +
 +      return spi_register_driver(&tsc2301_driver);
 +}
 +module_init(tsc2301_init);
 +
 +static void __exit tsc2301_exit(void)
 +{
 +      spi_unregister_driver(&tsc2301_driver);
 +}
 +module_exit(tsc2301_exit);
 +
 +MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>");
 +MODULE_LICENSE("GPL");
Simple merge
index 8ca21c276ed019a6a4bd1318e09937b3ae4b45ee,0000000000000000000000000000000000000000..8f122e511e7faca12ef737f60b176e30aab70ffa
mode 100644,000000..100644
--- /dev/null
@@@ -1,562 -1,0 +1,562 @@@
- #include <asm/arch/gpio.h>
 +/*
 + * ehci-omap.c - driver for USBHOST on OMAP 34xx processor
 + *
 + * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller
 + * Tested on OMAP3430 ES2.0 SDP
 + *
 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
 + *    Author: Vikram Pandita <vikram.pandita@ti.com>
 + *
 + * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers
 + *
 + * 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/platform_device.h>
 +#include <linux/clk.h>
++#include <mach/gpio.h>
 +
 +#include "ehci-omap.h"
 +
 +
 +#ifdef CONFIG_OMAP_EHCI_PHY_MODE
 +/* EHCI connected to External PHY */
 +
 +/* External USB connectivity board: 750-2083-001
 + * Connected to OMAP3430 SDP
 + * The board has Port1 and Port2 connected to ISP1504 in 12-pin ULPI mode
 + */
 +
 +/* ISSUE1:
 + *      ISP1504 for input clocking mode needs special reset handling
 + *    Hold the PHY in reset by asserting RESET_N signal
 + *    Then start the 60Mhz clock input to PHY
 + *    Release the reset after a delay -
 + *            to get the PHY state machine in working state
 + */
 +#define EXTERNAL_PHY_RESET
 +#define       EXT_PHY_RESET_GPIO_PORT1        (57)
 +#define       EXT_PHY_RESET_GPIO_PORT2        (61)
 +#define       EXT_PHY_RESET_DELAY             (10)
 +
 +/* ISSUE2:
 + * USBHOST supports External charge pump PHYs only
 + * Use the VBUS from Port1 to power VBUS of Port2 externally
 + * So use Port2 as the working ULPI port
 + */
 +#define VBUS_INTERNAL_CHARGEPUMP_HACK
 +
 +#endif /* CONFIG_OMAP_EHCI_PHY_MODE */
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/* Define USBHOST clocks for clock management */
 +struct ehci_omap_clock_defs {
 +      struct clk      *usbhost_ick_clk;
 +      struct clk      *usbhost2_120m_fck_clk;
 +      struct clk      *usbhost1_48m_fck_clk;
 +      struct clk      *usbtll_fck_clk;
 +      struct clk      *usbtll_ick_clk;
 +};
 +
 +/* Clock names as per clock framework: May change so keep as #defs */
 +#define USBHOST_ICKL          "usbhost_ick"
 +#define USBHOST_120M_FCLK     "usbhost_120m_fck"
 +#define USBHOST_48M_FCLK      "usbhost_48m_fck"
 +#define USBHOST_TLL_ICKL      "usbtll_ick"
 +#define USBHOST_TLL_FCLK      "usbtll_fck"
 +/*-------------------------------------------------------------------------*/
 +
 +
 +#ifndef CONFIG_OMAP_EHCI_PHY_MODE
 +
 +static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 +{
 +      int i;
 +
 +      /* Use UTMI Ports of TLL */
 +      omap_writel((1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
 +                      (0<<OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
 +                                              OMAP_UHH_HOSTCONFIG);
 +      /* Enusre bit is set */
 +      while (!(omap_readl(OMAP_UHH_HOSTCONFIG) &
 +              (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)));
 +
 +      dev_dbg(hcd->self.controller, "\nEntered UTMI MODE: success\n");
 +
 +      /* Program the 3 TLL channels upfront */
 +
 +      for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
 +
 +              /* Disable AutoIdle */
 +              omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
 +                          ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
 +                          OMAP_TLL_CHANNEL_CONF(i));
 +              /* Disable BitStuffing */
 +              omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
 +                          ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
 +                          OMAP_TLL_CHANNEL_CONF(i));
 +              /* SDR Mode */
 +              omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
 +                          ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
 +                          OMAP_TLL_CHANNEL_CONF(i));
 +
 +      }
 +
 +      /* Program Common TLL register */
 +      omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) |
 +                      (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) |
 +                      (0 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) |
 +                      (0 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT),
 +                              OMAP_TLL_SHARED_CONF);
 +
 +      /* Enable channels now */
 +      for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
 +
 +              /* Enable only the channel that is needed */
 +              if (!(tll_channel_mask & 1<<i))
 +                      continue;
 +
 +              omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) |
 +                          (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
 +                          OMAP_TLL_CHANNEL_CONF(i));
 +
 +              omap_writeb(0xBE, OMAP_TLL_ULPI_SCRATCH_REGISTER(i));
 +              dev_dbg(hcd->self.controller, "\nULPI_SCRATCH_REG[ch=%d]"
 +                      "= 0x%02x\n",
 +                      i+1, omap_readb(OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
 +      }
 +}
 +
 +#else
 +# define omap_usb_utmi_init(x, y)     0
 +#endif
 +
 +
 +/* omap_start_ehc
 + *    - Start the TI USBHOST controller
 + */
 +static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 +{
 +      struct ehci_omap_clock_defs *ehci_clocks;
 +
 +      dev_dbg(hcd->self.controller, ": starting TI EHCI USB Controller\n");
 +
 +      ehci_clocks = (struct ehci_omap_clock_defs *)(
 +                              ((char *)hcd_to_ehci(hcd)) +
 +                                      sizeof(struct ehci_hcd));
 +
 +      /* Start DPLL5 Programming:
 +       * Clock Framework is not doing this now:
 +       * This will be done in clock framework later
 +       */
 +      /* Enable DPLL 5 : Based on Input of 13Mhz*/
 +      cm_write_mod_reg((12 << OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT)|
 +                      (120 << OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT),
 +                      PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
 +
 +      cm_write_mod_reg(1 << OMAP3430ES2_DIV_120M_SHIFT,
 +                      PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
 +
 +      cm_write_mod_reg((7 << OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT) |
 +                      (7 << OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT),
 +                      PLL_MOD, OMAP3430ES2_CM_CLKEN2);
 +
 +      while (!(cm_read_mod_reg(PLL_MOD, CM_IDLEST2) &
 +                              OMAP3430ES2_ST_PERIPH2_CLK_MASK))
 +              dev_dbg(hcd->self.controller,
 +                      "idlest2 = 0x%x\n",
 +                      cm_read_mod_reg(PLL_MOD, CM_IDLEST2));
 +      /* End DPLL5 programming */
 +
 +
 +      /* PRCM settings for USBHOST:
 +       * Interface clk un-related to domain transition
 +       */
 +      cm_write_mod_reg(0 << OMAP3430ES2_AUTO_USBHOST_SHIFT,
 +                              OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
 +
 +      /* Disable sleep dependency with MPU and IVA */
 +      cm_write_mod_reg((0 << OMAP3430ES2_EN_MPU_SHIFT) |
 +                              (0 << OMAP3430ES2_EN_IVA2_SHIFT),
 +                              OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
 +
 +      /* Disable Automatic transition of clock */
 +      cm_write_mod_reg(0 << OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT,
 +                              OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
 +
 +      /* Enable Clocks for USBHOST */
 +      ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev,
 +                                              USBHOST_ICKL);
 +      if (IS_ERR(ehci_clocks->usbhost_ick_clk))
 +              return PTR_ERR(ehci_clocks->usbhost_ick_clk);
 +      clk_enable(ehci_clocks->usbhost_ick_clk);
 +
 +
 +      ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev,
 +                                                      USBHOST_120M_FCLK);
 +      if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk))
 +              return PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk);
 +      clk_enable(ehci_clocks->usbhost2_120m_fck_clk);
 +
 +      ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev,
 +                                              USBHOST_48M_FCLK);
 +      if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk))
 +              return PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk);
 +      clk_enable(ehci_clocks->usbhost1_48m_fck_clk);
 +
 +
 +#ifdef EXTERNAL_PHY_RESET
 +      /* Refer: ISSUE1 */
 +      omap_request_gpio(EXT_PHY_RESET_GPIO_PORT1);
 +      omap_set_gpio_direction(EXT_PHY_RESET_GPIO_PORT1, 0);
 +      omap_request_gpio(EXT_PHY_RESET_GPIO_PORT2);
 +      omap_set_gpio_direction(EXT_PHY_RESET_GPIO_PORT2, 0);
 +      omap_set_gpio_dataout(EXT_PHY_RESET_GPIO_PORT1, 0);
 +      omap_set_gpio_dataout(EXT_PHY_RESET_GPIO_PORT2, 0);
 +      /* Hold the PHY in RESET for enough time till DIR is high */
 +      udelay(EXT_PHY_RESET_DELAY);
 +#endif
 +
 +      /* Configure TLL for 60Mhz clk for ULPI */
 +      ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
 +      if (IS_ERR(ehci_clocks->usbtll_fck_clk))
 +              return PTR_ERR(ehci_clocks->usbtll_fck_clk);
 +      clk_enable(ehci_clocks->usbtll_fck_clk);
 +
 +      ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL);
 +      if (IS_ERR(ehci_clocks->usbtll_ick_clk))
 +              return PTR_ERR(ehci_clocks->usbtll_ick_clk);
 +      clk_enable(ehci_clocks->usbtll_ick_clk);
 +
 +      /* Disable Auto Idle of USBTLL */
 +      cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT),
 +                              CORE_MOD, CM_AUTOIDLE3);
 +
 +      /* Wait for TLL to be Active */
 +      while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3) &
 +              (1 << OMAP3430ES2_ST_USBTLL_SHIFT)));
 +
 +      /* perform TLL soft reset, and wait until reset is complete */
 +      omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT,
 +                      OMAP_USBTLL_SYSCONFIG);
 +      /* Wait for TLL reset to complete */
 +      while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) &
 +              (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT)));
 +
 +      dev_dbg(hcd->self.controller, "\n TLL RESET DONE\n");
 +
 +      /* (1<<3) = no idle mode only for initial debugging */
 +      omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) |
 +                      (1 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) |
 +                      (1 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT),
 +                      OMAP_USBTLL_SYSCONFIG);
 +
 +
 +      /* Put UHH in NoIdle/NoStandby mode */
 +      omap_writel((0 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) |
 +                      (1 << OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT) |
 +                      (1 << OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT) |
 +                      (1 << OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT) |
 +                      (1 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT),
 +                      OMAP_UHH_SYSCONFIG);
 +
 +#ifdef CONFIG_OMAP_EHCI_PHY_MODE
 +      /* Bypass the TLL module for PHY mode operation */
 +      omap_writel((0 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)|
 +                      (1<<OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
 +                      (0<<OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
 +                                              OMAP_UHH_HOSTCONFIG);
 +      /* Ensure that BYPASS is set */
 +      while (omap_readl(OMAP_UHH_HOSTCONFIG) &
 +              (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT));
 +
 +      dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success");
 +
 +#else
 +      /* Enable UTMI mode for all 3 TLL channels */
 +      omap_usb_utmi_init(hcd,
 +              OMAP_TLL_CHANNEL_1_EN_MASK |
 +              OMAP_TLL_CHANNEL_2_EN_MASK |
 +              OMAP_TLL_CHANNEL_3_EN_MASK
 +              );
 +#endif
 +
 +#ifdef EXTERNAL_PHY_RESET
 +      /* Refer ISSUE1:
 +       * Hold the PHY in RESET for enough time till PHY is settled and ready
 +       */
 +      udelay(EXT_PHY_RESET_DELAY);
 +      omap_set_gpio_dataout(EXT_PHY_RESET_GPIO_PORT1, 1);
 +      omap_set_gpio_dataout(EXT_PHY_RESET_GPIO_PORT2, 1);
 +#endif
 +
 +#ifdef VBUS_INTERNAL_CHARGEPUMP_HACK
 +      /* Refer ISSUE2: LINK assumes external charge pump */
 +
 +      /* use Port1 VBUS to charge externally Port2:
 +       *      So for PHY mode operation use Port2 only
 +       */
 +      omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/
 +                      (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
 +                      (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
 +                      (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
 +                      (0x26),
 +                      EHCI_INSNREG05_ULPI);
 +
 +      while (!(omap_readl(EHCI_INSNREG05_ULPI) &
 +              (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
 +
 +#endif
 +
 +      return 0;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 +{
 +      struct ehci_omap_clock_defs *ehci_clocks;
 +
 +      ehci_clocks = (struct ehci_omap_clock_defs *)
 +                      (((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd));
 +
 +      dev_dbg(hcd->self.controller, ": stopping TI EHCI USB Controller\n");
 +
 +      /* Reset OMAP modules for insmod/rmmod to work */
 +      omap_writel((1<<1), OMAP_UHH_SYSCONFIG);
 +      while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<0)));
 +      while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<1)));
 +      while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<2)));
 +      dev_dbg(hcd->self.controller,
 +              "UHH RESET DONE OMAP_UHH_SYSSTATUS %x !!\n",
 +                      omap_readl(OMAP_UHH_SYSSTATUS));
 +
 +      omap_writel((1<<1), OMAP_USBTLL_SYSCONFIG);
 +      while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1<<0)));
 +      dev_dbg(hcd->self.controller, ":TLL RESEET DONE");
 +
 +      if (ehci_clocks->usbtll_fck_clk != NULL) {
 +              clk_disable(ehci_clocks->usbtll_fck_clk);
 +              clk_put(ehci_clocks->usbtll_fck_clk);
 +              ehci_clocks->usbtll_fck_clk = NULL;
 +      }
 +
 +      if (ehci_clocks->usbhost_ick_clk != NULL) {
 +              clk_disable(ehci_clocks->usbhost_ick_clk);
 +              clk_put(ehci_clocks->usbhost_ick_clk);
 +              ehci_clocks->usbhost_ick_clk = NULL;
 +      }
 +
 +      if (ehci_clocks->usbhost1_48m_fck_clk != NULL) {
 +              clk_disable(ehci_clocks->usbhost1_48m_fck_clk);
 +              clk_put(ehci_clocks->usbhost1_48m_fck_clk);
 +              ehci_clocks->usbhost1_48m_fck_clk = NULL;
 +      }
 +
 +      if (ehci_clocks->usbhost2_120m_fck_clk != NULL) {
 +              clk_disable(ehci_clocks->usbhost2_120m_fck_clk);
 +              clk_put(ehci_clocks->usbhost2_120m_fck_clk);
 +              ehci_clocks->usbhost2_120m_fck_clk = NULL;
 +      }
 +
 +      if (ehci_clocks->usbtll_ick_clk != NULL) {
 +              clk_disable(ehci_clocks->usbtll_ick_clk);
 +              clk_put(ehci_clocks->usbtll_ick_clk);
 +              ehci_clocks->usbtll_ick_clk = NULL;
 +      }
 +
 +
 +#ifdef EXTERNAL_PHY_RESET
 +      omap_free_gpio(EXT_PHY_RESET_GPIO_PORT1);
 +      omap_free_gpio(EXT_PHY_RESET_GPIO_PORT2);
 +#endif
 +
 +      dev_dbg(hcd->self.controller,
 +              ": Clock to USB host has been disabled\n");
 +}
 +
 +static const struct hc_driver ehci_omap_hc_driver;
 +
 +/*-------------------------------------------------------------------------*/
 +/* configure so an HC device and id are always provided */
 +/* always called with process context; sleeping is OK */
 +
 +/**
 + * ehci_hcd_omap_drv_probe - initialize TI-based HCDs
 + * Context: !in_interrupt()
 + *
 + * Allocates basic resources for this USB host controller, and
 + * then invokes the start() method for the HCD associated with it
 + * through the hotplug entry's driver_data.
 + *
 + */
 +static int ehci_hcd_omap_drv_probe(struct platform_device *dev)
 +{
 +      int retval = 0;
 +      struct usb_hcd *hcd;
 +      struct ehci_hcd *ehci;
 +
 +      dev_dbg(&dev->dev, "ehci_hcd_omap_drv_probe()");
 +
 +      if (usb_disabled())
 +              return -ENODEV;
 +
 +      if (dev->resource[1].flags != IORESOURCE_IRQ) {
 +              dev_dbg(&dev->dev, "resource[1] is not IORESOURCE_IRQ");
 +              retval = -ENOMEM;
 +      }
 +
 +      hcd = usb_create_hcd(&ehci_omap_hc_driver, &dev->dev, dev->dev.bus_id);
 +      if (!hcd)
 +              return -ENOMEM;
 +
 +      retval = omap_start_ehc(dev, hcd);
 +      if (retval)
 +              return retval;
 +
 +      hcd->rsrc_start = 0;
 +      hcd->rsrc_len = 0;
 +      hcd->rsrc_start = dev->resource[0].start;
 +      hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
 +
 +      hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
 +
 +      ehci = hcd_to_ehci(hcd);
 +      ehci->caps = hcd->regs;
 +
 +      ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
 +      /* cache this readonly data; minimize chip reads */
 +      ehci->hcs_params = readl(&ehci->caps->hcs_params);
 +
 +      /* SET 1 micro-frame Interrupt interval */
 +      writel(readl(&ehci->regs->command) | (1<<16), &ehci->regs->command);
 +
 +      retval = usb_add_hcd(hcd, dev->resource[1].start,
 +                              IRQF_DISABLED | IRQF_SHARED);
 +      if (retval == 0)
 +              return retval;
 +
 +      dev_dbg(hcd->self.controller, "ERR: add_hcd");
 +      omap_stop_ehc(dev, hcd);
 +
 +      usb_put_hcd(hcd);
 +      return retval;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/* may be called without controller electrically present */
 +/* may be called with controller, bus, and devices active */
 +
 +/**
 + * ehci_hcd_omap_drv_remove - shutdown processing for EHCI HCDs
 + * @dev: USB Host Controller being removed
 + * Context: !in_interrupt()
 + *
 + * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking
 + * the HCD's stop() method.  It is always called from a thread
 + * context, normally "rmmod", "apmd", or something similar.
 + *
 + */
 +static int ehci_hcd_omap_drv_remove(struct platform_device *dev)
 +{
 +      struct usb_hcd *hcd = platform_get_drvdata(dev);
 +
 +      dev_dbg(&dev->dev, "ehci_hcd_omap_drv_remove()");
 +
 +      usb_remove_hcd(hcd);
 +      usb_put_hcd(hcd);
 +      omap_stop_ehc(dev, hcd);
 +
 +      return 0;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +#ifdef CONFIG_PM
 +static int omap_ehci_bus_suspend(struct usb_hcd *hcd)
 +{
 +      return ehci_bus_suspend(hcd);
 +}
 +
 +static int omap_ehci_bus_resume(struct usb_hcd *hcd)
 +{
 +      return ehci_bus_resume(hcd);
 +}
 +#endif
 +/*-------------------------------------------------------------------------*/
 +
 +static const struct hc_driver ehci_omap_hc_driver = {
 +      .description = hcd_name,
 +      .product_desc = "OMAP-EHCI Host Controller",
 +      .hcd_priv_size = sizeof(struct ehci_hcd)
 +                              + sizeof(struct ehci_omap_clock_defs),
 +
 +      /*
 +       * generic hardware linkage
 +       */
 +      .irq = ehci_irq,
 +      .flags = HCD_MEMORY | HCD_USB2,
 +
 +      /*
 +       * basic lifecycle operations
 +       */
 +      .reset = ehci_init,
 +      .start = ehci_run,
 +      .stop = ehci_stop,
 +      .shutdown = ehci_shutdown,
 +
 +      /*
 +       * managing i/o requests and associated device resources
 +       */
 +      .urb_enqueue = ehci_urb_enqueue,
 +      .urb_dequeue = ehci_urb_dequeue,
 +      .endpoint_disable = ehci_endpoint_disable,
 +
 +      /*
 +       * scheduling support
 +       */
 +      .get_frame_number = ehci_get_frame,
 +
 +      /*
 +       * root hub support
 +       */
 +      .hub_status_data = ehci_hub_status_data,
 +      .hub_control = ehci_hub_control,
 +#ifdef        CONFIG_PM
 +      .bus_suspend = omap_ehci_bus_suspend,
 +      .bus_resume = omap_ehci_bus_resume,
 +#endif
 +};
 +
 +/*-------------------------------------------------------------------------*/
 +MODULE_ALIAS("omap-ehci");
 +static struct platform_driver ehci_hcd_omap_driver = {
 +      .probe = ehci_hcd_omap_drv_probe,
 +      .remove = ehci_hcd_omap_drv_remove,
 +      .shutdown = usb_hcd_platform_shutdown,
 +      /*.suspend      = ehci_hcd_omap_drv_suspend, */
 +      /*.resume       = ehci_hcd_omap_drv_resume, */
 +      .driver = {
 +              .name = "ehci-omap",
 +              .bus = &platform_bus_type
 +      }
 +};
index f75eda702a4db915f97351312d4a9cbee4071f2d,0000000000000000000000000000000000000000..9e4378f6bbb3110bd0d37beda3456b0757ccd5eb
mode 100644,000000..100644
--- /dev/null
@@@ -1,125 -1,0 +1,125 @@@
- #include <asm/hardware.h>
 +/*
 + * ehci-omap.h - register definitions for USBHOST in OMAP 34xx
 + *
 + * Copyright (C) 2007-2008 Texas Instruments, Inc.
 + *    Author: Vikram Pandita <vikram.pandita@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
 + *
 + */
 +
 +#ifndef __EHCI_OMAP_H
 +#define __EHCI_OMAP_H
 +
++#include <mach/hardware.h>
 +#include "../../../arch/arm/mach-omap2/cm.h"
 +#include "../../../arch/arm/mach-omap2/cm-regbits-34xx.h"
 +
 +/*
 + * OMAP USBHOST Register addresses: PHYSICAL ADDRESSES
 + *    Use omap_readl()/omap_writel() functions
 + */
 +
 +/* USBHOST: TLL, UUH, OHCI, EHCI */
 +#define       OMAP_USBHOST_BASE       (L4_34XX_BASE + 0x60000)
 +
 +/* TLL Register Set */
 +#define       OMAP_USBHOST_TLL_BASE   (OMAP_USBHOST_BASE + 0x2000)
 +#define       OMAP_USBTLL_REVISION    (OMAP_USBHOST_TLL_BASE + 0x00)
 +#define       OMAP_USBTLL_SYSCONFIG   (OMAP_USBHOST_TLL_BASE + 0x10)
 +      #define OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT   8
 +      #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT   3
 +      #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT   2
 +      #define OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT   1
 +      #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE_SHIFT    0
 +#define       OMAP_USBTLL_SYSSTATUS   (OMAP_USBHOST_TLL_BASE + 0x14)
 +      #define OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT   0
 +#define       OMAP_USBTLL_IRQSTATUS   (OMAP_USBHOST_TLL_BASE + 0x18)
 +#define       OMAP_USBTLL_IRQENABLE   (OMAP_USBHOST_TLL_BASE + 0x1C)
 +
 +#define       OMAP_TLL_SHARED_CONF    (OMAP_USBHOST_TLL_BASE + 0x30)
 +      #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT        6
 +      #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT      5
 +      #define OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT        2
 +      #define OMAP_TLL_SHARED_CONF_FCLK_REQ_SHIFT             1
 +      #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT           0
 +
 +#define       OMAP_TLL_CHANNEL_CONF(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x040 + 0x004 * num))
 +      #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT      11
 +      #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE_SHIFT   10
 +      #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT        9
 +      #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT         8
 +      #define OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT              0
 +
 +#define       OMAP_TLL_ULPI_FUNCTION_CTRL(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x804 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_INTERFACE_CTRL(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x807 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_OTG_CTRL(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x80A + 0x100 * num))
 +#define       OMAP_TLL_ULPI_INT_EN_RISE(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x80D + 0x100 * num))
 +#define       OMAP_TLL_ULPI_INT_EN_FALL(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x810 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_INT_STATUS(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x813 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_INT_LATCH(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x814 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_DEBUG(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x815 + 0x100 * num))
 +#define       OMAP_TLL_ULPI_SCRATCH_REGISTER(num)\
 +                      (OMAP_USBHOST_TLL_BASE + (0x816 + 0x100 * num))
 +
 +#define OMAP_TLL_CHANNEL_COUNT                3
 +      #define OMAP_TLL_CHANNEL_1_EN_MASK      1
 +      #define OMAP_TLL_CHANNEL_2_EN_MASK      2
 +      #define OMAP_TLL_CHANNEL_3_EN_MASK      4
 +
 +/* UHH Register Set */
 +#define       OMAP_USBHOST_UHH_BASE   (OMAP_USBHOST_BASE + 0x4000)
 +#define       OMAP_UHH_REVISION       (OMAP_USBHOST_UHH_BASE + 0x00)
 +#define       OMAP_UHH_SYSCONFIG      (OMAP_USBHOST_UHH_BASE + 0x10)
 +      #define OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT      12
 +      #define OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT      8
 +      #define OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT      3
 +      #define OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT      2
 +      #define OMAP_UHH_SYSCONFIG_SOFTRESET_SHIFT      1
 +      #define OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT       0
 +
 +#define       OMAP_UHH_SYSSTATUS      (OMAP_USBHOST_UHH_BASE + 0x14)
 +#define       OMAP_UHH_HOSTCONFIG     (OMAP_USBHOST_UHH_BASE + 0x40)
 +      #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT   0
 +      #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT        2
 +      #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT        3
 +      #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT       4
 +      #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT        5
 +
 +#define       OMAP_UHH_DEBUG_CSR      (OMAP_USBHOST_UHH_BASE + 0x44)
 +
 +/* EHCI Register Set */
 +#define       OMAP_USBHOST_EHCI_BASE  (OMAP_USBHOST_BASE + 0x4800)
 +#define       EHCI_INSNREG05_ULPI             (OMAP_USBHOST_EHCI_BASE + 0xA4)
 +      #define EHCI_INSNREG05_ULPI_CONTROL_SHIFT       31
 +      #define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT       24
 +      #define EHCI_INSNREG05_ULPI_OPSEL_SHIFT         22
 +      #define EHCI_INSNREG05_ULPI_REGADD_SHIFT        16
 +      #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT     8
 +      #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT        0
 +
 +/* OHCI Register Set */
 +#define       OMAP_USBHOST_OHCI_BASE  (OMAP_USBHOST_BASE + 0x4400)
 +
 +#endif/* __EHCI_OMAP_H*/
Simple merge
index 75baf181a8cdff08098ec180e23cffdaaa430987,0000000000000000000000000000000000000000..d443a61e5c3b81cebd13ea4ec7673ae1f686893e
mode 100644,000000..100644
--- /dev/null
@@@ -1,462 -1,0 +1,462 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/memory.h>
- #include <asm/arch/gpio.h>
 +/*
 + * Copyright (C) 2005-2006 by Texas Instruments
 + *
 + * This file is part of the Inventra Controller Driver for Linux.
 + *
 + * The Inventra Controller Driver for Linux 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.
 + *
 + * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; 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/kernel.h>
 +#include <linux/sched.h>
 +#include <linux/slab.h>
 +#include <linux/init.h>
 +#include <linux/list.h>
 +#include <linux/delay.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +
- #include <asm/arch/i2c-client.h>
++#include <mach/hardware.h>
++#include <mach/memory.h>
++#include <mach/gpio.h>
 +#include <asm/mach-types.h>
 +
 +#include "musb_core.h"
 +
 +#ifdef CONFIG_MACH_DAVINCI_EVM
++#include <mach/i2c-client.h>
 +#endif
 +
 +#include "davinci.h"
 +#include "cppi_dma.h"
 +
 +
 +/* REVISIT (PM) we should be able to keep the PHY in low power mode most
 + * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
 + * and, when in host mode, autosuspending idle root ports... PHYPLLON
 + * (overriding SUSPENDM?) then likely needs to stay off.
 + */
 +
 +static inline void phy_on(void)
 +{
 +      /* start the on-chip PHY and its PLL */
 +      __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
 +                      (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR));
 +      while ((__raw_readl((void __force __iomem *)
 +                              IO_ADDRESS(USBPHY_CTL_PADDR))
 +                      & USBPHY_PHYCLKGD) == 0)
 +              cpu_relax();
 +}
 +
 +static inline void phy_off(void)
 +{
 +      /* powerdown the on-chip PHY and its oscillator */
 +      __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *)
 +                      IO_ADDRESS(USBPHY_CTL_PADDR));
 +}
 +
 +static int dma_off = 1;
 +
 +void musb_platform_enable(struct musb *musb)
 +{
 +      u32     tmp, old, val;
 +
 +      /* workaround:  setup irqs through both register sets */
 +      tmp = (musb->epmask & DAVINCI_USB_TX_ENDPTS_MASK)
 +                      << DAVINCI_USB_TXINT_SHIFT;
 +      musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
 +      old = tmp;
 +      tmp = (musb->epmask & (0xfffe & DAVINCI_USB_RX_ENDPTS_MASK))
 +                      << DAVINCI_USB_RXINT_SHIFT;
 +      musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
 +      tmp |= old;
 +
 +      val = ~MUSB_INTR_SOF;
 +      tmp |= ((val & 0x01ff) << DAVINCI_USB_USBINT_SHIFT);
 +      musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
 +
 +      if (is_dma_capable() && !dma_off)
 +              printk(KERN_WARNING "%s %s: dma not reactivated\n",
 +                              __FILE__, __func__);
 +      else
 +              dma_off = 0;
 +
 +      /* force a DRVVBUS irq so we can start polling for ID change */
 +      if (is_otg_enabled(musb))
 +              musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
 +                      DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT);
 +}
 +
 +/*
 + * Disable the HDRC and flush interrupts
 + */
 +void musb_platform_disable(struct musb *musb)
 +{
 +      /* because we don't set CTRLR.UINT, "important" to:
 +       *  - not read/write INTRUSB/INTRUSBE
 +       *  - (except during initial setup, as workaround)
 +       *  - use INTSETR/INTCLRR instead
 +       */
 +      musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_CLR_REG,
 +                        DAVINCI_USB_USBINT_MASK
 +                      | DAVINCI_USB_TXINT_MASK
 +                      | DAVINCI_USB_RXINT_MASK);
 +      musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
 +      musb_writel(musb->ctrl_base, DAVINCI_USB_EOI_REG, 0);
 +
 +      if (is_dma_capable() && !dma_off)
 +              WARNING("dma still active\n");
 +}
 +
 +
 +/* REVISIT it's not clear whether DaVinci can support full OTG.  */
 +
 +static int vbus_state = -1;
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +#define       portstate(stmt)         stmt
 +#else
 +#define       portstate(stmt)
 +#endif
 +
 +
 +/* VBUS SWITCHING IS BOARD-SPECIFIC */
 +
 +#ifdef CONFIG_MACH_DAVINCI_EVM
 +#ifndef CONFIG_MACH_DAVINCI_EVM_OTG
 +
 +/* I2C operations are always synchronous, and require a task context.
 + * With unloaded systems, using the shared workqueue seems to suffice
 + * to satisfy the 100msec A_WAIT_VRISE timeout...
 + */
 +static void evm_deferred_drvvbus(struct work_struct *ignored)
 +{
 +      davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state);
 +      vbus_state = !vbus_state;
 +}
 +static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
 +
 +#endif        /* modified board */
 +#endif        /* EVM */
 +
 +static void davinci_source_power(struct musb *musb, int is_on, int immediate)
 +{
 +      if (is_on)
 +              is_on = 1;
 +
 +      if (vbus_state == is_on)
 +              return;
 +      vbus_state = !is_on;            /* 0/1 vs "-1 == unknown/init" */
 +
 +#ifdef CONFIG_MACH_DAVINCI_EVM
 +      if (machine_is_davinci_evm()) {
 +#ifdef CONFIG_MACH_DAVINCI_EVM_OTG
 +              /* modified EVM board switching VBUS with GPIO(6) not I2C
 +               * NOTE:  PINMUX0.RGB888 (bit23) must be clear
 +               */
 +              if (is_on)
 +                      gpio_set(GPIO(6));
 +              else
 +                      gpio_clear(GPIO(6));
 +              immediate = 1;
 +#else
 +              if (immediate)
 +                      davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on);
 +              else
 +                      schedule_work(&evm_vbus_work);
 +#endif
 +      }
 +#endif
 +      if (immediate)
 +              vbus_state = is_on;
 +}
 +
 +static void davinci_set_vbus(struct musb *musb, int is_on)
 +{
 +      WARN_ON(is_on && is_peripheral_active(musb));
 +      davinci_source_power(musb, is_on, 0);
 +}
 +
 +
 +#define       POLL_SECONDS    2
 +
 +static struct timer_list otg_workaround;
 +
 +static void otg_timer(unsigned long _musb)
 +{
 +      struct musb             *musb = (void *)_musb;
 +      void __iomem            *mregs = musb->mregs;
 +      u8                      devctl;
 +      unsigned long           flags;
 +
 +      /* We poll because DaVinci's won't expose several OTG-critical
 +      * status change events (from the transceiver) otherwise.
 +       */
 +      devctl = musb_readb(mregs, MUSB_DEVCTL);
 +      DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      switch (musb->xceiv.state) {
 +      case OTG_STATE_A_WAIT_VFALL:
 +              /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
 +               * seems to mis-handle session "start" otherwise (or in our
 +               * case "recover"), in routine "VBUS was valid by the time
 +               * VBUSERR got reported during enumeration" cases.
 +               */
 +              if (devctl & MUSB_DEVCTL_VBUS) {
 +                      mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 +                      break;
 +              }
 +              musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
 +              musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
 +                      MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
 +              break;
 +      case OTG_STATE_B_IDLE:
 +              if (!is_peripheral_enabled(musb))
 +                      break;
 +
 +              /* There's no ID-changed IRQ, so we have no good way to tell
 +               * when to switch to the A-Default state machine (by setting
 +               * the DEVCTL.SESSION flag).
 +               *
 +               * Workaround:  whenever we're in B_IDLE, try setting the
 +               * session flag every few seconds.  If it works, ID was
 +               * grounded and we're now in the A-Default state machine.
 +               *
 +               * NOTE setting the session flag is _supposed_ to trigger
 +               * SRP, but clearly it doesn't.
 +               */
 +              musb_writeb(mregs, MUSB_DEVCTL,
 +                              devctl | MUSB_DEVCTL_SESSION);
 +              devctl = musb_readb(mregs, MUSB_DEVCTL);
 +              if (devctl & MUSB_DEVCTL_BDEVICE)
 +                      mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 +              else
 +                      musb->xceiv.state = OTG_STATE_A_IDLE;
 +              break;
 +      default:
 +              break;
 +      }
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +}
 +
 +static irqreturn_t davinci_interrupt(int irq, void *__hci)
 +{
 +      unsigned long   flags;
 +      irqreturn_t     retval = IRQ_NONE;
 +      struct musb     *musb = __hci;
 +      void __iomem    *tibase = musb->ctrl_base;
 +      u32             tmp;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      /* NOTE: DaVinci shadows the Mentor IRQs.  Don't manage them through
 +       * the Mentor registers (except for setup), use the TI ones and EOI.
 +       *
 +       * Docs describe irq "vector" registers asociated with the CPPI and
 +       * USB EOI registers.  These hold a bitmask corresponding to the
 +       * current IRQ, not an irq handler address.  Would using those bits
 +       * resolve some of the races observed in this dispatch code??
 +       */
 +
 +      /* CPPI interrupts share the same IRQ line, but have their own
 +       * mask, state, "vector", and EOI registers.
 +       */
 +      if (is_cppi_enabled()) {
 +              u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
 +              u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
 +
 +              if (cppi_tx || cppi_rx) {
 +                      DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx);
 +                      cppi_completion(musb, cppi_rx, cppi_tx);
 +                      retval = IRQ_HANDLED;
 +              }
 +      }
 +
 +      /* ack and handle non-CPPI interrupts */
 +      tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
 +      musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp);
 +      DBG(4, "IRQ %08x\n", tmp);
 +
 +      musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK)
 +                      >> DAVINCI_USB_RXINT_SHIFT;
 +      musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK)
 +                      >> DAVINCI_USB_TXINT_SHIFT;
 +      musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
 +                      >> DAVINCI_USB_USBINT_SHIFT;
 +
 +      /* DRVVBUS irqs are the only proxy we have (a very poor one!) for
 +       * DaVinci's missing ID change IRQ.  We need an ID change IRQ to
 +       * switch appropriately between halves of the OTG state machine.
 +       * Managing DEVCTL.SESSION per Mentor docs requires we know its
 +       * value, but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 +       * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 +       */
 +      if (tmp & (DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT)) {
 +              int     drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG);
 +              void __iomem *mregs = musb->mregs;
 +              u8      devctl = musb_readb(mregs, MUSB_DEVCTL);
 +              int     err = musb->int_usb & MUSB_INTR_VBUSERROR;
 +
 +              err = is_host_enabled(musb)
 +                              && (musb->int_usb & MUSB_INTR_VBUSERROR);
 +              if (err) {
 +                      /* The Mentor core doesn't debounce VBUS as needed
 +                       * to cope with device connect current spikes. This
 +                       * means it's not uncommon for bus-powered devices
 +                       * to get VBUS errors during enumeration.
 +                       *
 +                       * This is a workaround, but newer RTL from Mentor
 +                       * seems to allow a better one: "re"starting sessions
 +                       * without waiting (on EVM, a **long** time) for VBUS
 +                       * to stop registering in devctl.
 +                       */
 +                      musb->int_usb &= ~MUSB_INTR_VBUSERROR;
 +                      musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
 +                      mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 +                      WARNING("VBUS error workaround (delay coming)\n");
 +              } else if (is_host_enabled(musb) && drvvbus) {
 +                      musb->is_active = 1;
 +                      MUSB_HST_MODE(musb);
 +                      musb->xceiv.default_a = 1;
 +                      musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
 +                      portstate(musb->port1_status |= USB_PORT_STAT_POWER);
 +                      del_timer(&otg_workaround);
 +              } else {
 +                      musb->is_active = 0;
 +                      MUSB_DEV_MODE(musb);
 +                      musb->xceiv.default_a = 0;
 +                      musb->xceiv.state = OTG_STATE_B_IDLE;
 +                      portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 +              }
 +
 +              /* NOTE:  this must complete poweron within 100 msec */
 +              davinci_source_power(musb, drvvbus, 0);
 +              DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
 +                              drvvbus ? "on" : "off",
 +                              otg_state_string(musb),
 +                              err ? " ERROR" : "",
 +                              devctl);
 +              retval = IRQ_HANDLED;
 +      }
 +
 +      if (musb->int_tx || musb->int_rx || musb->int_usb)
 +              retval |= musb_interrupt(musb);
 +
 +      /* irq stays asserted until EOI is written */
 +      musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
 +
 +      /* poll for ID change */
 +      if (is_otg_enabled(musb)
 +                      && musb->xceiv.state == OTG_STATE_B_IDLE)
 +              mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 +
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      /* REVISIT we sometimes get unhandled IRQs
 +       * (e.g. ep0).  not clear why...
 +       */
 +      if (retval != IRQ_HANDLED)
 +              DBG(5, "unhandled? %08x\n", tmp);
 +      return IRQ_HANDLED;
 +}
 +
 +int __init musb_platform_init(struct musb *musb)
 +{
 +      void __iomem    *tibase = musb->ctrl_base;
 +      u32             revision;
 +
 +      musb->mregs += DAVINCI_BASE_OFFSET;
 +#if 0
 +      /* REVISIT there's something odd about clocking, this
 +       * didn't appear do the job ...
 +       */
 +      musb->clock = clk_get(pDevice, "usb");
 +      if (IS_ERR(musb->clock))
 +              return PTR_ERR(musb->clock);
 +
 +      status = clk_enable(musb->clock);
 +      if (status < 0)
 +              return -ENODEV;
 +#endif
 +
 +      /* returns zero if e.g. not clocked */
 +      revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
 +      if (revision == 0)
 +              return -ENODEV;
 +
 +      if (is_host_enabled(musb))
 +              setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 +
 +      musb->board_set_vbus = davinci_set_vbus;
 +      davinci_source_power(musb, 0, 1);
 +
 +      /* reset the controller */
 +      musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 +
 +      /* start the on-chip PHY and its PLL */
 +      phy_on();
 +
 +      msleep(5);
 +
 +      /* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
 +      pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
 +              revision, __raw_readl((void __force __iomem *)
 +                              IO_ADDRESS(USBPHY_CTL_PADDR)),
 +              musb_readb(tibase, DAVINCI_USB_CTRL_REG));
 +
 +      musb->isr = davinci_interrupt;
 +      return 0;
 +}
 +
 +int musb_platform_exit(struct musb *musb)
 +{
 +      if (is_host_enabled(musb))
 +              del_timer_sync(&otg_workaround);
 +
 +      davinci_source_power(musb, 0 /*off*/, 1);
 +
 +      /* delay, to avoid problems with module reload */
 +      if (is_host_enabled(musb) && musb->xceiv.default_a) {
 +              int     maxdelay = 30;
 +              u8      devctl, warn = 0;
 +
 +              /* if there's no peripheral connected, this can take a
 +               * long time to fall, especially on EVM with huge C133.
 +               */
 +              do {
 +                      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +                      if (!(devctl & MUSB_DEVCTL_VBUS))
 +                              break;
 +                      if ((devctl & MUSB_DEVCTL_VBUS) != warn) {
 +                              warn = devctl & MUSB_DEVCTL_VBUS;
 +                              DBG(1, "VBUS %d\n",
 +                                      warn >> MUSB_DEVCTL_VBUS_SHIFT);
 +                      }
 +                      msleep(1000);
 +                      maxdelay--;
 +              } while (maxdelay > 0);
 +
 +              /* in OTG mode, another host might be connected */
 +              if (devctl & MUSB_DEVCTL_VBUS)
 +                      DBG(1, "VBUS off timeout (devctl %02x)\n", devctl);
 +      }
 +
 +      phy_off();
 +      return 0;
 +}
index 1404a10a3e62212e16a811d00fc1a6409c62008c,0000000000000000000000000000000000000000..bcc92e69c426e7f5fac5876e12f4cfcc0aa8f9cc
mode 100644,000000..100644
--- /dev/null
@@@ -1,2269 -1,0 +1,2269 @@@
-  *    - <asm/arch/hdrc_cnf.h> for SOC or family details
 +/*
 + * MUSB OTG driver core code
 + *
 + * Copyright 2005 Mentor Graphics Corporation
 + * Copyright (C) 2005-2006 by Texas Instruments
 + * Copyright (C) 2006-2007 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 + * NO EVENT SHALL THE AUTHORS 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.
 + *
 + */
 +
 +/*
 + * Inventra (Multipoint) Dual-Role Controller Driver for Linux.
 + *
 + * This consists of a Host Controller Driver (HCD) and a peripheral
 + * controller driver implementing the "Gadget" API; OTG support is
 + * in the works.  These are normal Linux-USB controller drivers which
 + * use IRQs and have no dedicated thread.
 + *
 + * This version of the driver has only been used with products from
 + * Texas Instruments.  Those products integrate the Inventra logic
 + * with other DMA, IRQ, and bus modules, as well as other logic that
 + * needs to be reflected in this driver.
 + *
 + *
 + * NOTE:  the original Mentor code here was pretty much a collection
 + * of mechanisms that don't seem to have been fully integrated/working
 + * for *any* Linux kernel version.  This version aims at Linux 2.6.now,
 + * Key open issues include:
 + *
 + *  - Lack of host-side transaction scheduling, for all transfer types.
 + *    The hardware doesn't do it; instead, software must.
 + *
 + *    This is not an issue for OTG devices that don't support external
 + *    hubs, but for more "normal" USB hosts it's a user issue that the
 + *    "multipoint" support doesn't scale in the expected ways.  That
 + *    includes DaVinci EVM in a common non-OTG mode.
 + *
 + *      * Control and bulk use dedicated endpoints, and there's as
 + *        yet no mechanism to either (a) reclaim the hardware when
 + *        peripherals are NAKing, which gets complicated with bulk
 + *        endpoints, or (b) use more than a single bulk endpoint in
 + *        each direction.
 + *
 + *        RESULT:  one device may be perceived as blocking another one.
 + *
 + *      * Interrupt and isochronous will dynamically allocate endpoint
 + *        hardware, but (a) there's no record keeping for bandwidth;
 + *        (b) in the common case that few endpoints are available, there
 + *        is no mechanism to reuse endpoints to talk to multiple devices.
 + *
 + *        RESULT:  At one extreme, bandwidth can be overcommitted in
 + *        some hardware configurations, no faults will be reported.
 + *        At the other extreme, the bandwidth capabilities which do
 + *        exist tend to be severely undercommitted.  You can't yet hook
 + *        up both a keyboard and a mouse to an external USB hub.
 + */
 +
 +/*
 + * This gets many kinds of configuration information:
 + *    - Kconfig for everything user-configurable
- #include <asm/arch/hardware.h>
- #include <asm/arch/memory.h>
++ *    - <mach/hdrc_cnf.h> for SOC or family details
 + *    - platform_device for addressing, irq, and platform_data
 + *    - platform_data is mostly for board-specific informarion
 + *
 + * Most of the conditional compilation will (someday) vanish.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/sched.h>
 +#include <linux/slab.h>
 +#include <linux/init.h>
 +#include <linux/list.h>
 +#include <linux/kobject.h>
 +#include <linux/platform_device.h>
 +#include <linux/io.h>
 +
 +#ifdef        CONFIG_ARM
++#include <mach/hardware.h>
++#include <mach/memory.h>
 +#include <asm/mach-types.h>
 +#endif
 +
 +#include "musb_core.h"
 +
 +
 +#ifdef CONFIG_ARCH_DAVINCI
 +#include "davinci.h"
 +#endif
 +
 +
 +
 +#if MUSB_DEBUG > 0
 +unsigned debug = MUSB_DEBUG;
 +module_param(debug, uint, 0);
 +MODULE_PARM_DESC(debug, "initial debug message level");
 +
 +#define MUSB_VERSION_SUFFIX   "/dbg"
 +#endif
 +
 +#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
 +#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
 +
 +#define MUSB_VERSION_BASE "6.0"
 +
 +#ifndef MUSB_VERSION_SUFFIX
 +#define MUSB_VERSION_SUFFIX   ""
 +#endif
 +#define MUSB_VERSION  MUSB_VERSION_BASE MUSB_VERSION_SUFFIX
 +
 +#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
 +
 +#define MUSB_DRIVER_NAME "musb_hdrc"
 +const char musb_driver_name[] = MUSB_DRIVER_NAME;
 +
 +MODULE_DESCRIPTION(DRIVER_INFO);
 +MODULE_AUTHOR(DRIVER_AUTHOR);
 +MODULE_LICENSE("GPL");
 +MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static inline struct musb *dev_to_musb(struct device *dev)
 +{
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      /* usbcore insists dev->driver_data is a "struct hcd *" */
 +      return hcd_to_musb(dev_get_drvdata(dev));
 +#else
 +      return dev_get_drvdata(dev);
 +#endif
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +#ifndef CONFIG_USB_TUSB6010
 +/*
 + * Load an endpoint's FIFO
 + */
 +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
 +{
 +      void __iomem *fifo = hw_ep->fifo;
 +
 +      prefetch((u8 *)src);
 +
 +      DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
 +                      'T', hw_ep->epnum, fifo, len, src);
 +
 +      /* we can't assume unaligned reads work */
 +      if (likely((0x01 & (unsigned long) src) == 0)) {
 +              u16     index = 0;
 +
 +              /* best case is 32bit-aligned source address */
 +              if ((0x02 & (unsigned long) src) == 0) {
 +                      if (len >= 4) {
 +                              writesl(fifo, src + index, len >> 2);
 +                              index += len & ~0x03;
 +                      }
 +                      if (len & 0x02) {
 +                              musb_writew(fifo, 0, *(u16 *)&src[index]);
 +                              index += 2;
 +                      }
 +              } else {
 +                      if (len >= 2) {
 +                              writesw(fifo, src + index, len >> 1);
 +                              index += len & ~0x01;
 +                      }
 +              }
 +              if (len & 0x01)
 +                      musb_writeb(fifo, 0, src[index]);
 +      } else  {
 +              /* byte aligned */
 +              writesb(fifo, src, len);
 +      }
 +}
 +
 +/*
 + * Unload an endpoint's FIFO
 + */
 +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 +{
 +      void __iomem *fifo = hw_ep->fifo;
 +
 +      DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
 +                      'R', hw_ep->epnum, fifo, len, dst);
 +
 +      /* we can't assume unaligned writes work */
 +      if (likely((0x01 & (unsigned long) dst) == 0)) {
 +              u16     index = 0;
 +
 +              /* best case is 32bit-aligned destination address */
 +              if ((0x02 & (unsigned long) dst) == 0) {
 +                      if (len >= 4) {
 +                              readsl(fifo, dst, len >> 2);
 +                              index = len & ~0x03;
 +                      }
 +                      if (len & 0x02) {
 +                              *(u16 *)&dst[index] = musb_readw(fifo, 0);
 +                              index += 2;
 +                      }
 +              } else {
 +                      if (len >= 2) {
 +                              readsw(fifo, dst, len >> 1);
 +                              index = len & ~0x01;
 +                      }
 +              }
 +              if (len & 0x01)
 +                      dst[index] = musb_readb(fifo, 0);
 +      } else  {
 +              /* byte aligned */
 +              readsb(fifo, dst, len);
 +      }
 +}
 +
 +#endif        /* normal PIO */
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/* for high speed test mode; see USB 2.0 spec 7.1.20 */
 +static const u8 musb_test_packet[53] = {
 +      /* implicit SYNC then DATA0 to start */
 +
 +      /* JKJKJKJK x9 */
 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +      /* JJKKJJKK x8 */
 +      0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
 +      /* JJJJKKKK x8 */
 +      0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
 +      /* JJJJJJJKKKKKKK x8 */
 +      0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +      /* JJJJJJJK x8 */
 +      0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd,
 +      /* JKKKKKKK x10, JK */
 +      0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
 +
 +      /* implicit CRC16 then EOP to end */
 +};
 +
 +void musb_load_testpacket(struct musb *musb)
 +{
 +      void __iomem    *regs = musb->endpoints[0].regs;
 +
 +      musb_ep_select(musb->mregs, 0);
 +      musb_write_fifo(musb->control_ep,
 +                      sizeof(musb_test_packet), musb_test_packet);
 +      musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY);
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +const char *otg_state_string(struct musb *musb)
 +{
 +      switch (musb->xceiv.state) {
 +      case OTG_STATE_A_IDLE:          return "a_idle";
 +      case OTG_STATE_A_WAIT_VRISE:    return "a_wait_vrise";
 +      case OTG_STATE_A_WAIT_BCON:     return "a_wait_bcon";
 +      case OTG_STATE_A_HOST:          return "a_host";
 +      case OTG_STATE_A_SUSPEND:       return "a_suspend";
 +      case OTG_STATE_A_PERIPHERAL:    return "a_peripheral";
 +      case OTG_STATE_A_WAIT_VFALL:    return "a_wait_vfall";
 +      case OTG_STATE_A_VBUS_ERR:      return "a_vbus_err";
 +      case OTG_STATE_B_IDLE:          return "b_idle";
 +      case OTG_STATE_B_SRP_INIT:      return "b_srp_init";
 +      case OTG_STATE_B_PERIPHERAL:    return "b_peripheral";
 +      case OTG_STATE_B_WAIT_ACON:     return "b_wait_acon";
 +      case OTG_STATE_B_HOST:          return "b_host";
 +      default:                        return "UNDEFINED";
 +      }
 +}
 +
 +#ifdef        CONFIG_USB_MUSB_OTG
 +
 +/*
 + * See also USB_OTG_1-3.pdf 6.6.5 Timers
 + * REVISIT: Are the other timers done in the hardware?
 + */
 +#define TB_ASE0_BRST          100     /* Min 3.125 ms */
 +
 +/*
 + * Handles OTG hnp timeouts, such as b_ase0_brst
 + */
 +void musb_otg_timer_func(unsigned long data)
 +{
 +      struct musb     *musb = (struct musb *)data;
 +      unsigned long   flags;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      switch (musb->xceiv.state) {
 +      case OTG_STATE_B_WAIT_ACON:
 +              DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n");
 +              musb_g_disconnect(musb);
 +              musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
 +              musb->is_active = 0;
 +              break;
 +      case OTG_STATE_A_WAIT_BCON:
 +              DBG(1, "HNP: a_wait_bcon timeout; back to a_host\n");
 +              musb_hnp_stop(musb);
 +              break;
 +      default:
 +              DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb));
 +      }
 +      musb->ignore_disconnect = 0;
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +}
 +
 +static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0);
 +
 +/*
 + * Stops the B-device HNP state. Caller must take care of locking.
 + */
 +void musb_hnp_stop(struct musb *musb)
 +{
 +      struct usb_hcd  *hcd = musb_to_hcd(musb);
 +      void __iomem    *mbase = musb->mregs;
 +      u8      reg;
 +
 +      switch (musb->xceiv.state) {
 +      case OTG_STATE_A_PERIPHERAL:
 +      case OTG_STATE_A_WAIT_VFALL:
 +      case OTG_STATE_A_WAIT_BCON:
 +              DBG(1, "HNP: Switching back to A-host\n");
 +              musb_g_disconnect(musb);
 +              musb->xceiv.state = OTG_STATE_A_IDLE;
 +              MUSB_HST_MODE(musb);
 +              musb->is_active = 0;
 +              break;
 +      case OTG_STATE_B_HOST:
 +              DBG(1, "HNP: Disabling HR\n");
 +              hcd->self.is_b_host = 0;
 +              musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
 +              MUSB_DEV_MODE(musb);
 +              reg = musb_readb(mbase, MUSB_POWER);
 +              reg |= MUSB_POWER_SUSPENDM;
 +              musb_writeb(mbase, MUSB_POWER, reg);
 +              /* REVISIT: Start SESSION_REQUEST here? */
 +              break;
 +      default:
 +              DBG(1, "HNP: Stopping in unknown state %s\n",
 +                      otg_state_string(musb));
 +      }
 +
 +      /*
 +       * When returning to A state after HNP, avoid hub_port_rebounce(),
 +       * which cause occasional OPT A "Did not receive reset after connect"
 +       * errors.
 +       */
 +      musb->port1_status &=
 +              ~(1 << USB_PORT_FEAT_C_CONNECTION);
 +}
 +
 +#endif
 +
 +/*
 + * Interrupt Service Routine to record USB "global" interrupts.
 + * Since these do not happen often and signify things of
 + * paramount importance, it seems OK to check them individually;
 + * the order of the tests is specified in the manual
 + *
 + * @param musb instance pointer
 + * @param int_usb register contents
 + * @param devctl
 + * @param power
 + */
 +
 +#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
 +              | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
 +              | MUSB_INTR_RESET)
 +
 +static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 +                              u8 devctl, u8 power)
 +{
 +      irqreturn_t handled = IRQ_NONE;
 +      void __iomem *mbase = musb->mregs;
 +
 +      DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
 +              int_usb);
 +
 +      /* in host mode, the peripheral may issue remote wakeup.
 +       * in peripheral mode, the host may resume the link.
 +       * spurious RESUME irqs happen too, paired with SUSPEND.
 +       */
 +      if (int_usb & MUSB_INTR_RESUME) {
 +              handled = IRQ_HANDLED;
 +              DBG(3, "RESUME (%s)\n", otg_state_string(musb));
 +
 +              if (devctl & MUSB_DEVCTL_HM) {
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +                      switch (musb->xceiv.state) {
 +                      case OTG_STATE_A_SUSPEND:
 +                              /* remote wakeup?  later, GetPortStatus
 +                               * will stop RESUME signaling
 +                               */
 +
 +                              if (power & MUSB_POWER_SUSPENDM) {
 +                                      /* spurious */
 +                                      musb->int_usb &= ~MUSB_INTR_SUSPEND;
 +                                      DBG(2, "Spurious SUSPENDM\n");
 +                                      break;
 +                              }
 +
 +                              power &= ~MUSB_POWER_SUSPENDM;
 +                              musb_writeb(mbase, MUSB_POWER,
 +                                              power | MUSB_POWER_RESUME);
 +
 +                              musb->port1_status |=
 +                                              (USB_PORT_STAT_C_SUSPEND << 16)
 +                                              | MUSB_PORT_STAT_RESUME;
 +                              musb->rh_timer = jiffies
 +                                              + msecs_to_jiffies(20);
 +
 +                              musb->xceiv.state = OTG_STATE_A_HOST;
 +                              musb->is_active = 1;
 +                              usb_hcd_resume_root_hub(musb_to_hcd(musb));
 +                              break;
 +                      case OTG_STATE_B_WAIT_ACON:
 +                              musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
 +                              musb->is_active = 1;
 +                              MUSB_DEV_MODE(musb);
 +                              break;
 +                      default:
 +                              WARNING("bogus %s RESUME (%s)\n",
 +                                      "host",
 +                                      otg_state_string(musb));
 +                      }
 +#endif
 +              } else {
 +                      switch (musb->xceiv.state) {
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +                      case OTG_STATE_A_SUSPEND:
 +                              /* possibly DISCONNECT is upcoming */
 +                              musb->xceiv.state = OTG_STATE_A_HOST;
 +                              usb_hcd_resume_root_hub(musb_to_hcd(musb));
 +                              break;
 +#endif
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +                      case OTG_STATE_B_WAIT_ACON:
 +                      case OTG_STATE_B_PERIPHERAL:
 +                              /* disconnect while suspended?  we may
 +                               * not get a disconnect irq...
 +                               */
 +                              if ((devctl & MUSB_DEVCTL_VBUS)
 +                                              != (3 << MUSB_DEVCTL_VBUS_SHIFT)
 +                                              ) {
 +                                      musb->int_usb |= MUSB_INTR_DISCONNECT;
 +                                      musb->int_usb &= ~MUSB_INTR_SUSPEND;
 +                                      break;
 +                              }
 +                              musb_g_resume(musb);
 +                              break;
 +                      case OTG_STATE_B_IDLE:
 +                              musb->int_usb &= ~MUSB_INTR_SUSPEND;
 +                              break;
 +#endif
 +                      default:
 +                              WARNING("bogus %s RESUME (%s)\n",
 +                                      "peripheral",
 +                                      otg_state_string(musb));
 +                      }
 +              }
 +      }
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      /* see manual for the order of the tests */
 +      if (int_usb & MUSB_INTR_SESSREQ) {
 +              DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
 +
 +              /* IRQ arrives from ID pin sense or (later, if VBUS power
 +               * is removed) SRP.  responses are time critical:
 +               *  - turn on VBUS (with silicon-specific mechanism)
 +               *  - go through A_WAIT_VRISE
 +               *  - ... to A_WAIT_BCON.
 +               * a_wait_vrise_tmout triggers VBUS_ERROR transitions
 +               */
 +              musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
 +              musb->ep0_stage = MUSB_EP0_START;
 +              musb->xceiv.state = OTG_STATE_A_IDLE;
 +              MUSB_HST_MODE(musb);
 +              musb_set_vbus(musb, 1);
 +
 +              handled = IRQ_HANDLED;
 +      }
 +
 +      if (int_usb & MUSB_INTR_VBUSERROR) {
 +              int     ignore = 0;
 +
 +              /* During connection as an A-Device, we may see a short
 +               * current spikes causing voltage drop, because of cable
 +               * and peripheral capacitance combined with vbus draw.
 +               * (So: less common with truly self-powered devices, where
 +               * vbus doesn't act like a power supply.)
 +               *
 +               * Such spikes are short; usually less than ~500 usec, max
 +               * of ~2 msec.  That is, they're not sustained overcurrent
 +               * errors, though they're reported using VBUSERROR irqs.
 +               *
 +               * Workarounds:  (a) hardware: use self powered devices.
 +               * (b) software:  ignore non-repeated VBUS errors.
 +               *
 +               * REVISIT:  do delays from lots of DEBUG_KERNEL checks
 +               * make trouble here, keeping VBUS < 4.4V ?
 +               */
 +              switch (musb->xceiv.state) {
 +              case OTG_STATE_A_HOST:
 +                      /* recovery is dicey once we've gotten past the
 +                       * initial stages of enumeration, but if VBUS
 +                       * stayed ok at the other end of the link, and
 +                       * another reset is due (at least for high speed,
 +                       * to redo the chirp etc), it might work OK...
 +                       */
 +              case OTG_STATE_A_WAIT_BCON:
 +              case OTG_STATE_A_WAIT_VRISE:
 +                      if (musb->vbuserr_retry) {
 +                              musb->vbuserr_retry--;
 +                              ignore = 1;
 +                              devctl |= MUSB_DEVCTL_SESSION;
 +                              musb_writeb(mbase, MUSB_DEVCTL, devctl);
 +                      } else {
 +                              musb->port1_status |=
 +                                        (1 << USB_PORT_FEAT_OVER_CURRENT)
 +                                      | (1 << USB_PORT_FEAT_C_OVER_CURRENT);
 +                      }
 +                      break;
 +              default:
 +                      break;
 +              }
 +
 +              DBG(1, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
 +                              otg_state_string(musb),
 +                              devctl,
 +                              ({ char *s;
 +                              switch (devctl & MUSB_DEVCTL_VBUS) {
 +                              case 0 << MUSB_DEVCTL_VBUS_SHIFT:
 +                                      s = "<SessEnd"; break;
 +                              case 1 << MUSB_DEVCTL_VBUS_SHIFT:
 +                                      s = "<AValid"; break;
 +                              case 2 << MUSB_DEVCTL_VBUS_SHIFT:
 +                                      s = "<VBusValid"; break;
 +                              /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */
 +                              default:
 +                                      s = "VALID"; break;
 +                              }; s; }),
 +                              VBUSERR_RETRY_COUNT - musb->vbuserr_retry,
 +                              musb->port1_status);
 +
 +              /* go through A_WAIT_VFALL then start a new session */
 +              if (!ignore)
 +                      musb_set_vbus(musb, 0);
 +              handled = IRQ_HANDLED;
 +      }
 +
 +      if (int_usb & MUSB_INTR_CONNECT) {
 +              struct usb_hcd *hcd = musb_to_hcd(musb);
 +
 +              handled = IRQ_HANDLED;
 +              musb->is_active = 1;
 +              set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
 +
 +              musb->ep0_stage = MUSB_EP0_START;
 +
 +#ifdef CONFIG_USB_MUSB_OTG
 +              /* flush endpoints when transitioning from Device Mode */
 +              if (is_peripheral_active(musb)) {
 +                      /* REVISIT HNP; just force disconnect */
 +              }
 +              musb_writew(mbase, MUSB_INTRTXE, musb->epmask);
 +              musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe);
 +              musb_writeb(mbase, MUSB_INTRUSBE, 0xf7);
 +#endif
 +              musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
 +                                      |USB_PORT_STAT_HIGH_SPEED
 +                                      |USB_PORT_STAT_ENABLE
 +                                      );
 +              musb->port1_status |= USB_PORT_STAT_CONNECTION
 +                                      |(USB_PORT_STAT_C_CONNECTION << 16);
 +
 +              /* high vs full speed is just a guess until after reset */
 +              if (devctl & MUSB_DEVCTL_LSDEV)
 +                      musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
 +
 +              if (hcd->status_urb)
 +                      usb_hcd_poll_rh_status(hcd);
 +              else
 +                      usb_hcd_resume_root_hub(hcd);
 +
 +              MUSB_HST_MODE(musb);
 +
 +              /* indicate new connection to OTG machine */
 +              switch (musb->xceiv.state) {
 +              case OTG_STATE_B_PERIPHERAL:
 +                      if (int_usb & MUSB_INTR_SUSPEND) {
 +                              DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n");
 +                              musb->xceiv.state = OTG_STATE_B_HOST;
 +                              hcd->self.is_b_host = 1;
 +                              int_usb &= ~MUSB_INTR_SUSPEND;
 +                      } else
 +                              DBG(1, "CONNECT as b_peripheral???\n");
 +                      break;
 +              case OTG_STATE_B_WAIT_ACON:
 +                      DBG(1, "HNP: Waiting to switch to b_host state\n");
 +                      musb->xceiv.state = OTG_STATE_B_HOST;
 +                      hcd->self.is_b_host = 1;
 +                      break;
 +              default:
 +                      if ((devctl & MUSB_DEVCTL_VBUS)
 +                                      == (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
 +                              musb->xceiv.state = OTG_STATE_A_HOST;
 +                              hcd->self.is_b_host = 0;
 +                      }
 +                      break;
 +              }
 +              DBG(1, "CONNECT (%s) devctl %02x\n",
 +                              otg_state_string(musb), devctl);
 +      }
 +#endif        /* CONFIG_USB_MUSB_HDRC_HCD */
 +
 +      /* mentor saves a bit: bus reset and babble share the same irq.
 +       * only host sees babble; only peripheral sees bus reset.
 +       */
 +      if (int_usb & MUSB_INTR_RESET) {
 +              if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) {
 +                      /*
 +                       * Looks like non-HS BABBLE can be ignored, but
 +                       * HS BABBLE is an error condition. For HS the solution
 +                       * is to avoid babble in the first place and fix what
 +                       * caused BABBLE. When HS BABBLE happens we can only
 +                       * stop the session.
 +                       */
 +                      if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
 +                              DBG(1, "BABBLE devctl: %02x\n", devctl);
 +                      else {
 +                              ERR("Stopping host session -- babble\n");
 +                              musb_writeb(mbase, MUSB_DEVCTL, 0);
 +                      }
 +              } else if (is_peripheral_capable()) {
 +                      DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
 +                      switch (musb->xceiv.state) {
 +#ifdef CONFIG_USB_OTG
 +                      case OTG_STATE_A_SUSPEND:
 +                              /* We need to ignore disconnect on suspend
 +                               * otherwise tusb 2.0 won't reconnect after a
 +                               * power cycle, which breaks otg compliance.
 +                               */
 +                              musb->ignore_disconnect = 1;
 +                              musb_g_reset(musb);
 +                              /* FALLTHROUGH */
 +                      case OTG_STATE_A_WAIT_BCON:     /* OPT TD.4.7-900ms */
 +                              DBG(1, "HNP: Setting timer as %s\n",
 +                                              otg_state_string(musb));
 +                              musb_otg_timer.data = (unsigned long)musb;
 +                              mod_timer(&musb_otg_timer, jiffies
 +                                      + msecs_to_jiffies(100));
 +                              break;
 +                      case OTG_STATE_A_PERIPHERAL:
 +                              musb_hnp_stop(musb);
 +                              break;
 +                      case OTG_STATE_B_WAIT_ACON:
 +                              DBG(1, "HNP: RESET (%s), back to b_peripheral\n",
 +                                      otg_state_string(musb));
 +                              musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
 +                              musb_g_reset(musb);
 +                              break;
 +#endif
 +                      case OTG_STATE_B_IDLE:
 +                              musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
 +                              /* FALLTHROUGH */
 +                      case OTG_STATE_B_PERIPHERAL:
 +                              musb_g_reset(musb);
 +                              break;
 +                      default:
 +                              DBG(1, "Unhandled BUS RESET as %s\n",
 +                                      otg_state_string(musb));
 +                      }
 +              }
 +
 +              handled = IRQ_HANDLED;
 +      }
 +      schedule_work(&musb->irq_work);
 +
 +      return handled;
 +}
 +
 +/*
 + * Interrupt Service Routine to record USB "global" interrupts.
 + * Since these do not happen often and signify things of
 + * paramount importance, it seems OK to check them individually;
 + * the order of the tests is specified in the manual
 + *
 + * @param musb instance pointer
 + * @param int_usb register contents
 + * @param devctl
 + * @param power
 + */
 +static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
 +                              u8 devctl, u8 power)
 +{
 +      irqreturn_t handled = IRQ_NONE;
 +
 +#if 0
 +/* REVISIT ... this would be for multiplexing periodic endpoints, or
 + * supporting transfer phasing to prevent exceeding ISO bandwidth
 + * limits of a given frame or microframe.
 + *
 + * It's not needed for peripheral side, which dedicates endpoints;
 + * though it _might_ use SOF irqs for other purposes.
 + *
 + * And it's not currently needed for host side, which also dedicates
 + * endpoints, relies on TX/RX interval registers, and isn't claimed
 + * to support ISO transfers yet.
 + */
 +      if (int_usb & MUSB_INTR_SOF) {
 +              void __iomem *mbase = musb->mregs;
 +              struct musb_hw_ep       *ep;
 +              u8 epnum;
 +              u16 frame;
 +
 +              DBG(6, "START_OF_FRAME\n");
 +              handled = IRQ_HANDLED;
 +
 +              /* start any periodic Tx transfers waiting for current frame */
 +              frame = musb_readw(mbase, MUSB_FRAME);
 +              ep = musb->endpoints;
 +              for (epnum = 1; (epnum < musb->nr_endpoints)
 +                                      && (musb->epmask >= (1 << epnum));
 +                              epnum++, ep++) {
 +                      /*
 +                       * FIXME handle framecounter wraps (12 bits)
 +                       * eliminate duplicated StartUrb logic
 +                       */
 +                      if (ep->dwWaitFrame >= frame) {
 +                              ep->dwWaitFrame = 0;
 +                              printk("SOF --> periodic TX%s on %d\n",
 +                                      ep->tx_channel ? " DMA" : "",
 +                                      epnum);
 +                              if (!ep->tx_channel)
 +                                      musb_h_tx_start(musb, epnum);
 +                              else
 +                                      cppi_hostdma_start(musb, epnum);
 +                      }
 +              }               /* end of for loop */
 +      }
 +#endif
 +
 +      if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 +              DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n",
 +                              otg_state_string(musb),
 +                              MUSB_MODE(musb), devctl);
 +              handled = IRQ_HANDLED;
 +
 +              switch (musb->xceiv.state) {
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +              case OTG_STATE_A_HOST:
 +              case OTG_STATE_A_SUSPEND:
 +                      musb_root_disconnect(musb);
 +                      if (musb->a_wait_bcon != 0)
 +                              musb_platform_try_idle(musb, jiffies
 +                                      + msecs_to_jiffies(musb->a_wait_bcon));
 +                      break;
 +#endif        /* HOST */
 +#ifdef CONFIG_USB_MUSB_OTG
 +              case OTG_STATE_B_HOST:
 +                      musb_hnp_stop(musb);
 +                      break;
 +              case OTG_STATE_A_PERIPHERAL:
 +                      musb_hnp_stop(musb);
 +                      musb_root_disconnect(musb);
 +                      /* FALLTHROUGH */
 +              case OTG_STATE_B_WAIT_ACON:
 +                      /* FALLTHROUGH */
 +#endif        /* OTG */
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +              case OTG_STATE_B_PERIPHERAL:
 +              case OTG_STATE_B_IDLE:
 +                      musb_g_disconnect(musb);
 +                      break;
 +#endif        /* GADGET */
 +              default:
 +                      WARNING("unhandled DISCONNECT transition (%s)\n",
 +                              otg_state_string(musb));
 +                      break;
 +              }
 +
 +              schedule_work(&musb->irq_work);
 +      }
 +
 +      if (int_usb & MUSB_INTR_SUSPEND) {
 +              DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
 +                              otg_state_string(musb), devctl, power);
 +              handled = IRQ_HANDLED;
 +
 +              switch (musb->xceiv.state) {
 +#ifdef        CONFIG_USB_MUSB_OTG
 +              case OTG_STATE_A_PERIPHERAL:
 +                      /*
 +                       * We cannot stop HNP here, devctl BDEVICE might be
 +                       * still set.
 +                       */
 +                      break;
 +#endif
 +              case OTG_STATE_B_PERIPHERAL:
 +                      musb_g_suspend(musb);
 +                      musb->is_active = is_otg_enabled(musb)
 +                                      && musb->xceiv.gadget->b_hnp_enable;
 +                      if (musb->is_active) {
 +#ifdef        CONFIG_USB_MUSB_OTG
 +                              musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
 +                              DBG(1, "HNP: Setting timer for b_ase0_brst\n");
 +                              musb_otg_timer.data = (unsigned long)musb;
 +                              mod_timer(&musb_otg_timer, jiffies
 +                                      + msecs_to_jiffies(TB_ASE0_BRST));
 +#endif
 +                      }
 +                      break;
 +              case OTG_STATE_A_WAIT_BCON:
 +                      if (musb->a_wait_bcon != 0)
 +                              musb_platform_try_idle(musb, jiffies
 +                                      + msecs_to_jiffies(musb->a_wait_bcon));
 +                      break;
 +              case OTG_STATE_A_HOST:
 +                      musb->xceiv.state = OTG_STATE_A_SUSPEND;
 +                      musb->is_active = is_otg_enabled(musb)
 +                                      && musb->xceiv.host->b_hnp_enable;
 +                      break;
 +              case OTG_STATE_B_HOST:
 +                      /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
 +                      DBG(1, "REVISIT: SUSPEND as B_HOST\n");
 +                      break;
 +              default:
 +                      /* "should not happen" */
 +                      musb->is_active = 0;
 +                      break;
 +              }
 +              schedule_work(&musb->irq_work);
 +      }
 +
 +
 +      return handled;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/*
 +* Program the HDRC to start (enable interrupts, dma, etc.).
 +*/
 +void musb_start(struct musb *musb)
 +{
 +      void __iomem    *regs = musb->mregs;
 +      u8              devctl = musb_readb(regs, MUSB_DEVCTL);
 +
 +      DBG(2, "<== devctl %02x\n", devctl);
 +
 +      /*  Set INT enable registers, enable interrupts */
 +      musb_writew(regs, MUSB_INTRTXE, musb->epmask);
 +      musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
 +      musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
 +
 +      musb_writeb(regs, MUSB_TESTMODE, 0);
 +
 +      /* put into basic highspeed mode and start session */
 +      musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
 +                                              | MUSB_POWER_SOFTCONN
 +                                              | MUSB_POWER_HSENAB
 +                                              /* ENSUSPEND wedges tusb */
 +                                              /* | MUSB_POWER_ENSUSPEND */
 +                                              );
 +
 +      musb->is_active = 0;
 +      devctl = musb_readb(regs, MUSB_DEVCTL);
 +      devctl &= ~MUSB_DEVCTL_SESSION;
 +
 +      if (is_otg_enabled(musb)) {
 +              /* session started after:
 +               * (a) ID-grounded irq, host mode;
 +               * (b) vbus present/connect IRQ, peripheral mode;
 +               * (c) peripheral initiates, using SRP
 +               */
 +              if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
 +                      musb->is_active = 1;
 +              else
 +                      devctl |= MUSB_DEVCTL_SESSION;
 +
 +      } else if (is_host_enabled(musb)) {
 +              /* assume ID pin is hard-wired to ground */
 +              devctl |= MUSB_DEVCTL_SESSION;
 +
 +      } else /* peripheral is enabled */ {
 +              if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
 +                      musb->is_active = 1;
 +      }
 +      musb_platform_enable(musb);
 +      musb_writeb(regs, MUSB_DEVCTL, devctl);
 +}
 +
 +
 +static void musb_generic_disable(struct musb *musb)
 +{
 +      void __iomem    *mbase = musb->mregs;
 +      u16     temp;
 +
 +      /* disable interrupts */
 +      musb_writeb(mbase, MUSB_INTRUSBE, 0);
 +      musb_writew(mbase, MUSB_INTRTXE, 0);
 +      musb_writew(mbase, MUSB_INTRRXE, 0);
 +
 +      /* off */
 +      musb_writeb(mbase, MUSB_DEVCTL, 0);
 +
 +      /*  flush pending interrupts */
 +      temp = musb_readb(mbase, MUSB_INTRUSB);
 +      temp = musb_readw(mbase, MUSB_INTRTX);
 +      temp = musb_readw(mbase, MUSB_INTRRX);
 +
 +}
 +
 +/*
 + * Make the HDRC stop (disable interrupts, etc.);
 + * reversible by musb_start
 + * called on gadget driver unregister
 + * with controller locked, irqs blocked
 + * acts as a NOP unless some role activated the hardware
 + */
 +void musb_stop(struct musb *musb)
 +{
 +      /* stop IRQs, timers, ... */
 +      musb_platform_disable(musb);
 +      musb_generic_disable(musb);
 +      DBG(3, "HDRC disabled\n");
 +
 +      /* FIXME
 +       *  - mark host and/or peripheral drivers unusable/inactive
 +       *  - disable DMA (and enable it in HdrcStart)
 +       *  - make sure we can musb_start() after musb_stop(); with
 +       *    OTG mode, gadget driver module rmmod/modprobe cycles that
 +       *  - ...
 +       */
 +      musb_platform_try_idle(musb, 0);
 +}
 +
 +static void musb_shutdown(struct platform_device *pdev)
 +{
 +      struct musb     *musb = dev_to_musb(&pdev->dev);
 +      unsigned long   flags;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      musb_platform_disable(musb);
 +      musb_generic_disable(musb);
 +      if (musb->clock) {
 +              clk_put(musb->clock);
 +              musb->clock = NULL;
 +      }
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      /* FIXME power down */
 +}
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/*
 + * The silicon either has hard-wired endpoint configurations, or else
 + * "dynamic fifo" sizing.  The driver has support for both, though at this
 + * writing only the dynamic sizing is very well tested.   We use normal
 + * idioms to so both modes are compile-tested, but dead code elimination
 + * leaves only the relevant one in the object file.
 + *
 + * We don't currently use dynamic fifo setup capability to do anything
 + * more than selecting one of a bunch of predefined configurations.
 + */
 +#ifdef MUSB_C_DYNFIFO_DEF
 +#define       can_dynfifo()   1
 +#else
 +#define       can_dynfifo()   0
 +#endif
 +
 +#if defined(CONFIG_USB_TUSB6010) || \
 +      defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
 +static ushort __initdata fifo_mode = 4;
 +#else
 +static ushort __initdata fifo_mode = 2;
 +#endif
 +
 +/* "modprobe ... fifo_mode=1" etc */
 +module_param(fifo_mode, ushort, 0);
 +MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
 +
 +
 +#define DYN_FIFO_SIZE (1<<(MUSB_C_RAM_BITS+2))
 +
 +enum fifo_style { FIFO_RXTX, FIFO_TX, FIFO_RX } __attribute__ ((packed));
 +enum buf_mode { BUF_SINGLE, BUF_DOUBLE } __attribute__ ((packed));
 +
 +struct fifo_cfg {
 +      u8              hw_ep_num;
 +      enum fifo_style style;
 +      enum buf_mode   mode;
 +      u16             maxpacket;
 +};
 +
 +/*
 + * tables defining fifo_mode values.  define more if you like.
 + * for host side, make sure both halves of ep1 are set up.
 + */
 +
 +/* mode 0 - fits in 2KB */
 +static struct fifo_cfg __initdata mode_0_cfg[] = {
 +{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
 +{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
 +{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
 +};
 +
 +/* mode 1 - fits in 4KB */
 +static struct fifo_cfg __initdata mode_1_cfg[] = {
 +{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 +{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 +{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
 +{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
 +{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
 +};
 +
 +/* mode 2 - fits in 4KB */
 +static struct fifo_cfg __initdata mode_2_cfg[] = {
 +{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 2, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
 +{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
 +};
 +
 +/* mode 3 - fits in 4KB */
 +static struct fifo_cfg __initdata mode_3_cfg[] = {
 +{ .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 +{ .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 +{ .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 2, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
 +{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
 +};
 +
 +/* mode 4 - fits in 16KB */
 +static struct fifo_cfg __initdata mode_4_cfg[] = {
 +{ .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  2, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  3, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  3, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  4, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  4, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  5, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  5, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  6, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  6, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  7, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  7, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  8, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  8, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num =  9, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num =  9, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 10, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 10, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 11, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 11, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 12, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 12, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 13, .style = FIFO_TX,   .maxpacket = 512, },
 +{ .hw_ep_num = 13, .style = FIFO_RX,   .maxpacket = 512, },
 +{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
 +{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
 +};
 +
 +
 +/*
 + * configure a fifo; for non-shared endpoints, this may be called
 + * once for a tx fifo and once for an rx fifo.
 + *
 + * returns negative errno or offset for next fifo.
 + */
 +static int __init
 +fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
 +              const struct fifo_cfg *cfg, u16 offset)
 +{
 +      void __iomem    *mbase = musb->mregs;
 +      int     size = 0;
 +      u16     maxpacket = cfg->maxpacket;
 +      u16     c_off = offset >> 3;
 +      u8      c_size;
 +
 +      /* expect hw_ep has already been zero-initialized */
 +
 +      size = ffs(max(maxpacket, (u16) 8)) - 1;
 +      maxpacket = 1 << size;
 +
 +      c_size = size - 3;
 +      if (cfg->mode == BUF_DOUBLE) {
 +              if ((offset + (maxpacket << 1)) > DYN_FIFO_SIZE)
 +                      return -EMSGSIZE;
 +              c_size |= MUSB_FIFOSZ_DPB;
 +      } else {
 +              if ((offset + maxpacket) > DYN_FIFO_SIZE)
 +                      return -EMSGSIZE;
 +      }
 +
 +      /* configure the FIFO */
 +      musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      /* EP0 reserved endpoint for control, bidirectional;
 +       * EP1 reserved for bulk, two unidirection halves.
 +       */
 +      if (hw_ep->epnum == 1)
 +              musb->bulk_ep = hw_ep;
 +      /* REVISIT error check:  be sure ep0 can both rx and tx ... */
 +#endif
 +      switch (cfg->style) {
 +      case FIFO_TX:
 +              musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
 +              musb_writew(mbase, MUSB_TXFIFOADD, c_off);
 +              hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
 +              hw_ep->max_packet_sz_tx = maxpacket;
 +              break;
 +      case FIFO_RX:
 +              musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
 +              musb_writew(mbase, MUSB_RXFIFOADD, c_off);
 +              hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
 +              hw_ep->max_packet_sz_rx = maxpacket;
 +              break;
 +      case FIFO_RXTX:
 +              musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
 +              musb_writew(mbase, MUSB_TXFIFOADD, c_off);
 +              hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
 +              hw_ep->max_packet_sz_rx = maxpacket;
 +
 +              musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
 +              musb_writew(mbase, MUSB_RXFIFOADD, c_off);
 +              hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;
 +              hw_ep->max_packet_sz_tx = maxpacket;
 +
 +              hw_ep->is_shared_fifo = true;
 +              break;
 +      }
 +
 +      /* NOTE rx and tx endpoint irqs aren't managed separately,
 +       * which happens to be ok
 +       */
 +      musb->epmask |= (1 << hw_ep->epnum);
 +
 +      return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
 +}
 +
 +static struct fifo_cfg __initdata ep0_cfg = {
 +      .style = FIFO_RXTX, .maxpacket = 64,
 +};
 +
 +static int __init ep_config_from_table(struct musb *musb)
 +{
 +      const struct fifo_cfg   *cfg;
 +      unsigned                i, n;
 +      int                     offset;
 +      struct musb_hw_ep       *hw_ep = musb->endpoints;
 +
 +      switch (fifo_mode) {
 +      default:
 +              fifo_mode = 0;
 +              /* FALLTHROUGH */
 +      case 0:
 +              cfg = mode_0_cfg;
 +              n = ARRAY_SIZE(mode_0_cfg);
 +              break;
 +      case 1:
 +              cfg = mode_1_cfg;
 +              n = ARRAY_SIZE(mode_1_cfg);
 +              break;
 +      case 2:
 +              cfg = mode_2_cfg;
 +              n = ARRAY_SIZE(mode_2_cfg);
 +              break;
 +      case 3:
 +              cfg = mode_3_cfg;
 +              n = ARRAY_SIZE(mode_3_cfg);
 +              break;
 +      case 4:
 +              cfg = mode_4_cfg;
 +              n = ARRAY_SIZE(mode_4_cfg);
 +              break;
 +      }
 +
 +      printk(KERN_DEBUG "%s: setup fifo_mode %d\n",
 +                      musb_driver_name, fifo_mode);
 +
 +
 +      offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
 +      /* assert(offset > 0) */
 +
 +      /* NOTE:  for RTL versions >= 1.400 EPINFO and RAMINFO would
 +       * be better than static MUSB_C_NUM_EPS and DYN_FIFO_SIZE...
 +       */
 +
 +      for (i = 0; i < n; i++) {
 +              u8      epn = cfg->hw_ep_num;
 +
 +              if (epn >= MUSB_C_NUM_EPS) {
 +                      pr_debug("%s: invalid ep %d\n",
 +                                      musb_driver_name, epn);
 +                      continue;
 +              }
 +              offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
 +              if (offset < 0) {
 +                      pr_debug("%s: mem overrun, ep %d\n",
 +                                      musb_driver_name, epn);
 +                      return -EINVAL;
 +              }
 +              epn++;
 +              musb->nr_endpoints = max(epn, musb->nr_endpoints);
 +      }
 +
 +      printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",
 +                      musb_driver_name,
 +                      n + 1, MUSB_C_NUM_EPS * 2 - 1,
 +                      offset, DYN_FIFO_SIZE);
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      if (!musb->bulk_ep) {
 +              pr_debug("%s: missing bulk\n", musb_driver_name);
 +              return -EINVAL;
 +      }
 +#endif
 +
 +      return 0;
 +}
 +
 +
 +/*
 + * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
 + * @param musb the controller
 + */
 +static int __init ep_config_from_hw(struct musb *musb)
 +{
 +      u8 epnum = 0, reg;
 +      struct musb_hw_ep *hw_ep;
 +      void *mbase = musb->mregs;
 +
 +      DBG(2, "<== static silicon ep config\n");
 +
 +      /* FIXME pick up ep0 maxpacket size */
 +
 +      for (epnum = 1; epnum < MUSB_C_NUM_EPS; epnum++) {
 +              musb_ep_select(mbase, epnum);
 +              hw_ep = musb->endpoints + epnum;
 +
 +              /* read from core using indexed model */
 +              reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE);
 +              if (!reg) {
 +                      /* 0's returned when no more endpoints */
 +                      break;
 +              }
 +              musb->nr_endpoints++;
 +              musb->epmask |= (1 << epnum);
 +
 +              hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f);
 +
 +              /* shared TX/RX FIFO? */
 +              if ((reg & 0xf0) == 0xf0) {
 +                      hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx;
 +                      hw_ep->is_shared_fifo = true;
 +                      continue;
 +              } else {
 +                      hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4);
 +                      hw_ep->is_shared_fifo = false;
 +              }
 +
 +              /* FIXME set up hw_ep->{rx,tx}_double_buffered */
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +              /* pick an RX/TX endpoint for bulk */
 +              if (hw_ep->max_packet_sz_tx < 512
 +                              || hw_ep->max_packet_sz_rx < 512)
 +                      continue;
 +
 +              /* REVISIT:  this algorithm is lazy, we should at least
 +               * try to pick a double buffered endpoint.
 +               */
 +              if (musb->bulk_ep)
 +                      continue;
 +              musb->bulk_ep = hw_ep;
 +#endif
 +      }
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      if (!musb->bulk_ep) {
 +              pr_debug("%s: missing bulk\n", musb_driver_name);
 +              return -EINVAL;
 +      }
 +#endif
 +
 +      return 0;
 +}
 +
 +enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
 +
 +/* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
 + * configure endpoints, or take their config from silicon
 + */
 +static int __init musb_core_init(u16 musb_type, struct musb *musb)
 +{
 +#ifdef MUSB_AHB_ID
 +      u32 data;
 +#endif
 +      u8 reg;
 +      char *type;
 +      u16 hwvers, rev_major, rev_minor;
 +      char aInfo[78], aRevision[32], aDate[12];
 +      void __iomem    *mbase = musb->mregs;
 +      int             status = 0;
 +      int             i;
 +
 +      /* log core options (read using indexed model) */
 +      musb_ep_select(mbase, 0);
 +      reg = musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
 +
 +      strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
 +      if (reg & MUSB_CONFIGDATA_DYNFIFO)
 +              strcat(aInfo, ", dyn FIFOs");
 +      if (reg & MUSB_CONFIGDATA_MPRXE) {
 +              strcat(aInfo, ", bulk combine");
 +#ifdef C_MP_RX
 +              musb->bulk_combine = true;
 +#else
 +              strcat(aInfo, " (X)");          /* no driver support */
 +#endif
 +      }
 +      if (reg & MUSB_CONFIGDATA_MPTXE) {
 +              strcat(aInfo, ", bulk split");
 +#ifdef C_MP_TX
 +              musb->bulk_split = true;
 +#else
 +              strcat(aInfo, " (X)");          /* no driver support */
 +#endif
 +      }
 +      if (reg & MUSB_CONFIGDATA_HBRXE) {
 +              strcat(aInfo, ", HB-ISO Rx");
 +              strcat(aInfo, " (X)");          /* no driver support */
 +      }
 +      if (reg & MUSB_CONFIGDATA_HBTXE) {
 +              strcat(aInfo, ", HB-ISO Tx");
 +              strcat(aInfo, " (X)");          /* no driver support */
 +      }
 +      if (reg & MUSB_CONFIGDATA_SOFTCONE)
 +              strcat(aInfo, ", SoftConn");
 +
 +      printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",
 +                      musb_driver_name, reg, aInfo);
 +
 +#ifdef MUSB_AHB_ID
 +      data = musb_readl(mbase, 0x404);
 +      sprintf(aDate, "%04d-%02x-%02x", (data & 0xffff),
 +              (data >> 16) & 0xff, (data >> 24) & 0xff);
 +      /* FIXME ID2 and ID3 are unused */
 +      data = musb_readl(mbase, 0x408);
 +      printk("ID2=%lx\n", (long unsigned)data);
 +      data = musb_readl(mbase, 0x40c);
 +      printk("ID3=%lx\n", (long unsigned)data);
 +      reg = musb_readb(mbase, 0x400);
 +      musb_type = ('M' == reg) ? MUSB_CONTROLLER_MHDRC : MUSB_CONTROLLER_HDRC;
 +#else
 +      aDate[0] = 0;
 +#endif
 +      if (MUSB_CONTROLLER_MHDRC == musb_type) {
 +              musb->is_multipoint = 1;
 +              type = "M";
 +      } else {
 +              musb->is_multipoint = 0;
 +              type = "";
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +#ifndef       CONFIG_USB_OTG_BLACKLIST_HUB
 +              printk(KERN_ERR
 +                      "%s: kernel must blacklist external hubs\n",
 +                      musb_driver_name);
 +#endif
 +#endif
 +      }
 +
 +      /* log release info */
 +      hwvers = musb_readw(mbase, MUSB_HWVERS);
 +      rev_major = (hwvers >> 10) & 0x1f;
 +      rev_minor = hwvers & 0x3ff;
 +      snprintf(aRevision, 32, "%d.%d%s", rev_major,
 +              rev_minor, (hwvers & 0x8000) ? "RC" : "");
 +      printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",
 +                      musb_driver_name, type, aRevision, aDate);
 +
 +      /* configure ep0 */
 +      musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
 +      musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
 +
 +      /* discover endpoint configuration */
 +      musb->nr_endpoints = 1;
 +      musb->epmask = 1;
 +
 +      if (reg & MUSB_CONFIGDATA_DYNFIFO) {
 +              if (can_dynfifo())
 +                      status = ep_config_from_table(musb);
 +              else {
 +                      ERR("reconfigure software for Dynamic FIFOs\n");
 +                      status = -ENODEV;
 +              }
 +      } else {
 +              if (!can_dynfifo())
 +                      status = ep_config_from_hw(musb);
 +              else {
 +                      ERR("reconfigure software for static FIFOs\n");
 +                      return -ENODEV;
 +              }
 +      }
 +
 +      if (status < 0)
 +              return status;
 +
 +      /* finish init, and print endpoint config */
 +      for (i = 0; i < musb->nr_endpoints; i++) {
 +              struct musb_hw_ep       *hw_ep = musb->endpoints + i;
 +
 +              hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
 +#ifdef CONFIG_USB_TUSB6010
 +              hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
 +              hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
 +              hw_ep->fifo_sync_va =
 +                      musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
 +
 +              if (i == 0)
 +                      hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
 +              else
 +                      hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
 +#endif
 +
 +              hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +              hw_ep->target_regs = MUSB_BUSCTL_OFFSET(i, 0) + mbase;
 +              hw_ep->rx_reinit = 1;
 +              hw_ep->tx_reinit = 1;
 +#endif
 +
 +              if (hw_ep->max_packet_sz_tx) {
 +                      printk(KERN_DEBUG
 +                              "%s: hw_ep %d%s, %smax %d\n",
 +                              musb_driver_name, i,
 +                              hw_ep->is_shared_fifo ? "shared" : "tx",
 +                              hw_ep->tx_double_buffered
 +                                      ? "doublebuffer, " : "",
 +                              hw_ep->max_packet_sz_tx);
 +              }
 +              if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {
 +                      printk(KERN_DEBUG
 +                              "%s: hw_ep %d%s, %smax %d\n",
 +                              musb_driver_name, i,
 +                              "rx",
 +                              hw_ep->rx_double_buffered
 +                                      ? "doublebuffer, " : "",
 +                              hw_ep->max_packet_sz_rx);
 +              }
 +              if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))
 +                      DBG(1, "hw_ep %d not configured\n", i);
 +      }
 +
 +      return 0;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
 +
 +static irqreturn_t generic_interrupt(int irq, void *__hci)
 +{
 +      unsigned long   flags;
 +      irqreturn_t     retval = IRQ_NONE;
 +      struct musb     *musb = __hci;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
 +      musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
 +      musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
 +
 +      if (musb->int_usb || musb->int_tx || musb->int_rx)
 +              retval = musb_interrupt(musb);
 +
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      /* REVISIT we sometimes get spurious IRQs on g_ep0
 +       * not clear why...
 +       */
 +      if (retval != IRQ_HANDLED)
 +              DBG(5, "spurious?\n");
 +
 +      return IRQ_HANDLED;
 +}
 +
 +#else
 +#define generic_interrupt     NULL
 +#endif
 +
 +/*
 + * handle all the irqs defined by the HDRC core. for now we expect:  other
 + * irq sources (phy, dma, etc) will be handled first, musb->int_* values
 + * will be assigned, and the irq will already have been acked.
 + *
 + * called in irq context with spinlock held, irqs blocked
 + */
 +irqreturn_t musb_interrupt(struct musb *musb)
 +{
 +      irqreturn_t     retval = IRQ_NONE;
 +      u8              devctl, power;
 +      int             ep_num;
 +      u32             reg;
 +
 +      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +      power = musb_readb(musb->mregs, MUSB_POWER);
 +
 +      DBG(4, "** IRQ %s usb%04x tx%04x rx%04x\n",
 +              (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
 +              musb->int_usb, musb->int_tx, musb->int_rx);
 +
 +      /* the core can interrupt us for multiple reasons; docs have
 +       * a generic interrupt flowchart to follow
 +       */
 +      if (musb->int_usb & STAGE0_MASK)
 +              retval |= musb_stage0_irq(musb, musb->int_usb,
 +                              devctl, power);
 +
 +      /* "stage 1" is handling endpoint irqs */
 +
 +      /* handle endpoint 0 first */
 +      if (musb->int_tx & 1) {
 +              if (devctl & MUSB_DEVCTL_HM)
 +                      retval |= musb_h_ep0_irq(musb);
 +              else
 +                      retval |= musb_g_ep0_irq(musb);
 +      }
 +
 +      /* RX on endpoints 1-15 */
 +      reg = musb->int_rx >> 1;
 +      ep_num = 1;
 +      while (reg) {
 +              if (reg & 1) {
 +                      /* musb_ep_select(musb->mregs, ep_num); */
 +                      /* REVISIT just retval = ep->rx_irq(...) */
 +                      retval = IRQ_HANDLED;
 +                      if (devctl & MUSB_DEVCTL_HM) {
 +                              if (is_host_capable())
 +                                      musb_host_rx(musb, ep_num);
 +                      } else {
 +                              if (is_peripheral_capable())
 +                                      musb_g_rx(musb, ep_num);
 +                      }
 +              }
 +
 +              reg >>= 1;
 +              ep_num++;
 +      }
 +
 +      /* TX on endpoints 1-15 */
 +      reg = musb->int_tx >> 1;
 +      ep_num = 1;
 +      while (reg) {
 +              if (reg & 1) {
 +                      /* musb_ep_select(musb->mregs, ep_num); */
 +                      /* REVISIT just retval |= ep->tx_irq(...) */
 +                      retval = IRQ_HANDLED;
 +                      if (devctl & MUSB_DEVCTL_HM) {
 +                              if (is_host_capable())
 +                                      musb_host_tx(musb, ep_num);
 +                      } else {
 +                              if (is_peripheral_capable())
 +                                      musb_g_tx(musb, ep_num);
 +                      }
 +              }
 +              reg >>= 1;
 +              ep_num++;
 +      }
 +
 +      /* finish handling "global" interrupts after handling fifos */
 +      if (musb->int_usb)
 +              retval |= musb_stage2_irq(musb,
 +                              musb->int_usb, devctl, power);
 +
 +      return retval;
 +}
 +
 +
 +#ifndef CONFIG_MUSB_PIO_ONLY
 +static int __initdata use_dma = 1;
 +
 +/* "modprobe ... use_dma=0" etc */
 +module_param(use_dma, bool, 0);
 +MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
 +
 +void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
 +{
 +      u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +
 +      /* called with controller lock already held */
 +
 +      if (!epnum) {
 +#ifndef CONFIG_USB_TUSB_OMAP_DMA
 +              if (!is_cppi_enabled()) {
 +                      /* endpoint 0 */
 +                      if (devctl & MUSB_DEVCTL_HM)
 +                              musb_h_ep0_irq(musb);
 +                      else
 +                              musb_g_ep0_irq(musb);
 +              }
 +#endif
 +      } else {
 +              /* endpoints 1..15 */
 +              if (transmit) {
 +                      if (devctl & MUSB_DEVCTL_HM) {
 +                              if (is_host_capable())
 +                                      musb_host_tx(musb, epnum);
 +                      } else {
 +                              if (is_peripheral_capable())
 +                                      musb_g_tx(musb, epnum);
 +                      }
 +              } else {
 +                      /* receive */
 +                      if (devctl & MUSB_DEVCTL_HM) {
 +                              if (is_host_capable())
 +                                      musb_host_rx(musb, epnum);
 +                      } else {
 +                              if (is_peripheral_capable())
 +                                      musb_g_rx(musb, epnum);
 +                      }
 +              }
 +      }
 +}
 +
 +#else
 +#define use_dma                       0
 +#endif
 +
 +/*-------------------------------------------------------------------------*/
 +
 +#ifdef CONFIG_SYSFS
 +
 +static ssize_t
 +musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +      struct musb *musb = dev_to_musb(dev);
 +      unsigned long flags;
 +      int ret = -EINVAL;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      ret = sprintf(buf, "%s\n", otg_state_string(musb));
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      return ret;
 +}
 +
 +static ssize_t
 +musb_mode_store(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t n)
 +{
 +      struct musb     *musb = dev_to_musb(dev);
 +      unsigned long   flags;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      if (!strncmp(buf, "host", 4))
 +              musb_platform_set_mode(musb, MUSB_HOST);
 +      if (!strncmp(buf, "peripheral", 10))
 +              musb_platform_set_mode(musb, MUSB_PERIPHERAL);
 +      if (!strncmp(buf, "otg", 3))
 +              musb_platform_set_mode(musb, MUSB_OTG);
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      return n;
 +}
 +static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store);
 +
 +static ssize_t
 +musb_vbus_store(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t n)
 +{
 +      struct musb     *musb = dev_to_musb(dev);
 +      unsigned long   flags;
 +      unsigned long   val;
 +
 +      if (sscanf(buf, "%lu", &val) < 1) {
 +              printk(KERN_ERR "Invalid VBUS timeout ms value\n");
 +              return -EINVAL;
 +      }
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      musb->a_wait_bcon = val;
 +      if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON)
 +              musb->is_active = 0;
 +      musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      return n;
 +}
 +
 +static ssize_t
 +musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +      struct musb     *musb = dev_to_musb(dev);
 +      unsigned long   flags;
 +      unsigned long   val;
 +      int             vbus;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +      val = musb->a_wait_bcon;
 +      vbus = musb_platform_get_vbus_status(musb);
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +
 +      return sprintf(buf, "Vbus %s, timeout %lu\n",
 +                      vbus ? "on" : "off", val);
 +}
 +static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +
 +/* Gadget drivers can't know that a host is connected so they might want
 + * to start SRP, but users can.  This allows userspace to trigger SRP.
 + */
 +static ssize_t
 +musb_srp_store(struct device *dev, struct device_attribute *attr,
 +              const char *buf, size_t n)
 +{
 +      struct musb     *musb = dev_to_musb(dev);
 +      unsigned short  srp;
 +
 +      if (sscanf(buf, "%hu", &srp) != 1
 +                      || (srp != 1)) {
 +              printk(KERN_ERR "SRP: Value must be 1\n");
 +              return -EINVAL;
 +      }
 +
 +      if (srp == 1)
 +              musb_g_wakeup(musb);
 +
 +      return n;
 +}
 +static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);
 +
 +#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
 +
 +#endif        /* sysfs */
 +
 +/* Only used to provide driver mode change events */
 +static void musb_irq_work(struct work_struct *data)
 +{
 +      struct musb *musb = container_of(data, struct musb, irq_work);
 +      static int old_state;
 +
 +      if (musb->xceiv.state != old_state) {
 +              old_state = musb->xceiv.state;
 +              sysfs_notify(&musb->controller->kobj, NULL, "mode");
 +      }
 +}
 +
 +/* --------------------------------------------------------------------------
 + * Init support
 + */
 +
 +static struct musb *__init
 +allocate_instance(struct device *dev, void __iomem *mbase)
 +{
 +      struct musb             *musb;
 +      struct musb_hw_ep       *ep;
 +      int                     epnum;
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      struct usb_hcd  *hcd;
 +
 +      hcd = usb_create_hcd(&musb_hc_driver, dev, dev->bus_id);
 +      if (!hcd)
 +              return NULL;
 +      /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
 +
 +      musb = hcd_to_musb(hcd);
 +      INIT_LIST_HEAD(&musb->control);
 +      INIT_LIST_HEAD(&musb->in_bulk);
 +      INIT_LIST_HEAD(&musb->out_bulk);
 +
 +      hcd->uses_new_polling = 1;
 +
 +      musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
 +#else
 +      musb = kzalloc(sizeof *musb, GFP_KERNEL);
 +      if (!musb)
 +              return NULL;
 +      dev_set_drvdata(dev, musb);
 +
 +#endif
 +
 +      musb->mregs = mbase;
 +      musb->ctrl_base = mbase;
 +      musb->nIrq = -ENODEV;
 +      for (epnum = 0, ep = musb->endpoints;
 +                      epnum < MUSB_C_NUM_EPS;
 +                      epnum++, ep++) {
 +
 +              ep->musb = musb;
 +              ep->epnum = epnum;
 +      }
 +
 +#ifdef CONFIG_USB_MUSB_OTG
 +      otg_set_transceiver(&musb->xceiv);
 +#endif
 +      musb->controller = dev;
 +      return musb;
 +}
 +
 +static void musb_free(struct musb *musb)
 +{
 +      /* this has multiple entry modes. it handles fault cleanup after
 +       * probe(), where things may be partially set up, as well as rmmod
 +       * cleanup after everything's been de-activated.
 +       */
 +
 +#ifdef CONFIG_SYSFS
 +      device_remove_file(musb->controller, &dev_attr_mode);
 +      device_remove_file(musb->controller, &dev_attr_vbus);
 +#ifdef CONFIG_USB_MUSB_OTG
 +      device_remove_file(musb->controller, &dev_attr_srp);
 +#endif
 +#endif
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      musb_gadget_cleanup(musb);
 +#endif
 +
 +      if (musb->nIrq >= 0) {
 +              disable_irq_wake(musb->nIrq);
 +              free_irq(musb->nIrq, musb);
 +      }
 +      if (is_dma_capable() && musb->dma_controller) {
 +              struct dma_controller   *c = musb->dma_controller;
 +
 +              (void) c->stop(c);
 +              dma_controller_destroy(c);
 +      }
 +
 +      musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
 +      musb_platform_exit(musb);
 +      musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
 +
 +      if (musb->clock) {
 +              clk_disable(musb->clock);
 +              clk_put(musb->clock);
 +      }
 +
 +#ifdef CONFIG_USB_MUSB_OTG
 +      put_device(musb->xceiv.dev);
 +#endif
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      usb_put_hcd(musb_to_hcd(musb));
 +#else
 +      kfree(musb);
 +#endif
 +}
 +
 +/*
 + * Perform generic per-controller initialization.
 + *
 + * @pDevice: the controller (already clocked, etc)
 + * @nIrq: irq
 + * @mregs: virtual address of controller registers,
 + *    not yet corrected for platform-specific offsets
 + */
 +static int __init
 +musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 +{
 +      int                     status;
 +      struct musb             *musb;
 +      struct musb_hdrc_platform_data *plat = dev->platform_data;
 +
 +      /* The driver might handle more features than the board; OK.
 +       * Fail when the board needs a feature that's not enabled.
 +       */
 +      if (!plat) {
 +              dev_dbg(dev, "no platform_data?\n");
 +              return -ENODEV;
 +      }
 +      switch (plat->mode) {
 +      case MUSB_HOST:
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +              break;
 +#else
 +              goto bad_config;
 +#endif
 +      case MUSB_PERIPHERAL:
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +              break;
 +#else
 +              goto bad_config;
 +#endif
 +      case MUSB_OTG:
 +#ifdef CONFIG_USB_MUSB_OTG
 +              break;
 +#else
 +bad_config:
 +#endif
 +      default:
 +              dev_err(dev, "incompatible Kconfig role setting\n");
 +              return -EINVAL;
 +      }
 +
 +      /* allocate */
 +      musb = allocate_instance(dev, ctrl);
 +      if (!musb)
 +              return -ENOMEM;
 +
 +      spin_lock_init(&musb->lock);
 +      musb->board_mode = plat->mode;
 +      musb->board_set_power = plat->set_power;
 +      musb->set_clock = plat->set_clock;
 +      musb->min_power = plat->min_power;
 +
 +      /* Clock usage is chip-specific ... functional clock (DaVinci,
 +       * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core
 +       * code does is make sure a clock handle is available; platform
 +       * code manages it during start/stop and suspend/resume.
 +       */
 +      if (plat->clock) {
 +              musb->clock = clk_get(dev, plat->clock);
 +              if (IS_ERR(musb->clock)) {
 +                      status = PTR_ERR(musb->clock);
 +                      musb->clock = NULL;
 +                      goto fail;
 +              }
 +      }
 +
 +      /* assume vbus is off */
 +
 +      /* platform adjusts musb->mregs and musb->isr if needed,
 +       * and activates clocks
 +       */
 +      musb->isr = generic_interrupt;
 +      status = musb_platform_init(musb);
 +
 +      if (status < 0)
 +              goto fail;
 +      if (!musb->isr) {
 +              status = -ENODEV;
 +              goto fail2;
 +      }
 +
 +#ifndef CONFIG_MUSB_PIO_ONLY
 +      if (use_dma && dev->dma_mask) {
 +              struct dma_controller   *c;
 +
 +              c = dma_controller_create(musb, musb->mregs);
 +              musb->dma_controller = c;
 +              if (c)
 +                      (void) c->start(c);
 +      }
 +#endif
 +      /* ideally this would be abstracted in platform setup */
 +      if (!is_dma_capable() || !musb->dma_controller)
 +              dev->dma_mask = NULL;
 +
 +      /* be sure interrupts are disabled before connecting ISR */
 +      musb_platform_disable(musb);
 +      musb_generic_disable(musb);
 +
 +      /* setup musb parts of the core (especially endpoints) */
 +      status = musb_core_init(plat->multipoint
 +                      ? MUSB_CONTROLLER_MHDRC
 +                      : MUSB_CONTROLLER_HDRC, musb);
 +      if (status < 0)
 +              goto fail2;
 +
 +      /* Init IRQ workqueue before request_irq */
 +      INIT_WORK(&musb->irq_work, musb_irq_work);
 +
 +      /* attach to the IRQ */
 +      if (request_irq(nIrq, musb->isr, 0, dev->bus_id, musb)) {
 +              dev_err(dev, "request_irq %d failed!\n", nIrq);
 +              status = -ENODEV;
 +              goto fail2;
 +      }
 +      musb->nIrq = nIrq;
 +/* FIXME this handles wakeup irqs wrong */
 +      if (enable_irq_wake(nIrq) == 0)
 +              device_init_wakeup(dev, 1);
 +
 +      pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n",
 +                      musb_driver_name,
 +                      ({char *s;
 +                      switch (musb->board_mode) {
 +                      case MUSB_HOST:         s = "Host"; break;
 +                      case MUSB_PERIPHERAL:   s = "Peripheral"; break;
 +                      default:                s = "OTG"; break;
 +                      }; s; }),
 +                      ctrl,
 +                      (is_dma_capable() && musb->dma_controller)
 +                              ? "DMA" : "PIO",
 +                      musb->nIrq);
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      /* host side needs more setup, except for no-host modes */
 +      if (musb->board_mode != MUSB_PERIPHERAL) {
 +              struct usb_hcd  *hcd = musb_to_hcd(musb);
 +
 +              if (musb->board_mode == MUSB_OTG)
 +                      hcd->self.otg_port = 1;
 +              musb->xceiv.host = &hcd->self;
 +              hcd->power_budget = 2 * (plat->power ? : 250);
 +      }
 +#endif                                /* CONFIG_USB_MUSB_HDRC_HCD */
 +
 +      /* For the host-only role, we can activate right away.
 +       * (We expect the ID pin to be forcibly grounded!!)
 +       * Otherwise, wait till the gadget driver hooks up.
 +       */
 +      if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
 +              MUSB_HST_MODE(musb);
 +              musb->xceiv.default_a = 1;
 +              musb->xceiv.state = OTG_STATE_A_IDLE;
 +
 +              status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
 +
 +              DBG(1, "%s mode, status %d, devctl %02x %c\n",
 +                      "HOST", status,
 +                      musb_readb(musb->mregs, MUSB_DEVCTL),
 +                      (musb_readb(musb->mregs, MUSB_DEVCTL)
 +                                      & MUSB_DEVCTL_BDEVICE
 +                              ? 'B' : 'A'));
 +
 +      } else /* peripheral is enabled */ {
 +              MUSB_DEV_MODE(musb);
 +              musb->xceiv.default_a = 0;
 +              musb->xceiv.state = OTG_STATE_B_IDLE;
 +
 +              status = musb_gadget_setup(musb);
 +
 +              DBG(1, "%s mode, status %d, dev%02x\n",
 +                      is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
 +                      status,
 +                      musb_readb(musb->mregs, MUSB_DEVCTL));
 +
 +      }
 +
 +      if (status == 0)
 +              musb_debug_create("driver/musb_hdrc", musb);
 +      else {
 +fail:
 +              if (musb->clock)
 +                      clk_put(musb->clock);
 +              device_init_wakeup(dev, 0);
 +              musb_free(musb);
 +              return status;
 +      }
 +
 +#ifdef CONFIG_SYSFS
 +      status = device_create_file(dev, &dev_attr_mode);
 +      status = device_create_file(dev, &dev_attr_vbus);
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      status = device_create_file(dev, &dev_attr_srp);
 +#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
 +      status = 0;
 +#endif
 +
 +      return status;
 +
 +fail2:
 +      musb_platform_exit(musb);
 +      goto fail;
 +}
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
 + * bridge to a platform device; this driver then suffices.
 + */
 +
 +#ifndef CONFIG_MUSB_PIO_ONLY
 +static u64    *orig_dma_mask;
 +#endif
 +
 +static int __init musb_probe(struct platform_device *pdev)
 +{
 +      struct device   *dev = &pdev->dev;
 +      int             irq = platform_get_irq(pdev, 0);
 +      struct resource *iomem;
 +      void __iomem    *base;
 +
 +      iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (!iomem || irq == 0)
 +              return -ENODEV;
 +
 +      base = ioremap(iomem->start, iomem->end - iomem->start + 1);
 +      if (!base) {
 +              dev_err(dev, "ioremap failed\n");
 +              return -ENOMEM;
 +      }
 +
 +#ifndef CONFIG_MUSB_PIO_ONLY
 +      /* clobbered by use_dma=n */
 +      orig_dma_mask = dev->dma_mask;
 +#endif
 +      return musb_init_controller(dev, irq, base);
 +}
 +
 +static int __devexit musb_remove(struct platform_device *pdev)
 +{
 +      struct musb     *musb = dev_to_musb(&pdev->dev);
 +      void __iomem    *ctrl_base = musb->ctrl_base;
 +
 +      /* this gets called on rmmod.
 +       *  - Host mode: host may still be active
 +       *  - Peripheral mode: peripheral is deactivated (or never-activated)
 +       *  - OTG mode: both roles are deactivated (or never-activated)
 +       */
 +      musb_shutdown(pdev);
 +      musb_debug_delete("driver/musb_hdrc", musb);
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      if (musb->board_mode == MUSB_HOST)
 +              usb_remove_hcd(musb_to_hcd(musb));
 +#endif
 +      musb_free(musb);
 +      iounmap(ctrl_base);
 +      device_init_wakeup(&pdev->dev, 0);
 +#ifndef CONFIG_MUSB_PIO_ONLY
 +      pdev->dev.dma_mask = orig_dma_mask;
 +#endif
 +      return 0;
 +}
 +
 +#ifdef        CONFIG_PM
 +
 +static int musb_suspend(struct platform_device *pdev, pm_message_t message)
 +{
 +      unsigned long   flags;
 +      struct musb     *musb = dev_to_musb(&pdev->dev);
 +
 +      if (!musb->clock)
 +              return 0;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      if (is_peripheral_active(musb)) {
 +              /* FIXME force disconnect unless we know USB will wake
 +               * the system up quickly enough to respond ...
 +               */
 +      } else if (is_host_active(musb)) {
 +              /* we know all the children are suspended; sometimes
 +               * they will even be wakeup-enabled.
 +               */
 +      }
 +
 +      if (musb->set_clock)
 +              musb->set_clock(musb->clock, 0);
 +      else
 +              clk_disable(musb->clock);
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +      return 0;
 +}
 +
 +static int musb_resume(struct platform_device *pdev)
 +{
 +      unsigned long   flags;
 +      struct musb     *musb = dev_to_musb(&pdev->dev);
 +
 +      if (!musb->clock)
 +              return 0;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      if (musb->set_clock)
 +              musb->set_clock(musb->clock, 1);
 +      else
 +              clk_enable(musb->clock);
 +
 +      /* for static cmos like DaVinci, register values were preserved
 +       * unless for some reason the whole soc powered down and we're
 +       * not treating that as a whole-system restart (e.g. swsusp)
 +       */
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +      return 0;
 +}
 +
 +#else
 +#define       musb_suspend    NULL
 +#define       musb_resume     NULL
 +#endif
 +
 +static struct platform_driver musb_driver = {
 +      .driver = {
 +              .name           = (char *)musb_driver_name,
 +              .bus            = &platform_bus_type,
 +              .owner          = THIS_MODULE,
 +      },
 +      .remove         = __devexit_p(musb_remove),
 +      .shutdown       = musb_shutdown,
 +      .suspend        = musb_suspend,
 +      .resume         = musb_resume,
 +};
 +
 +/*-------------------------------------------------------------------------*/
 +
 +static int __init musb_init(void)
 +{
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      if (usb_disabled())
 +              return 0;
 +#endif
 +
 +      pr_info("%s: version " MUSB_VERSION ", "
 +#ifdef CONFIG_MUSB_PIO_ONLY
 +              "pio"
 +#elif defined(CONFIG_USB_TI_CPPI_DMA)
 +              "cppi-dma"
 +#elif defined(CONFIG_USB_INVENTRA_DMA)
 +              "musb-dma"
 +#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
 +              "tusb-omap-dma"
 +#else
 +              "?dma?"
 +#endif
 +              ", "
 +#ifdef CONFIG_USB_MUSB_OTG
 +              "otg (peripheral+host)"
 +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
 +              "peripheral"
 +#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
 +              "host"
 +#endif
 +              ", debug=%d\n",
 +              musb_driver_name, debug);
 +      return platform_driver_probe(&musb_driver, musb_probe);
 +}
 +
 +/* make us init after usbcore and before usb
 + * gadget and host-side drivers start to register
 + */
 +subsys_initcall(musb_init);
 +
 +static void __exit musb_cleanup(void)
 +{
 +      platform_driver_unregister(&musb_driver);
 +}
 +module_exit(musb_cleanup);
index c2cd5a9c486d96b4dae74c40cd7857afe8f2daa5,0000000000000000000000000000000000000000..2e42dc2210ce555b688111d204f5dff4b6fd7bfc
mode 100644,000000..100644
--- /dev/null
@@@ -1,516 -1,0 +1,516 @@@
- #include <asm/arch/hdrc_cnf.h>
 +/*
 + * MUSB OTG driver defines
 + *
 + * Copyright 2005 Mentor Graphics Corporation
 + * Copyright (C) 2005-2006 by Texas Instruments
 + * Copyright (C) 2006-2007 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 + * NO EVENT SHALL THE AUTHORS 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 __MUSB_CORE_H__
 +#define __MUSB_CORE_H__
 +
 +#include <linux/slab.h>
 +#include <linux/list.h>
 +#include <linux/interrupt.h>
 +#include <linux/smp_lock.h>
 +#include <linux/errno.h>
 +#include <linux/clk.h>
 +#include <linux/device.h>
 +#include <linux/usb/ch9.h>
 +#include <linux/usb/gadget.h>
 +#include <linux/usb.h>
 +#include <linux/usb/otg.h>
 +#include <linux/usb/musb.h>
 +
 +struct musb;
 +struct musb_hw_ep;
 +struct musb_ep;
 +
 +
 +#include "musb_debug.h"
 +#include "musb_dma.h"
 +
 +#ifdef CONFIG_USB_MUSB_SOC
 +/*
 + * Get core configuration from a header converted (by cfg_conv)
 + * from the Verilog config file generated by the core config utility
 + *
 + * For now we assume that header is provided along with other
 + * arch-specific files.  Discrete chips will need a build tweak.
 + * So will using AHB IDs from silicon that provides them.
 + */
++#include <mach/hdrc_cnf.h>
 +#endif
 +
 +#include "musb_io.h"
 +#include "musb_regs.h"
 +
 +#include "musb_gadget.h"
 +#include "../core/hcd.h"
 +#include "musb_host.h"
 +
 +
 +
 +#ifdef CONFIG_USB_MUSB_OTG
 +
 +#define       is_peripheral_enabled(musb)     ((musb)->board_mode != MUSB_HOST)
 +#define       is_host_enabled(musb)           ((musb)->board_mode != MUSB_PERIPHERAL)
 +#define       is_otg_enabled(musb)            ((musb)->board_mode == MUSB_OTG)
 +
 +/* NOTE:  otg and peripheral-only state machines start at B_IDLE.
 + * OTG or host-only go to A_IDLE when ID is sensed.
 + */
 +#define is_peripheral_active(m)               (!(m)->is_host)
 +#define is_host_active(m)             ((m)->is_host)
 +
 +#else
 +#define       is_peripheral_enabled(musb)     is_peripheral_capable()
 +#define       is_host_enabled(musb)           is_host_capable()
 +#define       is_otg_enabled(musb)            0
 +
 +#define       is_peripheral_active(musb)      is_peripheral_capable()
 +#define       is_host_active(musb)            is_host_capable()
 +#endif
 +
 +#if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL)
 +/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always
 + * override that choice selection (often USB_GADGET_DUMMY_HCD).
 + */
 +#ifndef CONFIG_USB_GADGET_MUSB_HDRC
 +#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
 +#endif
 +#endif        /* need MUSB gadget selection */
 +
 +
 +#ifdef CONFIG_PROC_FS
 +#include <linux/fs.h>
 +#define MUSB_CONFIG_PROC_FS
 +#endif
 +
 +/****************************** PERIPHERAL ROLE *****************************/
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +
 +#define       is_peripheral_capable() (1)
 +
 +extern irqreturn_t musb_g_ep0_irq(struct musb *);
 +extern void musb_g_tx(struct musb *, u8);
 +extern void musb_g_rx(struct musb *, u8);
 +extern void musb_g_reset(struct musb *);
 +extern void musb_g_suspend(struct musb *);
 +extern void musb_g_resume(struct musb *);
 +extern void musb_g_wakeup(struct musb *);
 +extern void musb_g_disconnect(struct musb *);
 +
 +#else
 +
 +#define       is_peripheral_capable() (0)
 +
 +static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; }
 +static inline void musb_g_reset(struct musb *m) {}
 +static inline void musb_g_suspend(struct musb *m) {}
 +static inline void musb_g_resume(struct musb *m) {}
 +static inline void musb_g_wakeup(struct musb *m) {}
 +static inline void musb_g_disconnect(struct musb *m) {}
 +
 +#endif
 +
 +/****************************** HOST ROLE ***********************************/
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +
 +#define       is_host_capable()       (1)
 +
 +extern irqreturn_t musb_h_ep0_irq(struct musb *);
 +extern void musb_host_tx(struct musb *, u8);
 +extern void musb_host_rx(struct musb *, u8);
 +
 +#else
 +
 +#define       is_host_capable()       (0)
 +
 +static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; }
 +static inline void musb_host_tx(struct musb *m, u8 e) {}
 +static inline void musb_host_rx(struct musb *m, u8 e) {}
 +
 +#endif
 +
 +
 +/****************************** CONSTANTS ********************************/
 +
 +#ifndef MUSB_C_NUM_EPS
 +#define MUSB_C_NUM_EPS ((u8)16)
 +#endif
 +
 +#ifndef MUSB_MAX_END0_PACKET
 +#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE)
 +#endif
 +
 +/* host side ep0 states */
 +enum musb_h_ep0_state {
 +      MUSB_EP0_IDLE,
 +      MUSB_EP0_START,                 /* expect ack of setup */
 +      MUSB_EP0_IN,                    /* expect IN DATA */
 +      MUSB_EP0_OUT,                   /* expect ack of OUT DATA */
 +      MUSB_EP0_STATUS,                /* expect ack of STATUS */
 +} __attribute__ ((packed));
 +
 +/* peripheral side ep0 states */
 +enum musb_g_ep0_state {
 +      MUSB_EP0_STAGE_SETUP,           /* idle, waiting for setup */
 +      MUSB_EP0_STAGE_TX,              /* IN data */
 +      MUSB_EP0_STAGE_RX,              /* OUT data */
 +      MUSB_EP0_STAGE_STATUSIN,        /* (after OUT data) */
 +      MUSB_EP0_STAGE_STATUSOUT,       /* (after IN data) */
 +      MUSB_EP0_STAGE_ACKWAIT,         /* after zlp, before statusin */
 +} __attribute__ ((packed));
 +
 +/* OTG protocol constants */
 +#define OTG_TIME_A_WAIT_VRISE 100             /* msec (max) */
 +#define OTG_TIME_A_WAIT_BCON  0               /* 0=infinite; min 1000 msec */
 +#define OTG_TIME_A_IDLE_BDIS  200             /* msec (min) */
 +
 +/*************************** REGISTER ACCESS ********************************/
 +
 +/* Endpoint registers (other than dynfifo setup) can be accessed either
 + * directly with the "flat" model, or after setting up an index register.
 + */
 +
 +#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \
 +              || defined(CONFIG_ARCH_OMAP3430)
 +/* REVISIT indexed access seemed to
 + * misbehave (on DaVinci) for at least peripheral IN ...
 + */
 +#define       MUSB_FLAT_REG
 +#endif
 +
 +/* TUSB mapping: "flat" plus ep0 special cases */
 +#if   defined(CONFIG_USB_TUSB6010)
 +#define musb_ep_select(_mbase, _epnum) \
 +      musb_writeb((_mbase), MUSB_INDEX, (_epnum))
 +#define       MUSB_EP_OFFSET                  MUSB_TUSB_OFFSET
 +
 +/* "flat" mapping: each endpoint has its own i/o address */
 +#elif defined(MUSB_FLAT_REG)
 +#define musb_ep_select(_mbase, _epnum)        (((void)(_mbase)), ((void)(_epnum)))
 +#define       MUSB_EP_OFFSET                  MUSB_FLAT_OFFSET
 +
 +/* "indexed" mapping: INDEX register controls register bank select */
 +#else
 +#define musb_ep_select(_mbase, _epnum) \
 +      musb_writeb((_mbase), MUSB_INDEX, (_epnum))
 +#define       MUSB_EP_OFFSET                  MUSB_INDEXED_OFFSET
 +#endif
 +
 +/****************************** FUNCTIONS ********************************/
 +
 +#define MUSB_HST_MODE(_musb)\
 +      { (_musb)->is_host = true; }
 +#define MUSB_DEV_MODE(_musb) \
 +      { (_musb)->is_host = false; }
 +
 +#define test_devctl_hst_mode(_x) \
 +      (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM)
 +
 +#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral")
 +
 +/******************************** TYPES *************************************/
 +
 +/*
 + * struct musb_hw_ep - endpoint hardware (bidirectional)
 + *
 + * Ordered slightly for better cacheline locality.
 + */
 +struct musb_hw_ep {
 +      struct musb             *musb;
 +      void __iomem            *fifo;
 +      void __iomem            *regs;
 +
 +#ifdef CONFIG_USB_TUSB6010
 +      void __iomem            *conf;
 +#endif
 +
 +      /* index in musb->endpoints[]  */
 +      u8                      epnum;
 +
 +      /* hardware configuration, possibly dynamic */
 +      bool                    is_shared_fifo;
 +      bool                    tx_double_buffered;
 +      bool                    rx_double_buffered;
 +      u16                     max_packet_sz_tx;
 +      u16                     max_packet_sz_rx;
 +
 +      struct dma_channel      *tx_channel;
 +      struct dma_channel      *rx_channel;
 +
 +#ifdef CONFIG_USB_TUSB6010
 +      /* TUSB has "asynchronous" and "synchronous" dma modes */
 +      dma_addr_t              fifo_async;
 +      dma_addr_t              fifo_sync;
 +      void __iomem            *fifo_sync_va;
 +#endif
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      void __iomem            *target_regs;
 +
 +      /* currently scheduled peripheral endpoint */
 +      struct musb_qh          *in_qh;
 +      struct musb_qh          *out_qh;
 +
 +      u8                      rx_reinit;
 +      u8                      tx_reinit;
 +#endif
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      /* peripheral side */
 +      struct musb_ep          ep_in;                  /* TX */
 +      struct musb_ep          ep_out;                 /* RX */
 +#endif
 +};
 +
 +static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
 +{
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      return next_request(&hw_ep->ep_in);
 +#else
 +      return NULL;
 +#endif
 +}
 +
 +static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep)
 +{
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      return next_request(&hw_ep->ep_out);
 +#else
 +      return NULL;
 +#endif
 +}
 +
 +/*
 + * struct musb - Driver instance data.
 + */
 +struct musb {
 +      spinlock_t              lock;
 +      struct clk              *clock;
 +      irqreturn_t             (*isr)(int, void *);
 +      struct work_struct      irq_work;
 +
 +/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
 +#define MUSB_PORT_STAT_RESUME (1 << 31)
 +
 +      u32                     port1_status;
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      unsigned long           rh_timer;
 +
 +      enum musb_h_ep0_state   ep0_stage;
 +
 +      /* bulk traffic normally dedicates endpoint hardware, and each
 +       * direction has its own ring of host side endpoints.
 +       * we try to progress the transfer at the head of each endpoint's
 +       * queue until it completes or NAKs too much; then we try the next
 +       * endpoint.
 +       */
 +      struct musb_hw_ep       *bulk_ep;
 +
 +      struct list_head        control;        /* of musb_qh */
 +      struct list_head        in_bulk;        /* of musb_qh */
 +      struct list_head        out_bulk;       /* of musb_qh */
 +      struct musb_qh          *periodic[32];  /* tree of interrupt+iso */
 +#endif
 +
 +      /* called with IRQs blocked; ON/nonzero implies starting a session,
 +       * and waiting at least a_wait_vrise_tmout.
 +       */
 +      void                    (*board_set_vbus)(struct musb *, int is_on);
 +
 +      struct dma_controller   *dma_controller;
 +
 +      struct device           *controller;
 +      void __iomem            *ctrl_base;
 +      void __iomem            *mregs;
 +
 +#ifdef CONFIG_USB_TUSB6010
 +      dma_addr_t              async;
 +      dma_addr_t              sync;
 +      void __iomem            *sync_va;
 +#endif
 +
 +      /* passed down from chip/board specific irq handlers */
 +      u8                      int_usb;
 +      u16                     int_rx;
 +      u16                     int_tx;
 +
 +      struct otg_transceiver  xceiv;
 +
 +      int nIrq;
 +
 +      struct musb_hw_ep        endpoints[MUSB_C_NUM_EPS];
 +#define control_ep            endpoints
 +
 +#define VBUSERR_RETRY_COUNT   3
 +      u16                     vbuserr_retry;
 +      u16 epmask;
 +      u8 nr_endpoints;
 +
 +      u8 board_mode;          /* enum musb_mode */
 +      int                     (*board_set_power)(int state);
 +
 +      int                     (*set_clock)(struct clk *clk, int is_active);
 +
 +      u8                      min_power;      /* vbus for periph, in mA/2 */
 +
 +      bool                    is_host;
 +
 +      int                     a_wait_bcon;    /* VBUS timeout in msecs */
 +      unsigned long           idle_timeout;   /* Next timeout in jiffies */
 +
 +      /* active means connected and not suspended */
 +      unsigned                is_active:1;
 +
 +      unsigned is_multipoint:1;
 +      unsigned ignore_disconnect:1;   /* during bus resets */
 +
 +#ifdef C_MP_TX
 +      unsigned bulk_split:1;
 +#define       can_bulk_split(musb,type) \
 +              (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
 +#else
 +#define       can_bulk_split(musb, type)      0
 +#endif
 +
 +#ifdef C_MP_RX
 +      unsigned bulk_combine:1;
 +#define       can_bulk_combine(musb,type) \
 +              (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
 +#else
 +#define       can_bulk_combine(musb, type)    0
 +#endif
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      /* is_suspended means USB B_PERIPHERAL suspend */
 +      unsigned                is_suspended:1;
 +
 +      /* may_wakeup means remote wakeup is enabled */
 +      unsigned                may_wakeup:1;
 +
 +      /* is_self_powered is reported in device status and the
 +       * config descriptor.  is_bus_powered means B_PERIPHERAL
 +       * draws some VBUS current; both can be true.
 +       */
 +      unsigned                is_self_powered:1;
 +      unsigned                is_bus_powered:1;
 +
 +      unsigned                set_address:1;
 +      unsigned                test_mode:1;
 +      unsigned                softconnect:1;
 +
 +      u8                      address;
 +      u8                      test_mode_nr;
 +      u16                     ackpend;                /* ep0 */
 +      enum musb_g_ep0_state   ep0_state;
 +      struct usb_gadget       g;                      /* the gadget */
 +      struct usb_gadget_driver *gadget_driver;        /* its driver */
 +#endif
 +
 +#ifdef MUSB_CONFIG_PROC_FS
 +      struct proc_dir_entry *proc_entry;
 +#endif
 +};
 +
 +static inline void musb_set_vbus(struct musb *musb, int is_on)
 +{
 +      musb->board_set_vbus(musb, is_on);
 +}
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +static inline struct musb *gadget_to_musb(struct usb_gadget *g)
 +{
 +      return container_of(g, struct musb, g);
 +}
 +#endif
 +
 +
 +/***************************** Glue it together *****************************/
 +
 +extern const char musb_driver_name[];
 +
 +extern void musb_start(struct musb *musb);
 +extern void musb_stop(struct musb *musb);
 +
 +extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 +extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
 +
 +extern void musb_load_testpacket(struct musb *);
 +
 +extern irqreturn_t musb_interrupt(struct musb *);
 +
 +extern void musb_platform_enable(struct musb *musb);
 +extern void musb_platform_disable(struct musb *musb);
 +
 +extern void musb_hnp_stop(struct musb *musb);
 +
 +extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
 +
 +#if defined(CONFIG_USB_TUSB6010) || \
 +      defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
 +extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
 +#else
 +#define musb_platform_try_idle(x, y)          do {} while (0)
 +#endif
 +
 +#ifdef CONFIG_USB_TUSB6010
 +extern int musb_platform_get_vbus_status(struct musb *musb);
 +#else
 +#define musb_platform_get_vbus_status(x)      0
 +#endif
 +
 +extern int __init musb_platform_init(struct musb *musb);
 +extern int musb_platform_exit(struct musb *musb);
 +
 +/*-------------------------- ProcFS definitions ---------------------*/
 +
 +struct proc_dir_entry;
 +
 +#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
 +extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
 +extern void musb_debug_delete(char *name, struct musb *data);
 +
 +#else
 +static inline struct proc_dir_entry *
 +musb_debug_create(char *name, struct musb *data)
 +{
 +      return NULL;
 +}
 +static inline void musb_debug_delete(char *name, struct musb *data)
 +{
 +}
 +#endif
 +
 +#endif        /* __MUSB_CORE_H__ */
index 61849414413f0a77405453b6440c3fc75608a256,0000000000000000000000000000000000000000..22c48d084a2564eaa696ddcad56402e214435d27
mode 100644,000000..100644
--- /dev/null
@@@ -1,830 -1,0 +1,830 @@@
- #include <asm/arch/hardware.h>
 +/*
 + * MUSB OTG driver debug support
 + *
 + * Copyright 2005 Mentor Graphics Corporation
 + * Copyright (C) 2005-2006 by Texas Instruments
 + * Copyright (C) 2006-2007 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/proc_fs.h>
 +#include <linux/seq_file.h>
 +#include <linux/uaccess.h>    /* FIXME remove procfs writes */
++#include <mach/hardware.h>
 +
 +#include "musb_core.h"
 +
 +#include "davinci.h"
 +
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +
 +static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
 +{
 +      int                             count;
 +      int                             tmp;
 +      struct usb_host_endpoint        *hep = qh->hep;
 +      struct urb                      *urb;
 +
 +      count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",
 +                      qh, qh->dev->devnum, qh->epnum,
 +                      ({ char *s; switch (qh->type) {
 +                      case USB_ENDPOINT_XFER_BULK:
 +                              s = "-bulk"; break;
 +                      case USB_ENDPOINT_XFER_INT:
 +                              s = "-int"; break;
 +                      case USB_ENDPOINT_XFER_CONTROL:
 +                              s = ""; break;
 +                      default:
 +                              s = "iso"; break;
 +                      }; s; }),
 +                      qh->maxpacket);
 +      if (count <= 0)
 +              return 0;
 +      buf += count;
 +      max -= count;
 +
 +      list_for_each_entry(urb, &hep->urb_list, urb_list) {
 +              tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
 +                              usb_pipein(urb->pipe) ? "in" : "out",
 +                              urb, urb->actual_length,
 +                              urb->transfer_buffer_length);
 +              if (tmp <= 0)
 +                      break;
 +              tmp = min(tmp, (int)max);
 +              count += tmp;
 +              buf += tmp;
 +              max -= tmp;
 +      }
 +      return count;
 +}
 +
 +static int
 +dump_queue(struct list_head *q, char *buf, unsigned max)
 +{
 +      int             count = 0;
 +      struct musb_qh  *qh;
 +
 +      list_for_each_entry(qh, q, ring) {
 +              int     tmp;
 +
 +              tmp = dump_qh(qh, buf, max);
 +              if (tmp <= 0)
 +                      break;
 +              tmp = min(tmp, (int)max);
 +              count += tmp;
 +              buf += tmp;
 +              max -= tmp;
 +      }
 +      return count;
 +}
 +
 +#endif        /* HCD */
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
 +{
 +      char            *buf = buffer;
 +      int             code = 0;
 +      void __iomem    *regs = ep->hw_ep->regs;
 +      char            *mode = "1buf";
 +
 +      if (ep->is_in) {
 +              if (ep->hw_ep->tx_double_buffered)
 +                      mode = "2buf";
 +      } else {
 +              if (ep->hw_ep->rx_double_buffered)
 +                      mode = "2buf";
 +      }
 +
 +      do {
 +              struct usb_request      *req;
 +
 +              code = snprintf(buf, max,
 +                              "\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
 +                              ep->name, ep->current_epnum,
 +                              mode, ep->dma ? " dma" : "",
 +                              musb_readw(regs,
 +                                      (ep->is_in || !ep->current_epnum)
 +                                              ? MUSB_TXCSR
 +                                              : MUSB_RXCSR),
 +                              musb_readw(regs, ep->is_in
 +                                              ? MUSB_TXMAXP
 +                                              : MUSB_RXMAXP)
 +                              );
 +              if (code <= 0)
 +                      break;
 +              code = min(code, (int) max);
 +              buf += code;
 +              max -= code;
 +
 +              if (is_cppi_enabled() && ep->current_epnum) {
 +                      unsigned        cppi = ep->current_epnum - 1;
 +                      void __iomem    *base = ep->musb->ctrl_base;
 +                      unsigned        off1 = cppi << 2;
 +                      void __iomem    *ram = base;
 +                      char            tmp[16];
 +
 +                      if (ep->is_in) {
 +                              ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
 +                              tmp[0] = 0;
 +                      } else {
 +                              ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
 +                              snprintf(tmp, sizeof tmp, "%d left, ",
 +                                      musb_readl(base,
 +                                      DAVINCI_RXCPPI_BUFCNT0_REG + off1));
 +                      }
 +
 +                      code = snprintf(buf, max, "%cX DMA%d: %s"
 +                                      "%08x %08x, %08x %08x; "
 +                                      "%08x %08x %08x .. %08x\n",
 +                              ep->is_in ? 'T' : 'R',
 +                              ep->current_epnum - 1, tmp,
 +                              musb_readl(ram, 0 * 4),
 +                              musb_readl(ram, 1 * 4),
 +                              musb_readl(ram, 2 * 4),
 +                              musb_readl(ram, 3 * 4),
 +                              musb_readl(ram, 4 * 4),
 +                              musb_readl(ram, 5 * 4),
 +                              musb_readl(ram, 6 * 4),
 +                              musb_readl(ram, 7 * 4));
 +                      if (code <= 0)
 +                              break;
 +                      code = min(code, (int) max);
 +                      buf += code;
 +                      max -= code;
 +              }
 +
 +              if (list_empty(&ep->req_list)) {
 +                      code = snprintf(buf, max, "\t(queue empty)\n");
 +                      if (code <= 0)
 +                              break;
 +                      code = min(code, (int) max);
 +                      buf += code;
 +                      max -= code;
 +                      break;
 +              }
 +              list_for_each_entry(req, &ep->req_list, list) {
 +                      code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
 +                                      req,
 +                                      req->zero ? "zero, " : "",
 +                                      req->short_not_ok ? "!short, " : "",
 +                                      req->actual, req->length);
 +                      if (code <= 0)
 +                              break;
 +                      code = min(code, (int) max);
 +                      buf += code;
 +                      max -= code;
 +              }
 +      } while (0);
 +      return buf - buffer;
 +}
 +#endif
 +
 +static int
 +dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
 +{
 +      int                     code = 0;
 +      char                    *buf = aBuffer;
 +      struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
 +
 +      do {
 +              musb_ep_select(musb->mregs, epnum);
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +              if (is_host_active(musb)) {
 +                      int             dump_rx, dump_tx;
 +                      void __iomem    *regs = hw_ep->regs;
 +
 +                      /* TEMPORARY (!) until we have a real periodic
 +                       * schedule tree ...
 +                       */
 +                      if (!epnum) {
 +                              /* control is shared, uses RX queue
 +                               * but (mostly) shadowed tx registers
 +                               */
 +                              dump_tx = !list_empty(&musb->control);
 +                              dump_rx = 0;
 +                      } else if (hw_ep == musb->bulk_ep) {
 +                              dump_tx = !list_empty(&musb->out_bulk);
 +                              dump_rx = !list_empty(&musb->in_bulk);
 +                      } else if (musb->periodic[epnum]) {
 +                              struct usb_host_endpoint        *hep;
 +
 +                              hep = musb->periodic[epnum]->hep;
 +                              dump_rx = hep->desc.bEndpointAddress
 +                                              & USB_ENDPOINT_DIR_MASK;
 +                              dump_tx = !dump_rx;
 +                      } else
 +                              break;
 +                      /* END TEMPORARY */
 +
 +
 +                      if (dump_rx) {
 +                              code = snprintf(buf, max,
 +                                      "\nRX%d: %s rxcsr %04x interval %02x "
 +                                      "max %04x type %02x; "
 +                                      "dev %d hub %d port %d"
 +                                      "\n",
 +                                      epnum,
 +                                      hw_ep->rx_double_buffered
 +                                              ? "2buf" : "1buf",
 +                                      musb_readw(regs, MUSB_RXCSR),
 +                                      musb_readb(regs, MUSB_RXINTERVAL),
 +                                      musb_readw(regs, MUSB_RXMAXP),
 +                                      musb_readb(regs, MUSB_RXTYPE),
 +                                      /* FIXME:  assumes multipoint */
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_RXFUNCADDR)),
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_RXHUBADDR)),
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_RXHUBPORT))
 +                                      );
 +                              if (code <= 0)
 +                                      break;
 +                              code = min(code, (int) max);
 +                              buf += code;
 +                              max -= code;
 +
 +                              if (is_cppi_enabled()
 +                                              && epnum
 +                                              && hw_ep->rx_channel) {
 +                                      unsigned        cppi = epnum - 1;
 +                                      unsigned        off1 = cppi << 2;
 +                                      void __iomem    *base;
 +                                      void __iomem    *ram;
 +                                      char            tmp[16];
 +
 +                                      base = musb->ctrl_base;
 +                                      ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
 +                                                      cppi) + base;
 +                                      snprintf(tmp, sizeof tmp, "%d left, ",
 +                                              musb_readl(base,
 +                                              DAVINCI_RXCPPI_BUFCNT0_REG
 +                                                              + off1));
 +
 +                                      code = snprintf(buf, max,
 +                                              "    rx dma%d: %s"
 +                                              "%08x %08x, %08x %08x; "
 +                                              "%08x %08x %08x .. %08x\n",
 +                                              cppi, tmp,
 +                                              musb_readl(ram, 0 * 4),
 +                                              musb_readl(ram, 1 * 4),
 +                                              musb_readl(ram, 2 * 4),
 +                                              musb_readl(ram, 3 * 4),
 +                                              musb_readl(ram, 4 * 4),
 +                                              musb_readl(ram, 5 * 4),
 +                                              musb_readl(ram, 6 * 4),
 +                                              musb_readl(ram, 7 * 4));
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              }
 +
 +                              if (hw_ep == musb->bulk_ep
 +                                              && !list_empty(
 +                                                      &musb->in_bulk)) {
 +                                      code = dump_queue(&musb->in_bulk,
 +                                                      buf, max);
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              } else if (musb->periodic[epnum]) {
 +                                      code = dump_qh(musb->periodic[epnum],
 +                                                      buf, max);
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              }
 +                      }
 +
 +                      if (dump_tx) {
 +                              code = snprintf(buf, max,
 +                                      "\nTX%d: %s txcsr %04x interval %02x "
 +                                      "max %04x type %02x; "
 +                                      "dev %d hub %d port %d"
 +                                      "\n",
 +                                      epnum,
 +                                      hw_ep->tx_double_buffered
 +                                              ? "2buf" : "1buf",
 +                                      musb_readw(regs, MUSB_TXCSR),
 +                                      musb_readb(regs, MUSB_TXINTERVAL),
 +                                      musb_readw(regs, MUSB_TXMAXP),
 +                                      musb_readb(regs, MUSB_TXTYPE),
 +                                      /* FIXME:  assumes multipoint */
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_TXFUNCADDR)),
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_TXHUBADDR)),
 +                                      musb_readb(musb->mregs,
 +                                              MUSB_BUSCTL_OFFSET(epnum,
 +                                              MUSB_TXHUBPORT))
 +                                      );
 +                              if (code <= 0)
 +                                      break;
 +                              code = min(code, (int) max);
 +                              buf += code;
 +                              max -= code;
 +
 +                              if (is_cppi_enabled()
 +                                              && epnum
 +                                              && hw_ep->tx_channel) {
 +                                      unsigned        cppi = epnum - 1;
 +                                      void __iomem    *base;
 +                                      void __iomem    *ram;
 +
 +                                      base = musb->ctrl_base;
 +                                      ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
 +                                                      cppi) + base;
 +                                      code = snprintf(buf, max,
 +                                              "    tx dma%d: "
 +                                              "%08x %08x, %08x %08x; "
 +                                              "%08x %08x %08x .. %08x\n",
 +                                              cppi,
 +                                              musb_readl(ram, 0 * 4),
 +                                              musb_readl(ram, 1 * 4),
 +                                              musb_readl(ram, 2 * 4),
 +                                              musb_readl(ram, 3 * 4),
 +                                              musb_readl(ram, 4 * 4),
 +                                              musb_readl(ram, 5 * 4),
 +                                              musb_readl(ram, 6 * 4),
 +                                              musb_readl(ram, 7 * 4));
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              }
 +
 +                              if (hw_ep == musb->control_ep
 +                                              && !list_empty(
 +                                                      &musb->control)) {
 +                                      code = dump_queue(&musb->control,
 +                                                      buf, max);
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              } else if (hw_ep == musb->bulk_ep
 +                                              && !list_empty(
 +                                                      &musb->out_bulk)) {
 +                                      code = dump_queue(&musb->out_bulk,
 +                                                      buf, max);
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              } else if (musb->periodic[epnum]) {
 +                                      code = dump_qh(musb->periodic[epnum],
 +                                                      buf, max);
 +                                      if (code <= 0)
 +                                              break;
 +                                      code = min(code, (int) max);
 +                                      buf += code;
 +                                      max -= code;
 +                              }
 +                      }
 +              }
 +#endif
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +              if (is_peripheral_active(musb)) {
 +                      code = 0;
 +
 +                      if (hw_ep->ep_in.desc || !epnum) {
 +                              code = dump_ep(&hw_ep->ep_in, buf, max);
 +                              if (code <= 0)
 +                                      break;
 +                              code = min(code, (int) max);
 +                              buf += code;
 +                              max -= code;
 +                      }
 +                      if (hw_ep->ep_out.desc) {
 +                              code = dump_ep(&hw_ep->ep_out, buf, max);
 +                              if (code <= 0)
 +                                      break;
 +                              code = min(code, (int) max);
 +                              buf += code;
 +                              max -= code;
 +                      }
 +              }
 +#endif
 +      } while (0);
 +
 +      return buf - aBuffer;
 +}
 +
 +/* Dump the current status and compile options.
 + * @param musb the device driver instance
 + * @param buffer where to dump the status; it must be big enough to hold the
 + * result otherwise "BAD THINGS HAPPENS(TM)".
 + */
 +static int dump_header_stats(struct musb *musb, char *buffer)
 +{
 +      int code, count = 0;
 +      const void __iomem *mbase = musb->mregs;
 +
 +      *buffer = 0;
 +      count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
 +                              "(Power=%02x, DevCtl=%02x)\n",
 +                      (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
 +                      musb_readb(mbase, MUSB_POWER),
 +                      musb_readb(mbase, MUSB_DEVCTL));
 +      if (count <= 0)
 +              return 0;
 +      buffer += count;
 +
 +      code = sprintf(buffer, "OTG state: %s; %sactive\n",
 +                      otg_state_string(musb),
 +                      musb->is_active ? "" : "in");
 +      if (code <= 0)
 +              goto done;
 +      buffer += code;
 +      count += code;
 +
 +      code = sprintf(buffer,
 +                      "Options: "
 +#ifdef CONFIG_MUSB_PIO_ONLY
 +                      "pio"
 +#elif defined(CONFIG_USB_TI_CPPI_DMA)
 +                      "cppi-dma"
 +#elif defined(CONFIG_USB_INVENTRA_DMA)
 +                      "musb-dma"
 +#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
 +                      "tusb-omap-dma"
 +#else
 +                      "?dma?"
 +#endif
 +                      ", "
 +#ifdef CONFIG_USB_MUSB_OTG
 +                      "otg (peripheral+host)"
 +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
 +                      "peripheral"
 +#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
 +                      "host"
 +#endif
 +                      ", debug=%d [eps=%d]\n",
 +              debug,
 +              musb->nr_endpoints);
 +      if (code <= 0)
 +              goto done;
 +      count += code;
 +      buffer += code;
 +
 +#ifdef        CONFIG_USB_GADGET_MUSB_HDRC
 +      code = sprintf(buffer, "Peripheral address: %02x\n",
 +                      musb_readb(musb->ctrl_base, MUSB_FADDR));
 +      if (code <= 0)
 +              goto done;
 +      buffer += code;
 +      count += code;
 +#endif
 +
 +#ifdef        CONFIG_USB_MUSB_HDRC_HCD
 +      code = sprintf(buffer, "Root port status: %08x\n",
 +                      musb->port1_status);
 +      if (code <= 0)
 +              goto done;
 +      buffer += code;
 +      count += code;
 +#endif
 +
 +#ifdef        CONFIG_ARCH_DAVINCI
 +      code = sprintf(buffer,
 +                      "DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
 +                      "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
 +                      "\n",
 +                      musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
 +                      musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
 +                      __raw_readl((void __force __iomem *)
 +                                      IO_ADDRESS(USBPHY_CTL_PADDR)),
 +                      musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
 +                      musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
 +                      musb_readl(musb->ctrl_base,
 +                                      DAVINCI_USB_INT_SOURCE_REG),
 +                      musb_readl(musb->ctrl_base,
 +                                      DAVINCI_USB_INT_MASK_REG));
 +      if (code <= 0)
 +              goto done;
 +      count += code;
 +      buffer += code;
 +#endif        /* DAVINCI */
 +
 +#ifdef CONFIG_USB_TUSB6010
 +      code = sprintf(buffer,
 +                      "TUSB6010: devconf %08x, phy enable %08x drive %08x"
 +                      "\n\totg %03x timer %08x"
 +                      "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
 +                      "\n",
 +                      musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
 +                      musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
 +                      musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
 +                      musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
 +                      musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
 +                      musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
 +                      musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
 +                      musb_readl(musb->ctrl_base, TUSB_INT_SRC),
 +                      musb_readl(musb->ctrl_base, TUSB_INT_MASK));
 +      if (code <= 0)
 +              goto done;
 +      count += code;
 +      buffer += code;
 +#endif        /* DAVINCI */
 +
 +      if (is_cppi_enabled() && musb->dma_controller) {
 +              code = sprintf(buffer,
 +                              "CPPI: txcr=%d txsrc=%01x txena=%01x; "
 +                              "rxcr=%d rxsrc=%01x rxena=%01x "
 +                              "\n",
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_TXCPPI_CTRL_REG),
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_TXCPPI_RAW_REG),
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_TXCPPI_INTENAB_REG),
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_RXCPPI_CTRL_REG),
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_RXCPPI_RAW_REG),
 +                              musb_readl(musb->ctrl_base,
 +                                              DAVINCI_RXCPPI_INTENAB_REG));
 +              if (code <= 0)
 +                      goto done;
 +              count += code;
 +              buffer += code;
 +      }
 +
 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 +      if (is_peripheral_enabled(musb)) {
 +              code = sprintf(buffer, "Gadget driver: %s\n",
 +                              musb->gadget_driver
 +                                      ? musb->gadget_driver->driver.name
 +                                      : "(none)");
 +              if (code <= 0)
 +                      goto done;
 +              count += code;
 +              buffer += code;
 +      }
 +#endif
 +
 +done:
 +      return count;
 +}
 +
 +/* Write to ProcFS
 + *
 + * C soft-connect
 + * c soft-disconnect
 + * I enable HS
 + * i disable HS
 + * s stop session
 + * F force session (OTG-unfriendly)
 + * E rElinquish bus (OTG)
 + * H request host mode
 + * h cancel host request
 + * T start sending TEST_PACKET
 + * D<num> set/query the debug level
 + */
 +static int musb_proc_write(struct file *file, const char __user *buffer,
 +                      unsigned long count, void *data)
 +{
 +      char cmd;
 +      u8 reg;
 +      struct musb *musb = (struct musb *)data;
 +      void __iomem *mbase = musb->mregs;
 +
 +      /* MOD_INC_USE_COUNT; */
 +
 +      if (unlikely(copy_from_user(&cmd, buffer, 1)))
 +              return -EFAULT;
 +
 +      switch (cmd) {
 +      case 'C':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_POWER)
 +                                      | MUSB_POWER_SOFTCONN;
 +                      musb_writeb(mbase, MUSB_POWER, reg);
 +              }
 +              break;
 +
 +      case 'c':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_POWER)
 +                                      & ~MUSB_POWER_SOFTCONN;
 +                      musb_writeb(mbase, MUSB_POWER, reg);
 +              }
 +              break;
 +
 +      case 'I':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_POWER)
 +                                      | MUSB_POWER_HSENAB;
 +                      musb_writeb(mbase, MUSB_POWER, reg);
 +              }
 +              break;
 +
 +      case 'i':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_POWER)
 +                                      & ~MUSB_POWER_HSENAB;
 +                      musb_writeb(mbase, MUSB_POWER, reg);
 +              }
 +              break;
 +
 +      case 'F':
 +              reg = musb_readb(mbase, MUSB_DEVCTL);
 +              reg |= MUSB_DEVCTL_SESSION;
 +              musb_writeb(mbase, MUSB_DEVCTL, reg);
 +              break;
 +
 +      case 'H':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_DEVCTL);
 +                      reg |= MUSB_DEVCTL_HR;
 +                      musb_writeb(mbase, MUSB_DEVCTL, reg);
 +                      /* MUSB_HST_MODE( ((struct musb*)data) ); */
 +                      /* WARNING("Host Mode\n"); */
 +              }
 +              break;
 +
 +      case 'h':
 +              if (mbase) {
 +                      reg = musb_readb(mbase, MUSB_DEVCTL);
 +                      reg &= ~MUSB_DEVCTL_HR;
 +                      musb_writeb(mbase, MUSB_DEVCTL, reg);
 +              }
 +              break;
 +
 +      case 'T':
 +              if (mbase) {
 +                      musb_load_testpacket(musb);
 +                      musb_writeb(mbase, MUSB_TESTMODE,
 +                                      MUSB_TEST_PACKET);
 +              }
 +              break;
 +
 +#if (MUSB_DEBUG > 0)
 +              /* set/read debug level */
 +      case 'D':{
 +                      if (count > 1) {
 +                              char digits[8], *p = digits;
 +                              int i = 0, level = 0, sign = 1;
 +                              int len = min(count - 1, (unsigned long)8);
 +
 +                              if (copy_from_user(&digits, &buffer[1], len))
 +                                      return -EFAULT;
 +
 +                              /* optional sign */
 +                              if (*p == '-') {
 +                                      len -= 1;
 +                                      sign = -sign;
 +                                      p++;
 +                              }
 +
 +                              /* read it */
 +                              while (i++ < len && *p > '0' && *p < '9') {
 +                                      level = level * 10 + (*p - '0');
 +                                      p++;
 +                              }
 +
 +                              level *= sign;
 +                              DBG(1, "debug level %d\n", level);
 +                              debug = level;
 +                      }
 +              }
 +              break;
 +
 +
 +      case '?':
 +              INFO("?: you are seeing it\n");
 +              INFO("C/c: soft connect enable/disable\n");
 +              INFO("I/i: hispeed enable/disable\n");
 +              INFO("F: force session start\n");
 +              INFO("H: host mode\n");
 +              INFO("T: start sending TEST_PACKET\n");
 +              INFO("D: set/read dbug level\n");
 +              break;
 +#endif
 +
 +      default:
 +              ERR("Command %c not implemented\n", cmd);
 +              break;
 +      }
 +
 +      musb_platform_try_idle(musb, 0);
 +
 +      return count;
 +}
 +
 +static int musb_proc_read(char *page, char **start,
 +                      off_t off, int count, int *eof, void *data)
 +{
 +      char *buffer = page;
 +      int code = 0;
 +      unsigned long   flags;
 +      struct musb     *musb = data;
 +      unsigned        epnum;
 +
 +      count -= off;
 +      count -= 1;             /* for NUL at end */
 +      if (count <= 0)
 +              return -EINVAL;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      code = dump_header_stats(musb, buffer);
 +      if (code > 0) {
 +              buffer += code;
 +              count -= code;
 +      }
 +
 +      /* generate the report for the end points */
 +      /* REVISIT ... not unless something's connected! */
 +      for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
 +                      epnum++) {
 +              code = dump_end_info(musb, epnum, buffer, count);
 +              if (code > 0) {
 +                      buffer += code;
 +                      count -= code;
 +              }
 +      }
 +
 +      musb_platform_try_idle(musb, 0);
 +
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +      *eof = 1;
 +
 +      return buffer - page;
 +}
 +
 +void __devexit musb_debug_delete(char *name, struct musb *musb)
 +{
 +      if (musb->proc_entry)
 +              remove_proc_entry(name, NULL);
 +}
 +
 +struct proc_dir_entry *__init
 +musb_debug_create(char *name, struct musb *data)
 +{
 +      struct proc_dir_entry   *pde;
 +
 +      /* FIXME convert everything to seq_file; then later, debugfs */
 +
 +      if (!name)
 +              return NULL;
 +
 +      data->proc_entry = pde = create_proc_entry(name,
 +                                      S_IFREG | S_IRUGO | S_IWUSR, NULL);
 +      if (pde) {
 +              pde->data = data;
 +              /* pde->owner = THIS_MODULE; */
 +
 +              pde->read_proc = musb_proc_read;
 +              pde->write_proc = musb_proc_write;
 +
 +              pde->size = 0;
 +
 +              pr_debug("Registered /proc/%s\n", name);
 +      } else {
 +              pr_debug("Cannot create a valid proc file entry");
 +      }
 +
 +      return pde;
 +}
index 472c30403c8f5e44b88ce3c5265255ff2d14811b,0000000000000000000000000000000000000000..ee010eca9a1a04df3bc2b2555569d8c8cf1ede45
mode 100644,000000..100644
--- /dev/null
@@@ -1,326 -1,0 +1,326 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/mux.h>
 +/*
 + * Copyright (C) 2005-2007 by Texas Instruments
 + * Some code has been taken from tusb6010.c
 + * Copyrights for that are attributable to:
 + * Copyright (C) 2006 Nokia Corporation
 + * Jarkko Nikula <jarkko.nikula@nokia.com>
 + * Tony Lindgren <tony@atomide.com>
 + *
 + * This file is part of the Inventra Controller Driver for Linux.
 + *
 + * The Inventra Controller Driver for Linux 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.
 + *
 + * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; 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/kernel.h>
 +#include <linux/sched.h>
 +#include <linux/slab.h>
 +#include <linux/init.h>
 +#include <linux/list.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +
 +#include <asm/mach-types.h>
++#include <mach/hardware.h>
++#include <mach/mux.h>
 +
 +#include "musb_core.h"
 +#include "omap2430.h"
 +
 +#ifdef CONFIG_ARCH_OMAP3430
 +#define       get_cpu_rev()   2
 +#endif
 +
 +#define MUSB_TIMEOUT_A_WAIT_BCON      1100
 +
 +static struct timer_list musb_idle_timer;
 +
 +static void musb_do_idle(unsigned long _musb)
 +{
 +      struct musb     *musb = (void *)_musb;
 +      unsigned long   flags;
 +      u8      power;
 +      u8      devctl;
 +
 +      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      switch (musb->xceiv.state) {
 +      case OTG_STATE_A_WAIT_BCON:
 +              devctl &= ~MUSB_DEVCTL_SESSION;
 +              musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 +
 +              devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +              if (devctl & MUSB_DEVCTL_BDEVICE) {
 +                      musb->xceiv.state = OTG_STATE_B_IDLE;
 +                      MUSB_DEV_MODE(musb);
 +              } else {
 +                      musb->xceiv.state = OTG_STATE_A_IDLE;
 +                      MUSB_HST_MODE(musb);
 +              }
 +              break;
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      case OTG_STATE_A_SUSPEND:
 +              /* finish RESUME signaling? */
 +              if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
 +                      power = musb_readb(musb->mregs, MUSB_POWER);
 +                      power &= ~MUSB_POWER_RESUME;
 +                      DBG(1, "root port resume stopped, power %02x\n", power);
 +                      musb_writeb(musb->mregs, MUSB_POWER, power);
 +                      musb->is_active = 1;
 +                      musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
 +                                              | MUSB_PORT_STAT_RESUME);
 +                      musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
 +                      usb_hcd_poll_rh_status(musb_to_hcd(musb));
 +                      /* NOTE: it might really be A_WAIT_BCON ... */
 +                      musb->xceiv.state = OTG_STATE_A_HOST;
 +              }
 +              break;
 +#endif
 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
 +      case OTG_STATE_A_HOST:
 +              devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +              if (devctl &  MUSB_DEVCTL_BDEVICE)
 +                      musb->xceiv.state = OTG_STATE_B_IDLE;
 +              else
 +                      musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
 +#endif
 +      default:
 +              break;
 +      }
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +}
 +
 +
 +void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
 +{
 +      unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
 +      static unsigned long    last_timer;
 +
 +      if (timeout == 0)
 +              timeout = default_timeout;
 +
 +      /* Never idle if active, or when VBUS timeout is not set as host */
 +      if (musb->is_active || ((musb->a_wait_bcon == 0)
 +                      && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) {
 +              DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
 +              del_timer(&musb_idle_timer);
 +              last_timer = jiffies;
 +              return;
 +      }
 +
 +      if (time_after(last_timer, timeout)) {
 +              if (!timer_pending(&musb_idle_timer))
 +                      last_timer = timeout;
 +              else {
 +                      DBG(4, "Longer idle timer already pending, ignoring\n");
 +                      return;
 +              }
 +      }
 +      last_timer = timeout;
 +
 +      DBG(4, "%s inactive, for idle timer for %lu ms\n",
 +              otg_state_string(musb),
 +              (unsigned long)jiffies_to_msecs(timeout - jiffies));
 +      mod_timer(&musb_idle_timer, timeout);
 +}
 +
 +void musb_platform_enable(struct musb *musb)
 +{
 +}
 +void musb_platform_disable(struct musb *musb)
 +{
 +}
 +static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
 +{
 +}
 +
 +static void omap_set_vbus(struct musb *musb, int is_on)
 +{
 +      u8              devctl;
 +      /* HDRC controls CPEN, but beware current surges during device
 +       * connect.  They can trigger transient overcurrent conditions
 +       * that must be ignored.
 +       */
 +
 +      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +
 +      if (is_on) {
 +              musb->is_active = 1;
 +              musb->xceiv.default_a = 1;
 +              musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
 +              devctl |= MUSB_DEVCTL_SESSION;
 +
 +              MUSB_HST_MODE(musb);
 +      } else {
 +              musb->is_active = 0;
 +
 +              /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
 +               * jumping right to B_IDLE...
 +               */
 +
 +              musb->xceiv.default_a = 0;
 +              musb->xceiv.state = OTG_STATE_B_IDLE;
 +              devctl &= ~MUSB_DEVCTL_SESSION;
 +
 +              MUSB_DEV_MODE(musb);
 +      }
 +      musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 +
 +      DBG(1, "VBUS %s, devctl %02x "
 +              /* otg %3x conf %08x prcm %08x */ "\n",
 +              otg_state_string(musb),
 +              musb_readb(musb->mregs, MUSB_DEVCTL));
 +}
 +static int omap_set_power(struct otg_transceiver *x, unsigned mA)
 +{
 +      return 0;
 +}
 +
 +int musb_platform_resume(struct musb *musb);
 +
 +void musb_platform_set_mode(struct musb *musb, u8 musb_mode)
 +{
 +      u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 +
 +      devctl |= MUSB_DEVCTL_SESSION;
 +      musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 +
 +      switch (musb_mode) {
 +      case MUSB_HOST:
 +              otg_set_host(&musb->xceiv, musb->xceiv.host);
 +              break;
 +      case MUSB_PERIPHERAL:
 +              otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget);
 +              break;
 +      case MUSB_OTG:
 +              break;
 +      }
 +}
 +
 +int __init musb_platform_init(struct musb *musb)
 +{
 +      struct otg_transceiver *xceiv = otg_get_transceiver();
 +      u32 l;
 +
 +#if defined(CONFIG_ARCH_OMAP2430)
 +      omap_cfg_reg(AE5_2430_USB0HS_STP);
 +#endif
 +
 +      musb->xceiv = *xceiv;
 +      musb_platform_resume(musb);
 +
 +      l = omap_readl(OTG_SYSCONFIG);
 +      l &= ~ENABLEWAKEUP;     /* disable wakeup */
 +      l &= ~NOSTDBY;          /* remove possible nostdby */
 +      l |= SMARTSTDBY;        /* enable smart standby */
 +      l &= ~AUTOIDLE;         /* disable auto idle */
 +      l &= ~NOIDLE;           /* remove possible noidle */
 +      l |= SMARTIDLE;         /* enable smart idle */
 +      l |= AUTOIDLE;          /* enable auto idle */
 +      omap_writel(l, OTG_SYSCONFIG);
 +
 +      l = omap_readl(OTG_INTERFSEL);
 +      l |= ULPI_12PIN;
 +      omap_writel(l, OTG_INTERFSEL);
 +
 +      pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 +                      "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
 +                      omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG),
 +                      omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL),
 +                      omap_readl(OTG_SIMENABLE));
 +
 +      omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
 +
 +      if (is_host_enabled(musb))
 +              musb->board_set_vbus = omap_set_vbus;
 +      if (is_peripheral_enabled(musb))
 +              musb->xceiv.set_power = omap_set_power;
 +      musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
 +
 +      setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 +
 +      return 0;
 +}
 +
 +int musb_platform_suspend(struct musb *musb)
 +{
 +      u32 l;
 +
 +      if (!musb->clock)
 +              return 0;
 +
 +      /* in any role */
 +      l = omap_readl(OTG_FORCESTDBY);
 +      l |= ENABLEFORCE;       /* enable MSTANDBY */
 +      omap_writel(l, OTG_FORCESTDBY);
 +
 +      l = omap_readl(OTG_SYSCONFIG);
 +      l |= ENABLEWAKEUP;      /* enable wakeup */
 +      omap_writel(l, OTG_SYSCONFIG);
 +
 +      if (musb->xceiv.set_suspend)
 +              musb->xceiv.set_suspend(&musb->xceiv, 1);
 +
 +      if (musb->set_clock)
 +              musb->set_clock(musb->clock, 0);
 +      else
 +              clk_disable(musb->clock);
 +
 +      return 0;
 +}
 +
 +int musb_platform_resume(struct musb *musb)
 +{
 +      u32 l;
 +
 +      if (!musb->clock)
 +              return 0;
 +
 +      if (musb->xceiv.set_suspend)
 +              musb->xceiv.set_suspend(&musb->xceiv, 0);
 +
 +      if (musb->set_clock)
 +              musb->set_clock(musb->clock, 1);
 +      else
 +              clk_enable(musb->clock);
 +
 +      l = omap_readl(OTG_SYSCONFIG);
 +      l &= ~ENABLEWAKEUP;     /* disable wakeup */
 +      omap_writel(l, OTG_SYSCONFIG);
 +
 +      l = omap_readl(OTG_FORCESTDBY);
 +      l &= ~ENABLEFORCE;      /* disable MSTANDBY */
 +      omap_writel(l, OTG_FORCESTDBY);
 +
 +      return 0;
 +}
 +
 +
 +int musb_platform_exit(struct musb *musb)
 +{
 +
 +      omap_vbus_power(musb, 0 /*off*/, 1);
 +
 +      musb_platform_suspend(musb);
 +
 +      clk_put(musb->clock);
 +      musb->clock = 0;
 +
 +      return 0;
 +}
index 786a62071f7236382be179f2cf3116d10f2e5135,0000000000000000000000000000000000000000..dc7670718cd2ba4bfd8aa4f080b54a2de0fe3a86
mode 100644,000000..100644
--- /dev/null
@@@ -1,56 -1,0 +1,56 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/usb.h>
 +/*
 + * Copyright (C) 2005-2006 by Texas Instruments
 + *
 + * The Inventra Controller Driver for Linux 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 __MUSB_OMAP243X_H__
 +#define __MUSB_OMAP243X_H__
 +
 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
++#include <mach/hardware.h>
++#include <mach/usb.h>
 +
 +/*
 + * OMAP2430-specific definitions
 + */
 +
 +#define MENTOR_BASE_OFFSET    0
 +#if   defined(CONFIG_ARCH_OMAP2430)
 +#define       OMAP_HSOTG_BASE         (OMAP243X_HS_BASE)
 +#elif defined(CONFIG_ARCH_OMAP3430)
 +#define       OMAP_HSOTG_BASE         (OMAP34XX_HSUSB_OTG_BASE)
 +#endif
 +#define OMAP_HSOTG(offset)    (OMAP_HSOTG_BASE + 0x400 + (offset))
 +#define OTG_REVISION          OMAP_HSOTG(0x0)
 +#define OTG_SYSCONFIG         OMAP_HSOTG(0x4)
 +#     define  MIDLEMODE       12      /* bit position */
 +#     define  FORCESTDBY              (0 << MIDLEMODE)
 +#     define  NOSTDBY                 (1 << MIDLEMODE)
 +#     define  SMARTSTDBY              (2 << MIDLEMODE)
 +#     define  SIDLEMODE               3       /* bit position */
 +#     define  FORCEIDLE               (0 << SIDLEMODE)
 +#     define  NOIDLE                  (1 << SIDLEMODE)
 +#     define  SMARTIDLE               (2 << SIDLEMODE)
 +#     define  ENABLEWAKEUP            (1 << 2)
 +#     define  SOFTRST                 (1 << 1)
 +#     define  AUTOIDLE                (1 << 0)
 +#define OTG_SYSSTATUS         OMAP_HSOTG(0x8)
 +#     define  RESETDONE               (1 << 0)
 +#define OTG_INTERFSEL         OMAP_HSOTG(0xc)
 +#     define  EXTCP                   (1 << 2)
 +#     define  PHYSEL          0       /* bit position */
 +#     define  UTMI_8BIT               (0 << PHYSEL)
 +#     define  ULPI_12PIN              (1 << PHYSEL)
 +#     define  ULPI_8PIN               (2 << PHYSEL)
 +#define OTG_SIMENABLE         OMAP_HSOTG(0x10)
 +#     define  TM1                     (1 << 0)
 +#define OTG_FORCESTDBY                OMAP_HSOTG(0x14)
 +#     define  ENABLEFORCE             (1 << 0)
 +
 +#endif        /* CONFIG_ARCH_OMAP2430 */
 +
 +#endif        /* __MUSB_OMAP243X_H__ */
index f7a3ffe9befab760c21a1ea9315e2f6755793dd1,0000000000000000000000000000000000000000..1020d464ece30cb1243a404d2502a4100df6b78f
mode 100644,000000..100644
--- /dev/null
@@@ -1,719 -1,0 +1,719 @@@
- #include <asm/arch/dma.h>
- #include <asm/arch/mux.h>
 +/*
 + * TUSB6010 USB 2.0 OTG Dual Role controller OMAP DMA interface
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Tony Lindgren <tony@atomide.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/init.h>
 +#include <linux/usb.h>
 +#include <linux/platform_device.h>
 +#include <linux/dma-mapping.h>
++#include <mach/dma.h>
++#include <mach/mux.h>
 +
 +#include "musb_core.h"
 +
 +#define to_chdat(c)           (struct tusb_omap_dma_ch *)(c)->private_data
 +
 +#define MAX_DMAREQ            5       /* REVISIT: Really 6, but req5 not OK */
 +
 +struct tusb_omap_dma_ch {
 +      struct musb             *musb;
 +      void __iomem            *tbase;
 +      unsigned long           phys_offset;
 +      int                     epnum;
 +      u8                      tx;
 +      struct musb_hw_ep       *hw_ep;
 +
 +      int                     ch;
 +      s8                      dmareq;
 +      s8                      sync_dev;
 +
 +      struct tusb_omap_dma    *tusb_dma;
 +
 +      void __iomem            *dma_addr;
 +
 +      u32                     len;
 +      u16                     packet_sz;
 +      u16                     transfer_packet_sz;
 +      u32                     transfer_len;
 +      u32                     completed_len;
 +};
 +
 +struct tusb_omap_dma {
 +      struct dma_controller           controller;
 +      struct musb                     *musb;
 +      void __iomem                    *tbase;
 +
 +      int                             ch;
 +      s8                              dmareq;
 +      s8                              sync_dev;
 +      unsigned                        multichannel:1;
 +};
 +
 +static int tusb_omap_dma_start(struct dma_controller *c)
 +{
 +      struct tusb_omap_dma    *tusb_dma;
 +
 +      tusb_dma = container_of(c, struct tusb_omap_dma, controller);
 +
 +      /* DBG(3, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
 +
 +      return 0;
 +}
 +
 +static int tusb_omap_dma_stop(struct dma_controller *c)
 +{
 +      struct tusb_omap_dma    *tusb_dma;
 +
 +      tusb_dma = container_of(c, struct tusb_omap_dma, controller);
 +
 +      /* DBG(3, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
 +
 +      return 0;
 +}
 +
 +/*
 + * Allocate dmareq0 to the current channel unless it's already taken
 + */
 +static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
 +{
 +      u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
 +
 +      if (reg != 0) {
 +              DBG(3, "ep%i dmareq0 is busy for ep%i\n",
 +                      chdat->epnum, reg & 0xf);
 +              return -EAGAIN;
 +      }
 +
 +      if (chdat->tx)
 +              reg = (1 << 4) | chdat->epnum;
 +      else
 +              reg = chdat->epnum;
 +
 +      musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
 +
 +      return 0;
 +}
 +
 +static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
 +{
 +      u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
 +
 +      if ((reg & 0xf) != chdat->epnum) {
 +              printk(KERN_ERR "ep%i trying to release dmareq0 for ep%i\n",
 +                      chdat->epnum, reg & 0xf);
 +              return;
 +      }
 +      musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0);
 +}
 +
 +/*
 + * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
 + * musb_gadget.c.
 + */
 +static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      struct dma_channel      *channel = (struct dma_channel *)data;
 +      struct tusb_omap_dma_ch *chdat = to_chdat(channel);
 +      struct tusb_omap_dma    *tusb_dma = chdat->tusb_dma;
 +      struct musb             *musb = chdat->musb;
 +      struct musb_hw_ep       *hw_ep = chdat->hw_ep;
 +      void __iomem            *ep_conf = hw_ep->conf;
 +      void __iomem            *mbase = musb->mregs;
 +      unsigned long           remaining, flags, pio;
 +      int                     ch;
 +
 +      spin_lock_irqsave(&musb->lock, flags);
 +
 +      if (tusb_dma->multichannel)
 +              ch = chdat->ch;
 +      else
 +              ch = tusb_dma->ch;
 +
 +      if (ch_status != OMAP_DMA_BLOCK_IRQ)
 +              printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
 +
 +      DBG(3, "ep%i %s dma callback ch: %i status: %x\n",
 +              chdat->epnum, chdat->tx ? "tx" : "rx",
 +              ch, ch_status);
 +
 +      if (chdat->tx)
 +              remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
 +      else
 +              remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
 +
 +      remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
 +
 +      /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
 +      if (unlikely(remaining > chdat->transfer_len)) {
 +              DBG(2, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
 +                      chdat->tx ? "tx" : "rx", chdat->ch,
 +                      remaining);
 +              remaining = 0;
 +      }
 +
 +      channel->actual_len = chdat->transfer_len - remaining;
 +      pio = chdat->len - channel->actual_len;
 +
 +      DBG(3, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len);
 +
 +      /* Transfer remaining 1 - 31 bytes */
 +      if (pio > 0 && pio < 32) {
 +              u8      *buf;
 +
 +              DBG(3, "Using PIO for remaining %lu bytes\n", pio);
 +              buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;
 +              if (chdat->tx) {
 +                      dma_cache_maint(phys_to_virt((u32)chdat->dma_addr),
 +                                      chdat->transfer_len, DMA_TO_DEVICE);
 +                      musb_write_fifo(hw_ep, pio, buf);
 +              } else {
 +                      musb_read_fifo(hw_ep, pio, buf);
 +                      dma_cache_maint(phys_to_virt((u32)chdat->dma_addr),
 +                                      chdat->transfer_len, DMA_FROM_DEVICE);
 +              }
 +              channel->actual_len += pio;
 +      }
 +
 +      if (!tusb_dma->multichannel)
 +              tusb_omap_free_shared_dmareq(chdat);
 +
 +      channel->status = MUSB_DMA_STATUS_FREE;
 +
 +      /* Handle only RX callbacks here. TX callbacks must be handled based
 +       * on the TUSB DMA status interrupt.
 +       * REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
 +       * interrupt for RX and TX.
 +       */
 +      if (!chdat->tx)
 +              musb_dma_completion(musb, chdat->epnum, chdat->tx);
 +
 +      /* We must terminate short tx transfers manually by setting TXPKTRDY.
 +       * REVISIT: This same problem may occur with other MUSB dma as well.
 +       * Easy to test with g_ether by pinging the MUSB board with ping -s54.
 +       */
 +      if ((chdat->transfer_len < chdat->packet_sz)
 +                      || (chdat->transfer_len % chdat->packet_sz != 0)) {
 +              u16     csr;
 +
 +              if (chdat->tx) {
 +                      DBG(3, "terminating short tx packet\n");
 +                      musb_ep_select(mbase, chdat->epnum);
 +                      csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
 +                      csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY
 +                              | MUSB_TXCSR_P_WZC_BITS;
 +                      musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
 +              }
 +      }
 +
 +      spin_unlock_irqrestore(&musb->lock, flags);
 +}
 +
 +static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
 +                              u8 rndis_mode, dma_addr_t dma_addr, u32 len)
 +{
 +      struct tusb_omap_dma_ch         *chdat = to_chdat(channel);
 +      struct tusb_omap_dma            *tusb_dma = chdat->tusb_dma;
 +      struct musb                     *musb = chdat->musb;
 +      struct musb_hw_ep               *hw_ep = chdat->hw_ep;
 +      void __iomem                    *mbase = musb->mregs;
 +      void __iomem                    *ep_conf = hw_ep->conf;
 +      dma_addr_t                      fifo = hw_ep->fifo_sync;
 +      struct omap_dma_channel_params  dma_params;
 +      u32                             dma_remaining;
 +      int                             src_burst, dst_burst;
 +      u16                             csr;
 +      int                             ch;
 +      s8                              dmareq;
 +      s8                              sync_dev;
 +
 +      if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
 +              return false;
 +
 +      /*
 +       * HW issue #10: Async dma will eventually corrupt the XFR_SIZE
 +       * register which will cause missed DMA interrupt. We could try to
 +       * use a timer for the callback, but it is unsafe as the XFR_SIZE
 +       * register is corrupt, and we won't know if the DMA worked.
 +       */
 +      if (dma_addr & 0x2)
 +              return false;
 +
 +      /*
 +       * Because of HW issue #10, it seems like mixing sync DMA and async
 +       * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before
 +       * using the channel for DMA.
 +       */
 +      if (chdat->tx)
 +              dma_remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
 +      else
 +              dma_remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
 +
 +      dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
 +      if (dma_remaining) {
 +              DBG(2, "Busy %s dma ch%i, not using: %08x\n",
 +                      chdat->tx ? "tx" : "rx", chdat->ch,
 +                      dma_remaining);
 +              return false;
 +      }
 +
 +      chdat->transfer_len = len & ~0x1f;
 +
 +      if (len < packet_sz)
 +              chdat->transfer_packet_sz = chdat->transfer_len;
 +      else
 +              chdat->transfer_packet_sz = packet_sz;
 +
 +      if (tusb_dma->multichannel) {
 +              ch = chdat->ch;
 +              dmareq = chdat->dmareq;
 +              sync_dev = chdat->sync_dev;
 +      } else {
 +              if (tusb_omap_use_shared_dmareq(chdat) != 0) {
 +                      DBG(3, "could not get dma for ep%i\n", chdat->epnum);
 +                      return false;
 +              }
 +              if (tusb_dma->ch < 0) {
 +                      /* REVISIT: This should get blocked earlier, happens
 +                       * with MSC ErrorRecoveryTest
 +                       */
 +                      WARN_ON(1);
 +                      return false;
 +              }
 +
 +              ch = tusb_dma->ch;
 +              dmareq = tusb_dma->dmareq;
 +              sync_dev = tusb_dma->sync_dev;
 +              omap_set_dma_callback(ch, tusb_omap_dma_cb, channel);
 +      }
 +
 +      chdat->packet_sz = packet_sz;
 +      chdat->len = len;
 +      channel->actual_len = 0;
 +      chdat->dma_addr = (void __iomem *)dma_addr;
 +      channel->status = MUSB_DMA_STATUS_BUSY;
 +
 +      /* Since we're recycling dma areas, we need to clean or invalidate */
 +      if (chdat->tx)
 +              dma_cache_maint(phys_to_virt(dma_addr), len, DMA_TO_DEVICE);
 +      else
 +              dma_cache_maint(phys_to_virt(dma_addr), len, DMA_FROM_DEVICE);
 +
 +      /* Use 16-bit transfer if dma_addr is not 32-bit aligned */
 +      if ((dma_addr & 0x3) == 0) {
 +              dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
 +              dma_params.elem_count = 8;              /* Elements in frame */
 +      } else {
 +              dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
 +              dma_params.elem_count = 16;             /* Elements in frame */
 +              fifo = hw_ep->fifo_async;
 +      }
 +
 +      dma_params.frame_count  = chdat->transfer_len / 32; /* Burst sz frame */
 +
 +      DBG(3, "ep%i %s dma ch%i dma: %08x len: %u(%u) packet_sz: %i(%i)\n",
 +              chdat->epnum, chdat->tx ? "tx" : "rx",
 +              ch, dma_addr, chdat->transfer_len, len,
 +              chdat->transfer_packet_sz, packet_sz);
 +
 +      /*
 +       * Prepare omap DMA for transfer
 +       */
 +      if (chdat->tx) {
 +              dma_params.src_amode    = OMAP_DMA_AMODE_POST_INC;
 +              dma_params.src_start    = (unsigned long)dma_addr;
 +              dma_params.src_ei       = 0;
 +              dma_params.src_fi       = 0;
 +
 +              dma_params.dst_amode    = OMAP_DMA_AMODE_DOUBLE_IDX;
 +              dma_params.dst_start    = (unsigned long)fifo;
 +              dma_params.dst_ei       = 1;
 +              dma_params.dst_fi       = -31;  /* Loop 32 byte window */
 +
 +              dma_params.trigger      = sync_dev;
 +              dma_params.sync_mode    = OMAP_DMA_SYNC_FRAME;
 +              dma_params.src_or_dst_synch     = 0;    /* Dest sync */
 +
 +              src_burst = OMAP_DMA_DATA_BURST_16;     /* 16x32 read */
 +              dst_burst = OMAP_DMA_DATA_BURST_8;      /* 8x32 write */
 +      } else {
 +              dma_params.src_amode    = OMAP_DMA_AMODE_DOUBLE_IDX;
 +              dma_params.src_start    = (unsigned long)fifo;
 +              dma_params.src_ei       = 1;
 +              dma_params.src_fi       = -31;  /* Loop 32 byte window */
 +
 +              dma_params.dst_amode    = OMAP_DMA_AMODE_POST_INC;
 +              dma_params.dst_start    = (unsigned long)dma_addr;
 +              dma_params.dst_ei       = 0;
 +              dma_params.dst_fi       = 0;
 +
 +              dma_params.trigger      = sync_dev;
 +              dma_params.sync_mode    = OMAP_DMA_SYNC_FRAME;
 +              dma_params.src_or_dst_synch     = 1;    /* Source sync */
 +
 +              src_burst = OMAP_DMA_DATA_BURST_8;      /* 8x32 read */
 +              dst_burst = OMAP_DMA_DATA_BURST_16;     /* 16x32 write */
 +      }
 +
 +      DBG(3, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
 +              chdat->epnum, chdat->tx ? "tx" : "rx",
 +              (dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
 +              ((dma_addr & 0x3) == 0) ? "sync" : "async",
 +              dma_params.src_start, dma_params.dst_start);
 +
 +      omap_set_dma_params(ch, &dma_params);
 +      omap_set_dma_src_burst_mode(ch, src_burst);
 +      omap_set_dma_dest_burst_mode(ch, dst_burst);
 +      omap_set_dma_write_mode(ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
 +
 +      /*
 +       * Prepare MUSB for DMA transfer
 +       */
 +      if (chdat->tx) {
 +              musb_ep_select(mbase, chdat->epnum);
 +              csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
 +              csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
 +                      | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
 +              csr &= ~MUSB_TXCSR_P_UNDERRUN;
 +              musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
 +      } else {
 +              musb_ep_select(mbase, chdat->epnum);
 +              csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
 +              csr |= MUSB_RXCSR_DMAENAB;
 +              csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
 +              musb_writew(hw_ep->regs, MUSB_RXCSR,
 +                      csr | MUSB_RXCSR_P_WZC_BITS);
 +      }
 +
 +      /*
 +       * Start DMA transfer
 +       */
 +      omap_start_dma(ch);
 +
 +      if (chdat->tx) {
 +              /* Send transfer_packet_sz packets at a time */
 +              musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
 +                      chdat->transfer_packet_sz);
 +
 +              musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
 +                      TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
 +      } else {
 +              /* Receive transfer_packet_sz packets at a time */
 +              musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
 +                      chdat->transfer_packet_sz << 16);
 +
 +              musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
 +                      TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
 +      }
 +
 +      return true;
 +}
 +
 +static int tusb_omap_dma_abort(struct dma_channel *channel)
 +{
 +      struct tusb_omap_dma_ch *chdat = to_chdat(channel);
 +      struct tusb_omap_dma    *tusb_dma = chdat->tusb_dma;
 +
 +      if (!tusb_dma->multichannel) {
 +              if (tusb_dma->ch >= 0) {
 +                      omap_stop_dma(tusb_dma->ch);
 +                      omap_free_dma(tusb_dma->ch);
 +                      tusb_dma->ch = -1;
 +              }
 +
 +              tusb_dma->dmareq = -1;
 +              tusb_dma->sync_dev = -1;
 +      }
 +
 +      channel->status = MUSB_DMA_STATUS_FREE;
 +
 +      return 0;
 +}
 +
 +static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
 +{
 +      u32             reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
 +      int             i, dmareq_nr = -1;
 +
 +      const int sync_dev[6] = {
 +              OMAP24XX_DMA_EXT_DMAREQ0,
 +              OMAP24XX_DMA_EXT_DMAREQ1,
 +              OMAP242X_DMA_EXT_DMAREQ2,
 +              OMAP242X_DMA_EXT_DMAREQ3,
 +              OMAP242X_DMA_EXT_DMAREQ4,
 +              OMAP242X_DMA_EXT_DMAREQ5,
 +      };
 +
 +      for (i = 0; i < MAX_DMAREQ; i++) {
 +              int cur = (reg & (0xf << (i * 5))) >> (i * 5);
 +              if (cur == 0) {
 +                      dmareq_nr = i;
 +                      break;
 +              }
 +      }
 +
 +      if (dmareq_nr == -1)
 +              return -EAGAIN;
 +
 +      reg |= (chdat->epnum << (dmareq_nr * 5));
 +      if (chdat->tx)
 +              reg |= ((1 << 4) << (dmareq_nr * 5));
 +      musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
 +
 +      chdat->dmareq = dmareq_nr;
 +      chdat->sync_dev = sync_dev[chdat->dmareq];
 +
 +      return 0;
 +}
 +
 +static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
 +{
 +      u32 reg;
 +
 +      if (!chdat || chdat->dmareq < 0)
 +              return;
 +
 +      reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
 +      reg &= ~(0x1f << (chdat->dmareq * 5));
 +      musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
 +
 +      chdat->dmareq = -1;
 +      chdat->sync_dev = -1;
 +}
 +
 +static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
 +
 +static struct dma_channel *
 +tusb_omap_dma_allocate(struct dma_controller *c,
 +              struct musb_hw_ep *hw_ep,
 +              u8 tx)
 +{
 +      int ret, i;
 +      const char              *dev_name;
 +      struct tusb_omap_dma    *tusb_dma;
 +      struct musb             *musb;
 +      void __iomem            *tbase;
 +      struct dma_channel      *channel = NULL;
 +      struct tusb_omap_dma_ch *chdat = NULL;
 +      u32                     reg;
 +
 +      tusb_dma = container_of(c, struct tusb_omap_dma, controller);
 +      musb = tusb_dma->musb;
 +      tbase = musb->ctrl_base;
 +
 +      reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
 +      if (tx)
 +              reg &= ~(1 << hw_ep->epnum);
 +      else
 +              reg &= ~(1 << (hw_ep->epnum + 15));
 +      musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
 +
 +      /* REVISIT: Why does dmareq5 not work? */
 +      if (hw_ep->epnum == 0) {
 +              DBG(3, "Not allowing DMA for ep0 %s\n", tx ? "tx" : "rx");
 +              return NULL;
 +      }
 +
 +      for (i = 0; i < MAX_DMAREQ; i++) {
 +              struct dma_channel *ch = dma_channel_pool[i];
 +              if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {
 +                      ch->status = MUSB_DMA_STATUS_FREE;
 +                      channel = ch;
 +                      chdat = ch->private_data;
 +                      break;
 +              }
 +      }
 +
 +      if (!channel)
 +              return NULL;
 +
 +      if (tx) {
 +              chdat->tx = 1;
 +              dev_name = "TUSB transmit";
 +      } else {
 +              chdat->tx = 0;
 +              dev_name = "TUSB receive";
 +      }
 +
 +      chdat->musb = tusb_dma->musb;
 +      chdat->tbase = tusb_dma->tbase;
 +      chdat->hw_ep = hw_ep;
 +      chdat->epnum = hw_ep->epnum;
 +      chdat->dmareq = -1;
 +      chdat->completed_len = 0;
 +      chdat->tusb_dma = tusb_dma;
 +
 +      channel->max_len = 0x7fffffff;
 +      channel->desired_mode = 0;
 +      channel->actual_len = 0;
 +
 +      if (tusb_dma->multichannel) {
 +              ret = tusb_omap_dma_allocate_dmareq(chdat);
 +              if (ret != 0)
 +                      goto free_dmareq;
 +
 +              ret = omap_request_dma(chdat->sync_dev, dev_name,
 +                              tusb_omap_dma_cb, channel, &chdat->ch);
 +              if (ret != 0)
 +                      goto free_dmareq;
 +      } else if (tusb_dma->ch == -1) {
 +              tusb_dma->dmareq = 0;
 +              tusb_dma->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
 +
 +              /* Callback data gets set later in the shared dmareq case */
 +              ret = omap_request_dma(tusb_dma->sync_dev, "TUSB shared",
 +                              tusb_omap_dma_cb, NULL, &tusb_dma->ch);
 +              if (ret != 0)
 +                      goto free_dmareq;
 +
 +              chdat->dmareq = -1;
 +              chdat->ch = -1;
 +      }
 +
 +      DBG(3, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
 +              chdat->epnum,
 +              chdat->tx ? "tx" : "rx",
 +              chdat->ch >= 0 ? "dedicated" : "shared",
 +              chdat->ch >= 0 ? chdat->ch : tusb_dma->ch,
 +              chdat->dmareq >= 0 ? chdat->dmareq : tusb_dma->dmareq,
 +              chdat->sync_dev >= 0 ? chdat->sync_dev : tusb_dma->sync_dev);
 +
 +      return channel;
 +
 +free_dmareq:
 +      tusb_omap_dma_free_dmareq(chdat);
 +
 +      DBG(3, "ep%i: Could not get a DMA channel\n", chdat->epnum);
 +      channel->status = MUSB_DMA_STATUS_UNKNOWN;
 +
 +      return NULL;
 +}
 +
 +static void tusb_omap_dma_release(struct dma_channel *channel)
 +{
 +      struct tusb_omap_dma_ch *chdat = to_chdat(channel);
 +      struct musb             *musb = chdat->musb;
 +      void __iomem            *tbase = musb->ctrl_base;
 +      u32                     reg;
 +
 +      DBG(3, "ep%i ch%i\n", chdat->epnum, chdat->ch);
 +
 +      reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
 +      if (chdat->tx)
 +              reg |= (1 << chdat->epnum);
 +      else
 +              reg |= (1 << (chdat->epnum + 15));
 +      musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
 +
 +      reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
 +      if (chdat->tx)
 +              reg |= (1 << chdat->epnum);
 +      else
 +              reg |= (1 << (chdat->epnum + 15));
 +      musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
 +
 +      channel->status = MUSB_DMA_STATUS_UNKNOWN;
 +
 +      if (chdat->ch >= 0) {
 +              omap_stop_dma(chdat->ch);
 +              omap_free_dma(chdat->ch);
 +              chdat->ch = -1;
 +      }
 +
 +      if (chdat->dmareq >= 0)
 +              tusb_omap_dma_free_dmareq(chdat);
 +
 +      channel = NULL;
 +}
 +
 +void dma_controller_destroy(struct dma_controller *c)
 +{
 +      struct tusb_omap_dma    *tusb_dma;
 +      int                     i;
 +
 +      tusb_dma = container_of(c, struct tusb_omap_dma, controller);
 +      for (i = 0; i < MAX_DMAREQ; i++) {
 +              struct dma_channel *ch = dma_channel_pool[i];
 +              if (ch) {
 +                      kfree(ch->private_data);
 +                      kfree(ch);
 +              }
 +      }
 +
 +      if (!tusb_dma->multichannel && tusb_dma && tusb_dma->ch >= 0)
 +              omap_free_dma(tusb_dma->ch);
 +
 +      kfree(tusb_dma);
 +}
 +
 +struct dma_controller *__init
 +dma_controller_create(struct musb *musb, void __iomem *base)
 +{
 +      void __iomem            *tbase = musb->ctrl_base;
 +      struct tusb_omap_dma    *tusb_dma;
 +      int                     i;
 +
 +      /* REVISIT: Get dmareq lines used from board-*.c */
 +
 +      musb_writel(musb->ctrl_base, TUSB_DMA_INT_MASK, 0x7fffffff);
 +      musb_writel(musb->ctrl_base, TUSB_DMA_EP_MAP, 0);
 +
 +      musb_writel(tbase, TUSB_DMA_REQ_CONF,
 +              TUSB_DMA_REQ_CONF_BURST_SIZE(2)
 +              | TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f)
 +              | TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
 +
 +      tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL);
 +      if (!tusb_dma)
 +              goto cleanup;
 +
 +      tusb_dma->musb = musb;
 +      tusb_dma->tbase = musb->ctrl_base;
 +
 +      tusb_dma->ch = -1;
 +      tusb_dma->dmareq = -1;
 +      tusb_dma->sync_dev = -1;
 +
 +      tusb_dma->controller.start = tusb_omap_dma_start;
 +      tusb_dma->controller.stop = tusb_omap_dma_stop;
 +      tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
 +      tusb_dma->controller.channel_release = tusb_omap_dma_release;
 +      tusb_dma->controller.channel_program = tusb_omap_dma_program;
 +      tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
 +
 +      if (tusb_get_revision(musb) >= TUSB_REV_30)
 +              tusb_dma->multichannel = 1;
 +
 +      for (i = 0; i < MAX_DMAREQ; i++) {
 +              struct dma_channel      *ch;
 +              struct tusb_omap_dma_ch *chdat;
 +
 +              ch = kzalloc(sizeof(struct dma_channel), GFP_KERNEL);
 +              if (!ch)
 +                      goto cleanup;
 +
 +              dma_channel_pool[i] = ch;
 +
 +              chdat = kzalloc(sizeof(struct tusb_omap_dma_ch), GFP_KERNEL);
 +              if (!chdat)
 +                      goto cleanup;
 +
 +              ch->status = MUSB_DMA_STATUS_UNKNOWN;
 +              ch->private_data = chdat;
 +      }
 +
 +      return &tusb_dma->controller;
 +
 +cleanup:
 +      dma_controller_destroy(&tusb_dma->controller);
 +
 +      return NULL;
 +}
index 2072f28578f2875cb3df94bc85a29050e0af8391,0000000000000000000000000000000000000000..eb9b5ba38c148b1d193c36dadc945d978a4dbab9
mode 100644,000000..100644
--- /dev/null
@@@ -1,218 -1,0 +1,218 @@@
- #include <asm/arch/hardware.h>
- #include <asm/arch/board.h>
- #include <asm/arch/mux.h>
 +/*
 + * drivers/video/backlight/omap_bl.c
 + *
 + * Backlight driver for OMAP based boards.
 + *
 + * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
 + *
 + * This package 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 package 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 package; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 + */
 +
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/fb.h>
 +#include <linux/backlight.h>
 +
++#include <mach/hardware.h>
++#include <mach/board.h>
++#include <mach/mux.h>
 +
 +#define OMAPBL_MAX_INTENSITY          0xff
 +
 +struct omap_backlight {
 +      int powermode;
 +      int current_intensity;
 +
 +      struct device *dev;
 +      struct omap_backlight_config *pdata;
 +};
 +
 +static void inline omapbl_send_intensity(int intensity)
 +{
 +      omap_writeb(intensity, OMAP_PWL_ENABLE);
 +}
 +
 +static void inline omapbl_send_enable(int enable)
 +{
 +      omap_writeb(enable, OMAP_PWL_CLK_ENABLE);
 +}
 +
 +static void omapbl_blank(struct omap_backlight *bl, int mode)
 +{
 +      if (bl->pdata->set_power)
 +              bl->pdata->set_power(bl->dev, mode);
 +
 +      switch (mode) {
 +      case FB_BLANK_NORMAL:
 +      case FB_BLANK_VSYNC_SUSPEND:
 +      case FB_BLANK_HSYNC_SUSPEND:
 +      case FB_BLANK_POWERDOWN:
 +              omapbl_send_intensity(0);
 +              omapbl_send_enable(0);
 +              break;
 +
 +      case FB_BLANK_UNBLANK:
 +              omapbl_send_intensity(bl->current_intensity);
 +              omapbl_send_enable(1);
 +              break;
 +      }
 +}
 +
 +#ifdef CONFIG_PM
 +static int omapbl_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct backlight_device *dev = platform_get_drvdata(pdev);
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +
 +      omapbl_blank(bl, FB_BLANK_POWERDOWN);
 +      return 0;
 +}
 +
 +static int omapbl_resume(struct platform_device *pdev)
 +{
 +      struct backlight_device *dev = platform_get_drvdata(pdev);
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +
 +      omapbl_blank(bl, bl->powermode);
 +      return 0;
 +}
 +#else
 +#define omapbl_suspend        NULL
 +#define omapbl_resume NULL
 +#endif
 +
 +static int omapbl_set_power(struct backlight_device *dev, int state)
 +{
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +
 +      omapbl_blank(bl, state);
 +      bl->powermode = state;
 +
 +      return 0;
 +}
 +
 +static int omapbl_update_status(struct backlight_device *dev)
 +{
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +
 +      if (bl->current_intensity != dev->props.brightness) {
 +              if (dev->props.brightness < 0)
 +                      return -EPERM;  /* Leave current_intensity untouched */
 +
 +              if (bl->powermode == FB_BLANK_UNBLANK)
 +                      omapbl_send_intensity(dev->props.brightness);
 +              bl->current_intensity = dev->props.brightness;
 +      }
 +
 +      if (dev->props.fb_blank != bl->powermode)
 +              omapbl_set_power(dev, dev->props.fb_blank);
 +
 +      return 0;
 +}
 +
 +
 +static int omapbl_get_intensity(struct backlight_device *dev)
 +{
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +      return bl->current_intensity;
 +}
 +
 +static struct backlight_ops omapbl_ops = {
 +      .get_brightness = omapbl_get_intensity,
 +      .update_status  = omapbl_update_status,
 +};
 +
 +
 +static int omapbl_probe(struct platform_device *pdev)
 +{
 +      struct backlight_device *dev;
 +      struct omap_backlight *bl;
 +      struct omap_backlight_config *pdata = pdev->dev.platform_data;
 +
 +      if (!pdata)
 +              return -ENXIO;
 +
 +      omapbl_ops.check_fb = pdata->check_fb;
 +
 +      bl = kzalloc(sizeof(struct omap_backlight), GFP_KERNEL);
 +      if (unlikely(!bl))
 +              return -ENOMEM;
 +
 +      dev = backlight_device_register("omap-bl", &pdev->dev,
 +                      bl, &omapbl_ops);
 +      if (IS_ERR(dev)) {
 +              kfree(bl);
 +              return PTR_ERR(dev);
 +      }
 +
 +      bl->powermode = FB_BLANK_POWERDOWN;
 +      bl->current_intensity = 0;
 +
 +      bl->pdata = pdata;
 +      bl->dev = &pdev->dev;
 +
 +      platform_set_drvdata(pdev, dev);
 +
 +      omap_cfg_reg(PWL);      /* Conflicts with UART3 */
 +
 +      dev->props.fb_blank = FB_BLANK_UNBLANK;
 +      dev->props.max_brightness = OMAPBL_MAX_INTENSITY;
 +      dev->props.brightness = pdata->default_intensity;
 +      omapbl_update_status(dev);
 +
 +      printk(KERN_INFO "OMAP LCD backlight initialised\n");
 +
 +      return 0;
 +}
 +
 +static int omapbl_remove(struct platform_device *pdev)
 +{
 +      struct backlight_device *dev = platform_get_drvdata(pdev);
 +      struct omap_backlight *bl = dev_get_drvdata(&dev->dev);
 +
 +      backlight_device_unregister(dev);
 +      kfree(bl);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver omapbl_driver = {
 +      .probe          = omapbl_probe,
 +      .remove         = omapbl_remove,
 +      .suspend        = omapbl_suspend,
 +      .resume         = omapbl_resume,
 +      .driver         = {
 +              .name   = "omap-bl",
 +      },
 +};
 +
 +static int __init omapbl_init(void)
 +{
 +      return platform_driver_register(&omapbl_driver);
 +}
 +
 +static void __exit omapbl_exit(void)
 +{
 +      platform_driver_unregister(&omapbl_driver);
 +}
 +
 +module_init(omapbl_init);
 +module_exit(omapbl_exit);
 +
 +MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>");
 +MODULE_DESCRIPTION("OMAP LCD Backlight driver");
 +MODULE_LICENSE("GPL");
Simple merge
Simple merge
index 8ba15dceb9253551ff9ab65dfb9bb9f608e6a68c,0000000000000000000000000000000000000000..9af6cd0a963b9bd1224d97e0da7698edd0b2ef35
mode 100644,000000..100644
--- /dev/null
@@@ -1,182 -1,0 +1,182 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the TI 2430SDP board
 + *
 + * Copyright (C) 2007 MontaVista
 + * Author: Hunyue Yau <hyau@mvista.com>
 + *
 + * Derived from drivers/video/omap/lcd-apollon.c
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c/twl4030.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +#include <asm/mach-types.h>
 +
 +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO      91
 +#define SDP2430_LCD_PANEL_ENABLE_GPIO         154
 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO      24
 +#define SDP3430_LCD_PANEL_ENABLE_GPIO                 28
 +
 +static unsigned backlight_gpio;
 +static unsigned enable_gpio;
 +
 +#define LCD_PIXCLOCK_MAX              5400 /* freq 5.4 MHz */
 +#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER
 +#define ENABLE_VAUX2_DEDICATED  0x09
 +#define ENABLE_VAUX2_DEV_GRP    0x20
 +#define ENABLE_VAUX3_DEDICATED        0x03
 +#define ENABLE_VAUX3_DEV_GRP  0x20
 +
 +
 +#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
 +
 +
 +static int sdp2430_panel_init(struct lcd_panel *panel,
 +                              struct omapfb_device *fbdev)
 +{
 +      if (machine_is_omap_3430sdp()) {
 +              enable_gpio    = SDP3430_LCD_PANEL_ENABLE_GPIO;
 +              backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
 +      } else {
 +              enable_gpio    = SDP2430_LCD_PANEL_ENABLE_GPIO;
 +              backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO;
 +      }
 +
 +      omap_request_gpio(enable_gpio);                 /* LCD panel */
 +      omap_request_gpio(backlight_gpio);              /* LCD backlight */
 +      omap_set_gpio_direction(enable_gpio, 0);        /* output */
 +      omap_set_gpio_direction(backlight_gpio, 0);     /* output */
 +
 +      return 0;
 +}
 +
 +static void sdp2430_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int sdp2430_panel_enable(struct lcd_panel *panel)
 +{
 +      u8 ded_val, ded_reg;
 +      u8 grp_val, grp_reg;
 +
 +      if (machine_is_omap_3430sdp()) {
 +              ded_reg = TWL4030_VAUX3_DEDICATED;
 +              ded_val = ENABLE_VAUX3_DEDICATED;
 +              grp_reg = TWL4030_VAUX3_DEV_GRP;
 +              grp_val = ENABLE_VAUX3_DEV_GRP;
 +      } else {
 +              ded_reg = TWL4030_VAUX2_DEDICATED;
 +              ded_val = ENABLE_VAUX2_DEDICATED;
 +              grp_reg = TWL4030_VAUX2_DEV_GRP;
 +              grp_val = ENABLE_VAUX2_DEV_GRP;
 +      }
 +              
 +      omap_set_gpio_dataout(enable_gpio, 1);
 +      omap_set_gpio_dataout(backlight_gpio, 1);
 +
 +      if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
 +              return -EIO;
 +      if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
 +              return -EIO;
 +
 +      return 0;
 +}
 +
 +static void sdp2430_panel_disable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(enable_gpio, 0);
 +      omap_set_gpio_dataout(backlight_gpio, 0);
 +}
 +
 +static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +struct lcd_panel sdp2430_panel = {
 +      .name           = "sdp2430",
 +      .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
 +                        OMAP_LCDC_INV_HSYNC,
 +
 +      .bpp            = 16,
 +      .data_lines     = 16,
 +      .x_res          = 240,
 +      .y_res          = 320,
 +      .hsw            = 3,            /* hsync_len (4) - 1 */
 +      .hfp            = 3,            /* right_margin (4) - 1 */
 +      .hbp            = 39,           /* left_margin (40) - 1 */
 +      .vsw            = 1,            /* vsync_len (2) - 1 */
 +      .vfp            = 2,            /* lower_margin */
 +      .vbp            = 7,            /* upper_margin (8) - 1 */
 +
 +      .pixel_clock    = LCD_PIXCLOCK_MAX,
 +
 +      .init           = sdp2430_panel_init,
 +      .cleanup        = sdp2430_panel_cleanup,
 +      .enable         = sdp2430_panel_enable,
 +      .disable        = sdp2430_panel_disable,
 +      .get_caps       = sdp2430_panel_get_caps,
 +};
 +
 +static int sdp2430_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&sdp2430_panel);
 +      return 0;
 +}
 +
 +static int sdp2430_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int sdp2430_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int sdp2430_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver sdp2430_panel_driver = {
 +      .probe          = sdp2430_panel_probe,
 +      .remove         = sdp2430_panel_remove,
 +      .suspend        = sdp2430_panel_suspend,
 +      .resume         = sdp2430_panel_resume,
 +      .driver         = {
 +              .name   = "sdp2430_lcd",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init sdp2430_panel_drv_init(void)
 +{
 +      return platform_driver_register(&sdp2430_panel_driver);
 +}
 +
 +static void __exit sdp2430_panel_drv_exit(void)
 +{
 +      platform_driver_unregister(&sdp2430_panel_driver);
 +}
 +
 +module_init(sdp2430_panel_drv_init);
 +module_exit(sdp2430_panel_drv_exit);
index 3476689467d3033c7e66099f5cc98e5cf15d075b,0000000000000000000000000000000000000000..3fd5342d645c9195233635d9a20ae83e2605d73e
mode 100644,000000..100644
--- /dev/null
@@@ -1,140 -1,0 +1,140 @@@
- #include <asm/arch/board-ams-delta.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * File: drivers/video/omap/lcd_ams_delta.c
 + *
 + * Based on drivers/video/omap/lcd_inn1510.c
 + *
 + * LCD panel support for the Amstrad E3 (Delta) videophone.
 + *
 + * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
 + *
 + * 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/platform_device.h>
 +
 +#include <asm/delay.h>
 +#include <asm/io.h>
 +
++#include <mach/board-ams-delta.h>
++#include <mach/hardware.h>
++#include <mach/omapfb.h>
 +
 +#define AMS_DELTA_DEFAULT_CONTRAST    112
 +
 +static int ams_delta_panel_init(struct lcd_panel *panel,
 +              struct omapfb_device *fbdev)
 +{
 +      return 0;
 +}
 +
 +static void ams_delta_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int ams_delta_panel_enable(struct lcd_panel *panel)
 +{
 +      ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP,
 +                      AMS_DELTA_LATCH2_LCD_NDISP);
 +      ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN,
 +                      AMS_DELTA_LATCH2_LCD_VBLEN);
 +
 +      omap_writeb(1, OMAP_PWL_CLK_ENABLE);
 +      omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE);
 +
 +      return 0;
 +}
 +
 +static void ams_delta_panel_disable(struct lcd_panel *panel)
 +{
 +      ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 0);
 +      ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, 0);
 +}
 +
 +static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +static struct lcd_panel ams_delta_panel = {
 +      .name           = "ams-delta",
 +      .config         = 0,
 +
 +      .bpp            = 12,
 +      .data_lines     = 16,
 +      .x_res          = 480,
 +      .y_res          = 320,
 +      .pixel_clock    = 4687,
 +      .hsw            = 3,
 +      .hfp            = 1,
 +      .hbp            = 1,
 +      .vsw            = 1,
 +      .vfp            = 0,
 +      .vbp            = 0,
 +      .pcd            = 0,
 +      .acb            = 37,
 +
 +      .init           = ams_delta_panel_init,
 +      .cleanup        = ams_delta_panel_cleanup,
 +      .enable         = ams_delta_panel_enable,
 +      .disable        = ams_delta_panel_disable,
 +      .get_caps       = ams_delta_panel_get_caps,
 +};
 +
 +static int ams_delta_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&ams_delta_panel);
 +      return 0;
 +}
 +
 +static int ams_delta_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int ams_delta_panel_suspend(struct platform_device *pdev,
 +              pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int ams_delta_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver ams_delta_panel_driver = {
 +      .probe          = ams_delta_panel_probe,
 +      .remove         = ams_delta_panel_remove,
 +      .suspend        = ams_delta_panel_suspend,
 +      .resume         = ams_delta_panel_resume,
 +      .driver         = {
 +              .name   = "lcd_ams_delta",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int ams_delta_panel_drv_init(void)
 +{
 +      return platform_driver_register(&ams_delta_panel_driver);
 +}
 +
 +static void ams_delta_panel_drv_cleanup(void)
 +{
 +      platform_driver_unregister(&ams_delta_panel_driver);
 +}
 +
 +module_init(ams_delta_panel_drv_init);
 +module_exit(ams_delta_panel_drv_cleanup);
index 179315f1a433c727a4940708fe2c36eeceb4b902,0000000000000000000000000000000000000000..beae5d9329a44788d5432c5902b0eb3810558dde
mode 100644,000000..100644
--- /dev/null
@@@ -1,137 -1,0 +1,137 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the Samsung OMAP2 Apollon board
 + *
 + * Copyright (C) 2005,2006 Samsung Electronics
 + * Author: Kyungmin Park <kyungmin.park@samsung.com>
 + *
 + * Derived from drivers/video/omap/lcd-h4.c
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +
 +/* #define USE_35INCH_LCD 1 */
 +
 +static int apollon_panel_init(struct lcd_panel *panel,
 +                              struct omapfb_device *fbdev)
 +{
 +      /* configure LCD PWR_EN */
 +      omap_cfg_reg(M21_242X_GPIO11);
 +      return 0;
 +}
 +
 +static void apollon_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int apollon_panel_enable(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +static void apollon_panel_disable(struct lcd_panel *panel)
 +{
 +}
 +
 +static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +struct lcd_panel apollon_panel = {
 +      .name           = "apollon",
 +      .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
 +                        OMAP_LCDC_INV_HSYNC,
 +
 +      .bpp            = 16,
 +      .data_lines     = 18,
 +#ifdef USE_35INCH_LCD
 +      .x_res          = 240,
 +      .y_res          = 320,
 +      .hsw            = 2,
 +      .hfp            = 3,
 +      .hbp            = 9,
 +      .vsw            = 4,
 +      .vfp            = 3,
 +      .vbp            = 5,
 +#else
 +      .x_res          = 480,
 +      .y_res          = 272,
 +      .hsw            = 41,
 +      .hfp            = 2,
 +      .hbp            = 2,
 +      .vsw            = 10,
 +      .vfp            = 2,
 +      .vbp            = 2,
 +#endif
 +      .pixel_clock    = 6250,
 +
 +      .init           = apollon_panel_init,
 +      .cleanup        = apollon_panel_cleanup,
 +      .enable         = apollon_panel_enable,
 +      .disable        = apollon_panel_disable,
 +      .get_caps       = apollon_panel_get_caps,
 +};
 +
 +static int apollon_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&apollon_panel);
 +      return 0;
 +}
 +
 +static int apollon_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int apollon_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int apollon_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver apollon_panel_driver = {
 +      .probe          = apollon_panel_probe,
 +      .remove         = apollon_panel_remove,
 +      .suspend        = apollon_panel_suspend,
 +      .resume         = apollon_panel_resume,
 +      .driver         = {
 +              .name   = "apollon_lcd",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init apollon_panel_drv_init(void)
 +{
 +      return platform_driver_register(&apollon_panel_driver);
 +}
 +
 +static void __exit apollon_panel_drv_exit(void)
 +{
 +      platform_driver_unregister(&apollon_panel_driver);
 +}
 +
 +module_init(apollon_panel_drv_init);
 +module_exit(apollon_panel_drv_exit);
index 7d16b5703c95dd29fea9589d4db2d0cf88294d58,0000000000000000000000000000000000000000..96b4816f6489ca3c5af12e16c84a65a17919cab9
mode 100644,000000..100644
--- /dev/null
@@@ -1,155 -1,0 +1,155 @@@
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the TI OMAP H2 board
 + *
 + * Copyright (C) 2004 Nokia Corporation
 + * Author: Imre Deak <imre.deak@nokia.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/platform_device.h>
 +#include <linux/spi/tsc2101.h>
 +
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +
 +static struct {
 +      struct platform_device  *lcd_dev;
 +      struct spi_device       *tsc2101_dev;
 +} h2_panel_dev;
 +
 +static int h2_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
 +{
 +      return 0;
 +}
 +
 +static void h2_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int h2_panel_enable(struct lcd_panel *panel)
 +{
 +      int r;
 +
 +      /*
 +       * Assert LCD_EN, BKLIGHT_EN pins on LCD panel
 +       * page2, GPIO config reg, GPIO(0,1) to out and asserted
 +       */
 +      r = tsc2101_write_sync(h2_panel_dev.tsc2101_dev, 2, 0x23, 0xcc00);
 +      if (r < 0)
 +              dev_err(&h2_panel_dev.lcd_dev->dev,
 +                      "failed to enable LCD panel\n");
 +
 +      return r;
 +}
 +
 +static void h2_panel_disable(struct lcd_panel *panel)
 +{
 +      /*
 +       * Deassert LCD_EN and BKLIGHT_EN pins on LCD panel
 +       * page2, GPIO config reg, GPIO(0,1) to out and deasserted
 +       */
 +      if (tsc2101_write_sync(h2_panel_dev.tsc2101_dev, 2, 0x23, 0x8800))
 +              dev_err(&h2_panel_dev.lcd_dev->dev,
 +                      "failed to disable LCD panel\n");
 +}
 +
 +static unsigned long h2_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +struct lcd_panel h2_panel = {
 +      .name           = "h2",
 +      .config         = OMAP_LCDC_PANEL_TFT,
 +
 +      .bpp            = 16,
 +      .data_lines     = 16,
 +      .x_res          = 240,
 +      .y_res          = 320,
 +      .pixel_clock    = 5000,
 +      .hsw            = 12,
 +      .hfp            = 12,
 +      .hbp            = 46,
 +      .vsw            = 1,
 +      .vfp            = 1,
 +      .vbp            = 0,
 +
 +      .init           = h2_panel_init,
 +      .cleanup        = h2_panel_cleanup,
 +      .enable         = h2_panel_enable,
 +      .disable        = h2_panel_disable,
 +      .get_caps       = h2_panel_get_caps,
 +};
 +
 +static int h2_panel_probe(struct platform_device *pdev)
 +{
 +      struct spi_device *tsc2101;
 +
 +      tsc2101 = pdev->dev.platform_data;
 +      if (tsc2101 == NULL) {
 +              dev_err(&pdev->dev, "no platform data\n");
 +              return -ENODEV;
 +      }
 +      if (strncmp(tsc2101->modalias, "tsc2101", 8) != 0) {
 +              dev_err(&pdev->dev, "tsc2101 not found\n");
 +              return -EINVAL;
 +      }
 +      h2_panel_dev.lcd_dev = pdev;
 +      h2_panel_dev.tsc2101_dev = tsc2101;
 +      omapfb_register_panel(&h2_panel);
 +      return 0;
 +}
 +
 +static int h2_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int h2_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int h2_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver h2_panel_driver = {
 +      .probe          = h2_panel_probe,
 +      .remove         = h2_panel_remove,
 +      .suspend        = h2_panel_suspend,
 +      .resume         = h2_panel_resume,
 +      .driver         = {
 +              .name   = "lcd_h2",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int h2_panel_drv_init(void)
 +{
 +      return platform_driver_register(&h2_panel_driver);
 +}
 +
 +static void h2_panel_drv_cleanup(void)
 +{
 +      platform_driver_unregister(&h2_panel_driver);
 +}
 +
 +module_init(h2_panel_drv_init);
 +module_exit(h2_panel_drv_cleanup);
 +
index 3af8b2fd9714311e45f1a7e99a41a4957a842c19,0000000000000000000000000000000000000000..1895997d8d8e0eed1a322558eed77bbaccd6126a
mode 100644,000000..100644
--- /dev/null
@@@ -1,617 -1,0 +1,617 @@@
- #include <asm/arch/omapfb.h>
- #include <asm/arch/lcd_mipid.h>
 +/*
 + * LCD driver for MIPI DBI-C / DCS compatible LCDs
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + * Author: Imre Deak <imre.deak@nokia.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/device.h>
 +#include <linux/delay.h>
 +#include <linux/workqueue.h>
 +#include <linux/spi/spi.h>
 +
++#include <mach/omapfb.h>
++#include <mach/lcd_mipid.h>
 +
 +#include "../../cbus/tahvo.h"
 +
 +#define MIPID_MODULE_NAME             "lcd_mipid"
 +
 +#define MIPID_CMD_READ_DISP_ID                0x04
 +#define MIPID_CMD_READ_RED            0x06
 +#define MIPID_CMD_READ_GREEN          0x07
 +#define MIPID_CMD_READ_BLUE           0x08
 +#define MIPID_CMD_READ_DISP_STATUS    0x09
 +#define MIPID_CMD_RDDSDR              0x0F
 +#define MIPID_CMD_SLEEP_IN            0x10
 +#define MIPID_CMD_SLEEP_OUT           0x11
 +#define MIPID_CMD_DISP_OFF            0x28
 +#define MIPID_CMD_DISP_ON             0x29
 +
 +#define MIPID_VER_LPH8923             3
 +#define MIPID_VER_LS041Y3             4
 +
 +#define MIPID_ESD_CHECK_PERIOD                msecs_to_jiffies(5000)
 +
 +#define to_mipid_device(p)            container_of(p, struct mipid_device, \
 +                                              panel)
 +struct mipid_device {
 +      int             enabled;
 +      int             model;
 +      int             revision;
 +      u8              display_id[3];
 +      unsigned int    saved_bklight_level;
 +      unsigned long   hw_guard_end;           /* next value of jiffies
 +                                                 when we can issue the
 +                                                 next sleep in/out command */
 +      unsigned long   hw_guard_wait;          /* max guard time in jiffies */
 +
 +      struct omapfb_device    *fbdev;
 +      struct spi_device       *spi;
 +      struct mutex            mutex;
 +      struct lcd_panel        panel;
 +
 +      struct workqueue_struct *esd_wq;
 +      struct delayed_work     esd_work;
 +      void                    (*esd_check)(struct mipid_device *m);
 +};
 +
 +static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
 +                         int wlen, u8 *rbuf, int rlen)
 +{
 +      struct spi_message      m;
 +      struct spi_transfer     *x, xfer[4];
 +      u16                     w;
 +      int                     r;
 +
 +      BUG_ON(md->spi == NULL);
 +
 +      spi_message_init(&m);
 +
 +      memset(xfer, 0, sizeof(xfer));
 +      x = &xfer[0];
 +
 +      cmd &=  0xff;
 +      x->tx_buf       = &cmd;
 +      x->bits_per_word= 9;
 +      x->len          = 2;
 +      spi_message_add_tail(x, &m);
 +
 +      if (wlen) {
 +              x++;
 +              x->tx_buf       = wbuf;
 +              x->len          = wlen;
 +              x->bits_per_word= 9;
 +              spi_message_add_tail(x, &m);
 +      }
 +
 +      if (rlen) {
 +              x++;
 +              x->rx_buf       = &w;
 +              x->len          = 1;
 +              spi_message_add_tail(x, &m);
 +
 +              if (rlen > 1) {
 +                      /* Arrange for the extra clock before the first
 +                       * data bit.
 +                       */
 +                      x->bits_per_word = 9;
 +                      x->len           = 2;
 +
 +                      x++;
 +                      x->rx_buf        = &rbuf[1];
 +                      x->len           = rlen - 1;
 +                      spi_message_add_tail(x, &m);
 +              }
 +      }
 +
 +      r = spi_sync(md->spi, &m);
 +      if (r < 0)
 +              dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
 +
 +      if (rlen)
 +              rbuf[0] = w & 0xff;
 +}
 +
 +static inline void mipid_cmd(struct mipid_device *md, int cmd)
 +{
 +      mipid_transfer(md, cmd, NULL, 0, NULL, 0);
 +}
 +
 +static inline void mipid_write(struct mipid_device *md,
 +                             int reg, const u8 *buf, int len)
 +{
 +      mipid_transfer(md, reg, buf, len, NULL, 0);
 +}
 +
 +static inline void mipid_read(struct mipid_device *md,
 +                            int reg, u8 *buf, int len)
 +{
 +      mipid_transfer(md, reg, NULL, 0, buf, len);
 +}
 +
 +static void set_data_lines(struct mipid_device *md, int data_lines)
 +{
 +      u16 par;
 +
 +      switch (data_lines) {
 +      case 16:
 +              par = 0x150;
 +              break;
 +      case 18:
 +              par = 0x160;
 +              break;
 +      case 24:
 +              par = 0x170;
 +              break;
 +      }
 +      mipid_write(md, 0x3a, (u8 *)&par, 2);
 +}
 +
 +static void send_init_string(struct mipid_device *md)
 +{
 +      u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
 +
 +      mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
 +      set_data_lines(md, md->panel.data_lines);
 +}
 +
 +static void hw_guard_start(struct mipid_device *md, int guard_msec)
 +{
 +      md->hw_guard_wait = msecs_to_jiffies(guard_msec);
 +      md->hw_guard_end = jiffies + md->hw_guard_wait;
 +}
 +
 +static void hw_guard_wait(struct mipid_device *md)
 +{
 +      unsigned long wait = md->hw_guard_end - jiffies;
 +
 +      if ((long)wait > 0 && wait <= md->hw_guard_wait) {
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              schedule_timeout(wait);
 +      }
 +}
 +
 +static void set_sleep_mode(struct mipid_device *md, int on)
 +{
 +      int cmd, sleep_time = 50;
 +
 +      if (on)
 +              cmd = MIPID_CMD_SLEEP_IN;
 +      else
 +              cmd = MIPID_CMD_SLEEP_OUT;
 +      hw_guard_wait(md);
 +      mipid_cmd(md, cmd);
 +      hw_guard_start(md, 120);
 +      /*
 +       * When we enable the panel, it seems we _have_ to sleep
 +       * 120 ms before sending the init string. When disabling the
 +       * panel we'll sleep for the duration of 2 frames, so that the
 +       * controller can still provide the PCLK,HS,VS signals. */
 +      if (!on)
 +              sleep_time = 120;
 +      msleep(sleep_time);
 +}
 +
 +static void set_display_state(struct mipid_device *md, int enabled)
 +{
 +      int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
 +
 +      mipid_cmd(md, cmd);
 +}
 +
 +static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +
 +      if (level > tahvo_get_max_backlight_level())
 +              return -EINVAL;
 +      if (!md->enabled) {
 +              md->saved_bklight_level = level;
 +              return 0;
 +      }
 +      tahvo_set_backlight_level(level);
 +
 +      return 0;
 +}
 +
 +static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
 +{
 +      return tahvo_get_backlight_level();
 +}
 +
 +static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
 +{
 +      return tahvo_get_max_backlight_level();
 +}
 +
 +
 +static unsigned long mipid_get_caps(struct lcd_panel *panel)
 +{
 +      return OMAPFB_CAPS_SET_BACKLIGHT;
 +}
 +
 +static u16 read_first_pixel(struct mipid_device *md)
 +{
 +      u16 pixel;
 +      u8 red, green, blue;
 +
 +      mutex_lock(&md->mutex);
 +      mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
 +      mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
 +      mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
 +      mutex_unlock(&md->mutex);
 +
 +      switch (md->panel.data_lines) {
 +      case 16:
 +              pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
 +              break;
 +      case 24:
 +              /* 24 bit -> 16 bit */
 +              pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
 +                      (blue >> 3);
 +              break;
 +      default:
 +              BUG();
 +      }
 +
 +      return pixel;
 +}
 +
 +static int mipid_run_test(struct lcd_panel *panel, int test_num)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +      static const u16 test_values[4] = {
 +              0x0000, 0xffff, 0xaaaa, 0x5555,
 +      };
 +      int i;
 +
 +      if (test_num != MIPID_TEST_RGB_LINES)
 +              return MIPID_TEST_INVALID;
 +
 +      for (i = 0; i < ARRAY_SIZE(test_values); i++) {
 +              int delay;
 +              unsigned long tmo;
 +
 +              omapfb_write_first_pixel(md->fbdev, test_values[i]);
 +              tmo = jiffies + msecs_to_jiffies(100);
 +              delay = 25;
 +              while (1) {
 +                      u16 pixel;
 +
 +                      msleep(delay);
 +                      pixel = read_first_pixel(md);
 +                      if (pixel == test_values[i])
 +                              break;
 +                      if (time_after(jiffies, tmo)) {
 +                              dev_err(&md->spi->dev,
 +                                      "MIPI LCD RGB I/F test failed: "
 +                                      "expecting %04x, got %04x\n",
 +                                      test_values[i], pixel);
 +                              return MIPID_TEST_FAILED;
 +                      }
 +                      delay = 10;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static void ls041y3_esd_recover(struct mipid_device *md)
 +{
 +      dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
 +      set_sleep_mode(md, 1);
 +      set_sleep_mode(md, 0);
 +}
 +
 +static void ls041y3_esd_check_mode1(struct mipid_device *md)
 +{
 +      u8 state1, state2;
 +
 +      mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
 +      set_sleep_mode(md, 0);
 +      mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
 +      dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
 +              state1, state2);
 +      /* Each sleep out command will trigger a self diagnostic and flip
 +      * Bit6 if the test passes.
 +      */
 +      if (!((state1 ^ state2) & (1 << 6)))
 +              ls041y3_esd_recover(md);
 +}
 +
 +static void ls041y3_esd_check_mode2(struct mipid_device *md)
 +{
 +      int i;
 +      u8 rbuf[2];
 +      static const struct {
 +              int     cmd;
 +              int     wlen;
 +              u16     wbuf[3];
 +      } *rd, rd_ctrl[7] = {
 +              { 0xb0, 4, { 0x0101, 0x01fe, } },
 +              { 0xb1, 4, { 0x01de, 0x0121, } },
 +              { 0xc2, 4, { 0x0100, 0x0100, } },
 +              { 0xbd, 2, { 0x0100, } },
 +              { 0xc2, 4, { 0x01fc, 0x0103, } },
 +              { 0xb4, 0, },
 +              { 0x00, 0, },
 +      };
 +
 +      rd = rd_ctrl;
 +      for (i = 0; i < 3; i++, rd++)
 +              mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
 +
 +      udelay(10);
 +      mipid_read(md, rd->cmd, rbuf, 2);
 +      rd++;
 +
 +      for (i = 0; i < 3; i++, rd++) {
 +              udelay(10);
 +              mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
 +      }
 +
 +      dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
 +      if (rbuf[1] == 0x00)
 +              ls041y3_esd_recover(md);
 +}
 +
 +static void ls041y3_esd_check(struct mipid_device *md)
 +{
 +      ls041y3_esd_check_mode1(md);
 +      if (md->revision >= 0x88)
 +              ls041y3_esd_check_mode2(md);
 +}
 +
 +static void mipid_esd_start_check(struct mipid_device *md)
 +{
 +      if (md->esd_check != NULL)
 +              queue_delayed_work(md->esd_wq, &md->esd_work,
 +                                 MIPID_ESD_CHECK_PERIOD);
 +}
 +
 +static void mipid_esd_stop_check(struct mipid_device *md)
 +{
 +      if (md->esd_check != NULL)
 +              cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work);
 +}
 +
 +static void mipid_esd_work(struct work_struct *work)
 +{
 +      struct mipid_device *md = container_of(work, struct mipid_device, esd_work.work);
 +
 +      mutex_lock(&md->mutex);
 +      md->esd_check(md);
 +      mutex_unlock(&md->mutex);
 +      mipid_esd_start_check(md);
 +}
 +
 +static int mipid_enable(struct lcd_panel *panel)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +
 +      mutex_lock(&md->mutex);
 +
 +      if (md->enabled) {
 +              mutex_unlock(&md->mutex);
 +              return 0;
 +      }
 +      set_sleep_mode(md, 0);
 +      md->enabled = 1;
 +      send_init_string(md);
 +      set_display_state(md, 1);
 +      mipid_set_bklight_level(panel, md->saved_bklight_level);
 +      mipid_esd_start_check(md);
 +
 +      mutex_unlock(&md->mutex);
 +      return 0;
 +}
 +
 +static void mipid_disable(struct lcd_panel *panel)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +
 +      /*
 +       * A final ESD work might be called before returning,
 +       * so do this without holding the lock.
 +       */
 +      mipid_esd_stop_check(md);
 +      mutex_lock(&md->mutex);
 +
 +      if (!md->enabled) {
 +              mutex_unlock(&md->mutex);
 +              return;
 +      }
 +      md->saved_bklight_level = mipid_get_bklight_level(panel);
 +      mipid_set_bklight_level(panel, 0);
 +      set_display_state(md, 0);
 +      set_sleep_mode(md, 1);
 +      md->enabled = 0;
 +
 +      mutex_unlock(&md->mutex);
 +}
 +
 +static int panel_enabled(struct mipid_device *md)
 +{
 +      u32 disp_status;
 +      int enabled;
 +
 +      mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
 +      disp_status = __be32_to_cpu(disp_status);
 +      enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
 +      dev_dbg(&md->spi->dev,
 +              "LCD panel %senabled by bootloader (status 0x%04x)\n",
 +              enabled ? "" : "not ", disp_status);
 +      return enabled;
 +}
 +
 +static int mipid_init(struct lcd_panel *panel,
 +                          struct omapfb_device *fbdev)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +
 +      md->fbdev = fbdev;
 +      md->esd_wq = create_singlethread_workqueue("mipid_esd");
 +      if (md->esd_wq == NULL) {
 +              dev_err(&md->spi->dev, "can't create ESD workqueue\n");
 +              return -ENOMEM;
 +      }
 +      INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
 +      mutex_init(&md->mutex);
 +
 +      md->enabled = panel_enabled(md);
 +
 +      if (md->enabled)
 +              mipid_esd_start_check(md);
 +      else
 +              md->saved_bklight_level = mipid_get_bklight_level(panel);
 +
 +      return 0;
 +}
 +
 +static void mipid_cleanup(struct lcd_panel *panel)
 +{
 +      struct mipid_device *md = to_mipid_device(panel);
 +
 +      if (md->enabled)
 +              mipid_esd_stop_check(md);
 +      destroy_workqueue(md->esd_wq);
 +}
 +
 +static struct lcd_panel mipid_panel = {
 +      .config         = OMAP_LCDC_PANEL_TFT,
 +
 +      .bpp            = 16,
 +      .x_res          = 800,
 +      .y_res          = 480,
 +      .pixel_clock    = 21940,
 +      .hsw            = 50,
 +      .hfp            = 20,
 +      .hbp            = 15,
 +      .vsw            = 2,
 +      .vfp            = 1,
 +      .vbp            = 3,
 +
 +      .init           = mipid_init,
 +      .cleanup        = mipid_cleanup,
 +      .enable         = mipid_enable,
 +      .disable        = mipid_disable,
 +      .get_caps       = mipid_get_caps,
 +      .set_bklight_level= mipid_set_bklight_level,
 +      .get_bklight_level= mipid_get_bklight_level,
 +      .get_bklight_max= mipid_get_bklight_max,
 +      .run_test       = mipid_run_test,
 +};
 +
 +static int mipid_detect(struct mipid_device *md)
 +{
 +      struct mipid_platform_data *pdata;
 +
 +      pdata = md->spi->dev.platform_data;
 +      if (pdata == NULL) {
 +              dev_err(&md->spi->dev, "missing platform data\n");
 +              return -ENOENT;
 +      }
 +
 +      mipid_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
 +      dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
 +              md->display_id[0], md->display_id[1], md->display_id[2]);
 +
 +      switch (md->display_id[0]) {
 +      case 0x45:
 +              md->model = MIPID_VER_LPH8923;
 +              md->panel.name = "lph8923";
 +              break;
 +      case 0x83:
 +              md->model = MIPID_VER_LS041Y3;
 +              md->panel.name = "ls041y3";
 +              md->esd_check = ls041y3_esd_check;
 +              break;
 +      default:
 +              md->panel.name = "unknown";
 +              dev_err(&md->spi->dev, "invalid display ID\n");
 +              return -ENODEV;
 +      }
 +
 +      md->revision = md->display_id[1];
 +      md->panel.data_lines = pdata->data_lines;
 +      pr_info("omapfb: %s rev %02x LCD detected\n",
 +                      md->panel.name, md->revision);
 +
 +      return 0;
 +}
 +
 +static int mipid_spi_probe(struct spi_device *spi)
 +{
 +      struct mipid_device *md;
 +      int r;
 +
 +      md = kzalloc(sizeof(*md), GFP_KERNEL);
 +      if (md == NULL) {
 +              dev_err(&spi->dev, "out of memory\n");
 +              return -ENOMEM;
 +      }
 +
 +      spi->mode = SPI_MODE_0;
 +      md->spi = spi;
 +      dev_set_drvdata(&spi->dev, md);
 +      md->panel = mipid_panel;
 +
 +      r = mipid_detect(md);
 +      if (r < 0)
 +              return r;
 +
 +      omapfb_register_panel(&md->panel);
 +
 +      return 0;
 +}
 +
 +static int mipid_spi_remove(struct spi_device *spi)
 +{
 +      struct mipid_device *md = dev_get_drvdata(&spi->dev);
 +
 +      mipid_disable(&md->panel);
 +      kfree(md);
 +
 +      return 0;
 +}
 +
 +static struct spi_driver mipid_spi_driver = {
 +      .driver = {
 +              .name   = MIPID_MODULE_NAME,
 +              .bus    = &spi_bus_type,
 +              .owner  = THIS_MODULE,
 +      },
 +      .probe  = mipid_spi_probe,
 +      .remove = __devexit_p(mipid_spi_remove),
 +};
 +
 +static int mipid_drv_init(void)
 +{
 +      spi_register_driver(&mipid_spi_driver);
 +
 +      return 0;
 +}
 +module_init(mipid_drv_init);
 +
 +static void mipid_drv_cleanup(void)
 +{
 +      spi_unregister_driver(&mipid_spi_driver);
 +}
 +module_exit(mipid_drv_cleanup);
 +
 +MODULE_DESCRIPTION("MIPI display driver");
 +MODULE_LICENSE("GPL");
index 8311cac19e242f60fe2cf3c6af2ebfdebd13a57b,0000000000000000000000000000000000000000..8a0105e3520d5bfbfc21f5f81f675fbbf5608a26
mode 100644,000000..100644
--- /dev/null
@@@ -1,195 -1,0 +1,195 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the MISTRAL OMAP2EVM board
 + *
 + * Author: Arun C <arunedarath@mistralsolutions.com>
 + *
 + * Derived from drivers/video/omap/lcd_omap3evm.c
 + * Derived from drivers/video/omap/lcd-apollon.c
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c/twl4030.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +#include <asm/mach-types.h>
 +
 +#define LCD_PANEL_ENABLE_GPIO 154
 +#define LCD_PANEL_LR          128
 +#define LCD_PANEL_UD          129
 +#define LCD_PANEL_INI         152
 +#define LCD_PANEL_QVGA                148
 +#define LCD_PANEL_RESB                153
 +
 +#define LCD_XRES              480
 +#define LCD_YRES              640
 +#define LCD_PIXCLOCK_MAX      20000 /* in kHz */
 +
 +#define TWL_LED_LEDEN         0x00
 +#define TWL_PWMA_PWMAON               0x00
 +#define TWL_PWMA_PWMAOFF      0x01
 +
 +static unsigned int bklight_level;
 +
 +static int omap2evm_panel_init(struct lcd_panel *panel,
 +                              struct omapfb_device *fbdev)
 +{
 +      omap_request_gpio(LCD_PANEL_ENABLE_GPIO);
 +      omap_request_gpio(LCD_PANEL_LR);
 +      omap_request_gpio(LCD_PANEL_UD);
 +      omap_request_gpio(LCD_PANEL_INI);
 +      omap_request_gpio(LCD_PANEL_QVGA);
 +      omap_request_gpio(LCD_PANEL_RESB);
 +
 +      omap_set_gpio_direction(LCD_PANEL_ENABLE_GPIO, 0);
 +      omap_set_gpio_direction(LCD_PANEL_LR, 0);
 +      omap_set_gpio_direction(LCD_PANEL_UD, 0);
 +      omap_set_gpio_direction(LCD_PANEL_INI, 0);
 +      omap_set_gpio_direction(LCD_PANEL_QVGA, 0);
 +      omap_set_gpio_direction(LCD_PANEL_RESB, 0);
 +
 +      omap_set_gpio_dataout(LCD_PANEL_RESB, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_INI, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_QVGA, 0);
 +      omap_set_gpio_dataout(LCD_PANEL_LR, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_UD, 1);
 +
 +      twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
 +      bklight_level = 100;
 +
 +      return 0;
 +}
 +
 +static void omap2evm_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int omap2evm_panel_enable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 0);
 +      return 0;
 +}
 +
 +static void omap2evm_panel_disable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 1);
 +}
 +
 +static unsigned long omap2evm_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +static int omap2evm_bklight_setlevel(struct lcd_panel *panel,
 +                                              unsigned int level)
 +{
 +      u8 c;
 +      if ((level >= 0) && (level <= 100)) {
 +              c = (125 * (100 - level)) / 100 + 2;
 +              twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
 +              bklight_level = level;
 +      }
 +      return 0;
 +}
 +
 +static unsigned int omap2evm_bklight_getlevel(struct lcd_panel *panel)
 +{
 +      return bklight_level;
 +}
 +
 +static unsigned int omap2evm_bklight_getmaxlevel(struct lcd_panel *panel)
 +{
 +      return 100;
 +}
 +
 +struct lcd_panel omap2evm_panel = {
 +      .name           = "omap2evm",
 +      .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
 +                        OMAP_LCDC_INV_HSYNC,
 +
 +      .bpp            = 16,
 +      .data_lines     = 18,
 +      .x_res          = LCD_XRES,
 +      .y_res          = LCD_YRES,
 +      .hsw            = 3,
 +      .hfp            = 0,
 +      .hbp            = 28,
 +      .vsw            = 2,
 +      .vfp            = 1,
 +      .vbp            = 0,
 +
 +      .pixel_clock    = LCD_PIXCLOCK_MAX,
 +
 +      .init           = omap2evm_panel_init,
 +      .cleanup        = omap2evm_panel_cleanup,
 +      .enable         = omap2evm_panel_enable,
 +      .disable        = omap2evm_panel_disable,
 +      .get_caps       = omap2evm_panel_get_caps,
 +      .set_bklight_level      = omap2evm_bklight_setlevel,
 +      .get_bklight_level      = omap2evm_bklight_getlevel,
 +      .get_bklight_max        = omap2evm_bklight_getmaxlevel,
 +};
 +
 +static int omap2evm_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&omap2evm_panel);
 +      return 0;
 +}
 +
 +static int omap2evm_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int omap2evm_panel_suspend(struct platform_device *pdev,
 +                                 pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int omap2evm_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver omap2evm_panel_driver = {
 +      .probe          = omap2evm_panel_probe,
 +      .remove         = omap2evm_panel_remove,
 +      .suspend        = omap2evm_panel_suspend,
 +      .resume         = omap2evm_panel_resume,
 +      .driver         = {
 +              .name   = "omap2evm_lcd",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap2evm_panel_drv_init(void)
 +{
 +      return platform_driver_register(&omap2evm_panel_driver);
 +}
 +
 +static void __exit omap2evm_panel_drv_exit(void)
 +{
 +      platform_driver_unregister(&omap2evm_panel_driver);
 +}
 +
 +module_init(omap2evm_panel_drv_init);
 +module_exit(omap2evm_panel_drv_exit);
index 69d4e06a9431e358cce2eee0fa625555e04f5d49,0000000000000000000000000000000000000000..96377353b757431fbafebe1d9a186b9083d963f6
mode 100644,000000..100644
--- /dev/null
@@@ -1,133 -1,0 +1,133 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the TI OMAP3 Beagle board
 + *
 + * Author: Koen Kooi <koen@openembedded.org>
 + *
 + * Derived from drivers/video/omap/lcd-omap3evm.c
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c/twl4030.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +#include <asm/mach-types.h>
 +
 +#define LCD_PANEL_ENABLE_GPIO       170
 +
 +#define LCD_XRES              1024    
 +#define LCD_YRES              768
 +#define LCD_PIXCLOCK          64000 /* in kHz */
 +
 +static int omap3beagle_panel_init(struct lcd_panel *panel,
 +                              struct omapfb_device *fbdev)
 +{
 +      omap_request_gpio(LCD_PANEL_ENABLE_GPIO);
 +      return 0;
 +}
 +
 +static void omap3beagle_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int omap3beagle_panel_enable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 1);
 +      return 0;
 +}
 +
 +static void omap3beagle_panel_disable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 0);
 +}
 +
 +static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +struct lcd_panel omap3beagle_panel = {
 +      .name           = "omap3beagle",
 +      .config         = OMAP_LCDC_PANEL_TFT,
 +
 +      .bpp            = 24,
 +      .data_lines     = 24,
 +      .x_res          = LCD_XRES,
 +      .y_res          = LCD_YRES,
 +      .hsw            = 3,            /* hsync_len (4) - 1 */
 +      .hfp            = 3,            /* right_margin (4) - 1 */
 +      .hbp            = 39,           /* left_margin (40) - 1 */
 +      .vsw            = 1,            /* vsync_len (2) - 1 */
 +      .vfp            = 2,            /* lower_margin */
 +      .vbp            = 7,            /* upper_margin (8) - 1 */
 +
 +      .pixel_clock    = LCD_PIXCLOCK,
 +
 +      .init           = omap3beagle_panel_init,
 +      .cleanup        = omap3beagle_panel_cleanup,
 +      .enable         = omap3beagle_panel_enable,
 +      .disable        = omap3beagle_panel_disable,
 +      .get_caps       = omap3beagle_panel_get_caps,
 +};
 +
 +static int omap3beagle_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&omap3beagle_panel);
 +      return 0;
 +}
 +
 +static int omap3beagle_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int omap3beagle_panel_suspend(struct platform_device *pdev,
 +                                 pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int omap3beagle_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver omap3beagle_panel_driver = {
 +      .probe          = omap3beagle_panel_probe,
 +      .remove         = omap3beagle_panel_remove,
 +      .suspend        = omap3beagle_panel_suspend,
 +      .resume         = omap3beagle_panel_resume,
 +      .driver         = {
 +              .name   = "omap3beagle_lcd",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap3beagle_panel_drv_init(void)
 +{
 +      return platform_driver_register(&omap3beagle_panel_driver);
 +}
 +
 +static void __exit omap3beagle_panel_drv_exit(void)
 +{
 +      platform_driver_unregister(&omap3beagle_panel_driver);
 +}
 +
 +module_init(omap3beagle_panel_drv_init);
 +module_exit(omap3beagle_panel_drv_exit);
index f5a1477036bc5e6d6a3ad9e6cc907fa3430e87e0,0000000000000000000000000000000000000000..a564ca54b5c83506a9f0504e0a7e22426cc3150a
mode 100644,000000..100644
--- /dev/null
@@@ -1,197 -1,0 +1,197 @@@
- #include <asm/arch/gpio.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the TI OMAP3 EVM board
 + *
 + * Author: Steve Sakoman <steve@sakoman.com>
 + *
 + * Derived from drivers/video/omap/lcd-apollon.c
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c/twl4030.h>
 +
++#include <mach/gpio.h>
++#include <mach/mux.h>
++#include <mach/omapfb.h>
 +#include <asm/mach-types.h>
 +
 +#define LCD_PANEL_ENABLE_GPIO       153
 +#define LCD_PANEL_LR                2
 +#define LCD_PANEL_UD                3
 +#define LCD_PANEL_INI               152
 +#define LCD_PANEL_QVGA              154
 +#define LCD_PANEL_RESB              155
 +
 +#define LCD_XRES              480
 +#define LCD_YRES              640
 +#define LCD_PIXCLOCK          26000 /* in kHz  */
 +
 +#define ENABLE_VDAC_DEDICATED 0x03
 +#define ENABLE_VDAC_DEV_GRP   0x20
 +#define ENABLE_VPLL2_DEDICATED        0x05
 +#define ENABLE_VPLL2_DEV_GRP  0xE0
 +
 +#define TWL_LED_LEDEN         0x00
 +#define TWL_PWMA_PWMAON               0x00
 +#define TWL_PWMA_PWMAOFF      0x01
 +
 +static unsigned int bklight_level;
 +
 +static int omap3evm_panel_init(struct lcd_panel *panel,
 +                              struct omapfb_device *fbdev)
 +{
 +      omap_request_gpio(LCD_PANEL_LR);
 +      omap_request_gpio(LCD_PANEL_UD);
 +      omap_request_gpio(LCD_PANEL_INI);
 +      omap_request_gpio(LCD_PANEL_RESB);
 +      omap_request_gpio(LCD_PANEL_QVGA);
 +
 +      omap_set_gpio_direction(LCD_PANEL_LR, 0);
 +      omap_set_gpio_direction(LCD_PANEL_UD, 0);
 +      omap_set_gpio_direction(LCD_PANEL_INI, 0);
 +      omap_set_gpio_direction(LCD_PANEL_RESB, 0);
 +      omap_set_gpio_direction(LCD_PANEL_QVGA, 0);
 +
 +      twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
 +      twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
 +      bklight_level = 100;
 +
 +      omap_set_gpio_dataout(LCD_PANEL_RESB, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_INI, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_QVGA, 0);
 +      omap_set_gpio_dataout(LCD_PANEL_LR, 1);
 +      omap_set_gpio_dataout(LCD_PANEL_UD, 1);
 +
 +      return 0;
 +}
 +
 +static void omap3evm_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int omap3evm_panel_enable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 0);
 +      return 0;
 +}
 +
 +static void omap3evm_panel_disable(struct lcd_panel *panel)
 +{
 +      omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 1);
 +}
 +
 +static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
 +                                              unsigned int level)
 +{
 +      u8 c;
 +      if ((level >= 0) && (level <= 100)) {
 +              c = (125 * (100 - level)) / 100 + 2;
 +              twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
 +              bklight_level = level;
 +      }
 +      return 0;
 +}
 +
 +static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
 +{
 +      return bklight_level;
 +}
 +
 +static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel)
 +{
 +      return 100;
 +}
 +
 +struct lcd_panel omap3evm_panel = {
 +      .name           = "omap3evm",
 +      .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
 +                        OMAP_LCDC_INV_HSYNC,
 +
 +      .bpp            = 16,
 +      .data_lines     = 18,
 +      .x_res          = LCD_XRES,
 +      .y_res          = LCD_YRES,
 +      .hsw            = 3,            /* hsync_len (4) - 1 */
 +      .hfp            = 3,            /* right_margin (4) - 1 */
 +      .hbp            = 39,           /* left_margin (40) - 1 */
 +      .vsw            = 1,            /* vsync_len (2) - 1 */
 +      .vfp            = 2,            /* lower_margin */
 +      .vbp            = 7,            /* upper_margin (8) - 1 */
 +
 +      .pixel_clock    = LCD_PIXCLOCK,
 +
 +      .init           = omap3evm_panel_init,
 +      .cleanup        = omap3evm_panel_cleanup,
 +      .enable         = omap3evm_panel_enable,
 +      .disable        = omap3evm_panel_disable,
 +      .get_caps       = omap3evm_panel_get_caps,
 +      .set_bklight_level      = omap3evm_bklight_setlevel,
 +      .get_bklight_level      = omap3evm_bklight_getlevel,
 +      .get_bklight_max        = omap3evm_bklight_getmaxlevel,
 +};
 +
 +static int omap3evm_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&omap3evm_panel);
 +      return 0;
 +}
 +
 +static int omap3evm_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int omap3evm_panel_suspend(struct platform_device *pdev,
 +                                 pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int omap3evm_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver omap3evm_panel_driver = {
 +      .probe          = omap3evm_panel_probe,
 +      .remove         = omap3evm_panel_remove,
 +      .suspend        = omap3evm_panel_suspend,
 +      .resume         = omap3evm_panel_resume,
 +      .driver         = {
 +              .name   = "omap3evm_lcd",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap3evm_panel_drv_init(void)
 +{
 +      return platform_driver_register(&omap3evm_panel_driver);
 +}
 +
 +static void __exit omap3evm_panel_drv_exit(void)
 +{
 +      platform_driver_unregister(&omap3evm_panel_driver);
 +}
 +
 +module_init(omap3evm_panel_drv_init);
 +module_exit(omap3evm_panel_drv_exit);
index b0a0af8bf206350469487b64404621600c5991f4,0000000000000000000000000000000000000000..8c66bf635d680371639faa0fb98e1af2295a5fad
mode 100644,000000..100644
--- /dev/null
@@@ -1,342 -1,0 +1,342 @@@
- #include <asm/arch/mux.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/omapfb.h>
 +/*
 + * LCD panel support for the TI OMAP P2 board
 + *
 + * Authors:
 + *   jekyll <jekyll@mail.jekyll.idv.tw>
 + *   B Jp <lastjp_fr@yahoo.fr>
 + *   Brian Swetland <swetland@android.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/delay.h>
 +#include <linux/platform_device.h>
 +
++#include <mach/mux.h>
++#include <mach/gpio.h>
++#include <mach/omapfb.h>
 +
 +/*
 + * File: epson-md-tft.h
 + *
 + * This file contains definitions for Epsons MD-TF LCD Module
 + *
 + * Copyright (C) 2004 MPC-Data Limited  (http://www.mpc-data.co.uk)
 + * Author: Dave Peverley <dpeverley at mpc-data.co.uk>
 + *
 + *  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  SOFTWARE  IS  PROVIDED  ``AS  IS''  AND   ANY  EXPRESS  OR IMPLIED
 + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 + *  NO  EVENT  SHALL   THE 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.
 + *
 + *  You should have received a copy of the  GNU General Public License along
 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
 + *  675 Mass Ave, Cambridge, MA 02139, USA.
 + *
 + * Please report all bugs and problems to the author.
 + *
 + */
 +
 +/* LCD uWire commands & params
 + * All values from Epson
 + */
 +#define LCD_DISON 0xAF
 +#define LCD_DISOFF 0xAE
 +#define LCD_DISNOR 0xA6
 +#define LCD_DISINV 0xA7
 +#define LCD_DISCTL 0xCA
 +#define LCD_GCP64 0xCB
 +#define LCD_GCP16 0xCC
 +#define LCD_GSSET 0xCD
 +#define LCD_SLPIN 0x95
 +#define LCD_SLPOUT 0x94
 +#define LCD_SD_PSET 0x75
 +#define LCD_MD_PSET 0x76
 +#define LCD_SD_CSET 0x15
 +#define LCD_MD_CSET 0x16
 +#define LCD_DATCTL 0xBC
 +#define LCD_RAMWR 0x5C
 +#define LCD_RAMRD 0x5D
 +#define LCD_PTLIN 0xA8
 +#define LCD_PTLOUT 0xA9
 +#define LCD_ASCSET 0xAA
 +#define LCD_SCSTART 0xAB
 +#define LCD_VOLCTL 0xC6
 +#define LCD_NOP 0x25
 +#define LCD_OSCISEL 0x7
 +#define LCD_3500KSET 0xD1
 +#define LCD_3500KEND 0xD2
 +#define LCD_14MSET 0xD3
 +#define LCD_14MEND 0xD4
 +
 +#define INIT_3500KSET 0x45
 +#define INIT_14MSET 0x4B
 +#define INIT_DATCTL 0x08 /* 6.6.6 bits for D-Sample */
 +
 +#define INIT_OSCISEL 0x05
 +
 +#define INIT_VOLCTL 0x77 /* Nominel "volume" */
 +
 +#define INIT_VOLCTL_Ton 0x98 /* Activate power-IC timer */
 +#define INIT_GSSET 0x00
 +
 +const unsigned short INIT_DISCTL[11] =
 +{
 +      0xDE, 0x01, 0x64, 0x00, 0x1B, 0xF4, 0x00, 0xDC, 0x00, 0x02, 0x00
 +};
 +
 +const unsigned short INIT_GCP64[126] =
 +{
 +      0x3B,0x00,0x42,0x00,0x4A,0x00,0x51,0x00,
 +      0x58,0x00,0x5F,0x00,0x66,0x00,0x6E,0x00,
 +      0x75,0x00,0x7C,0x00,0x83,0x00,0x8A,0x00,
 +      0x92,0x00,0x99,0x00,0xA0,0x00,0xA7,0x00,
 +      0xAE,0x00,0xB6,0x00,0xBD,0x00,0xC4,0x00,
 +      0xCB,0x00,0xD2,0x00,0xDA,0x00,0xE1,0x00,
 +      0xE8,0x00,0xEF,0x00,0xF6,0x00,0xFE,0x00,
 +      0x05,0x01,0x0C,0x01,0x13,0x01,0x1A,0x01,
 +      0x22,0x01,0x29,0x01,0x30,0x01,0x37,0x01,
 +      0x3E,0x01,0x46,0x01,0x4D,0x01,0x54,0x01,
 +      0x5B,0x01,0x62,0x01,0x6A,0x01,0x71,0x01,
 +      0x78,0x01,0x7F,0x01,0x86,0x01,0x8E,0x01,
 +      0x95,0x01,0x9C,0x01,0xA3,0x01,0xAA,0x01,
 +      0xB2,0x01,0xB9,0x01,0xC0,0x01,0xC7,0x01,
 +      0xCE,0x01,0xD6,0x01,0xDD,0x01,0xE4,0x01,
 +      0xEB,0x01,0xF2,0x01,0xFA,0x01
 +};
 +
 +const unsigned short INIT_GCP16[15] =
 +{
 +      0x1A,0x31,0x48,0x54,0x5F,0x67,0x70,0x76,0x7C,0x80,0x83,0x84,0x85,0x87,0x96
 +};
 +
 +const unsigned short INIT_MD_PSET[4] = { 0, 0, 219, 0 };
 +const unsigned short INIT_MD_CSET[4] = { 2, 0, 177, 0 };
 +
 +const unsigned short INIT_SD_PSET[4] = { 0x00, 0x01, 0x00, 0x01 };
 +const unsigned short INIT_SD_CSET[4] = { 0x00, 0x02, 0x00, 0x02 };
 +
 +const unsigned short INIT_ASCSET[7] = { 0x00, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0x01 };
 +const unsigned short INIT_SCSTART[2] = { 0x00, 0x00 };
 +
 +/* ----- end of epson_md_tft.h ----- */
 +
 +
 +#include "../drivers/ssi/omap-uwire.h"
 +
 +#define LCD_UWIRE_CS 0
 +
 +static int p2_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
 +{
 +      return 0;
 +}
 +
 +static void p2_panel_cleanup(struct lcd_panel *panel)
 +{
 +}
 +
 +static int p2_panel_enable(struct lcd_panel *panel)
 +{
 +      int i;
 +      unsigned long value;
 +
 +              /* thwack the reset line */
 +      omap_set_gpio_direction(19, 0);
 +      omap_set_gpio_dataout(19, 0);
 +      mdelay(2);
 +      omap_set_gpio_dataout(19, 1);
 +
 +              /* bits 31:28 -> 0  LCD_PXL_15 .. 12 */
 +      value = omap_readl(OMAP730_IO_CONF_3) & 0x0FFFFFFF;
 +      omap_writel(value, OMAP730_IO_CONF_3);
 +
 +              /* bits 19:0 -> 0  LCD_VSYNC, AC, PXL_0, PCLK, HSYNC,
 +              **                 PXL_9..1, PXL_10, PXL_11
 +              */
 +      value = omap_readl(OMAP730_IO_CONF_4) & 0xFFF00000;
 +      omap_writel(value, OMAP730_IO_CONF_4);
 +
 +      omap_uwire_configure_mode(0,16);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISOFF, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPIN, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISNOR, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GSSET, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GSSET | 0x100), 9, 0,NULL,1);
 +
 +      /* DISCTL */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISCTL, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_DISCTL)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DISCTL[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* GCP64 */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP64, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_GCP64)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP64[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* GCP16 */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP16, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_GCP16)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP16[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* MD_CSET */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_CSET, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_MD_CSET)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_CSET[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* MD_PSET */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_PSET, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_MD_PSET)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_PSET[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* SD_CSET */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_CSET, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_SD_CSET)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_CSET[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* SD_PSET */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_PSET, 9, 0,NULL,1);
 +      for (i = 0; i < (sizeof(INIT_SD_PSET)/sizeof(unsigned short)); i++)
 +              omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_PSET[i] | 0x100), 9, 0,NULL,1);
 +
 +      /* DATCTL */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DATCTL, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DATCTL | 0x100), 9, 0,NULL,1);
 +
 +      /* OSSISEL = d'5 */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_OSCISEL, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_OSCISEL | 0x100), 9, 0,NULL,1);
 +
 +      /* 14MSET = d'74 */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MSET, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_14MSET | 0x100), 9, 0,NULL,1);
 +
 +      /* 14MEND */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MEND, 9, 0,NULL,1);
 +
 +      /* 3500KSET = d'69 */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KSET, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_3500KSET | 0x100), 9, 0,NULL,1);
 +
 +      /* 3500KEND */
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KEND, 9, 0,NULL,1);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPOUT, 9, 0,NULL,1);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL_Ton | 0x100), 9, 0,NULL,1);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL | 0x100), 9, 0,NULL,1);
 +
 +      omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISON, 9, 0,NULL,1);
 +
 +      /* enable backlight */
 +      omap_set_gpio_direction(134, 0);
 +      omap_set_gpio_dataout(134, 1);
 +
 +      return 0;
 +}
 +
 +static void p2_panel_disable(struct lcd_panel *panel)
 +{
 +}
 +
 +static unsigned long p2_panel_get_caps(struct lcd_panel *panel)
 +{
 +      return 0;
 +}
 +
 +struct lcd_panel p2_panel = {
 +      .name           = "p2",
 +      .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_PIX_CLOCK,
 +
 +      .bpp            = 16,
 +      .data_lines     = 16,
 +      .x_res          = 176,
 +      .y_res          = 220,
 +      .pixel_clock    = 12500,
 +      .hsw            = 5,
 +      .hfp            = 1,
 +      .hbp            = 1,
 +      .vsw            = 2,
 +      .vfp            = 12,
 +      .vbp            = 1,
 +
 +      .init           = p2_panel_init,
 +      .cleanup        = p2_panel_cleanup,
 +      .enable         = p2_panel_enable,
 +      .disable        = p2_panel_disable,
 +      .get_caps       = p2_panel_get_caps,
 +};
 +
 +static int p2_panel_probe(struct platform_device *pdev)
 +{
 +      omapfb_register_panel(&p2_panel);
 +      return 0;
 +}
 +
 +static int p2_panel_remove(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +static int p2_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
 +{
 +      return 0;
 +}
 +
 +static int p2_panel_resume(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +
 +struct platform_driver p2_panel_driver = {
 +      .probe          = p2_panel_probe,
 +      .remove         = p2_panel_remove,
 +      .suspend        = p2_panel_suspend,
 +      .resume         = p2_panel_resume,
 +      .driver         = {
 +              .name   = "lcd_p2",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int p2_panel_drv_init(void)
 +{
 +      return platform_driver_register(&p2_panel_driver);
 +}
 +
 +static void p2_panel_drv_cleanup(void)
 +{
 +      platform_driver_unregister(&p2_panel_driver);
 +}
 +
 +module_init(p2_panel_drv_init);
 +module_exit(p2_panel_drv_cleanup);
 +
Simple merge
Simple merge
Simple merge
index 8cb6aa38d647880785de77afedda58fb2df80d55,0000000000000000000000000000000000000000..880e282b75dfa6452cdd71ccd2e65bf6e2db79b3
mode 100644,000000..100644
--- /dev/null
@@@ -1,704 -1,0 +1,704 @@@
- #include <asm/hardware.h>
 +/*
 + * drivers/w1/masters/omap_hdq.c
 + *
 + * Copyright (C) 2007 Texas Instruments, Inc.
 + *
 + * This file is licensed under the terms of the GNU General Public License
 + * version 2. This program is licensed "as is" without any warranty of any
 + * kind, whether express or implied.
 + *
 + */
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/interrupt.h>
 +#include <linux/err.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <asm/irq.h>
++#include <mach/hardware.h>
 +
 +#include "../w1.h"
 +#include "../w1_int.h"
 +
 +#define       MOD_NAME        "OMAP_HDQ:"
 +
 +#define OMAP_HDQ_REVISION                     0x00
 +#define OMAP_HDQ_TX_DATA                      0x04
 +#define OMAP_HDQ_RX_DATA                      0x08
 +#define OMAP_HDQ_CTRL_STATUS                  0x0c
 +#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK    (1<<6)
 +#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE      (1<<5)
 +#define OMAP_HDQ_CTRL_STATUS_GO                       (1<<4)
 +#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION   (1<<2)
 +#define OMAP_HDQ_CTRL_STATUS_DIR              (1<<1)
 +#define OMAP_HDQ_CTRL_STATUS_MODE             (1<<0)
 +#define OMAP_HDQ_INT_STATUS                   0x10
 +#define OMAP_HDQ_INT_STATUS_TXCOMPLETE                (1<<2)
 +#define OMAP_HDQ_INT_STATUS_RXCOMPLETE                (1<<1)
 +#define OMAP_HDQ_INT_STATUS_TIMEOUT           (1<<0)
 +#define OMAP_HDQ_SYSCONFIG                    0x14
 +#define OMAP_HDQ_SYSCONFIG_SOFTRESET          (1<<1)
 +#define OMAP_HDQ_SYSCONFIG_AUTOIDLE           (1<<0)
 +#define OMAP_HDQ_SYSSTATUS                    0x18
 +#define OMAP_HDQ_SYSSTATUS_RESETDONE          (1<<0)
 +
 +#define OMAP_HDQ_FLAG_CLEAR                   0
 +#define OMAP_HDQ_FLAG_SET                     1
 +#define OMAP_HDQ_TIMEOUT                      (HZ/5)
 +
 +#define OMAP_HDQ_MAX_USER                     4
 +
 +DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue);
 +int W1_ID;
 +
 +struct hdq_data {
 +      resource_size_t         hdq_base;
 +      struct  semaphore       hdq_semlock;
 +      int                     hdq_usecount;
 +      struct  clk             *hdq_ick;
 +      struct  clk             *hdq_fck;
 +      u8                      hdq_irqstatus;
 +      spinlock_t              hdq_spinlock;
 +};
 +
 +static struct hdq_data *hdq_data;
 +
 +static int omap_hdq_get(void);
 +static int omap_hdq_put(void);
 +static int omap_hdq_break(void);
 +
 +static int __init omap_hdq_probe(struct platform_device *pdev);
 +static int omap_hdq_remove(struct platform_device *pdev);
 +
 +static struct platform_driver omap_hdq_driver = {
 +      .probe = omap_hdq_probe,
 +      .remove = omap_hdq_remove,
 +      .suspend = NULL,
 +      .resume = NULL,
 +      .driver = {
 +              .name = "omap_hdq",
 +      },
 +};
 +
 +static u8 omap_w1_read_byte(void *data);
 +static void omap_w1_write_byte(void *data, u8 byte);
 +static u8 omap_w1_reset_bus(void *data);
 +static void omap_w1_search_bus(void *data, u8 search_type,
 +      w1_slave_found_callback slave_found);
 +
 +static struct w1_bus_master omap_w1_master = {
 +      .read_byte      = omap_w1_read_byte,
 +      .write_byte     = omap_w1_write_byte,
 +      .reset_bus      = omap_w1_reset_bus,
 +      .search         = omap_w1_search_bus,
 +};
 +
 +/*
 + * HDQ register I/O routines
 + */
 +static inline u8
 +hdq_reg_in(u32 offset)
 +{
 +      return omap_readb(hdq_data->hdq_base + offset);
 +}
 +
 +static inline u8
 +hdq_reg_out(u32 offset, u8 val)
 +{
 +      omap_writeb(val, hdq_data->hdq_base + offset);
 +      return val;
 +}
 +
 +static inline u8
 +hdq_reg_merge(u32 offset, u8 val, u8 mask)
 +{
 +      u8 new_val = (omap_readb(hdq_data->hdq_base + offset) & ~mask)
 +                      | (val & mask);
 +      omap_writeb(new_val, hdq_data->hdq_base + offset);
 +      return new_val;
 +}
 +
 +/*
 + * Wait for one or more bits in flag change.
 + * HDQ_FLAG_SET: wait until any bit in the flag is set.
 + * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared.
 + * return 0 on success and -ETIMEDOUT in the case of timeout.
 + */
 +static int
 +hdq_wait_for_flag(u32 offset, u8 flag, u8 flag_set, u8 *status)
 +{
 +      int ret = 0;
 +      unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
 +
 +      if (flag_set == OMAP_HDQ_FLAG_CLEAR) {
 +              /* wait for the flag clear */
 +              while (((*status = hdq_reg_in(offset)) & flag)
 +                      && time_before(jiffies, timeout)) {
 +                      set_current_state(TASK_UNINTERRUPTIBLE);
 +                      schedule_timeout(1);
 +              }
 +              if (unlikely(*status & flag))
 +                      ret = -ETIMEDOUT;
 +      } else if (flag_set == OMAP_HDQ_FLAG_SET) {
 +              /* wait for the flag set */
 +              while (!((*status = hdq_reg_in(offset)) & flag)
 +                      && time_before(jiffies, timeout)) {
 +                      set_current_state(TASK_UNINTERRUPTIBLE);
 +                      schedule_timeout(1);
 +              }
 +              if (unlikely(!(*status & flag)))
 +                      ret = -ETIMEDOUT;
 +      } else
 +              return -EINVAL;
 +
 +      return ret;
 +}
 +
 +/*
 + * write out a byte and fill *status with HDQ_INT_STATUS
 + */
 +static int
 +hdq_write_byte(u8 val, u8 *status)
 +{
 +      int ret;
 +      u8 tmp_status;
 +      unsigned long irqflags;
 +
 +      *status = 0;
 +
 +      spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +      /* clear interrupt flags via a dummy read */
 +      hdq_reg_in(OMAP_HDQ_INT_STATUS);
 +      /* ISR loads it with new INT_STATUS */
 +      hdq_data->hdq_irqstatus = 0;
 +      spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +
 +      hdq_reg_out(OMAP_HDQ_TX_DATA, val);
 +
 +      /* set the GO bit */
 +      hdq_reg_merge(OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO,
 +              OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
 +      /* wait for the TXCOMPLETE bit */
 +      ret = wait_event_interruptible_timeout(hdq_wait_queue,
 +              hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
 +      if (unlikely(ret < 0)) {
 +              pr_debug("wait interrupted");
 +              return -EINTR;
 +      }
 +
 +      spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +      *status = hdq_data->hdq_irqstatus;
 +      spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +      /* check irqstatus */
 +      if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {
 +              pr_debug("timeout waiting for TXCOMPLETE/RXCOMPLETE, %x",
 +                      *status);
 +              return -ETIMEDOUT;
 +      }
 +
 +      /* wait for the GO bit return to zero */
 +      ret = hdq_wait_for_flag(OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO,
 +              OMAP_HDQ_FLAG_CLEAR, &tmp_status);
 +      if (ret) {
 +              pr_debug("timeout waiting GO bit return to zero, %x",
 +                      tmp_status);
 +              return ret;
 +      }
 +
 +      return ret;
 +}
 +
 +/*
 + * HDQ Interrupt service routine.
 + */
 +static irqreturn_t
 +hdq_isr(int irq, void *arg)
 +{
 +      unsigned long irqflags;
 +
 +      spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +      hdq_data->hdq_irqstatus = hdq_reg_in(OMAP_HDQ_INT_STATUS);
 +      spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +      pr_debug("hdq_isr: %x", hdq_data->hdq_irqstatus);
 +
 +      if (hdq_data->hdq_irqstatus &
 +              (OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE
 +              | OMAP_HDQ_INT_STATUS_TIMEOUT)) {
 +              /* wake up sleeping process */
 +              wake_up_interruptible(&hdq_wait_queue);
 +      }
 +
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * HDQ Mode: always return success.
 + */
 +static u8 omap_w1_reset_bus(void *data)
 +{
 +      return 0;
 +}
 +
 +/*
 + * W1 search callback function.
 + */
 +static void omap_w1_search_bus(void *data, u8 search_type,
 +      w1_slave_found_callback slave_found)
 +{
 +      u64 module_id, rn_le, cs, id;
 +
 +      if (W1_ID)
 +              module_id = W1_ID;
 +      else
 +              module_id = 0x1;
 +
 +      rn_le = cpu_to_le64(module_id);
 +      /*
 +       * HDQ might not obey truly the 1-wire spec.
 +       * So calculate CRC based on module parameter.
 +       */
 +      cs = w1_calc_crc8((u8 *)&rn_le, 7);
 +      id = (cs << 56) | module_id;
 +
 +      slave_found(data, id);
 +}
 +
 +static int
 +_omap_hdq_reset(void)
 +{
 +      int ret;
 +      u8 tmp_status;
 +
 +      hdq_reg_out(OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET);
 +      /*
 +       * Select HDQ mode & enable clocks.
 +       * It is observed that INT flags can't be cleared via a read and GO/INIT
 +       * won't return to zero if interrupt is disabled. So we always enable
 +       * interrupt.
 +       */
 +      hdq_reg_out(OMAP_HDQ_CTRL_STATUS,
 +              OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
 +              OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
 +
 +      /* wait for reset to complete */
 +      ret = hdq_wait_for_flag(OMAP_HDQ_SYSSTATUS,
 +              OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status);
 +      if (ret)
 +              pr_debug("timeout waiting HDQ reset, %x", tmp_status);
 +      else {
 +              hdq_reg_out(OMAP_HDQ_CTRL_STATUS,
 +                      OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
 +                      OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
 +              hdq_reg_out(OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_AUTOIDLE);
 +      }
 +
 +      return ret;
 +}
 +
 +/*
 + * Issue break pulse to the device.
 + */
 +static int
 +omap_hdq_break()
 +{
 +      int ret;
 +      u8 tmp_status;
 +      unsigned long irqflags;
 +
 +      ret = down_interruptible(&hdq_data->hdq_semlock);
 +      if (ret < 0)
 +              return -EINTR;
 +
 +      if (!hdq_data->hdq_usecount) {
 +              up(&hdq_data->hdq_semlock);
 +              return -EINVAL;
 +      }
 +
 +      spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +      /* clear interrupt flags via a dummy read */
 +      hdq_reg_in(OMAP_HDQ_INT_STATUS);
 +      /* ISR loads it with new INT_STATUS */
 +      hdq_data->hdq_irqstatus = 0;
 +      spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +
 +      /* set the INIT and GO bit */
 +      hdq_reg_merge(OMAP_HDQ_CTRL_STATUS,
 +              OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO,
 +              OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
 +              OMAP_HDQ_CTRL_STATUS_GO);
 +
 +      /* wait for the TIMEOUT bit */
 +      ret = wait_event_interruptible_timeout(hdq_wait_queue,
 +              hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
 +      if (unlikely(ret < 0)) {
 +              pr_debug("wait interrupted");
 +              up(&hdq_data->hdq_semlock);
 +              return -EINTR;
 +      }
 +
 +      spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +      tmp_status = hdq_data->hdq_irqstatus;
 +      spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +      /* check irqstatus */
 +      if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) {
 +              pr_debug("timeout waiting for TIMEOUT, %x", tmp_status);
 +              up(&hdq_data->hdq_semlock);
 +              return -ETIMEDOUT;
 +      }
 +      /*
 +       * wait for both INIT and GO bits rerurn to zero.
 +       * zero wait time expected for interrupt mode.
 +       */
 +      ret = hdq_wait_for_flag(OMAP_HDQ_CTRL_STATUS,
 +                      OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
 +                      OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR,
 +                      &tmp_status);
 +      if (ret)
 +              pr_debug("timeout waiting INIT&GO bits return to zero, %x",
 +                      tmp_status);
 +
 +      up(&hdq_data->hdq_semlock);
 +      return ret;
 +}
 +
 +static int hdq_read_byte(u8 *val)
 +{
 +      int ret;
 +      u8 status;
 +      unsigned long irqflags;
 +
 +      ret = down_interruptible(&hdq_data->hdq_semlock);
 +      if (ret < 0)
 +              return -EINTR;
 +
 +      if (!hdq_data->hdq_usecount) {
 +              up(&hdq_data->hdq_semlock);
 +              return -EINVAL;
 +      }
 +
 +      if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
 +              hdq_reg_merge(OMAP_HDQ_CTRL_STATUS,
 +                      OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
 +                      OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
 +              /*
 +               * The RX comes immediately after TX. It
 +               * triggers another interrupt before we
 +               * sleep. So we have to wait for RXCOMPLETE bit.
 +               */
 +              {
 +                      unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
 +                      while (!(hdq_data->hdq_irqstatus
 +                              & OMAP_HDQ_INT_STATUS_RXCOMPLETE)
 +                              && time_before(jiffies, timeout)) {
 +                              set_current_state(TASK_UNINTERRUPTIBLE);
 +                              schedule_timeout(1);
 +                      }
 +              }
 +              hdq_reg_merge(OMAP_HDQ_CTRL_STATUS, 0,
 +                      OMAP_HDQ_CTRL_STATUS_DIR);
 +              spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
 +              status = hdq_data->hdq_irqstatus;
 +              spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
 +              /* check irqstatus */
 +              if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
 +                      pr_debug("timeout waiting for RXCOMPLETE, %x", status);
 +                      up(&hdq_data->hdq_semlock);
 +                      return -ETIMEDOUT;
 +              }
 +      }
 +      /* the data is ready. Read it in! */
 +      *val = hdq_reg_in(OMAP_HDQ_RX_DATA);
 +      up(&hdq_data->hdq_semlock);
 +
 +      return 0;
 +
 +}
 +
 +/*
 + * Enable clocks and set the controller to HDQ mode.
 + */
 +static int
 +omap_hdq_get()
 +{
 +      int ret = 0;
 +
 +      ret = down_interruptible(&hdq_data->hdq_semlock);
 +      if (ret < 0)
 +              return -EINTR;
 +
 +      if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) {
 +              pr_debug("attempt to exceed the max use count");
 +              up(&hdq_data->hdq_semlock);
 +              ret = -EINVAL;
 +      } else {
 +              hdq_data->hdq_usecount++;
 +              try_module_get(THIS_MODULE);
 +              if (1 == hdq_data->hdq_usecount) {
 +                      if (clk_enable(hdq_data->hdq_ick)) {
 +                              pr_debug("Can not enable ick\n");
 +                              clk_put(hdq_data->hdq_ick);
 +                              clk_put(hdq_data->hdq_fck);
 +                              up(&hdq_data->hdq_semlock);
 +                              return -ENODEV;
 +                      }
 +                      if (clk_enable(hdq_data->hdq_fck)) {
 +                              pr_debug("Can not enable fck\n");
 +                              clk_put(hdq_data->hdq_ick);
 +                              clk_put(hdq_data->hdq_fck);
 +                              up(&hdq_data->hdq_semlock);
 +                              return -ENODEV;
 +                      }
 +
 +                      /* make sure HDQ is out of reset */
 +                      if (!(hdq_reg_in(OMAP_HDQ_SYSSTATUS) &
 +                              OMAP_HDQ_SYSSTATUS_RESETDONE)) {
 +                              ret = _omap_hdq_reset();
 +                              if (ret)
 +                                      /* back up the count */
 +                                      hdq_data->hdq_usecount--;
 +                      } else {
 +                              /* select HDQ mode & enable clocks */
 +                              hdq_reg_out(OMAP_HDQ_CTRL_STATUS,
 +                                      OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
 +                                      OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
 +                              hdq_reg_out(OMAP_HDQ_SYSCONFIG,
 +                                      OMAP_HDQ_SYSCONFIG_AUTOIDLE);
 +                              hdq_reg_in(OMAP_HDQ_INT_STATUS);
 +                      }
 +              }
 +      }
 +      up(&hdq_data->hdq_semlock);
 +      return ret;
 +}
 +
 +/*
 + * Disable clocks to the module.
 + */
 +static int
 +omap_hdq_put()
 +{
 +      int ret = 0;
 +
 +      ret = down_interruptible(&hdq_data->hdq_semlock);
 +      if (ret < 0)
 +              return -EINTR;
 +
 +      if (0 == hdq_data->hdq_usecount) {
 +              pr_debug("attempt to decrement use count when it is zero");
 +              ret = -EINVAL;
 +      } else {
 +              hdq_data->hdq_usecount--;
 +              module_put(THIS_MODULE);
 +              if (0 == hdq_data->hdq_usecount) {
 +                      clk_disable(hdq_data->hdq_ick);
 +                      clk_disable(hdq_data->hdq_fck);
 +              }
 +      }
 +      up(&hdq_data->hdq_semlock);
 +      return ret;
 +}
 +
 +/*
 + * Used to control the call to omap_hdq_get and omap_hdq_put.
 + * HDQ Protocol: Write the CMD|REG_address first, followed by
 + * the data wrire or read.
 + */
 +static int init_trans;
 +
 +/*
 + * Read a byte of data from the device.
 + */
 +static u8 omap_w1_read_byte(void *data)
 +{
 +      u8 val;
 +      int ret;
 +
 +      ret = hdq_read_byte(&val);
 +      if (ret) {
 +              init_trans = 0;
 +              omap_hdq_put();
 +              return -1;
 +      }
 +
 +      /* Write followed by a read, release the module */
 +      if (init_trans) {
 +              init_trans = 0;
 +              omap_hdq_put();
 +      }
 +
 +      return val;
 +}
 +
 +/*
 + * Write a byte of data to the device.
 + */
 +static void omap_w1_write_byte(void *data, u8 byte)
 +{
 +      u8 status;
 +
 +      /* First write to initialize the transfer */
 +      if (init_trans == 0)
 +              omap_hdq_get();
 +
 +      init_trans++;
 +
 +      hdq_write_byte(byte, &status);
 +      pr_debug("Ctrl status %x\n", status);
 +
 +      /* Second write, data transfered. Release the module */
 +      if (init_trans > 1) {
 +              omap_hdq_put();
 +              init_trans = 0;
 +      }
 +
 +      return;
 +}
 +
 +static int __init omap_hdq_probe(struct platform_device *pdev)
 +{
 +      struct resource *res;
 +      int ret, irq;
 +      u8 rev;
 +
 +      if (!pdev)
 +              return -ENODEV;
 +
 +      hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL);
 +      if (!hdq_data)
 +              return -ENODEV;
 +
 +      platform_set_drvdata(pdev, hdq_data);
 +
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (res == NULL) {
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return -ENXIO;
 +      }
 +
 +      hdq_data->hdq_base = res->start;
 +
 +      /* get interface & functional clock objects */
 +      hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick");
 +      hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck");
 +
 +      if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) {
 +              pr_debug("Can't get HDQ clock objects\n");
 +              if (IS_ERR(hdq_data->hdq_ick)) {
 +                      ret = PTR_ERR(hdq_data->hdq_ick);
 +                      platform_set_drvdata(pdev, NULL);
 +                      kfree(hdq_data);
 +                      return ret;
 +              }
 +              if (IS_ERR(hdq_data->hdq_fck)) {
 +                      ret = PTR_ERR(hdq_data->hdq_fck);
 +                      platform_set_drvdata(pdev, NULL);
 +                      kfree(hdq_data);
 +                      return ret;
 +              }
 +      }
 +
 +      hdq_data->hdq_usecount = 0;
 +      sema_init(&hdq_data->hdq_semlock, 1);
 +
 +      if (clk_enable(hdq_data->hdq_ick)) {
 +              pr_debug("Can not enable ick\n");
 +              clk_put(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_fck);
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return -ENODEV;
 +      }
 +
 +      if (clk_enable(hdq_data->hdq_fck)) {
 +              pr_debug("Can not enable fck\n");
 +              clk_disable(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_fck);
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return -ENODEV;
 +      }
 +
 +      rev = hdq_reg_in(OMAP_HDQ_REVISION);
 +      pr_info("OMAP HDQ Hardware Revision %c.%c. Driver in %s mode.\n",
 +              (rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt");
 +
 +      spin_lock_init(&hdq_data->hdq_spinlock);
 +      omap_hdq_break();
 +
 +      irq = platform_get_irq(pdev, 0);
 +      if (irq < 0) {
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return -ENXIO;
 +      }
 +
 +      if (request_irq(irq, hdq_isr, IRQF_DISABLED, "OMAP HDQ",
 +              &hdq_data->hdq_semlock)) {
 +              pr_debug("request_irq failed\n");
 +              clk_disable(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_fck);
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return -ENODEV;
 +      }
 +
 +      /* don't clock the HDQ until it is needed */
 +      clk_disable(hdq_data->hdq_ick);
 +      clk_disable(hdq_data->hdq_fck);
 +
 +      ret = w1_add_master_device(&omap_w1_master);
 +      if (ret) {
 +              pr_debug("Failure in registering w1 master\n");
 +              clk_put(hdq_data->hdq_ick);
 +              clk_put(hdq_data->hdq_fck);
 +              platform_set_drvdata(pdev, NULL);
 +              kfree(hdq_data);
 +              return ret;
 +      }
 +
 +      return 0;
 +}
 +
 +static int omap_hdq_remove(struct platform_device *pdev)
 +{
 +      down_interruptible(&hdq_data->hdq_semlock);
 +      if (0 != hdq_data->hdq_usecount) {
 +              pr_debug("removed when use count is not zero\n");
 +              return -EBUSY;
 +      }
 +      up(&hdq_data->hdq_semlock);
 +
 +      /* remove module dependency */
 +      clk_put(hdq_data->hdq_ick);
 +      clk_put(hdq_data->hdq_fck);
 +      free_irq(INT_24XX_HDQ_IRQ, &hdq_data->hdq_semlock);
 +      platform_set_drvdata(pdev, NULL);
 +      kfree(hdq_data);
 +
 +      return 0;
 +}
 +
 +static int __init
 +omap_hdq_init(void)
 +{
 +      return platform_driver_register(&omap_hdq_driver);
 +}
 +
 +static void __exit
 +omap_hdq_exit(void)
 +{
 +      platform_driver_unregister(&omap_hdq_driver);
 +}
 +
 +module_init(omap_hdq_init);
 +module_exit(omap_hdq_exit);
 +
 +module_param(W1_ID, int, S_IRUSR);
 +
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION("HDQ driver Library");
 +MODULE_LICENSE("GPL");
Simple merge
index d4c7959cffd0bee6674cdf1e28bbae61182024a3,3a11dadfd8e7dba34103f9d9b8685648e14a6f31..b111dec8059d8f4d56c56370e7a5631e2dae19b2
  #include <linux/platform_device.h>
  #include <linux/moduleparam.h>
  #include <linux/clk.h>
 -#include <linux/bitops.h>
 -#include <linux/io.h>
 -#include <linux/uaccess.h>
 +
 +#include <asm/io.h>
 +#include <asm/uaccess.h>
- #include <asm/hardware.h>
+ #include <mach/hardware.h>
 +#include <asm/bitops.h>
 +
- #include <asm/arch/prcm.h>
+ #include <mach/prcm.h>
  
  #include "omap_wdt.h"
  
index be88882cf7f4884f9bdd4cf24cc96568d342b7d0,bf34c5f4c0511abc17c664655559918e2da01ef5..3ae0f7660135148c813e2ad1cfd9682d90625508
  #define I2C_DRIVERID_TDA9840   7      /* stereo sound processor       */
  #define I2C_DRIVERID_SAA7111A  8      /* video input processor        */
  #define I2C_DRIVERID_SAA7185B 13      /* video encoder                */
 +#define I2C_DRIVERID_TEA6300  18      /* audio mixer                  */
 +#define I2C_DRIVERID_TDA9850  20      /* audio mixer                  */
 +#define I2C_DRIVERID_TDA9855  21      /* audio mixer                  */
  #define I2C_DRIVERID_SAA7110  22      /* video decoder                */
- #define I2C_DRIVERID_MGATVO   23      /* Matrox TVOut                 */
  #define I2C_DRIVERID_SAA5249  24      /* SAA5249 and compatibles      */
  #define I2C_DRIVERID_PCF8583  25      /* real time clock              */
  #define I2C_DRIVERID_SAB3036  26      /* SAB3036 tuner                */
index b141cc73c23b7796beebf1b27866307199f0c301,0000000000000000000000000000000000000000..00e14fc37f4416d0f490ca7e156e34dc3ad969bf
mode 100644,000000..100644
--- /dev/null
@@@ -1,137 -1,0 +1,137 @@@
- #include <asm/arch/irqs.h>
 +/*
 + * twl4030.h - header for TWL4030 PM and audio CODEC device
 + *
 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
 + *
 + * Based on tlv320aic23.c:
 + * Copyright (c) by Kai Svahn <kai.svahn@nokia.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 __TWL4030_H_
 +#define __TWL4030_H_
 +
 +/* USB ID */
 +#define TWL4030_MODULE_USB            0x00
 +/* AUD ID */
 +#define TWL4030_MODULE_AUDIO_VOICE    0x01
 +#define TWL4030_MODULE_GPIO           0x02
 +#define TWL4030_MODULE_INTBR          0x03
 +#define TWL4030_MODULE_PIH            0x04
 +#define TWL4030_MODULE_TEST           0x05
 +/* AUX ID */
 +#define TWL4030_MODULE_KEYPAD         0x06
 +#define TWL4030_MODULE_MADC           0x07
 +#define TWL4030_MODULE_INTERRUPTS     0x08
 +#define TWL4030_MODULE_LED            0x09
 +#define TWL4030_MODULE_MAIN_CHARGE    0x0A
 +#define TWL4030_MODULE_PRECHARGE      0x0B
 +#define TWL4030_MODULE_PWM0           0x0C
 +#define TWL4030_MODULE_PWM1           0x0D
 +#define TWL4030_MODULE_PWMA           0x0E
 +#define TWL4030_MODULE_PWMB           0x0F
 +/* POWER ID */
 +#define TWL4030_MODULE_BACKUP         0x10
 +#define TWL4030_MODULE_INT            0x11
 +#define TWL4030_MODULE_PM_MASTER      0x12
 +#define TWL4030_MODULE_PM_RECEIVER    0x13
 +#define TWL4030_MODULE_RTC            0x14
 +#define TWL4030_MODULE_SECURED_REG    0x15
 +
 +/* IRQ information-need base */
++#include <mach/irqs.h>
 +/* TWL4030 interrupts */
 +
 +#define TWL4030_MODIRQ_GPIO           (TWL4030_IRQ_BASE + 0)
 +#define TWL4030_MODIRQ_KEYPAD         (TWL4030_IRQ_BASE + 1)
 +#define TWL4030_MODIRQ_BCI            (TWL4030_IRQ_BASE + 2)
 +#define TWL4030_MODIRQ_MADC           (TWL4030_IRQ_BASE + 3)
 +#define TWL4030_MODIRQ_USB            (TWL4030_IRQ_BASE + 4)
 +#define TWL4030_MODIRQ_PWR            (TWL4030_IRQ_BASE + 5)
 +
 +#define TWL4030_PWRIRQ_PWRBTN         (TWL4030_PWR_IRQ_BASE + 0)
 +#define TWL4030_PWRIRQ_CHG_PRES               (TWL4030_PWR_IRQ_BASE + 1)
 +#define TWL4030_PWRIRQ_USB_PRES               (TWL4030_PWR_IRQ_BASE + 2)
 +#define TWL4030_PWRIRQ_RTC            (TWL4030_PWR_IRQ_BASE + 3)
 +#define TWL4030_PWRIRQ_HOT_DIE                (TWL4030_PWR_IRQ_BASE + 4)
 +#define TWL4030_PWRIRQ_PWROK_TIMEOUT  (TWL4030_PWR_IRQ_BASE + 5)
 +#define TWL4030_PWRIRQ_MBCHG          (TWL4030_PWR_IRQ_BASE + 6)
 +#define TWL4030_PWRIRQ_SC_DETECT      (TWL4030_PWR_IRQ_BASE + 7)
 +
 +/* Rest are unsued currently*/
 +
 +/* Offsets to Power Registers */
 +#define TWL4030_VDAC_DEV_GRP          0x3B
 +#define TWL4030_VDAC_DEDICATED                0x3E
 +#define TWL4030_VAUX1_DEV_GRP         0x17
 +#define TWL4030_VAUX1_DEDICATED               0x1A
 +#define TWL4030_VAUX2_DEV_GRP         0x1B
 +#define TWL4030_VAUX2_DEDICATED               0x1E
 +#define TWL4030_VAUX3_DEV_GRP         0x1F
 +#define TWL4030_VAUX3_DEDICATED               0x22
 +
 +/* TWL4030 GPIO interrupt definitions */
 +
 +#define TWL4030_GPIO_MIN              0
 +#define TWL4030_GPIO_MAX              18
 +#define TWL4030_GPIO_MAX_CD           2
 +#define TWL4030_GPIO_IRQ_NO(n)                (TWL4030_GPIO_IRQ_BASE + (n))
 +#define TWL4030_GPIO_IS_INPUT         1
 +#define TWL4030_GPIO_IS_OUTPUT                0
 +#define TWL4030_GPIO_IS_ENABLE                1
 +#define TWL4030_GPIO_IS_DISABLE               0
 +#define TWL4030_GPIO_PULL_UP          0
 +#define TWL4030_GPIO_PULL_DOWN                1
 +#define TWL4030_GPIO_PULL_NONE                2
 +#define TWL4030_GPIO_EDGE_NONE                0
 +#define TWL4030_GPIO_EDGE_RISING      1
 +#define TWL4030_GPIO_EDGE_FALLING     2
 +
 +/* Functions to read and write from TWL4030 */
 +
 +/*
 + * IMP NOTE:
 + * The base address of the module will be added by the triton driver
 + * It is the caller's responsibility to ensure sane values
 + */
 +int twl4030_i2c_write_u8(u8 mod_no, u8 val, u8 reg);
 +int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
 +
 + /*
 +  * i2c_write: IMPORTANT - Allocate value num_bytes+1 and valid data starts at
 +  *           Offset 1.
 +  */
 +int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
 +int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
 +
 +/*
 + * Exported TWL4030 GPIO APIs
 + */
 +int twl4030_get_gpio_datain(int gpio);
 +int twl4030_request_gpio(int gpio);
 +int twl4030_set_gpio_edge_ctrl(int gpio, int edge);
 +int twl4030_set_gpio_debounce(int gpio, int enable);
 +int twl4030_free_gpio(int gpio);
 +
 +#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
 +      defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
 +      extern int twl4030charger_usb_en(int enable);
 +#else
 +      static inline int twl4030charger_usb_en(int enable) { return 0; }
 +#endif
 +
 +#endif /* End of __TWL4030_H */
index 6ae2677d653f8c35ff096d1b3c34f8007d4ae99e,0000000000000000000000000000000000000000..9fe8d7435c1391c0913202bb47f0872a9e18113e
mode 100644,000000..100644
--- /dev/null
@@@ -1,801 -1,0 +1,801 @@@
- #include <asm/arch/eac.h>
 +/*
 + * linux/sound/arm/omap/omap-alsa-eac.c
 + *
 + * OMAP24xx Enhanced Audio Controller sound driver
 + *
 + * Copyright (C) 2006 Nokia Corporation
 + *
 + * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
 + *          Juha Yrjölä
 + *
 + * Definitions:
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#define DEBUG
 +
 +#include <linux/device.h>
 +#include <linux/init.h>
 +#include <linux/kernel.h>
 +#include <linux/err.h>
 +#include <linux/module.h>
 +#include <linux/moduleparam.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +
 +#include <asm/io.h>
++#include <mach/eac.h>
 +
 +#include <sound/core.h>
 +#include <sound/initval.h>
 +
 +
 +#define EAC_CPCFR1            0x0000
 +#define EAC_CPCFR2            0x0004
 +#define EAC_CPCFR3            0x0008
 +#define EAC_CPCFR4            0x000C
 +#define EAC_CPTCTL            0x0010
 +#define EAC_CPTTADR           0x0014
 +#define EAC_CPTDATL           0x0018
 +#define EAC_CPTDATH           0x001C
 +#define EAC_CPTVSLL           0x0020
 +#define EAC_CPTVSLH           0x0024
 +#define EAC_MPCTR             0x0040
 +#define EAC_MPMCCFR           0x0044
 +#define EAC_BPCTR             0x0060
 +#define EAC_BPMCCFR           0x0064
 +#define EAC_AMSCFR            0x0080
 +#define EAC_AMVCTR            0x0084
 +#define EAC_AM1VCTR           0x0088
 +#define EAC_AM2VCTR           0x008C
 +#define EAC_AM3VCTR           0x0090
 +#define EAC_ASTCTR            0x0094
 +#define EAC_APD1LCR           0x0098
 +#define EAC_APD1RCR           0x009C
 +#define EAC_APD2LCR           0x00A0
 +#define EAC_APD2RCR           0x00A4
 +#define EAC_APD3LCR           0x00A8
 +#define EAC_APD3RCR           0x00AC
 +#define EAC_APD4R             0x00B0
 +#define EAC_ADWR              0x00B4
 +#define EAC_ADRDR             0x00B8
 +#define EAC_AGCFR             0x00BC
 +#define EAC_AGCTR             0x00C0
 +#define EAC_AGCFR2            0x00C4
 +#define EAC_AGCFR3            0x00C8
 +#define EAC_MBPDMACTR         0x00CC
 +#define EAC_MPDDMARR          0x00D0
 +#define EAC_MPDDMAWR          0x00D4
 +#define EAC_MPUDMARR          0x00D8
 +#define EAC_MPUDMAWR          0x00E0
 +#define EAC_BPDDMARR          0x00E4
 +#define EAC_BPDDMAWR          0x00E8
 +#define EAC_BPUDMARR          0x00EC
 +#define EAC_BPUDMAWR          0x00F0
 +#define EAC_VERSION           0x0100
 +#define EAC_SYSCONFIG         0x0104
 +#define EAC_SYSSTATUS         0x0108
 +
 +/* CPTCTL */
 +#define CPTCTL_RXF            (1 << 7)        /* receive data register full */
 +#define CPTCTL_RXIE           (1 << 6)        /* receive interrupt enable */
 +#define CPTCTL_TXE            (1 << 5)        /* transmit register empty */
 +#define CPTCTL_TXIE           (1 << 4)        /* transmit interrupt enable */
 +#define CPTCTL_CPEN           (1 << 3)        /* codec port enable */
 +#define CPTCTL_CRST           (1 << 0)        /* external codec reset */
 +
 +/* CPCFR1 */
 +#define CPCFR1_MTSL(val)      ((val & 0x1f) << 3)     /* number of time slots per frame */
 +#define CPCFR1_MTSL_BITS      (0x1f << 3)
 +#define CPCFR1_MODE(val)      ((val & 0x7) << 0)      /* codec port interface mode */
 +#define CPCFR1_MODE_BITS      (0x7 << 0)
 +
 +/* CPCFR2 */
 +#define CPCFR2_TSLOL(val)     ((val & 0x3) << 6)      /* time slot 0 length in number of serial clock (CLK_BIT) cycles */
 +#define CPCFR2_TSLOL_BITS     (0x3 << 6)
 +#define CPCFR2_BPTSL(val)     ((val & 0x7) << 3)      /* number of data bits per audio time slot */
 +#define CPCFR2_BPTSL_BITS     (0x7 << 3)
 +#define CPCFR2_TSLL(val)      ((val & 0x7) << 0)      /* time slot lenght (except slot 0) in number of serial clock cycles */
 +#define CPCFR2_TSLL_BITS      (0x7 << 0)
 +
 +/* CPCFR3 */
 +#define CPCFR3_DDLY           (1 << 7)        /* data delay: data bits start according to SYNC signal leading edge */
 +#define CPCFR3_TRSEN          (1 << 6)        /* 3-state enable: data serial output state during nonvalid audio frames */
 +#define CPCFR3_CLKBP          (1 << 5)        /* clock polarity */
 +#define CPCFR3_CSYNCP         (1 << 4)        /* cp_sync(synchro) polarity */
 +#define CPCFR3_CSYNCL         (1 << 3)        /* csync length */
 +/* bit 2 reserved */
 +#define CPCFR3_CSCLKD         (1 << 1)        /* cp_sclk port (serial clock) direction */
 +#define CPCFR3_CSYNCD         (1 << 0)        /* cp_sync (synchro) direction */
 +
 +/* CPCFR4 */
 +#define CPCFR4_ATSL(val)      ((val & 0xf) << 4)      /* audio time slots for secondary communication address and data values */
 +#define CPCFR4_ATSL_BITS      (0xf << 4)
 +#define CPCFR4_CLKS           (1 << 3)                /* clock source */
 +#define CPCFR4_DIVB(val)      ((val & 0x7) << 0)      /* cp_sclk driver value */
 +#define CPCFR4_DIVB_BITS      (0x7 << 0)
 +
 +/* AGCFR */
 +#define AGCFR_MN_ST           (1 << 10)       /* mono/stereo audio file */
 +#define AGCFR_B8_16           (1 << 9)        /* 8 bits/16 bits audio file */
 +#define AGCFR_LI_BI           (1 << 8)        /* audio file endianism */
 +#define AGCFR_FSINT(val)      ((val & 0x3) << 6) /* intermediate sample frequency for DMA read and write operations */
 +#define AGCFR_FINST_BITS      (0x3 << 6)
 +
 +#define AGCFR_FSINT_8000      (0)             /* 8000  Hz */
 +#define AGCFR_FSINT_11025     (1)             /* 11025 Hz */
 +#define AGCFR_FSINT_22050     (2)             /* 22050 Hz */
 +#define AGCFR_FSINT_44100     (3)             /* 44100 Hz */
 +
 +#define AGCFR_AUD_CKSRC(val)((val & 0x3) << 4)        /* audio processing clock source */
 +#define AGCFR_AUD_CKSRC_BITS  (0x3 << 4)
 +#define AGCFR_M_CKSRC         (1 << 3)        /* modem interface clock source */
 +#define AGCFR_MCLK_OUT                (1 << 1)
 +#define AGCFR_MCLK            (1 << 0)
 +
 +
 +/* AGCTR */
 +#define AGCTR_AUDRD           (1 << 15)       /* audio ready */
 +#define AGCTR_AUDRDI          (1 << 14)       /* audio ready interrupt status */
 +#define AGCTR_AUDRDIEN                (1 << 13)       /* audio ready interrupt enable */
 +#define AGCTR_DMAREN          (1 << 12)       /* audio files play operation */
 +#define AGCTR_DMAWEN          (1 << 11)       /* audio file record operation */
 +/* bits 10:4 reserved */
 +#define AGCTR_MCLK_EN         (1 << 3)        /* internal MCLK enable */
 +#define AGCTR_OSCMCLK_EN      (1 << 2)        /* OSCMCLK_EN output for MCLK oscillator control */
 +#define AGCTR_AUDEN           (1 << 1)        /* audio processing enable/disable */
 +#define AGCTR_EACPWD          (1 << 0)        /* EAC operation */
 +
 +/* AGCFR2 */
 +#define AGCFR2_BT_MD_WIDEBAND (1 << 5)        /* the BT device and modem AuSPIs wide-band mode */
 +#define AGCFR2_MCLK_I2S_N11M_12M (1 << 4)     /* MCLK freq indicator for audio operations */
 +#define AGCFR2_I2S_N44K_48K   (1 << 3)        /* Frame sample frecuency of I2S codec port, does not generate value */
 +#define AGCFR2_FSINT2(val)    ((val & 0x7) << 0) /* intermediate sample frequency for DMA channel read and write operations */
 +#define AGCFR2_FSINT2_BITS    (0x7 << 0)
 +
 +#define AGCFR2_FSINT2_8000    (0)             /* 8000  Hz */
 +#define AGCFR2_FSINT2_11025   (1)             /* 11025 Hz */
 +#define AGCFR2_FSINT2_22050   (2)             /* 22050 Hz */
 +#define AGCFR2_FSINT2_44100   (3)             /* 44100 Hz */
 +#define AGCFR2_FSINT2_48000   (4)             /* 48000 Hz */
 +#define AGCFR2_FSINT2_FSINT   (7)             /* based on AGCFR/FSINT */
 +
 +
 +/* AGCFR3 */
 +#define AGCFR3_CP_TR_DMA      (1 << 15)       /* codec port transparent DMA (to audio DMAs) */
 +#define AGCFR3_BT_TR_DMA      (1 << 14)       /* BT transparent DMA (to BT UL write & DL read DMAs */     
 +#define AGCFR3_MD_TR_DMA      (1 << 13)       /* modem transparent DMA (to modem UL write and DL read DMAs) */
 +#define AGCFR3_FSINT(val)     ((val & 0xf) << 9) /* FSINT */
 +#define AGCFR3_FSINT_BITS     (0xf << 9)
 +
 +#define AGCFR3_FSINT_8000     (0)             /* 8000  Hz */
 +#define AGCFR3_FSINT_11025    (1)             /* 11025 Hz */
 +#define AGCFR3_FSINT_16000    (2)             /* 16000 Hz */
 +#define AGCFR3_FSINT_22050    (3)             /* 22050 Hz */
 +#define AGCFR3_FSINT_24000    (4)             /* 24000 Hz */
 +#define AGCFR3_FSINT_32000    (5)             /* 32000 Hz */
 +#define AGCFR3_FSINT_44100    (6)             /* 44100 Hz */
 +#define AGCFR3_FSINT_48000    (7)             /* 48000 Hz */
 +#define AGCFR3_FSINT_FSINT    (15)            /* based on AGCFR2/AGCFR */
 +
 +
 +#define AGCFR3_BT_CKSRC(val)  ((val & 0x3) << 7)      /* BT port clock selection */
 +#define AGCFR3_BT_CKSRC_BITS  (0x3 << 7)
 +#define AGCFR3_MD_CKSRC(val)  ((val & 0x3) << 5)      /* modem port clock source */
 +#define AGCFR3_MD_CKSRC_BITS  (0x3 << 5)
 +#define AGCFR3_AUD_CKSRC(val) ((val & 0x7) << 2)      /* audio and codec port clock source */
 +#define AGCFR3_AUD_CKSRC_BITS (0x7 << 2)
 +#define AGCFR3_CLK12MINT_SEL  (1 << 1)                /* internal 12MHz clock source */
 +#define AGCFR3_MCLKINT_SEL    (1 << 0)                /* internal codec master clock source */
 +
 +/* AMSCFR */
 +#define AMSCFR_K12            (1 << 11)               /* K12 switch open/close */
 +#define AMSCFR_K11            (1 << 10)
 +#define AMSCFR_K10            (1 << 9)
 +#define AMSCFR_K9             (1 << 8)
 +#define AMSCFR_K8             (1 << 7)
 +#define AMSCFR_K7             (1 << 6)
 +#define AMSCFR_K6             (1 << 5)
 +#define AMSCFR_K5             (1 << 4)
 +#define AMSCFR_K4             (1 << 3)
 +#define AMSCFR_K3             (1 << 2)
 +#define AMSCFR_K2             (1 << 1)
 +#define AMSCFR_K1             (1 << 0)
 +
 +/* AMVCTR */
 +#define AMVCTR_GWO_BITS               (0xff << 8)
 +#define AMVCTR_GWO(val)               ((val & 0xff) << 8)     /* Gain on write DMA operation */
 +#define AMVCTR_GRO_BITS               (0xff << 0)
 +#define AMVCTR_GRO(val)               ((val & 0xff) << 0)     /* Gain on read DMA operation */
 +
 +/* AM1VCTR */
 +#define AM1VCTR_MUTE          (1 << 15)               /* mute/no mute on mixer output */
 +#define AM1VCTR_GINB(val)     ((val & 0x7f) << 8)     /* gain on input B */
 +#define AM1VCTR_GINB_BITS     (0x7f << 8)
 +#define AM1VCTR_GINA(val)     ((val & 0x7f) << 0)     /* gain on input A */
 +#define AM1VCTR_GINA_BITS     (0x7f << 0)
 +
 +/* AM2VCTR */
 +#define AM2VCTR_MUTE          (1 << 15)               /* mute/no mute on mixer output */
 +#define AM2VCTR_GINB(val)     ((val & 0x7f) << 8)     /* gain on input B */
 +#define AM2VCTR_GINB_BITS     (0x7f << 8)
 +#define AM2VCTR_GINA(val)     ((val & 0x7f) << 0)     /* gain on input A */
 +#define AM2VCTR_GINA_BITS     (0x7f << 0)
 +
 +/* AM3VCTR */
 +#define AM3VCTR_MUTE          (1 << 15)               /* mute/no mute */
 +#define AM3VCTR_GINB(val)     ((val & 0x7f) << 8)     /* gain on input B */
 +#define AM3VCTR_GINB_BITS     (0x7f << 8)
 +#define AM3VCTR_GINA(val)     ((val & 0x7f) << 0)     /* gain on input A */
 +#define AM3VCTR_GINA_BITS     (0x7f << 0)
 +
 +/* ASTCTR */
 +#define ASTCTR_ATT(val)               ((val & 0x7f) << 1)     /* Attenuation of side tone */
 +#define ASTCTR_ATT_BITS               (0x7f << 1)
 +#define ASTCTR_ATTEN          (1 << 0)                /* side tone enabled/disabled */
 +
 +
 +/* internal structure of the EAC driver */
 +struct omap_eac {
 +      struct mutex                    mutex;
 +      void __iomem *                  base;
 +      struct platform_device *        pdev;
 +      struct eac_platform_data *      pdata;
 +      struct snd_card *               card;
 +      struct clk *                    fck;
 +      struct clk *                    ick;
 +      struct eac_codec *              codec;
 +
 +      unsigned                        clocks_enabled:1;
 +};
 +
 +static char *id = SNDRV_DEFAULT_STR1;
 +module_param(id, charp, 0444);
 +MODULE_PARM_DESC(id, "ID string for OMAP24xx EAC");
 +
 +
 +#define MOD_REG_BIT(val, mask, set) do { \
 +      if (set) \
 +              val |= mask; \
 +      else \
 +              val &= ~mask; \
 +} while(0)
 +
 +static inline void eac_write_reg(struct omap_eac *eac, int idx, u16 val)
 +{
 +      __raw_writew(val, eac->base + idx);
 +}
 +
 +static inline u16 eac_read_reg(struct omap_eac *eac, int idx)
 +{
 +      return __raw_readw(eac->base + idx);
 +}
 +
 +static int eac_get_clocks(struct omap_eac *eac)
 +{
 +      eac->ick = clk_get(NULL, "eac_ick");
 +      if (IS_ERR(eac->ick)) {
 +              dev_err(&eac->pdev->dev, "Could not get eac_ick");
 +              return -ENODEV;
 +      }
 +
 +      eac->fck = clk_get(NULL, "eac_fck");
 +      if (IS_ERR(eac->fck)) {
 +              dev_err(&eac->pdev->dev, "Could not get eac_fck");
 +              clk_put(eac->ick);
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +static void eac_put_clocks(struct omap_eac *eac)
 +{
 +      clk_put(eac->fck);
 +      clk_put(eac->ick);
 +}
 +
 +static int eac_enable_clocks(struct omap_eac *eac)
 +{
 +      int err = 0;
 +
 +      if (eac->clocks_enabled)
 +              return 0;
 +
 +      if (eac->pdata != NULL && eac->pdata->enable_ext_clocks != NULL) {
 +              if ((err = eac->pdata->enable_ext_clocks(&eac->pdev->dev)) != 0)
 +                      return err;
 +      }
 +      clk_enable(eac->ick);
 +      clk_enable(eac->fck);
 +      eac->clocks_enabled = 1;
 +
 +      return 0;
 +}
 +
 +static void eac_disable_clocks(struct omap_eac *eac)
 +{
 +      if (!eac->clocks_enabled)
 +              return;
 +      eac->clocks_enabled = 0;
 +
 +      clk_disable(eac->fck);
 +      clk_disable(eac->ick);
 +      if (eac->pdata != NULL && eac->pdata->disable_ext_clocks != NULL)
 +              eac->pdata->disable_ext_clocks(&eac->pdev->dev);
 +}
 +
 +static int eac_reset(struct omap_eac *eac)
 +{
 +      int i;
 +
 +      /* step 1 (see TRM) */
 +      /* first, let's reset the EAC */
 +      eac_write_reg(eac, EAC_SYSCONFIG, 0x2);
 +      /* step 2 (see TRM) */
 +      eac_write_reg(eac, EAC_AGCTR, AGCTR_MCLK_EN | AGCTR_AUDEN);
 +      /* step 3 (see TRM) */
 +      /* wait until reset done */
 +      i = 10000;
 +      while (!(eac_read_reg(eac, EAC_SYSSTATUS) & 1)) {
 +              if (--i == 0)
 +                      return -ENODEV;
 +              udelay(1);
 +      }
 +
 +      return 0;
 +}
 +
 +static int eac_calc_agcfr3_fsint(int rate)
 +{
 +      int fsint;
 +
 +      if (rate >= 48000)
 +              fsint = AGCFR3_FSINT_48000;
 +      else if (rate >= 44100)
 +              fsint = AGCFR3_FSINT_44100;
 +      else if (rate >= 32000)
 +              fsint = AGCFR3_FSINT_32000;
 +      else if (rate >= 24000)
 +              fsint = AGCFR3_FSINT_24000;
 +      else if (rate >= 22050)
 +              fsint = AGCFR3_FSINT_22050;
 +      else if (rate >= 16000)
 +              fsint = AGCFR3_FSINT_16000;
 +      else if (rate >= 11025)
 +              fsint = AGCFR3_FSINT_11025;
 +      else
 +              fsint = AGCFR3_FSINT_8000;
 +
 +      return fsint;
 +}
 +
 +static int eac_configure_pcm(struct omap_eac *eac, struct eac_codec *conf)
 +{
 +      dev_err(&eac->pdev->dev,
 +              "EAC codec port configuration for PCM not implemented\n");
 +
 +      return -ENODEV;
 +}
 +
 +static int eac_configure_ac97(struct omap_eac *eac, struct eac_codec *conf)
 +{
 +      dev_err(&eac->pdev->dev,
 +              "EAC codec port configuration for AC97 not implemented\n");
 +
 +      return -ENODEV;
 +}
 +
 +static int eac_configure_i2s(struct omap_eac *eac, struct eac_codec *conf)
 +{
 +      u16 cpcfr1, cpcfr2, cpcfr3, cpcfr4;
 +
 +      cpcfr1 = eac_read_reg(eac, EAC_CPCFR1);
 +      cpcfr2 = eac_read_reg(eac, EAC_CPCFR2);
 +      cpcfr3 = eac_read_reg(eac, EAC_CPCFR3);
 +      cpcfr4 = eac_read_reg(eac, EAC_CPCFR4);
 +
 +      cpcfr1 &= ~(CPCFR1_MODE_BITS | CPCFR1_MTSL_BITS);
 +      cpcfr1 |= CPCFR1_MTSL(1); /* 2 timeslots per frame (I2S default) */
 +
 +      /* audio time slot configuration for I2S mode */
 +      cpcfr2 &= ~(CPCFR2_TSLL_BITS | CPCFR2_BPTSL_BITS | CPCFR2_TSLOL_BITS);
 +      cpcfr2 |= CPCFR2_TSLOL(0); /* time slot 0 length same as TSLL */
 +      cpcfr2 |= CPCFR2_BPTSL(1); /* 16 data bits per time slot */
 +      cpcfr2 |= CPCFR2_TSLL(1); /* time slot length 16 serial clock cycles */
 +
 +      /* I2S link configuration */
 +      MOD_REG_BIT(cpcfr3, CPCFR3_DDLY,
 +              conf->codec_conf.i2s.sync_delay_enable); /* 0/1 clk delay */
 +      /* data serial output enabled during nonvalid audio frames, clock
 +       * polarity = falling edge, CSYNC lenght equal to time slot0 length */
 +      MOD_REG_BIT(cpcfr3, CPCFR3_TRSEN, 1);
 +      MOD_REG_BIT(cpcfr3, CPCFR3_CLKBP, 1);
 +      MOD_REG_BIT(cpcfr3, CPCFR3_CSYNCL, 1);
 +
 +      cpcfr4 &= ~(CPCFR4_DIVB_BITS | CPCFR4_ATSL_BITS);
 +      cpcfr4 |= CPCFR4_DIVB(7); /* CP_SCLK = MCLK / 8 */
 +
 +      /* configuration for normal I2S or polarity-changed I2S */
 +      if (!conf->codec_conf.i2s.polarity_changed_mode) {
 +              cpcfr1 |= CPCFR1_MODE(4); /* I2S mode */
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSYNCP, 0); /* CP_SYNC active low */
 +              /* audio time slots configuration for I2S */
 +              cpcfr4 |= CPCFR4_ATSL(0);
 +      } else {
 +              cpcfr1 |= CPCFR1_MODE(1); /* PCM mode/polarity-changed I2S */
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSYNCP, 1); /* CP_SYNC active
 +                                                        high */
 +              /* audio time slots configuration for polarity-changed I2S */
 +              cpcfr4 |= CPCFR4_ATSL(0xf);
 +      };
 +
 +      /* master/slave configuration */
 +      if (conf->codec_mode == EAC_CODEC_I2S_MASTER) {
 +              /* EAC is master. Set CP_SCLK and CP_SYNC as outputs */
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSCLKD, 0);
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSYNCD, 0);
 +      } else {
 +              /* EAC is slave. Set CP_SCLK and CP_SYNC as inputs */
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSCLKD, 1);
 +              MOD_REG_BIT(cpcfr3, CPCFR3_CSYNCD, 1);
 +      }
 +
 +      eac_write_reg(eac, EAC_CPCFR1, cpcfr1);
 +      eac_write_reg(eac, EAC_CPCFR2, cpcfr2);
 +      eac_write_reg(eac, EAC_CPCFR3, cpcfr3);
 +      eac_write_reg(eac, EAC_CPCFR4, cpcfr4);
 +
 +      return 0;
 +}
 +
 +static int eac_codec_port_init(struct omap_eac *eac, struct eac_codec *conf)
 +{
 +      u16 agcfr, agcfr2, agcfr3, agctr;
 +      u16 cpctl, reg;
 +      int err = 0, i;
 +
 +      /* use internal MCLK gating before doing full configuration for it.
 +       * Partial or misconfigured MCLK will cause that access to some of the
 +       * EAC registers causes "external abort on linefetch". Same happens
 +       * also when using external clock as a MCLK source and if that clock is
 +       * either missing or not having a right rate (e.g. half of it) */
 +      agcfr3 = eac_read_reg(eac, EAC_AGCFR3);
 +      MOD_REG_BIT(agcfr3, AGCFR3_MCLKINT_SEL, 1); /* 96 Mhz / 8.5 */
 +      eac_write_reg(eac, EAC_AGCFR3, agcfr3);
 +
 +      /* disable codec port, enable access to config registers */
 +      cpctl = eac_read_reg(eac, EAC_CPTCTL);
 +      MOD_REG_BIT(cpctl, CPTCTL_CPEN, 0);
 +      eac_write_reg(eac, EAC_CPTCTL, cpctl);
 +
 +      agcfr = eac_read_reg(eac, EAC_AGCFR);
 +      agctr = eac_read_reg(eac, EAC_AGCTR);
 +      agcfr2 = eac_read_reg(eac, EAC_AGCFR2);
 +
 +      /* MCLK source and frequency configuration */
 +      MOD_REG_BIT(agcfr, AGCFR_MCLK, 0);
 +      switch (conf->mclk_src) {
 +      case EAC_MCLK_EXT_2x11289600:
 +              MOD_REG_BIT(agcfr, AGCFR_MCLK, 1); /* div by 2 path */
 +              MOD_REG_BIT(agcfr, AGCFR_MCLK_OUT, 1); /* div by 2 */
 +      case EAC_MCLK_EXT_11289600:
 +              MOD_REG_BIT(agcfr, AGCFR_MCLK, 1);
 +              MOD_REG_BIT(agcfr2, AGCFR2_I2S_N44K_48K, 0); /* 44.1 kHz */
 +              MOD_REG_BIT(agcfr2, AGCFR2_MCLK_I2S_N11M_12M, 0); /* 11.2896 */
 +              MOD_REG_BIT(agcfr3, AGCFR3_MCLKINT_SEL, 0);
 +              break;
 +
 +      case EAC_MCLK_EXT_2x12288000:
 +              MOD_REG_BIT(agcfr, AGCFR_MCLK, 1); /* div by 2 path */
 +              MOD_REG_BIT(agcfr, AGCFR_MCLK_OUT, 1); /* div by 2 */
 +      case EAC_MCLK_EXT_12288000:
 +              MOD_REG_BIT(agcfr2, AGCFR2_I2S_N44K_48K, 1); /* 48 kHz */
 +              MOD_REG_BIT(agcfr2, AGCFR2_MCLK_I2S_N11M_12M, 1); /* 12.288 */
 +              MOD_REG_BIT(agcfr3, AGCFR3_MCLKINT_SEL, 0);
 +              break;
 +
 +      default:
 +              /* internal MCLK gating */
 +              break;
 +      }
 +      MOD_REG_BIT(agctr, AGCTR_MCLK_EN, 1);
 +      MOD_REG_BIT(agctr, AGCTR_OSCMCLK_EN, 1); /* oscillator enabled? */
 +      /* use MCLK just configured above as audio & codec port clock source */
 +      agcfr3 &= ~AGCFR3_AUD_CKSRC_BITS;
 +      agcfr3 |= AGCFR3_AUD_CKSRC(0);
 +
 +      /* audio data format */
 +      MOD_REG_BIT(agcfr, AGCFR_MN_ST, 1);     /* stereo file */
 +      MOD_REG_BIT(agcfr, AGCFR_B8_16, 1);     /* 16 bit audio file */
 +      MOD_REG_BIT(agcfr, AGCFR_LI_BI, 0);     /* little endian stream */
 +
 +      /* there are FSINT configuration bits in AGCFR, AGCFR2 and AGCFR3
 +       * registers but it seems that it is just enough to set in AGCFR3
 +       * only */
 +      agcfr3 &= ~AGCFR3_FSINT_BITS;
 +      agcfr3 |= AGCFR3_FSINT(eac_calc_agcfr3_fsint(conf->default_rate));
 +
 +      /* transparent DMA enable bits */
 +      MOD_REG_BIT(agcfr3, AGCFR3_MD_TR_DMA, 1); /* modem */
 +      MOD_REG_BIT(agcfr3, AGCFR3_BT_TR_DMA, 1); /* BT */
 +      if (conf->codec_mode != EAC_CODEC_I2S_SLAVE)
 +              MOD_REG_BIT(agcfr3, AGCFR3_CP_TR_DMA, 0);
 +      else
 +              MOD_REG_BIT(agcfr3, AGCFR3_CP_TR_DMA, 1);
 +
 +      /* step 4 (see TRM) */
 +      eac_write_reg(eac, EAC_AGCFR3, agcfr3);
 +      /* pre-write AGCTR now (finally in step 10) in order to get MCLK
 +       * settings effective (especially when using external MCLK) */
 +      eac_write_reg(eac, EAC_AGCTR, agctr);
 +      eac_write_reg(eac, EAC_AGCFR2, agcfr2);
 +
 +      /* step 5 (see TRM) */
 +      eac_write_reg(eac, EAC_AGCFR, agcfr);
 +
 +      /* step 6 (see TRM) */
 +      /* wait until audio reset done */
 +      i = 10000;
 +      while (!(eac_read_reg(eac, EAC_SYSSTATUS) & (1 << 3))) {
 +              if (--i == 0)
 +                      return -ETIMEDOUT;
 +              udelay(1);
 +      }
 +
 +      /* step 7 (see TRM) */
 +      reg = eac_read_reg(eac, EAC_AMSCFR);
 +      MOD_REG_BIT(reg, AMSCFR_K1, 1);         /* K1 switch closed */
 +      MOD_REG_BIT(reg, AMSCFR_K5, 1);         /* K5 switch closed */
 +      MOD_REG_BIT(reg, AMSCFR_K2, 0);         /* K2 switch open */
 +      MOD_REG_BIT(reg, AMSCFR_K6, 0);         /* K6 switch open */
 +      eac_write_reg(eac, EAC_AMSCFR, reg);
 +
 +      /* step 8 (see TRM) */
 +      switch (conf->codec_mode) {
 +      case EAC_CODEC_PCM:
 +              err = eac_configure_pcm(eac, conf);
 +              break;
 +      case EAC_CODEC_AC97:
 +              err = eac_configure_ac97(eac, conf);
 +              break;
 +      default:
 +              err = eac_configure_i2s(eac, conf);
 +              break;
 +      }
 +
 +      /* step 9 (see TRM) */
 +      MOD_REG_BIT(cpctl, CPTCTL_CPEN, 1);     /* codec port enable */
 +      MOD_REG_BIT(cpctl, CPTCTL_RXIE, 1);     /* receive int enable */
 +      MOD_REG_BIT(cpctl, CPTCTL_TXIE, 1);     /* transmit int enable */
 +      eac_write_reg(eac, EAC_CPTCTL, cpctl);
 +
 +      /* step 10 (see TRM) */
 +      /* enable playing & recording */
 +      MOD_REG_BIT(agctr, AGCTR_DMAREN, 1);    /* playing enabled (DMA R) */
 +      MOD_REG_BIT(agctr, AGCTR_DMAWEN, 1);    /* recording enabled (DMA W) */
 +      MOD_REG_BIT(agctr, AGCTR_AUDEN, 1);     /* audio processing enabled */
 +      eac_write_reg(eac, EAC_AGCTR, agctr);
 +
 +      /* audio mixer1, no mute on mixer output, gain = 0 dB */
 +      reg = eac_read_reg(eac, EAC_AM1VCTR);
 +      MOD_REG_BIT(reg, AM1VCTR_MUTE, 0);
 +      reg = ((reg & ~AM1VCTR_GINB_BITS) | (AM1VCTR_GINB(0x67)));
 +      eac_write_reg(eac, EAC_AM1VCTR, reg);
 +
 +      /* audio mixer3, no mute on mixer output, gain = 0 dB */
 +      reg = eac_read_reg(eac, EAC_AM3VCTR);
 +      MOD_REG_BIT(reg, AM3VCTR_MUTE, 0);
 +      reg = ((reg & ~AM3VCTR_GINB_BITS) | (AM3VCTR_GINB(0x67)));
 +      eac_write_reg(eac, EAC_AM3VCTR, reg);
 +
 +      /* audio side tone disabled */
 +      eac_write_reg(eac, EAC_ASTCTR, 0x0);
 +
 +      return 0;
 +}
 +
 +int eac_set_mode(struct device *dev, int play, int rec)
 +{
 +      struct omap_eac *eac = dev_get_drvdata(dev);
 +
 +#ifdef DEBUG
 +      printk(KERN_DEBUG "EAC mode: play %s, rec %s\n",
 +             play ? "enabled" : "disabled",
 +             rec  ? "enabled" : "disabled");
 +#endif
 +      BUG_ON(eac == NULL);
 +      mutex_lock(&eac->mutex);
 +      if (play || rec) {
 +              /* activate clocks */
 +              eac_enable_clocks(eac);
 +
 +              /* power-up codec */
 +              if (eac->codec != NULL && eac->codec->set_power != NULL)
 +                      eac->codec->set_power(eac->codec->private_data,
 +                              play, rec);
 +      } else {
 +              /* shutdown codec */
 +              if (eac->codec != NULL && eac->codec->set_power != NULL)
 +                      eac->codec->set_power(eac->codec->private_data, 0, 0);
 +
 +              /* de-activate clocks */
 +              eac_disable_clocks(eac);
 +      }
 +      mutex_unlock(&eac->mutex);
 +
 +      return 0;
 +}
 +
 +int eac_register_codec(struct device *dev, struct eac_codec *codec)
 +{
 +      struct omap_eac *eac = dev_get_drvdata(dev);
 +      struct snd_card *card = eac->card;
 +      int err;
 +
 +      BUG_ON(eac->codec != NULL);
 +
 +      mutex_lock(&eac->mutex);
 +      eac->codec = codec;
 +      eac_enable_clocks(eac);
 +      err = eac_codec_port_init(eac, codec);
 +      eac_disable_clocks(eac);
 +      mutex_unlock(&eac->mutex);
 +      if (err)
 +              return err;
 +
 +      /* register mixer controls implemented by a codec driver */
 +      if (codec->register_controls != NULL) {
 +              err = codec->register_controls(codec->private_data, card);
 +              if (err)
 +                      return err;
 +      }
 +
 +      if (codec->short_name != NULL) {
 +              sprintf(card->longname, "%s with codec %s", card->shortname,
 +                      codec->short_name);
 +              strcpy(card->mixername, codec->short_name);
 +      }
 +
 +      err = snd_card_register(card);
 +      return err;
 +}
 +
 +void eac_unregister_codec(struct device *dev)
 +{
 +      struct omap_eac *eac = dev_get_drvdata(dev);
 +
 +      BUG_ON(eac->codec == NULL);
 +      eac_set_mode(dev, 0, 0);
 +      snd_card_disconnect(eac->card);
 +      eac->codec = NULL;
 +}
 +
 +static int __devinit eac_probe(struct platform_device *pdev)
 +{
 +      struct eac_platform_data *pdata = pdev->dev.platform_data;
 +      struct snd_card *card;
 +      struct omap_eac *eac;
 +      struct resource *res;
 +      int err;
 +
 +      eac = kzalloc(sizeof(*eac), GFP_KERNEL);
 +      if (!eac)
 +              return -ENOMEM;
 +
 +      mutex_init(&eac->mutex);
 +      eac->pdev = pdev;
 +      platform_set_drvdata(pdev, eac);
 +      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (res == NULL) {
 +              err = -ENODEV;
 +              goto err1;
 +      }
 +      eac->base = (void __iomem *)io_p2v(res->start);
 +      eac->pdata = pdata;
 +
 +      /* pre-initialize EAC hw */
 +      err = eac_get_clocks(eac);
 +      if (err)
 +              goto err1;
 +      err = eac_enable_clocks(eac);
 +      if (err)
 +              goto err2;
 +
 +      err = eac_reset(eac);
 +      if (err)
 +              goto err3;
 +
 +      dev_info(&pdev->dev, "EAC version: %d.%d\n",
 +               eac_read_reg(eac, EAC_VERSION) >> 4,
 +               eac_read_reg(eac, EAC_VERSION) & 0x0f);
 +      eac_disable_clocks(eac);
 +
 +      /* create soundcard instance */
 +      card = snd_card_new(-1, id, THIS_MODULE, 0);
 +      if (card == NULL) {
 +              err = -ENOMEM;
 +              goto err3;
 +      }
 +      eac->card = card;
 +      strcpy(card->driver, "EAC");
 +      strcpy(card->shortname, "OMAP24xx EAC");
 +
 +      sprintf(card->longname, "%s", card->shortname);
 +      strcpy(card->mixername, "EAC Mixer");
 +
 +      if (eac->pdata->init) {
 +              err = eac->pdata->init(&pdev->dev);
 +              if (err < 0) {
 +                      printk("init %d\n", err);
 +                      goto err4;
 +              }
 +      }
 +
 +      return 0;
 +
 +err4:
 +      snd_card_free(card);
 +err3:
 +      eac_disable_clocks(eac);
 +err2:
 +      eac_put_clocks(eac);
 +err1:
 +      kfree(eac);
 +      return err;
 +}
 +
 +static int __devexit eac_remove(struct platform_device *pdev)
 +{
 +      struct omap_eac *eac = platform_get_drvdata(pdev);
 +      struct snd_card *card = eac->card;
 +
 +      snd_card_free(card);
 +
 +      eac_disable_clocks(eac);
 +      eac_put_clocks(eac);
 +
 +      platform_set_drvdata(pdev, NULL);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver eac_driver = {
 +      .driver = {
 +              .name           = "omap24xx-eac",
 +              .bus            = &platform_bus_type,
 +      },
 +      .probe          = eac_probe,
 +      .remove         = eac_remove,
 +};
 +
 +int __init eac_init(void)
 +{
 +      return platform_driver_register(&eac_driver);
 +}
 +
 +void __exit eac_exit(void)
 +{
 +      platform_driver_unregister(&eac_driver);
 +}
 +
 +module_init(eac_init);
 +module_exit(eac_exit);
 +MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
 +MODULE_LICENSE("GPL");
index 7f06582a462fcb0f89d2d3313a2db9dd8694267e,0000000000000000000000000000000000000000..da2a875f4172bf78e4cf8795af7677afddf30007
mode 100644,000000..100644
--- /dev/null
@@@ -1,523 -1,0 +1,523 @@@
- #include <asm/arch/aic23.h>
 +/*
 + * sound/arm/omap/omap-alsa-aic23-mixer.c
 + *
 + * Alsa Driver Mixer for generic codecs for omap boards
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + * Written by David Cohen, Daniel Petrini
 + *            {david.cohen, daniel.petrini}@indt.org.br
 + *
 + * Based on es1688_lib.c,
 + * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the  GNU General Public License along
 + * with this program; if not, write  to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + *
 + * History:
 + *
 + * 2005-08-02   INdT Kernel Team - Alsa mixer driver for omap osk.
 + *                            Creation of new file omap-alsa-mixer.c.
 + *                            Initial version with aic23 codec for osk5912
 + */
 +
 +#include <linux/kernel.h>
 +
- #include <asm/arch/omap-alsa.h>
++#include <mach/aic23.h>
 +
++#include <mach/omap-alsa.h>
 +#include "omap-alsa-aic23.h"
 +#include <sound/initval.h>
 +#include <sound/control.h>
 +
 +MODULE_AUTHOR("David Cohen");
 +MODULE_AUTHOR("Daniel Petrini");
 +
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("OMAP Alsa mixer driver for ALSA");
 +
 +/*
 + * Codec dependent region
 + */
 +
 +/* Codec AIC23 */
 +#if defined(CONFIG_SENSORS_TLV320AIC23) || \
 +      defined(CONFIG_SENSORS_TLV320AIC23_MODULE)
 +
 +#define MIXER_NAME                 "Mixer AIC23"
 +#define SND_OMAP_WRITE(reg, val)     audio_aic23_write(reg, val)
 +
 +#endif
 +
 +/* Callback Functions */
 +#define OMAP_BOOL(xname, xindex, reg, reg_index, mask, invert) \
 +{ \
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 +      .name = xname, \
 +      .index = xindex, \
 +      .info = snd_omap_info_bool, \
 +      .get = snd_omap_get_bool, \
 +      .put = snd_omap_put_bool, \
 +      .private_value = reg | (reg_index << 8) | (invert << 10) | \
 +                              (mask << 12) \
 +}
 +
 +#define OMAP_MUX(xname, reg, reg_index, mask) \
 +{ \
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 +      .name = xname, \
 +      .info = snd_omap_info_mux, \
 +      .get = snd_omap_get_mux, \
 +      .put = snd_omap_put_mux, \
 +      .private_value = reg | (reg_index << 8) | (mask << 10) \
 +}
 +
 +#define OMAP_SINGLE(xname, xindex, reg, reg_index, reg_val, mask) \
 +{\
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 +      .name = xname, \
 +      .index = xindex, \
 +      .info = snd_omap_info_single, \
 +      .get = snd_omap_get_single, \
 +      .put = snd_omap_put_single, \
 +      .private_value = reg | (reg_val << 8) | (reg_index << 16) |\
 +                              (mask << 18) \
 +}
 +
 +#define OMAP_DOUBLE(xname, xindex, left_reg, right_reg, reg_index, mask) \
 +{\
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 +      .name = xname, \
 +      .index = xindex, \
 +      .info = snd_omap_info_double, \
 +      .get = snd_omap_get_double, \
 +      .put = snd_omap_put_double, \
 +      .private_value = left_reg | (right_reg << 8) | (reg_index << 16) | \
 +                              (mask << 18) \
 +}
 +
 +/* Local Registers */
 +enum snd_device_index {
 +      PCM_INDEX = 0,
 +      LINE_INDEX,
 +      AAC_INDEX, /* Analog Audio Control: reg = l_reg */
 +};
 +
 +struct {
 +      u16 l_reg;
 +      u16 r_reg;
 +      u8 sw;
 +} omap_regs[3];
 +
 +#ifdef CONFIG_PM
 +struct {
 +      u16 l_reg;
 +      u16 r_reg;
 +      u8 sw;
 +} omap_pm_regs[3];
 +#endif
 +
 +u16 snd_sidetone[6] = {
 +      SIDETONE_18,
 +      SIDETONE_12,
 +      SIDETONE_9,
 +      SIDETONE_6,
 +      SIDETONE_0,
 +      0
 +};
 +
 +/* Begin Bool Functions */
 +
 +static int snd_omap_info_bool(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_info *uinfo)
 +{
 +      uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count = 1;
 +      uinfo->value.integer.min = 0;
 +      uinfo->value.integer.max = 1;
 +
 +      return 0;
 +}
 +
 +static int snd_omap_get_bool(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      int mic_index = (kcontrol->private_value >> 8) & 0x03;
 +      u16 mask = (kcontrol->private_value >> 12) & 0xff;
 +      int invert = (kcontrol->private_value >> 10) & 0x03;
 +
 +      if (invert)
 +              ucontrol->value.integer.value[0] =
 +                      (omap_regs[mic_index].l_reg & mask) ? 0 : 1;
 +      else
 +              ucontrol->value.integer.value[0] =
 +                      (omap_regs[mic_index].l_reg & mask) ? 1 : 0;
 +
 +      return 0;
 +}
 +
 +static int snd_omap_put_bool(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      int mic_index = (kcontrol->private_value >> 8) & 0x03;
 +      u16 mask = (kcontrol->private_value >> 12) & 0xff;
 +      u16 reg = kcontrol->private_value & 0xff;
 +      int invert = (kcontrol->private_value >> 10) & 0x03;
 +
 +      int changed = 1;
 +
 +      if (ucontrol->value.integer.value[0]) /* XOR */
 +              if (invert)
 +                      omap_regs[mic_index].l_reg &= ~mask;
 +              else
 +                      omap_regs[mic_index].l_reg |= mask;
 +      else
 +              if (invert)
 +                      omap_regs[mic_index].l_reg |= mask;
 +              else
 +                      omap_regs[mic_index].l_reg &= ~mask;
 +
 +      SND_OMAP_WRITE(reg, omap_regs[mic_index].l_reg);
 +
 +      return changed;
 +}
 +
 +/* End Bool Functions */
 +
 +/* Begin Mux Functions */
 +
 +static int snd_omap_info_mux(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_info *uinfo)
 +{
 +      /* Mic = 0
 +       * Line = 1 */
 +      static char *texts[2] = { "Mic", "Line" };
 +
 +      uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 +      uinfo->count = 1;
 +      uinfo->value.enumerated.items = 2;
 +
 +      if (uinfo->value.enumerated.item > 1)
 +              uinfo->value.enumerated.item = 1;
 +
 +      strcpy(uinfo->value.enumerated.name,
 +                      texts[uinfo->value.enumerated.item]);
 +
 +      return 0;
 +}
 +
 +static int snd_omap_get_mux(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      u16 mask = (kcontrol->private_value >> 10) & 0xff;
 +      int mux_idx = (kcontrol->private_value >> 8) & 0x03;
 +
 +      ucontrol->value.enumerated.item[0] =
 +              (omap_regs[mux_idx].l_reg & mask) ? 0 /* Mic */ : 1 /* Line */;
 +
 +      return 0;
 +}
 +
 +static int snd_omap_put_mux(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      u16 reg = kcontrol->private_value & 0xff;
 +      u16 mask = (kcontrol->private_value >> 10) & 0xff;
 +      int mux_index = (kcontrol->private_value >> 8) & 0x03;
 +
 +      int changed = 1;
 +
 +      if (!ucontrol->value.integer.value[0])
 +              omap_regs[mux_index].l_reg |= mask; /* AIC23: Mic */
 +      else
 +              omap_regs[mux_index].l_reg &= ~mask; /* AIC23: Line */
 +
 +      SND_OMAP_WRITE(reg, omap_regs[mux_index].l_reg);
 +
 +      return changed;
 +}
 +
 +/* End Mux Functions */
 +
 +/* Begin Single Functions */
 +
 +static int snd_omap_info_single(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_info *uinfo)
 +{
 +      int mask = (kcontrol->private_value >> 18) & 0xff;
 +      int reg_val = (kcontrol->private_value >> 8) & 0xff;
 +
 +      uinfo->type = mask ? SNDRV_CTL_ELEM_TYPE_INTEGER :
 +                      SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count = 1;
 +      uinfo->value.integer.min = 0;
 +      uinfo->value.integer.max = reg_val-1;
 +
 +      return 0;
 +}
 +
 +static int snd_omap_get_single(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      u16 reg_val = (kcontrol->private_value >> 8) & 0xff;
 +
 +      ucontrol->value.integer.value[0] = snd_sidetone[reg_val];
 +
 +      return 0;
 +}
 +
 +static int snd_omap_put_single(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      u16 reg_index = (kcontrol->private_value >> 16) & 0x03;
 +      u16 mask = (kcontrol->private_value >> 18) & 0x1ff;
 +      u16 reg = kcontrol->private_value & 0xff;
 +      u16 reg_val = (kcontrol->private_value >> 8) & 0xff;
 +
 +      int changed = 0;
 +
 +      /* Volume */
 +      if ((omap_regs[reg_index].l_reg !=
 +               (ucontrol->value.integer.value[0] & mask))) {
 +              changed = 1;
 +
 +              omap_regs[reg_index].l_reg &= ~mask;
 +              omap_regs[reg_index].l_reg |=
 +                      snd_sidetone[ucontrol->value.integer.value[0]];
 +
 +              snd_sidetone[reg_val] = ucontrol->value.integer.value[0];
 +              SND_OMAP_WRITE(reg, omap_regs[reg_index].l_reg);
 +      } else {
 +              changed = 0;
 +      }
 +
 +      return changed;
 +}
 +
 +/* End Single Functions */
 +
 +/* Begin Double Functions */
 +
 +static int snd_omap_info_double(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_info *uinfo)
 +{
 +      /*
 +       * mask == 0 : Switch
 +       * mask != 0 : Volume
 +       */
 +      int mask = (kcontrol->private_value >> 18) & 0xff;
 +
 +      uinfo->type = mask ? SNDRV_CTL_ELEM_TYPE_INTEGER :
 +                      SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count = mask ? 2 : 1;
 +      uinfo->value.integer.min = 0;
 +      uinfo->value.integer.max = mask ? mask : 1;
 +
 +      return 0;
 +}
 +
 +static int snd_omap_get_double(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      /*
 +       * mask == 0 : Switch
 +       * mask != 0 : Volume
 +       */
 +      int mask = (kcontrol->private_value >> 18) & 0xff;
 +      int vol_index = (kcontrol->private_value >> 16) & 0x03;
 +
 +      if (!mask) {
 +              /* Switch */
 +              ucontrol->value.integer.value[0] = omap_regs[vol_index].sw;
 +      } else {
 +              /* Volume */
 +              ucontrol->value.integer.value[0] = omap_regs[vol_index].l_reg;
 +              ucontrol->value.integer.value[1] = omap_regs[vol_index].r_reg;
 +      }
 +
 +      return 0;
 +}
 +
 +static int snd_omap_put_double(struct snd_kcontrol *kcontrol,
 +                              struct snd_ctl_elem_value *ucontrol)
 +{
 +      /* mask == 0 : Switch
 +       * mask != 0 : Volume */
 +      int vol_index = (kcontrol->private_value >> 16) & 0x03;
 +      int mask = (kcontrol->private_value >> 18) & 0xff;
 +      int left_reg = kcontrol->private_value & 0xff;
 +      int right_reg = (kcontrol->private_value >> 8) & 0xff;
 +
 +      int changed = 0;
 +
 +      if (!mask) {
 +              /* Switch */
 +              if (!ucontrol->value.integer.value[0]) {
 +                      SND_OMAP_WRITE(left_reg, 0x00);
 +                      SND_OMAP_WRITE(right_reg, 0x00);
 +              } else {
 +                      SND_OMAP_WRITE(left_reg, omap_regs[vol_index].l_reg);
 +                      SND_OMAP_WRITE(right_reg, omap_regs[vol_index].r_reg);
 +              }
 +              changed = 1;
 +              omap_regs[vol_index].sw = ucontrol->value.integer.value[0];
 +      } else {
 +              /* Volume */
 +              if ((omap_regs[vol_index].l_reg !=
 +                              (ucontrol->value.integer.value[0] & mask)) ||
 +                      (omap_regs[vol_index].r_reg !=
 +                              (ucontrol->value.integer.value[1] & mask))) {
 +                      changed = 1;
 +
 +                      omap_regs[vol_index].l_reg &= ~mask;
 +                      omap_regs[vol_index].r_reg &= ~mask;
 +                      omap_regs[vol_index].l_reg |=
 +                              (ucontrol->value.integer.value[0] & mask);
 +                      omap_regs[vol_index].r_reg |=
 +                              (ucontrol->value.integer.value[1] & mask);
 +                      if (omap_regs[vol_index].sw) {
 +                              /* write to registers only if sw is actived */
 +                              SND_OMAP_WRITE(left_reg,
 +                                              omap_regs[vol_index].l_reg);
 +                              SND_OMAP_WRITE(right_reg,
 +                                              omap_regs[vol_index].r_reg);
 +                      }
 +              } else {
 +                      changed = 0;
 +              }
 +      }
 +
 +      return changed;
 +}
 +
 +/* End Double Functions */
 +
 +static struct snd_kcontrol_new snd_omap_controls[] = {
 +      OMAP_DOUBLE("PCM Playback Switch", 0, LEFT_CHANNEL_VOLUME_ADDR,
 +                      RIGHT_CHANNEL_VOLUME_ADDR, PCM_INDEX, 0x00),
 +      OMAP_DOUBLE("PCM Playback Volume", 0, LEFT_CHANNEL_VOLUME_ADDR,
 +                      RIGHT_CHANNEL_VOLUME_ADDR, PCM_INDEX,
 +                      OUTPUT_VOLUME_MASK),
 +      OMAP_BOOL("Line Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR,
 +                      AAC_INDEX, BYPASS_ON, 0),
 +      OMAP_DOUBLE("Line Capture Switch", 0, LEFT_LINE_VOLUME_ADDR,
 +                      RIGHT_LINE_VOLUME_ADDR, LINE_INDEX, 0x00),
 +      OMAP_DOUBLE("Line Capture Volume", 0, LEFT_LINE_VOLUME_ADDR,
 +                      RIGHT_LINE_VOLUME_ADDR, LINE_INDEX, INPUT_VOLUME_MASK),
 +      OMAP_BOOL("Mic Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR,
 +                      AAC_INDEX, STE_ENABLED, 0),
 +      OMAP_SINGLE("Mic Playback Volume", 0, ANALOG_AUDIO_CONTROL_ADDR,
 +                      AAC_INDEX, 5, SIDETONE_MASK),
 +      OMAP_BOOL("Mic Capture Switch", 0, ANALOG_AUDIO_CONTROL_ADDR,
 +                      AAC_INDEX, MICM_MUTED, 1),
 +      OMAP_BOOL("Mic Booster Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR,
 +                      AAC_INDEX, MICB_20DB, 0),
 +      OMAP_MUX("Capture Source", ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX,
 +                      INSEL_MIC),
 +};
 +
 +#ifdef CONFIG_PM
 +
 +void snd_omap_suspend_mixer(void)
 +{
 +      /* Saves current values to wake-up correctly */
 +      omap_pm_regs[LINE_INDEX].l_reg = omap_regs[LINE_INDEX].l_reg;
 +      omap_pm_regs[LINE_INDEX].r_reg = omap_regs[LINE_INDEX].l_reg;
 +      omap_pm_regs[LINE_INDEX].sw = omap_regs[LINE_INDEX].sw;
 +
 +      omap_pm_regs[AAC_INDEX].l_reg = omap_regs[AAC_INDEX].l_reg;
 +
 +      omap_pm_regs[PCM_INDEX].l_reg = omap_regs[PCM_INDEX].l_reg;
 +      omap_pm_regs[PCM_INDEX].r_reg = omap_regs[PCM_INDEX].r_reg;
 +      omap_pm_regs[PCM_INDEX].sw = omap_regs[PCM_INDEX].sw;
 +}
 +
 +void snd_omap_resume_mixer(void)
 +{
 +      /* Line's saved values */
 +      omap_regs[LINE_INDEX].l_reg = omap_pm_regs[LINE_INDEX].l_reg;
 +      omap_regs[LINE_INDEX].r_reg = omap_pm_regs[LINE_INDEX].l_reg;
 +      omap_regs[LINE_INDEX].sw = omap_pm_regs[LINE_INDEX].sw;
 +      SND_OMAP_WRITE(LEFT_LINE_VOLUME_ADDR, omap_pm_regs[LINE_INDEX].l_reg);
 +      SND_OMAP_WRITE(RIGHT_LINE_VOLUME_ADDR, omap_pm_regs[LINE_INDEX].l_reg);
 +
 +      /* Analog Audio Control's saved values */
 +      omap_regs[AAC_INDEX].l_reg = omap_pm_regs[AAC_INDEX].l_reg;
 +      SND_OMAP_WRITE(ANALOG_AUDIO_CONTROL_ADDR, omap_regs[AAC_INDEX].l_reg);
 +
 +      /* Headphone's saved values */
 +      omap_regs[PCM_INDEX].l_reg = omap_pm_regs[PCM_INDEX].l_reg;
 +      omap_regs[PCM_INDEX].r_reg = omap_pm_regs[PCM_INDEX].r_reg;
 +      omap_regs[PCM_INDEX].sw = omap_pm_regs[PCM_INDEX].sw;
 +      SND_OMAP_WRITE(LEFT_CHANNEL_VOLUME_ADDR,
 +                      omap_pm_regs[PCM_INDEX].l_reg);
 +      SND_OMAP_WRITE(RIGHT_CHANNEL_VOLUME_ADDR,
 +                      omap_pm_regs[PCM_INDEX].r_reg);
 +}
 +#endif
 +
 +void snd_omap_init_mixer(void)
 +{
 +      u16 vol_reg;
 +
 +      /* Line's default values */
 +      omap_regs[LINE_INDEX].l_reg = DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK;
 +      omap_regs[LINE_INDEX].r_reg = DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK;
 +      omap_regs[LINE_INDEX].sw = 0;
 +      SND_OMAP_WRITE(LEFT_LINE_VOLUME_ADDR,
 +                      DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK);
 +      SND_OMAP_WRITE(RIGHT_LINE_VOLUME_ADDR,
 +                      DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK);
 +
 +      /* Analog Audio Control's default values */
 +      omap_regs[AAC_INDEX].l_reg = DEFAULT_ANALOG_AUDIO_CONTROL;
 +
 +      /* Headphone's default values */
 +      vol_reg = LZC_ON;
 +      vol_reg &= ~OUTPUT_VOLUME_MASK;
 +      vol_reg |= DEFAULT_OUTPUT_VOLUME;
 +      omap_regs[PCM_INDEX].l_reg = DEFAULT_OUTPUT_VOLUME;
 +      omap_regs[PCM_INDEX].r_reg = DEFAULT_OUTPUT_VOLUME;
 +      omap_regs[PCM_INDEX].sw = 1;
 +      SND_OMAP_WRITE(LEFT_CHANNEL_VOLUME_ADDR, vol_reg);
 +      SND_OMAP_WRITE(RIGHT_CHANNEL_VOLUME_ADDR, vol_reg);
 +}
 +
 +int snd_omap_mixer(struct snd_card_omap_codec *chip)
 +{
 +      struct snd_card *card;
 +      unsigned int idx;
 +      int err;
 +
 +      snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
 +
 +      card = chip->card;
 +
 +      strcpy(card->mixername, MIXER_NAME);
 +
 +      /* Registering alsa mixer controls */
 +      for (idx = 0; idx < ARRAY_SIZE(snd_omap_controls); idx++) {
 +              err = snd_ctl_add(card,
 +                      snd_ctl_new1(&snd_omap_controls[idx], chip));
 +              if (err < 0)
 +                      return err;
 +      }
 +
 +      return 0;
 +}
index 1e43608b68e6952fc76090fa107e61c650207c81,0000000000000000000000000000000000000000..9820e51c2e955240c177d9dc7c2697f347baf285
mode 100644,000000..100644
--- /dev/null
@@@ -1,327 -1,0 +1,327 @@@
- #include <asm/arch/clock.h>
- #include <asm/arch/aic23.h>
 +/*
 + * arch/arm/mach-omap1/omap-alsa-aic23.c
 + *
 + * Alsa codec Driver for AIC23 chip on OSK5912 platform board
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + * Written by Daniel Petrini, David Cohen, Anderson Briglia
 + *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * Based in former alsa driver for osk and oss 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.
 + */
 +
 +#include <sound/core.h>
 +#include <sound/pcm.h>
 +#include <sound/initval.h>
 +#include <sound/control.h>
 +#include <linux/clk.h>
- #include <asm/arch/omap-alsa.h>
++#include <mach/clock.h>
++#include <mach/aic23.h>
 +
++#include <mach/omap-alsa.h>
 +#include "omap-alsa-aic23.h"
 +
 +static struct clk *aic23_mclk;
 +
 +/* aic23 related */
 +static const struct aic23_samplerate_reg_info
 + rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
 +      {4000, 0x06, 1},                /*  4000 */
 +      {8000, 0x06, 0},                /*  8000 */
 +      {16000, 0x0C, 1},               /* 16000 */
 +      {22050, 0x11, 1},               /* 22050 */
 +      {24000, 0x00, 1},               /* 24000 */
 +      {32000, 0x0C, 0},               /* 32000 */
 +      {44100, 0x11, 0},               /* 44100 */
 +      {48000, 0x00, 0},               /* 48000 */
 +      {88200, 0x1F, 0},               /* 88200 */
 +      {96000, 0x0E, 0},               /* 96000 */
 +};
 +
 +/*
 + * Hardware capabilities
 + */
 +
 + /*
 + * DAC USB-mode sampling rates (MCLK = 12 MHz)
 + * The rates and rate_reg_into MUST be in the same order
 + */
 +static unsigned int rates[] = {
 +      4000, 8000, 16000, 22050,
 +      24000, 32000, 44100,
 +      48000, 88200, 96000,
 +};
 +
 +static struct snd_pcm_hw_constraint_list aic23_hw_constraints_rates = {
 +      .count = ARRAY_SIZE(rates),
 +      .list = rates,
 +      .mask = 0,
 +};
 +
 +static struct snd_pcm_hardware aic23_snd_omap_alsa_playback = {
 +      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
 +      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
 +      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
 +                SNDRV_PCM_RATE_KNOT),
 +      .rate_min = 8000,
 +      .rate_max = 96000,
 +      .channels_min = 2,
 +      .channels_max = 2,
 +      .buffer_bytes_max = 128 * 1024,
 +      .period_bytes_min = 32,
 +      .period_bytes_max = 8 * 1024,
 +      .periods_min = 16,
 +      .periods_max = 255,
 +      .fifo_size = 0,
 +};
 +
 +static struct snd_pcm_hardware aic23_snd_omap_alsa_capture = {
 +      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
 +      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
 +      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
 +                SNDRV_PCM_RATE_KNOT),
 +      .rate_min = 8000,
 +      .rate_max = 96000,
 +      .channels_min = 2,
 +      .channels_max = 2,
 +      .buffer_bytes_max = 128 * 1024,
 +      .period_bytes_min = 32,
 +      .period_bytes_max = 8 * 1024,
 +      .periods_min = 16,
 +      .periods_max = 255,
 +      .fifo_size = 0,
 +};
 +
 +/*
 + * Codec/mcbsp init and configuration section
 + * codec dependent code.
 + */
 +
 +/* TLV320AIC23 is a write only device */
 +void audio_aic23_write(u8 address, u16 data)
 +{
 +      aic23_write_value(address, data);
 +}
 +EXPORT_SYMBOL_GPL(audio_aic23_write);
 +
 +/*
 + * Sample rate changing
 + */
 +void aic23_set_samplerate(long rate)
 +{
 +      u8 count = 0;
 +      u16 data = 0;
 +
 +      /* Fix the rate if it has a wrong value */
 +      if (rate >= 96000)
 +              rate = 96000;
 +      else if (rate >= 88200)
 +              rate = 88200;
 +      else if (rate >= 48000)
 +              rate = 48000;
 +      else if (rate >= 44100)
 +              rate = 44100;
 +      else if (rate >= 32000)
 +              rate = 32000;
 +      else if (rate >= 24000)
 +              rate = 24000;
 +      else if (rate >= 22050)
 +              rate = 22050;
 +      else if (rate >= 16000)
 +              rate = 16000;
 +      else if (rate >= 8000)
 +              rate = 8000;
 +      else
 +              rate = 4000;
 +
 +      /* Search for the right sample rate */
 +      /* Verify what happens if the rate is not supported
 +       * now it goes to 96Khz */
 +      while ((rate_reg_info[count].sample_rate != rate) &&
 +             (count < (NUMBER_SAMPLE_RATES_SUPPORTED - 1))) {
 +              count++;
 +      }
 +
 +      data = (rate_reg_info[count].divider << CLKIN_SHIFT) |
 +          (rate_reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
 +
 +      audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
 +}
 +
 +inline void aic23_configure(void)
 +{
 +      /* Reset codec */
 +      audio_aic23_write(RESET_CONTROL_ADDR, 0);
 +
 +      /* Initialize the AIC23 internal state */
 +
 +      /*
 +       * Analog audio path control, DAC selected,
 +       * delete INSEL_MIC for line-in
 +       */
 +      audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR,
 +                              DEFAULT_ANALOG_AUDIO_CONTROL);
 +
 +      /* Digital audio path control, de-emphasis control 44.1kHz */
 +      audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
 +
 +      /* Digital audio interface, master/slave mode, I2S, 16 bit */
 +#ifdef AIC23_MASTER
 +      audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR,
 +                        MS_MASTER | IWL_16 | FOR_DSP);
 +#else
 +      audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
 +#endif
 +
 +      /* Enable digital interface */
 +      audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
 +}
 +
 +/*
 + *  OMAP MCBSP clock configuration and Power Management
 + *
 + *  Here we have some functions that allow clock to be enabled and
 + *   disabled only when needed. Besides doing clock configuration
 + *   it allows turn on/turn off audio when necessary.
 + */
 +/*
 + * Do clock framework mclk search
 + */
 +void aic23_clock_setup(void)
 +{
 +      aic23_mclk = clk_get(0, "mclk");
 +}
 +
 +/*
 + * Do some sanity check, set clock rate, starts it and
 + *  turn codec audio on
 + */
 +int aic23_clock_on(void)
 +{
 +      uint    curRate;
 +
 +      if (clk_get_usecount(aic23_mclk) > 0) {
 +              /* MCLK is already in use */
 +              printk(KERN_WARNING
 +                     "MCLK in use at %d Hz. We change it to %d Hz\n",
 +                     (uint) clk_get_rate(aic23_mclk),
 +                     CODEC_CLOCK);
 +      }
 +      curRate = (uint)clk_get_rate(aic23_mclk);
 +      if (curRate != CODEC_CLOCK) {
 +              if (clk_set_rate(aic23_mclk, CODEC_CLOCK)) {
 +                      printk(KERN_ERR
 +                             "Cannot set MCLK for AIC23 CODEC\n");
 +                      return -ECANCELED;
 +              }
 +      }
 +      clk_enable(aic23_mclk);
 +
 +      printk(KERN_DEBUG
 +              "MCLK = %d [%d], usecount = %d\n",
 +             (uint) clk_get_rate(aic23_mclk), CODEC_CLOCK,
 +             clk_get_usecount(aic23_mclk));
 +
 +      /* Now turn the audio on */
 +      audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
 +                        ~DEVICE_POWER_OFF & ~OUT_OFF & ~DAC_OFF &
 +                        ~ADC_OFF & ~MIC_OFF & ~LINE_OFF);
 +      return 0;
 +}
 +
 +/*
 + * Do some sanity check, turn clock off and then turn
 + *  codec audio off
 + */
 +int aic23_clock_off(void)
 +{
 +      if (clk_get_usecount(aic23_mclk) > 0) {
 +              if (clk_get_rate(aic23_mclk) != CODEC_CLOCK) {
 +                      printk(KERN_WARNING
 +                             "MCLK for audio should be %d Hz. But is %d Hz\n",
 +                             (uint) clk_get_rate(aic23_mclk),
 +                             CODEC_CLOCK);
 +              }
 +
 +              clk_disable(aic23_mclk);
 +      }
 +
 +      audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
 +                        DEVICE_POWER_OFF | OUT_OFF | DAC_OFF |
 +                        ADC_OFF | MIC_OFF | LINE_OFF);
 +      return 0;
 +}
 +
 +int aic23_get_default_samplerate(void)
 +{
 +      return DEFAULT_SAMPLE_RATE;
 +}
 +
 +static int __devinit snd_omap_alsa_aic23_probe(struct platform_device *pdev)
 +{
 +      int     ret;
 +      struct  omap_alsa_codec_config *codec_cfg;
 +
 +      codec_cfg = pdev->dev.platform_data;
 +      if (codec_cfg != NULL) {
 +              codec_cfg->hw_constraints_rates = &aic23_hw_constraints_rates;
 +              codec_cfg->snd_omap_alsa_playback =
 +                                              &aic23_snd_omap_alsa_playback;
 +              codec_cfg->snd_omap_alsa_capture = &aic23_snd_omap_alsa_capture;
 +              codec_cfg->codec_configure_dev  = aic23_configure;
 +              codec_cfg->codec_set_samplerate = aic23_set_samplerate;
 +              codec_cfg->codec_clock_setup    = aic23_clock_setup;
 +              codec_cfg->codec_clock_on       = aic23_clock_on;
 +              codec_cfg->codec_clock_off      = aic23_clock_off;
 +              codec_cfg->get_default_samplerate =
 +                                              aic23_get_default_samplerate;
 +              ret     = snd_omap_alsa_post_probe(pdev, codec_cfg);
 +      } else
 +              ret = -ENODEV;
 +      return ret;
 +}
 +
 +static struct platform_driver omap_alsa_driver = {
 +      .probe          = snd_omap_alsa_aic23_probe,
 +      .remove         = snd_omap_alsa_remove,
 +      .suspend        = snd_omap_alsa_suspend,
 +      .resume         = snd_omap_alsa_resume,
 +      .driver = {
 +              .name = "omap_alsa_mcbsp",
 +      },
 +};
 +
 +static int __init omap_alsa_aic23_init(void)
 +{
 +      int err;
 +
 +      ADEBUG();
 +      err = platform_driver_register(&omap_alsa_driver);
 +
 +      return err;
 +}
 +
 +static void __exit omap_alsa_aic23_exit(void)
 +{
 +      ADEBUG();
 +
 +      platform_driver_unregister(&omap_alsa_driver);
 +}
 +
 +module_init(omap_alsa_aic23_init);
 +module_exit(omap_alsa_aic23_exit);
index e7dfc155c0aaa4a7feb0394489a90a20ce130280,0000000000000000000000000000000000000000..5431b022699e784640ae6658af1b50f3f2a07535
mode 100644,000000..100644
--- /dev/null
@@@ -1,86 -1,0 +1,86 @@@
- #include <asm/arch/dma.h>
 +/*
 + * sound/arm/omap-alsa-aic23.h
 + *
 + * Alsa Driver for AIC23 codec on OSK5912 platform board
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + * Written by Daniel Petrini, David Cohen, Anderson Briglia
 + *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + */
 +
 +#ifndef __OMAP_ALSA_AIC23_H
 +#define __OMAP_ALSA_AIC23_H
 +
- #include <asm/arch/mcbsp.h>
++#include <mach/dma.h>
 +#include <sound/core.h>
 +#include <sound/pcm.h>
++#include <mach/mcbsp.h>
 +
 +/* Define to set the AIC23 as the master w.r.t McBSP */
 +#define AIC23_MASTER
 +
 +#define NUMBER_SAMPLE_RATES_SUPPORTED 10
 +
 +/*
 + * AUDIO related MACROS
 + */
 +#ifndef DEFAULT_BITPERSAMPLE
 +#define DEFAULT_BITPERSAMPLE          16
 +#endif
 +
 +#define DEFAULT_SAMPLE_RATE           44100
 +#define CODEC_CLOCK                   12000000
 +#define AUDIO_MCBSP                   OMAP_MCBSP1
 +
 +#define DEFAULT_OUTPUT_VOLUME         0x60
 +#define DEFAULT_INPUT_VOLUME          0x00    /* 0 ==> mute line in */
 +
 +#define OUTPUT_VOLUME_MIN             LHV_MIN
 +#define OUTPUT_VOLUME_MAX             LHV_MAX
 +#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
 +#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
 +
 +#define INPUT_VOLUME_MIN              LIV_MIN
 +#define INPUT_VOLUME_MAX              LIV_MAX
 +#define INPUT_VOLUME_RANGE            (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
 +#define INPUT_VOLUME_MASK             INPUT_VOLUME_MAX
 +
 +#define SIDETONE_MASK                 0x1c0
 +#define SIDETONE_0                    0x100
 +#define SIDETONE_6                    0x000
 +#define SIDETONE_9                    0x040
 +#define SIDETONE_12                   0x080
 +#define SIDETONE_18                   0x0c0
 +
 +#define DEFAULT_ANALOG_AUDIO_CONTROL  (DAC_SELECTED | STE_ENABLED | \
 +                                      BYPASS_ON | INSEL_MIC | MICB_20DB)
 +
 +struct aic23_samplerate_reg_info {
 +      u32 sample_rate;
 +      u8 control;             /* SR3, SR2, SR1, SR0 and BOSR */
 +      u8 divider;             /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
 +};
 +
 +extern int aic23_write_value(u8 reg, u16 value);
 +
 +/*
 + * Defines codec specific function pointers that can be used from the
 + * common omap-alsa base driver for all omap codecs. (tsc2101 and aic23)
 + */
 +void audio_aic23_write(u8 address, u16 data);
 +void define_codec_functions(struct omap_alsa_codec_config *codec_config);
 +inline void aic23_configure(void);
 +void aic23_set_samplerate(long rate);
 +void aic23_clock_setup(void);
 +int aic23_clock_on(void);
 +int aic23_clock_off(void);
 +int aic23_get_default_samplerate(void);
 +
 +#endif
index baafacf4b70cd2441c42987a27b26b7723255d1a,0000000000000000000000000000000000000000..b2623cbb53f62249d02fc6cd7d8e3ecfc0236747
mode 100644,000000..100644
--- /dev/null
@@@ -1,437 -1,0 +1,437 @@@
- #include <asm/hardware.h>
- #include <asm/arch/dma.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
 +/*
 + * sound/arm/omap/omap-alsa-dma.c
 + *
 + * Common audio DMA handling for the OMAP processors
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + * History:
 + *
 + * 2004-06-07 Sriram Kannan   - Created new file from omap_audio_dma_intfc.c.
 + *                            This file will contain only the DMA interface
 + *                            and buffer handling of OMAP audio driver.
 + *
 + * 2004-06-22 Sriram Kannan   - removed legacy code (auto-init). Self-linking
 + *                            of DMA logical channel.
 + *
 + * 2004-08-12   Nishanth Menon  - Modified to integrate Audio requirements on
 + *                            1610, 1710 platforms
 + *
 + * 2004-11-01   Nishanth Menon  - 16xx platform code base modified to support
 + *                            multi channel chaining.
 + *
 + * 2004-12-15   Nishanth Menon  - Improved 16xx platform channel logic
 + *                            introduced - tasklets, queue handling updated
 + *
 + * 2005-07-19 INdT Kernel Team - Alsa port. Creation of new file
 + *                            omap-alsa-dma.c based in omap-audio-dma-intfc.c
 + *                            oss file. Support for aic23 codec. Removal of
 + *                            buffer handling (Alsa does that), modifications
 + *                            in dma handling and port to alsa structures.
 + *
 + * 2005-12-18   Dirk Behme      - Added L/R Channel Interchange fix as proposed
 + *                            by Ajaya Babu
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/types.h>
 +#include <linux/fs.h>
 +#include <linux/mm.h>
 +#include <linux/slab.h>
 +#include <linux/sched.h>
 +#include <linux/poll.h>
 +#include <linux/pm.h>
 +#include <linux/errno.h>
 +#include <linux/sound.h>
 +#include <linux/soundcard.h>
 +#include <linux/sysrq.h>
 +#include <linux/interrupt.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/io.h>
 +#include <linux/uaccess.h>
 +#include <linux/semaphore.h>
 +
++#include <mach/hardware.h>
++#include <mach/dma.h>
++#include <mach/mcbsp.h>
++#include <mach/omap-alsa.h>
 +
 +#include "omap-alsa-dma.h"
 +
 +#undef DEBUG
 +
 +/*
 + * Channel Queue Handling macros
 + * tail always points to the current free entry
 + * Head always points to the current entry being used
 + * end is either head or tail
 + */
 +
 +#define AUDIO_QUEUE_INIT(s) s->dma_q_head = s->dma_q_tail = s->dma_q_count = 0;
 +#define AUDIO_QUEUE_FULL(s) (nr_linked_channels == s->dma_q_count)
 +#define AUDIO_QUEUE_LAST(s) (1 == s->dma_q_count)
 +#define AUDIO_QUEUE_EMPTY(s) (0 == s->dma_q_count)
 +#define __AUDIO_INCREMENT_QUEUE(end) ((end) = ((end)+1) % nr_linked_channels)
 +#define AUDIO_INCREMENT_HEAD(s)                       \
 +      do {                                            \
 +              __AUDIO_INCREMENT_QUEUE(s->dma_q_head); \
 +              s->dma_q_count--;                       \
 +      } while (0)
 +#define AUDIO_INCREMENT_TAIL(s)                               \
 +      do {                                            \
 +              __AUDIO_INCREMENT_QUEUE(s->dma_q_tail); \
 +              s->dma_q_count++;                       \
 +      } while (0)
 +
 +/* DMA buffer fragmentation sizes */
 +#define MAX_DMA_SIZE           0x1000000 /* todo: sync with alsa */
 +/* #define CUT_DMA_SIZE                0x1000 */
 +/* TODO: To be moved to more appropriate location */
 +#define DCSR_ERROR           0x3
 +#define DCSR_END_BLOCK       (1 << 5)
 +#define DCSR_SYNC_SET        (1 << 6)
 +
 +#define DCCR_FS              (1 << 5)
 +#define DCCR_PRIO            (1 << 6)
 +#define DCCR_AI              (1 << 8)
 +#define DCCR_REPEAT          (1 << 9)
 +/* if 0 the channel works in 3.1 compatible mode */
 +#define DCCR_N31COMP         (1 << 10)
 +#define DCCR_EP              (1 << 11)
 +#define DCCR_SRC_AMODE_BIT   12
 +#define DCCR_SRC_AMODE_MASK  (0x3<<12)
 +#define DCCR_DST_AMODE_BIT   14
 +#define DCCR_DST_AMODE_MASK  (0x3<<14)
 +#define AMODE_CONST          0x0
 +#define AMODE_POST_INC       0x1
 +#define AMODE_SINGLE_INDEX   0x2
 +#define AMODE_DOUBLE_INDEX   0x3
 +
 +/* Data structures */
 +DEFINE_SPINLOCK(dma_list_lock);
 +static char nr_linked_channels = 1;
 +
 +/* Module specific functions */
 +
 +static void sound_dma_irq_handler(int lch, u16 ch_status, void *data);
 +static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
 +                                   u_int dma_size);
 +static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
 +                                      u_int dma_size);
 +static int audio_start_dma_chain(struct audio_stream *s);
 +
 +/*
 + * DMA channel requests
 + */
 +static void omap_sound_dma_link_lch(void *data)
 +{
 +
 +      struct audio_stream *s = (struct audio_stream *) data;
 +      int *chan = s->lch;
 +      int i;
 +
 +      FN_IN;
 +      if (s->linked) {
 +              FN_OUT(1);
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              int nex_chan =
 +                  ((nr_linked_channels - 1 ==
 +                    i) ? chan[0] : chan[i + 1]);
 +              omap_dma_link_lch(cur_chan, nex_chan);
 +      }
 +      s->linked = 1;
 +      FN_OUT(0);
 +}
 +
 +int omap_request_alsa_sound_dma(int device_id, const char *device_name,
 +                         void *data, int **channels)
 +{
 +      int i, err = 0;
 +      int *chan = NULL;
 +      FN_IN;
 +      if (unlikely((NULL == channels) || (NULL == device_name))) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      /* Try allocate memory for the num channels */
 +      *channels = kmalloc(sizeof(int) * nr_linked_channels, GFP_KERNEL);
 +      chan = *channels;
 +      if (NULL == chan) {
 +              ERR("No Memory for channel allocs!\n");
 +              FN_OUT(-ENOMEM);
 +              return -ENOMEM;
 +      }
 +      spin_lock(&dma_list_lock);
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              err = omap_request_dma(device_id,
 +                              device_name,
 +                              sound_dma_irq_handler,
 +                              data,
 +                              &chan[i]);
 +
 +              /* Handle Failure condition here */
 +              if (err < 0) {
 +                      int j;
 +
 +                      for (j = 0; j < i; j++)
 +                              omap_free_dma(chan[j]);
 +
 +                      spin_unlock(&dma_list_lock);
 +                      kfree(chan);
 +                      *channels = NULL;
 +                      ERR("Error in requesting channel %d=0x%x\n", i,
 +                          err);
 +                      FN_OUT(err);
 +                      return err;
 +              }
 +      }
 +
 +      /* Chain the channels together */
 +      if (!cpu_is_omap15xx())
 +              omap_sound_dma_link_lch(data);
 +
 +      spin_unlock(&dma_list_lock);
 +      FN_OUT(0);
 +      return 0;
 +}
 +EXPORT_SYMBOL(omap_request_alsa_sound_dma);
 +
 +/*
 + * DMA channel requests Freeing
 + */
 +static void omap_sound_dma_unlink_lch(void *data)
 +{
 +      struct audio_stream *s = (struct audio_stream *)data;
 +      int *chan = s->lch;
 +      int i;
 +
 +      FN_IN;
 +      if (!s->linked) {
 +              FN_OUT(1);
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              int nex_chan =
 +                  ((nr_linked_channels - 1 ==
 +                    i) ? chan[0] : chan[i + 1]);
 +              omap_dma_unlink_lch(cur_chan, nex_chan);
 +      }
 +      s->linked = 0;
 +      FN_OUT(0);
 +}
 +
 +int omap_free_alsa_sound_dma(void *data, int **channels)
 +{
 +      int i;
 +      int *chan = NULL;
 +
 +      FN_IN;
 +      if (unlikely(NULL == channels)) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      if (unlikely(NULL == *channels)) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      chan = (*channels);
 +
 +      if (!cpu_is_omap15xx())
 +              omap_sound_dma_unlink_lch(data);
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              omap_stop_dma(cur_chan);
 +              omap_free_dma(cur_chan);
 +      }
 +      kfree(*channels);
 +      *channels = NULL;
 +      FN_OUT(0);
 +      return 0;
 +}
 +EXPORT_SYMBOL(omap_free_alsa_sound_dma);
 +
 +/*
 + * Stop all the DMA channels of the stream
 + */
 +void omap_stop_alsa_sound_dma(struct audio_stream *s)
 +{
 +      int *chan = s->lch;
 +      int i;
 +
 +      FN_IN;
 +      if (unlikely(NULL == chan)) {
 +              BUG();
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              omap_stop_dma(cur_chan);
 +      }
 +      s->started = 0;
 +      FN_OUT(0);
 +      return;
 +}
 +EXPORT_SYMBOL(omap_stop_alsa_sound_dma);
 +
 +/*
 + * Clear any pending transfers
 + */
 +void omap_clear_alsa_sound_dma(struct audio_stream *s)
 +{
 +      FN_IN;
 +      omap_clear_dma(s->lch[s->dma_q_head]);
 +      FN_OUT(0);
 +      return;
 +}
 +EXPORT_SYMBOL(omap_clear_alsa_sound_dma);
 +
 +/*
 + * DMA related functions
 + */
 +static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
 +                                   u_int dma_size)
 +{
 +      int dt = 0x1;           /* data type 16 */
 +      int cen = 32;           /* Stereo */
 +      int cfn = dma_size / (2 * cen);
 +
 +      FN_IN;
 +      omap_set_dma_dest_params(channel, 0x05, 0x00,
 +                               (OMAP1510_MCBSP1_BASE + 0x06),
 +                               0, 0);
 +      omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr,
 +                              0, 0);
 +      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
 +                                      u_int dma_size)
 +{
 +      int dt = 0x1;           /* data type 16 */
 +      int cen = 32;           /* stereo */
 +      int cfn = dma_size / (2 * cen);
 +
 +      FN_IN;
 +      omap_set_dma_src_params(channel, 0x05, 0x00,
 +                              (OMAP1510_MCBSP1_BASE + 0x02),
 +                              0, 0);
 +      omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
 +      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +static int audio_start_dma_chain(struct audio_stream *s)
 +{
 +      int channel = s->lch[s->dma_q_head];
 +      FN_IN;
 +      if (!s->started) {
 +              s->hw_stop();      /* stops McBSP Interface */
 +              omap_start_dma(channel);
 +              s->started = 1;
 +              s->hw_start();     /* start McBSP interface */
 +      } else if (cpu_is_omap310())
 +              omap_start_dma(channel);
 +      /* else the dma itself will progress forward with out our help */
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*
 + * Start DMA -
 + * Do the initial set of work to initialize all the channels as required.
 + * We shall then initate a transfer
 + */
 +int omap_start_alsa_sound_dma(struct audio_stream *s,
 +                      dma_addr_t dma_ptr,
 +                      u_int dma_size)
 +{
 +      int ret = -EPERM;
 +
 +      FN_IN;
 +
 +      if (unlikely(dma_size > MAX_DMA_SIZE)) {
 +              ERR("DmaSoundDma: Start: overflowed %d-%d\n", dma_size,
 +                  MAX_DMA_SIZE);
 +              return -EOVERFLOW;
 +      }
 +
 +      if (s->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
 +              /* playback */
 +              ret =
 +                  audio_set_dma_params_play(s->lch[s->dma_q_tail],
 +                                            dma_ptr, dma_size);
 +      } else {
 +              ret =
 +                  audio_set_dma_params_capture(s->lch[s->dma_q_tail],
 +                                               dma_ptr, dma_size);
 +      }
 +      if (ret != 0) {
 +              ret = -3;       /* indicate queue full */
 +              goto sound_out;
 +      }
 +      AUDIO_INCREMENT_TAIL(s);
 +      ret = audio_start_dma_chain(s);
 +      if (ret)
 +              ERR("dma start failed");
 +
 +sound_out:
 +      FN_OUT(ret);
 +      return ret;
 +
 +}
 +EXPORT_SYMBOL(omap_start_alsa_sound_dma);
 +
 +/*
 + * ISRs have to be short and smart..
 + * Here we call alsa handling, after some error checking
 + */
 +static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status,
 +                                void *data)
 +{
 +      int dma_status = ch_status;
 +      struct audio_stream *s = (struct audio_stream *) data;
 +      FN_IN;
 +
 +      /* some register checking */
 +      DPRINTK("lch=%d,status=0x%x, dma_status=%d, data=%p\n",
 +              sound_curr_lch, ch_status, dma_status, data);
 +
 +      if (dma_status & (DCSR_ERROR)) {
 +              omap_stop_dma(sound_curr_lch);
 +              ERR("DCSR_ERROR!\n");
 +              FN_OUT(-1);
 +              return;
 +      }
 +
 +      if (ch_status & DCSR_END_BLOCK)
 +              callback_omap_alsa_sound_dma(s);
 +      FN_OUT(0);
 +      return;
 +}
 +
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION("Common DMA handling for Audio driver on OMAP processors");
 +MODULE_LICENSE("GPL");
 +
index 2f0e4e8a2f9e7f4e44c80364a9ed343a54960d3e,0000000000000000000000000000000000000000..0dcd379141830b6c0bd0e2d9b99854953c209dac
mode 100644,000000..100644
--- /dev/null
@@@ -1,53 -1,0 +1,53 @@@
- #include <asm/arch/omap-alsa.h>
 +/*
 + * linux/sound/arm/omap/omap-alsa-dma.h
 + *
 + * Common audio DMA handling for the OMAP processors
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + * History:
 + *
 + *
 + * 2004/08/12  Nishanth Menon - Modified to integrate Audio requirements on
 + *                            1610, 1710 platforms
 + *
 + * 2005/07/25  INdT Kernel Team - Renamed to omap-alsa-dma.h. Ported to Alsa.
 + */
 +
 +#ifndef __OMAP_AUDIO_ALSA_DMA_H
 +#define __OMAP_AUDIO_ALSA_DMA_H
 +
++#include <mach/omap-alsa.h>
 +
 +/* Global data structures */
 +
 +typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
 +
 +/* arch specific functions */
 +
 +void omap_clear_alsa_sound_dma(struct audio_stream *s);
 +
 +int omap_request_alsa_sound_dma(int device_id, const char *device_name,
 +                              void *data, int **channels);
 +int omap_free_alsa_sound_dma(void *data, int **channels);
 +
 +int omap_start_alsa_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
 +                              u_int dma_size);
 +
 +void omap_stop_alsa_sound_dma(struct audio_stream *s);
 +
 +#endif
index efcabff4a226b0d00ed58aa9d222553e8d7359c3,0000000000000000000000000000000000000000..62530430fd9dd9d7f022fcf642d5b6243b03ba93
mode 100644,000000..100644
--- /dev/null
@@@ -1,306 -1,0 +1,306 @@@
- #include <asm/arch/dma.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/omap-alsa.h>
 +/*
 + * Alsa codec Driver for Siemens SX1 board.
 + * based on omap-alsa-tsc2101.c       and cn_test.c example by Evgeniy Polyakov
 + *
 + * Copyright (C) 2006 Vladimir Ananiev (vovan888 at gmail com)
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2 of the License, or (at your
 + * option) any later version.
 + */
 +
 +#include <linux/delay.h>
 +#include <linux/soundcard.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +#include <linux/connector.h>
 +#include <linux/slab.h>
 +#include <linux/pm.h>
 +
++#include <mach/dma.h>
++#include <mach/clock.h>
++#include <mach/gpio.h>
++#include <mach/mcbsp.h>
++#include <mach/omap-alsa.h>
 +
 +#include "omap-alsa-sx1.h"
 +
 +/* Connector implementation */
 +static struct cb_id cn_sx1snd_id = { CN_IDX_SX1SND, CN_VAL_SX1SND };
 +static char cn_sx1snd_name[] = "cn_sx1snd";
 +
 +static void cn_sx1snd_callback(void *data)
 +{
 +      struct cn_msg *msg = (struct cn_msg *)data;
 +
 +      printk(KERN_INFO
 +              "%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
 +              __func__, jiffies, msg->id.idx, msg->id.val,
 +              msg->seq, msg->ack, msg->len, (char *)msg->data);
 +}
 +
 +/* Send IPC message to sound server */
 +int cn_sx1snd_send(unsigned int cmd, unsigned int arg1, unsigned int arg2)
 +{
 +      struct cn_msg *m;
 +      unsigned short data[3];
 +      int err;
 +
 +      m = kzalloc(sizeof(*m) + sizeof(data), gfp_any());
 +      if (!m)
 +              return -1;
 +
 +      memcpy(&m->id, &cn_sx1snd_id, sizeof(m->id));
 +      m->seq = 1;
 +      m->len = sizeof(data);
 +
 +      data[0] = (unsigned short)cmd;
 +      data[1] = (unsigned short)arg1;
 +      data[2] = (unsigned short)arg2;
 +
 +      memcpy(m + 1, data, m->len);
 +
 +      err = cn_netlink_send(m, CN_IDX_SX1SND, gfp_any());
 +      snd_printd("sent= %02X %02X %02X, err=%d\n", cmd, arg1, arg2, err);
 +      kfree(m);
 +
 +      if (err == -ESRCH)
 +              return -1;      /* there are no listeners on socket */
 +      return 0;
 +}
 +
 +/* Hardware capabilities
 + *
 + * DAC USB-mode sampling rates (MCLK = 12 MHz)
 + * The rates and rate_reg_into MUST be in the same order
 + */
 +static unsigned int rates[] = {
 +       8000, 11025, 12000,
 +       16000, 22050, 24000,
 +       32000, 44100, 48000,
 +};
 +
 +static struct snd_pcm_hw_constraint_list egold_hw_constraints_rates = {
 +      .count  = ARRAY_SIZE(rates),
 +      .list   = rates,
 +      .mask   = 0,
 +};
 +
 +static struct snd_pcm_hardware egold_snd_omap_alsa_playback = {
 +      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
 +      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
 +      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 +                SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_KNOT),
 +      .rate_min               = 8000,
 +      .rate_max               = 48000,
 +      .channels_min           = 2,
 +      .channels_max           = 2,
 +      .buffer_bytes_max       = 128 * 1024,
 +      .period_bytes_min       = 32,
 +      .period_bytes_max       = 8 * 1024,
 +      .periods_min            = 16,
 +      .periods_max            = 255,
 +      .fifo_size              = 0,
 +};
 +
 +static struct snd_pcm_hardware egold_snd_omap_alsa_capture = {
 +      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
 +      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
 +      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 +                SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_KNOT),
 +      .rate_min               = 8000,
 +      .rate_max               = 48000,
 +      .channels_min           = 2,
 +      .channels_max           = 2,
 +      .buffer_bytes_max       = 128 * 1024,
 +      .period_bytes_min       = 32,
 +      .period_bytes_max       = 8 * 1024,
 +      .periods_min            = 16,
 +      .periods_max            = 255,
 +      .fifo_size              = 0,
 +};
 +
 +static long current_rate = -1; /* current rate in egold format 0..8 */
 +/*
 + * ALSA operations according to board file
 + */
 +
 +/*
 + * Sample rate changing
 + */
 +static void egold_set_samplerate(long sample_rate)
 +{
 +      int egold_rate = 0;
 +      int clkgdv = 0;
 +      u16 srgr1, srgr2;
 +
 +      /* Set the sample rate */
 +#if 0
 +      /* fw15: 5005E490 - divs are different !!! */
 +      clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
 +#endif
 +      switch (sample_rate) {
 +      case 8000:
 +              clkgdv = 71;
 +              egold_rate = FRQ_8000;
 +              break;
 +      case 11025:
 +              clkgdv = 51;
 +              egold_rate = FRQ_11025;
 +              break;
 +      case 12000:
 +              clkgdv = 47;
 +              egold_rate = FRQ_12000;
 +              break;
 +      case 16000:
 +              clkgdv = 35;
 +              egold_rate = FRQ_16000;
 +              break;
 +      case 22050:
 +              clkgdv = 25;
 +              egold_rate = FRQ_22050;
 +              break;
 +      case 24000:
 +              clkgdv = 23;
 +              egold_rate = FRQ_24000;
 +              break;
 +      case 32000:
 +              clkgdv = 17;
 +              egold_rate = FRQ_32000;
 +              break;
 +      case 44100:
 +              clkgdv = 12;
 +              egold_rate = FRQ_44100;
 +              break;
 +      case 48000:
 +              clkgdv = 11;
 +              egold_rate = FRQ_48000;
 +              break;
 +      }
 +
 +      srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      srgr2 = ((FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
 +
 +      OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR2, srgr2);
 +      OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR1, srgr1);
 +      current_rate = egold_rate;
 +      snd_printd("set samplerate=%ld\n", sample_rate);
 +
 +}
 +
 +static void egold_configure(void)
 +{
 +}
 +
 +/*
 + * Omap MCBSP clock and Power Management configuration
 + *
 + * Here we have some functions that allows clock to be enabled and
 + * disabled only when needed. Besides doing clock configuration
 + * it allows turn on/turn off audio when necessary.
 + */
 +
 +/*
 + * Do clock framework mclk search
 + */
 +static void egold_clock_setup(void)
 +{
 +      omap_request_gpio(OSC_EN);
 +      omap_set_gpio_direction(OSC_EN, 0); /* output */
 +      snd_printd("\n");
 +}
 +
 +/*
 + * Do some sanity check, set clock rate, starts it and turn codec audio on
 + */
 +static int egold_clock_on(void)
 +{
 +      omap_set_gpio_dataout(OSC_EN, 1);
 +      egold_set_samplerate(44100); /* TODO */
 +      cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_SPEAKER, 0);
 +      cn_sx1snd_send(DAC_OPEN_DEFAULT, current_rate , 4);
 +      snd_printd("\n");
 +      return 0;
 +}
 +
 +/*
 + * Do some sanity check, turn clock off and then turn codec audio off
 + */
 +static int egold_clock_off(void)
 +{
 +      cn_sx1snd_send(DAC_CLOSE, 0 , 0);
 +      cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_PHONE, 0);
 +      omap_set_gpio_dataout(OSC_EN, 0);
 +      snd_printd("\n");
 +      return 0;
 +}
 +
 +static int egold_get_default_samplerate(void)
 +{
 +      snd_printd("\n");
 +      return DEFAULT_SAMPLE_RATE;
 +}
 +
 +static int __init snd_omap_alsa_egold_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +      struct omap_alsa_codec_config *codec_cfg;
 +
 +      codec_cfg = pdev->dev.platform_data;
 +      if (!codec_cfg)
 +              return -ENODEV;
 +
 +      codec_cfg->hw_constraints_rates = &egold_hw_constraints_rates;
 +      codec_cfg->snd_omap_alsa_playback = &egold_snd_omap_alsa_playback;
 +      codec_cfg->snd_omap_alsa_capture = &egold_snd_omap_alsa_capture;
 +      codec_cfg->codec_configure_dev  = egold_configure;
 +      codec_cfg->codec_set_samplerate = egold_set_samplerate;
 +      codec_cfg->codec_clock_setup    = egold_clock_setup;
 +      codec_cfg->codec_clock_on       = egold_clock_on;
 +      codec_cfg->codec_clock_off      = egold_clock_off;
 +      codec_cfg->get_default_samplerate = egold_get_default_samplerate;
 +      ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
 +
 +      snd_printd("\n");
 +      return ret;
 +}
 +
 +static struct platform_driver omap_alsa_driver = {
 +      .probe          = snd_omap_alsa_egold_probe,
 +      .remove         = snd_omap_alsa_remove,
 +      .suspend        = snd_omap_alsa_suspend,
 +      .resume         = snd_omap_alsa_resume,
 +      .driver = {
 +              .name = "omap_alsa_mcbsp",
 +      },
 +};
 +
 +static int __init omap_alsa_egold_init(void)
 +{
 +      int retval;
 +
 +      retval = cn_add_callback(&cn_sx1snd_id, cn_sx1snd_name,
 +                                      cn_sx1snd_callback);
 +      if (retval)
 +              printk(KERN_WARNING "cn_sx1snd failed to register\n");
 +      return platform_driver_register(&omap_alsa_driver);
 +}
 +
 +static void __exit omap_alsa_egold_exit(void)
 +{
 +      cn_del_callback(&cn_sx1snd_id);
 +      platform_driver_unregister(&omap_alsa_driver);
 +}
 +
 +module_init(omap_alsa_egold_init);
 +module_exit(omap_alsa_egold_exit);
index 8a7e770a3d2ca5449b8dfe64f3b0404b7bfc3ad0,0000000000000000000000000000000000000000..6b0e10633469147d11b247f7627bcbef19038d54
mode 100644,000000..100644
--- /dev/null
@@@ -1,543 -1,0 +1,543 @@@
- #include <asm/arch/dma.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/mcbsp.h>
 +/*
 + * sound/arm/omap/omap-alsa-tsc2101.c
 + *
 + * Alsa codec Driver for TSC2101 chip for OMAP platform boards.
 + * Code obtained from oss omap drivers
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *    Written by Nishanth Menon and Sriram Kannan
 + *
 + * Copyright (C) 2006 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + *    Alsa modularization by Daniel Petrini (d.pensator@gmail.com)
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * 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/delay.h>
 +#include <linux/soundcard.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/spi/tsc2101.h>
 +#include <linux/io.h>
 +#include <linux/slab.h>
 +#ifdef CONFIG_PM
 +#include <linux/pm.h>
 +#endif
 +
 +#include <asm/mach-types.h>
- #include <asm/arch/omap-alsa.h>
++#include <mach/dma.h>
++#include <mach/clock.h>
++#include <mach/mcbsp.h>
 +#include <asm/hardware/tsc2101.h>
++#include <mach/omap-alsa.h>
 +
 +#include "omap-alsa-tsc2101.h"
 +
 +struct mcbsp_dev_info mcbsp_dev;
 +
 +static struct clk *tsc2101_mclk;
 +
 +/* #define DUMP_TSC2101_AUDIO_REGISTERS */
 +#undef DUMP_TSC2101_AUDIO_REGISTERS
 +
 +/*
 + * Hardware capabilities
 + */
 +
 +/*
 + * DAC USB-mode sampling rates (MCLK = 12 MHz)
 + * The rates and rate_reg_into MUST be in the same order
 + */
 +static unsigned int rates[] = {
 +      7350, 8000, 8018, 8727,
 +      8820, 9600, 11025, 12000,
 +      14700, 16000, 22050, 24000,
 +      29400, 32000, 44100, 48000,
 +};
 +
 +static struct snd_pcm_hw_constraint_list tsc2101_hw_constraints_rates = {
 +      .count = ARRAY_SIZE(rates),
 +      .list = rates,
 +      .mask = 0,
 +};
 +
 +static const struct tsc2101_samplerate_reg_info
 +    rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
 +      /* Div 6 */
 +      {7350, 7, 1},
 +      {8000, 7, 0},
 +      /* Div 5.5 */
 +      {8018, 6, 1},
 +      {8727, 6, 0},
 +      /* Div 5 */
 +      {8820, 5, 1},
 +      {9600, 5, 0},
 +      /* Div 4 */
 +      {11025, 4, 1},
 +      {12000, 4, 0},
 +      /* Div 3 */
 +      {14700, 3, 1},
 +      {16000, 3, 0},
 +      /* Div 2 */
 +      {22050, 2, 1},
 +      {24000, 2, 0},
 +      /* Div 1.5 */
 +      {29400, 1, 1},
 +      {32000, 1, 0},
 +      /* Div 1 */
 +      {44100, 0, 1},
 +      {48000, 0, 0},
 +};
 +
 +static struct snd_pcm_hardware tsc2101_snd_omap_alsa_playback = {
 +      .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID,
 +#ifdef CONFIG_MACH_OMAP_H6300
 +      .formats = SNDRV_PCM_FMTBIT_S8,
 +#else
 +      .formats = SNDRV_PCM_FMTBIT_S16_LE,
 +#endif
 +      .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 +                SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_KNOT,
 +      .rate_min = 7350,
 +      .rate_max = 48000,
 +      .channels_min = 2,
 +      .channels_max = 2,
 +      .buffer_bytes_max = 128 * 1024,
 +      .period_bytes_min = 32,
 +      .period_bytes_max = 8 * 1024,
 +      .periods_min = 16,
 +      .periods_max = 255,
 +      .fifo_size = 0,
 +};
 +
 +static struct snd_pcm_hardware tsc2101_snd_omap_alsa_capture = {
 +      .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 +               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID,
 +      .formats = SNDRV_PCM_FMTBIT_S16_LE,
 +      .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 +                SNDRV_PCM_RATE_16000 |
 +                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 +                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 +                SNDRV_PCM_RATE_KNOT,
 +      .rate_min = 7350,
 +      .rate_max = 48000,
 +      .channels_min = 2,
 +      .channels_max = 2,
 +      .buffer_bytes_max = 128 * 1024,
 +      .period_bytes_min = 32,
 +      .period_bytes_max = 8 * 1024,
 +      .periods_min = 16,
 +      .periods_max = 255,
 +      .fifo_size = 0,
 +};
 +
 +/*
 + * Simplified write for tsc2101 audio registers.
 + */
 +inline void tsc2101_audio_write(u8 address, u16 data)
 +{
 +      tsc2101_write_sync(mcbsp_dev.tsc2101_dev, PAGE2_AUDIO_CODEC_REGISTERS,
 +                              address, data);
 +}
 +
 +/*
 + * Simplified read for tsc2101 audio registers.
 + */
 +inline u16 tsc2101_audio_read(u8 address)
 +{
 +      return (tsc2101_read_sync(mcbsp_dev.tsc2101_dev,
 +                                      PAGE2_AUDIO_CODEC_REGISTERS, address));
 +}
 +
 +#ifdef DUMP_TSC2101_AUDIO_REGISTERS
 +void dump_tsc2101_audio_reg(void)
 +{
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_HEADSET_GAIN_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_DAC_GAIN_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_MIXER_PGA_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_MIXER_PGA_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_2 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_CODEC_POWER_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_CODEC_POWER_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_3 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_3));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N0 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N0));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N2 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N3 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N3));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N4 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N4));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_N5 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N5));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_D1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_D2 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_D4 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D4));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_LCH_BASS_BOOST_D5 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D5));
 +
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N0 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N0));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N2 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N3 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N3));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N4 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N4));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_N5 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N5));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_D1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_D2 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_D4 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D4));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_RCH_BASS_BOOST_D5 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D5));
 +
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_PLL_PROG_1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_PLL_PROG_1));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_PLL_PROG_1 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_PLL_PROG_2));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_4 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_HANDSET_GAIN_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_BUZZER_GAIN_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_5 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_5));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_6 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_6));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AUDIO_CTRL_7 = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AUDIO_CTRL_7));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_GPIO_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_GPIO_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_AGC_CTRL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_AGC_CTRL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_POWERDOWN_STS = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_POWERDOWN_STS));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_MIC_AGC_CONTROL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_MIC_AGC_CONTROL));
 +      dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
 +              "TSC2101_CELL_AGC_CONTROL = 0x%04x\n",
 +              tsc2101_audio_read(TSC2101_CELL_AGC_CONTROL));
 +}
 +#endif
 +
 +/*
 + * ALSA operations according to board file
 + */
 +
 +/*
 + * Sample rate changing
 + */
 +void tsc2101_set_samplerate(long sample_rate)
 +{
 +      u8 count = 0;
 +      u16 data = 0;
 +      int clkgdv = 0;
 +
 +      u16 srgr1, srgr2;
 +      /* wait for any frame to complete */
 +      udelay(125);
 +      ADEBUG();
 +
 +      sample_rate     = sample_rate;
 +      /* Search for the right sample rate */
 +      while ((rate_reg_info[count].sample_rate != sample_rate) &&
 +             (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
 +              count++;
 +      }
 +      if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
 +              printk(KERN_ERR "Invalid Sample Rate %d requested\n",
 +                     (int) sample_rate);
 +              return;
 +      }
 +
 +      /* Set AC1 */
 +      data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1);
 +      /* Clear prev settings */
 +      data    &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
 +      data    |= AC1_DACFS(rate_reg_info[count].divisor) |
 +                      AC1_ADCFS(rate_reg_info[count].divisor);
 +      tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data);
 +
 +      /* Set the AC3 */
 +      data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3);
 +      /*Clear prev settings */
 +      data    &= ~(AC3_REFFS | AC3_SLVMS);
 +      data    |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
 +#ifdef TSC_MASTER
 +      data    |= AC3_SLVMS;
 +#endif                                /* #ifdef TSC_MASTER */
 +      tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
 +
 +      /*
 +       * Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
 +       * If MCLK rate is something else, these values must be changed.
 +       * See the tsc2101 specification for the details.
 +       */
 +      if (rate_reg_info[count].fs_44kHz) {
 +              /* samplerate = (44.1kHZ / x), where x is int. */
 +              tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
 +                              /* PVAL 1; I_VAL 7 */
 +                              PLL1_PVAL(1) | PLL1_I_VAL(7));
 +              /* D_VAL 5264 */
 +              tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));
 +      } else {
 +              /* samplerate = (48.kHZ / x), where x is int. */
 +              tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
 +                              /* PVAL 1; I_VAL 8 */
 +                             PLL1_PVAL(1) | PLL1_I_VAL(8));
 +              /* D_VAL 1920 */
 +              tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));
 +      }
 +
 +      /* Set the sample rate */
 +#ifndef TSC_MASTER
 +      clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
 +      if (clkgdv)
 +              srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      else
 +              return (1);
 +
 +      /* Stereo Mode */
 +      srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
 +#else
 +      srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
 +
 +#endif                                /* end of #ifdef TSC_MASTER */
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2);
 +      OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1);
 +}
 +
 +void tsc2101_configure(void)
 +{
 +}
 +
 +/*
 + *  Omap MCBSP clock and Power Management configuration
 + *
 + *  Here we have some functions that allows clock to be enabled and
 + *   disabled only when needed. Besides doing clock configuration
 + *   it allows turn on/turn off audio when necessary.
 + */
 +
 +/*
 + * Do clock framework mclk search
 + */
 +void tsc2101_clock_setup(void)
 +{
 +      tsc2101_mclk = clk_get(0, "mclk");
 +}
 +
 +/*
 + * Do some sanity check, set clock rate, starts it and turn codec audio on
 + */
 +int tsc2101_clock_on(void)
 +{
 +      int     curUseCount;
 +      uint    curRate;
 +      int     err;
 +
 +      curUseCount     = clk_get_usecount(tsc2101_mclk);
 +      DPRINTK("clock use count = %d\n", curUseCount);
 +      if (curUseCount > 0) {
 +              /* MCLK is already in use */
 +              printk(KERN_WARNING
 +                     "MCLK already in use at %d Hz. We change it to %d Hz\n",
 +                     (uint) clk_get_rate(tsc2101_mclk),
 +                     CODEC_CLOCK);
 +      }
 +      curRate = (uint)clk_get_rate(tsc2101_mclk);
 +      if (curRate != CODEC_CLOCK) {
 +              err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
 +              if (err) {
 +                      printk(KERN_WARNING "Cannot set MCLK clock rate for "
 +                              "TSC2101 CODEC, error code = %d\n", err);
 +                      return -ECANCELED;
 +              }
 +      }
 +      err             = clk_enable(tsc2101_mclk);
 +      curRate         = (uint)clk_get_rate(tsc2101_mclk);
 +      curUseCount     = clk_get_usecount(tsc2101_mclk);
 +      DPRINTK("MCLK = %d [%d], usecount = %d, clk_enable retval = %d\n",
 +             curRate,
 +             CODEC_CLOCK,
 +             curUseCount,
 +             err);
 +
 +      /* Now turn the audio on */
 +      tsc2101_write_sync(mcbsp_dev.tsc2101_dev, PAGE2_AUDIO_CODEC_REGISTERS,
 +                              TSC2101_CODEC_POWER_CTRL,
 +                              0x0000);
 +      return 0;
 +}
 +
 +/*
 + * Do some sanity check, turn clock off and then turn codec audio off
 + */
 +int tsc2101_clock_off(void)
 +{
 +      int curUseCount;
 +      int curRate;
 +
 +      curUseCount     = clk_get_usecount(tsc2101_mclk);
 +      DPRINTK("clock use count = %d\n", curUseCount);
 +      if  (curUseCount > 0) {
 +              curRate = clk_get_rate(tsc2101_mclk);
 +              DPRINTK("clock rate = %d\n", curRate);
 +              if (curRate != CODEC_CLOCK) {
 +                      printk(KERN_WARNING
 +                             "MCLK for audio should be %d Hz. But is %d Hz\n",
 +                             (uint) clk_get_rate(tsc2101_mclk),
 +                             CODEC_CLOCK);
 +              }
 +              clk_disable(tsc2101_mclk);
 +              DPRINTK("clock disabled\n");
 +      }
 +      tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
 +                          ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
 +      DPRINTK("audio codec off\n");
 +      return 0;
 +}
 +
 +int tsc2101_get_default_samplerate(void)
 +{
 +      return DEFAULT_SAMPLE_RATE;
 +}
 +
 +static int __devinit snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
 +{
 +      struct spi_device *tsc2101;
 +      int     ret;
 +      struct  omap_alsa_codec_config *codec_cfg;
 +
 +      tsc2101 = dev_get_drvdata(&pdev->dev);
 +      if (tsc2101 == NULL) {
 +              dev_err(&pdev->dev, "no platform data\n");
 +              return -ENODEV;
 +      }
 +      if (strncmp(tsc2101->modalias, "tsc2101", 8) != 0) {
 +              dev_err(&pdev->dev, "tsc2101 not found\n");
 +              return -EINVAL;
 +      }
 +      mcbsp_dev.mcbsp_dev = pdev;
 +      mcbsp_dev.tsc2101_dev = tsc2101;
 +
 +      codec_cfg = pdev->dev.platform_data;
 +      if (codec_cfg != NULL) {
 +              codec_cfg->hw_constraints_rates =
 +                                              &tsc2101_hw_constraints_rates;
 +              codec_cfg->snd_omap_alsa_playback =
 +                                      &tsc2101_snd_omap_alsa_playback;
 +              codec_cfg->snd_omap_alsa_capture =
 +                                              &tsc2101_snd_omap_alsa_capture;
 +              codec_cfg->codec_configure_dev  = tsc2101_configure;
 +              codec_cfg->codec_set_samplerate = tsc2101_set_samplerate;
 +              codec_cfg->codec_clock_setup    = tsc2101_clock_setup;
 +              codec_cfg->codec_clock_on       = tsc2101_clock_on;
 +              codec_cfg->codec_clock_off      = tsc2101_clock_off;
 +              codec_cfg->get_default_samplerate =
 +                                              tsc2101_get_default_samplerate;
 +              ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
 +      } else
 +              ret = -ENODEV;
 +      return ret;
 +}
 +
 +static struct platform_driver omap_alsa_driver = {
 +      .probe          = snd_omap_alsa_tsc2101_probe,
 +      .remove         = snd_omap_alsa_remove,
 +      .suspend        = snd_omap_alsa_suspend,
 +      .resume         = snd_omap_alsa_resume,
 +      .driver = {
 +              .name = "omap_alsa_mcbsp",
 +      },
 +};
 +
 +static int __init omap_alsa_tsc2101_init(void)
 +{
 +      ADEBUG();
 +#ifdef DUMP_TSC2101_AUDIO_REGISTERS
 +      printk(KERN_INFO "omap_alsa_tsc2101_init()\n");
 +      dump_tsc2101_audio_reg();
 +#endif
 +      return platform_driver_register(&omap_alsa_driver);
 +}
 +
 +static void __exit omap_alsa_tsc2101_exit(void)
 +{
 +      ADEBUG();
 +#ifdef DUMP_TSC2101_AUDIO_REGISTERS
 +      printk(KERN_INFO "omap_alsa_tsc2101_exit()\n");
 +      dump_tsc2101_audio_reg();
 +#endif
 +      platform_driver_unregister(&omap_alsa_driver);
 +}
 +
 +module_init(omap_alsa_tsc2101_init);
 +module_exit(omap_alsa_tsc2101_exit);
index cf1f852057516e279eb37bf04c3ccc09b247b19a,0000000000000000000000000000000000000000..74c1fd6de0bc055eb1c58a231b45c4ed1a878d10
mode 100644,000000..100644
--- /dev/null
@@@ -1,284 -1,0 +1,284 @@@
- #include <asm/arch/omap-alsa.h>
 +/*
 + * sound/arm/omap/omap-alsa-tsc2102-mixer.c
 + *
 + * Alsa mixer driver for TSC2102 chip for OMAP platforms.
 + *
 + * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
 + * Code based on the TSC2101 ALSA 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the  GNU General Public License along
 + * with this program; if not, write  to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#include <linux/types.h>
 +#include <linux/spi/tsc2102.h>
 +
++#include <mach/omap-alsa.h>
 +
 +#include <sound/initval.h>
 +#include <sound/control.h>
 +
 +#include "omap-alsa-tsc2102.h"
 +#include "omap-alsa-dma.h"
 +
 +static int vol[2], mute[2], filter[2];
 +
 +/*
 + * Converts the Alsa mixer volume (0 - 100) to actual Digital
 + * Gain Control (DGC) value that can be written or read from the
 + * TSC2102 registers.
 + *
 + * Note that the number "OUTPUT_VOLUME_MAX" is smaller than
 + * OUTPUT_VOLUME_MIN because DGC works as a volume decreaser.  (The
 + * higher the value sent to DAC, the more the volume of controlled
 + * channel is decreased)
 + */
 +static void set_dac_gain_stereo(int left_ch, int right_ch)
 +{
 +      int lch, rch;
 +
 +      if (left_ch > 100)
 +              vol[0] = 100;
 +      else if (left_ch < 0)
 +              vol[0] = 0;
 +      else
 +              vol[0] = left_ch;
 +      lch = OUTPUT_VOLUME_MIN - vol[0] *
 +              (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
 +
 +      if (right_ch > 100)
 +              vol[1] = 100;
 +      else if (right_ch < 0)
 +              vol[1] = 0;
 +      else
 +              vol[1] = right_ch;
 +      rch = OUTPUT_VOLUME_MIN - vol[1] *
 +              (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
 +
 +      tsc2102_set_volume(lch, rch);
 +}
 +
 +void init_playback_targets(void)
 +{
 +      set_dac_gain_stereo(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);
 +
 +      /* Unmute */
 +      tsc2102_set_mute(0, 0);
 +
 +      mute[0] = 0;
 +      mute[1] = 0;
 +      filter[0] = 0;
 +      filter[1] = 0;
 +}
 +
 +/*
 + * Initializes TSC 2102 and playback target.
 + */
 +void snd_omap_init_mixer(void)
 +{
 +      FN_IN;
 +
 +      init_playback_targets();
 +
 +      FN_OUT(0);
 +}
 +
 +static int __pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_info *uinfo)
 +{
 +      uinfo->type                     = SNDRV_CTL_ELEM_TYPE_INTEGER;
 +      uinfo->count                    = 2;
 +      uinfo->value.integer.min        = 0;
 +      uinfo->value.integer.max        = 100;
 +      return 0;
 +}
 +
 +static int __pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      ucontrol->value.integer.value[0] = vol[0];      /* L */
 +      ucontrol->value.integer.value[1] = vol[1];      /* R */
 +
 +      return 0;
 +}
 +
 +static int __pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      set_dac_gain_stereo(
 +                      ucontrol->value.integer.value[0],       /* L */
 +                      ucontrol->value.integer.value[1]);      /* R */
 +      return 1;
 +}
 +
 +static int __pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_info *uinfo)
 +{
 +      uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count                    = 2;
 +      uinfo->value.integer.min        = 0;
 +      uinfo->value.integer.max        = 1;
 +      return 0;
 +}
 +
 +static int __pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      ucontrol->value.integer.value[0] = !mute[0];            /* L */
 +      ucontrol->value.integer.value[1] = !mute[1];            /* R */
 +
 +      return 0;
 +}
 +
 +static int __pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      mute[0] = (ucontrol->value.integer.value[0] == 0);      /* L */
 +      mute[1] = (ucontrol->value.integer.value[1] == 0);      /* R */
 +
 +      tsc2102_set_mute(mute[0], mute[1]);
 +      return 1;
 +}
 +
 +static int __pcm_playback_deemphasis_info(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_info *uinfo)
 +{
 +      uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count                    = 1;
 +      uinfo->value.integer.min        = 0;
 +      uinfo->value.integer.max        = 1;
 +      return 0;
 +}
 +
 +static int __pcm_playback_deemphasis_get(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      ucontrol->value.integer.value[0] = filter[0];
 +      return 0;
 +}
 +
 +static int __pcm_playback_deemphasis_put(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      filter[0] = (ucontrol->value.integer.value[0] > 0);
 +
 +      tsc2102_set_deemphasis(filter[0]);
 +      return 1;
 +}
 +
 +static int __pcm_playback_bassboost_info(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_info *uinfo)
 +{
 +      uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 +      uinfo->count                    = 1;
 +      uinfo->value.integer.min        = 0;
 +      uinfo->value.integer.max        = 1;
 +      return 0;
 +}
 +
 +static int __pcm_playback_bassboost_get(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      ucontrol->value.integer.value[0] = filter[1];
 +      return 0;
 +}
 +
 +static int __pcm_playback_bassboost_put(struct snd_kcontrol *kcontrol,
 +              struct snd_ctl_elem_value *ucontrol)
 +{
 +      filter[1] = (ucontrol->value.integer.value[0] > 0);
 +
 +      tsc2102_set_bassboost(filter[1]);
 +      return 1;
 +}
 +
 +static struct snd_kcontrol_new tsc2102_controls[] __devinitdata = {
 +      {
 +              .name   = "Master Playback Volume",
 +              .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .index  = 0,
 +              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 +              .info   = __pcm_playback_volume_info,
 +              .get    = __pcm_playback_volume_get,
 +              .put    = __pcm_playback_volume_put,
 +      },
 +      {
 +              .name   = "Master Playback Switch",
 +              .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .index  = 0,
 +              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 +              .info   = __pcm_playback_switch_info,
 +              .get    = __pcm_playback_switch_get,
 +              .put    = __pcm_playback_switch_put,
 +      },
 +      {
 +              .name   = "De-emphasis Filter Switch",
 +              .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .index  = 0,
 +              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 +              .info   = __pcm_playback_deemphasis_info,
 +              .get    = __pcm_playback_deemphasis_get,
 +              .put    = __pcm_playback_deemphasis_put,
 +      },
 +      {
 +              .name   = "Bass-boost Filter Switch",
 +              .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .index  = 0,
 +              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 +              .info   = __pcm_playback_bassboost_info,
 +              .get    = __pcm_playback_bassboost_get,
 +              .put    = __pcm_playback_bassboost_put,
 +      },
 +};
 +
 +#ifdef CONFIG_PM
 +void snd_omap_suspend_mixer(void)
 +{
 +      /* Nothing to do */
 +}
 +
 +void snd_omap_resume_mixer(void)
 +{
 +      /* The chip was reset, restore the last used values */
 +      set_dac_gain_stereo(vol[0], vol[1]);
 +
 +      tsc2102_set_mute(mute[0], mute[1]);
 +      tsc2102_set_deemphasis(filter[0]);
 +      tsc2102_set_bassboost(filter[1]);
 +}
 +#endif
 +
 +int snd_omap_mixer(struct snd_card_omap_codec *tsc2102)
 +{
 +      int i, err;
 +
 +      if (!tsc2102)
 +              return -EINVAL;
 +
 +      for (i = 0; i < ARRAY_SIZE(tsc2102_controls); i++) {
 +              err = snd_ctl_add(tsc2102->card,
 +                              snd_ctl_new1(&tsc2102_controls[i],
 +                              tsc2102->card));
 +
 +              if (err < 0)
 +                      return err;
 +      }
 +      return 0;
 +}
index 911e776ffc80615224de564316325047c2f52228,0000000000000000000000000000000000000000..4c34f7cf312725b6e036a725be3669128c523391
mode 100644,000000..100644
--- /dev/null
@@@ -1,318 -1,0 +1,318 @@@
- #include <asm/arch/dma.h>
- #include <asm/arch/clock.h>
- #include <asm/arch/omap-alsa.h>
 +/*
 + * sound/arm/omap/omap-alsa-tsc2102.c
 + *
 + * Alsa codec driver for TSC2102 chip for OMAP platforms.
 + *
 + * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
 + * Code based on the TSC2101 ALSA 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.
 + */
 +
 +#include <linux/delay.h>
 +#include <linux/soundcard.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/module.h>
 +#include <linux/io.h>
 +#include <linux/spi/tsc2102.h>
 +
++#include <mach/dma.h>
++#include <mach/clock.h>
++#include <mach/omap-alsa.h>
 +
 +#include "omap-alsa-tsc2102.h"
 +
 +static struct clk *tsc2102_bclk;
 +
 +/*
 + * Hardware capabilities
 + */
 +
 +/* DAC sampling rates (BCLK = 12 MHz) */
 +static unsigned int rates[] = {
 +      7350, 8000, 8820, 9600, 11025, 12000, 14700,
 +      16000, 22050, 24000, 29400, 32000, 44100, 48000,
 +};
 +
 +static struct snd_pcm_hw_constraint_list tsc2102_hw_constraints_rates = {
 +      .count = ARRAY_SIZE(rates),
 +      .list = rates,
 +      .mask = 0,
 +};
 +
 +static struct snd_pcm_hardware tsc2102_snd_omap_alsa_playback = {
 +      .info                   = SNDRV_PCM_INFO_INTERLEAVED |
 +              SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
 +              SNDRV_PCM_INFO_MMAP_VALID,
 +      .formats                = SNDRV_PCM_FMTBIT_S16_LE,
 +      .rates                  = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 +              SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
 +              SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
 +              SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_KNOT,
 +      .rate_min               = 7350,
 +      .rate_max               = 48000,
 +      .channels_min           = 2,
 +      .channels_max           = 2,
 +      .buffer_bytes_max       = 128 * 1024,
 +      .period_bytes_min       = 32,
 +      .period_bytes_max       = 8 * 1024,
 +      .periods_min            = 16,
 +      .periods_max            = 255,
 +      .fifo_size              = 0,
 +};
 +
 +#ifdef DUMP_TSC2102_AUDIO_REGISTERS
 +static void dump_tsc2102_audio_regs(void)
 +{
 +      printk(KERN_INFO "TSC2102_AUDIO1_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_AUDIO1_CTRL));
 +      printk(KERN_INFO "TSC2102_DAC_GAIN_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_DAC_GAIN_CTRL));
 +      printk(KERN_INFO "TSC2102_AUDIO2_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_AUDIO2_CTRL));
 +      printk(KERN_INFO "TSC2102_DAC_POWER_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_DAC_POWER_CTRL));
 +      printk(KERN_INFO "TSC2102_AUDIO3_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_AUDIO_CTRL_3));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N0 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N0));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N1 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N1));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N2 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N2));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N3 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N3));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N4 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N4));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_N5 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N5));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_D1 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D1));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_D2 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D2));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_D4 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D4));
 +      printk(KERN_INFO "TSC2102_LCH_BASS_BOOST_D5 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D5));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N0 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N0));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N1 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N1));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N2 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N2));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N3 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N3));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N4 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N4));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_N5 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N5));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_D1 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D1));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_D2 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D2));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_D4 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D4));
 +      printk(KERN_INFO "TSC2102_RCH_BASS_BOOST_D5 = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D5));
 +      printk(KERN_INFO "TSC2102_PLL1_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_PLL1_CTRL));
 +      printk(KERN_INFO "TSC2102_PLL2_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_PLL2_CTRL));
 +      printk(KERN_INFO "TSC2102_AUDIO4_CTRL = 0x%04x\n",
 +                      tsc2102_read_sync(TSC2102_AUDIO4_CTRL));
 +}
 +#endif
 +
 +/*
 + * ALSA operations according to board file
 + */
 +
 +static long current_rate;
 +
 +/*
 + * Sample rate changing
 + */
 +static void tsc2102_set_samplerate(long sample_rate)
 +{
 +      int clkgdv = 0;
 +      u16 srgr1, srgr2;
 +
 +      if (sample_rate == current_rate)
 +              return;
 +      current_rate = 0;
 +
 +      if (tsc2102_set_rate(sample_rate))
 +              return;
 +
 +      /* Set the sample rate */
 +#ifndef TSC_MASTER
 +      clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
 +      if (clkgdv)
 +              srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      else
 +              return;
 +
 +      /* Stereo Mode */
 +      srgr2 = CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1);
 +#else
 +      srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv);
 +      srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1);
 +#endif
 +      OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR2, srgr2);
 +      OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR1, srgr1);
 +      current_rate = sample_rate;
 +}
 +
 +static void tsc2102_configure(void)
 +{
 +      tsc2102_dac_power(1);
 +
 +#ifdef TSC_MASTER
 +      tsc2102_set_i2s_master(1);
 +#else
 +      tsc2102_set_i2s_master(0);
 +#endif
 +}
 +
 +/*
 + * Omap McBSP clock and Power Management configuration
 + *
 + * Here we have some functions that allow clock to be enabled and
 + * disabled only when needed.  Besides doing clock configuration
 + * they allow turn audio on and off when necessary.
 + */
 +
 +/*
 + * Do clock framework bclk search
 + */
 +static void tsc2102_clock_setup(void)
 +{
 +      tsc2102_bclk = clk_get(0, "bclk");
 +}
 +
 +/*
 + * Do some sanity checks, set clock rate, start it.
 + */
 +static int tsc2102_clock_on(void)
 +{
 +      int err;
 +
 +      if (clk_get_usecount(tsc2102_bclk) > 0 &&
 +                      clk_get_rate(tsc2102_bclk) != CODEC_CLOCK) {
 +              /* BCLK is already in use */
 +              printk(KERN_WARNING
 +                      "BCLK already in use at %d Hz. We change it to %d Hz\n",
 +                      (uint) clk_get_rate(tsc2102_bclk), CODEC_CLOCK);
 +
 +              err = clk_set_rate(tsc2102_bclk, CODEC_CLOCK);
 +              if (err)
 +                      printk(KERN_WARNING "Cannot set BCLK clock rate "
 +                              "for TSC2102 codec, error code = %d\n", err);
 +      }
 +
 +      clk_enable(tsc2102_bclk);
 +      return 0;
 +}
 +
 +/*
 + * Turn off the audio codec and then stop the clock.
 + */
 +static int tsc2102_clock_off(void)
 +{
 +      DPRINTK("clock use count = %d\n", clk_get_usecount(tsc2102_bclk));
 +
 +      clk_disable(tsc2102_bclk);
 +      return 0;
 +}
 +
 +static int tsc2102_get_default_samplerate(void)
 +{
 +      return DEFAULT_SAMPLE_RATE;
 +}
 +
 +static int snd_omap_alsa_tsc2102_suspend(
 +              struct platform_device *pdev, pm_message_t state)
 +{
 +      tsc2102_dac_power(0);
 +      current_rate = 0;
 +
 +      return snd_omap_alsa_suspend(pdev, state);
 +}
 +
 +static int snd_omap_alsa_tsc2102_resume(struct platform_device *pdev)
 +{
 +      tsc2102_dac_power(1);
 +
 +#ifdef TSC_MASTER
 +      tsc2102_set_i2s_master(1);
 +#else
 +      tsc2102_set_i2s_master(0);
 +#endif
 +
 +      return snd_omap_alsa_resume(pdev);
 +}
 +
 +static int __init snd_omap_alsa_tsc2102_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +      struct omap_alsa_codec_config *codec_cfg = pdev->dev.platform_data;
 +
 +      if (codec_cfg) {
 +              codec_cfg->hw_constraints_rates =
 +                      &tsc2102_hw_constraints_rates;
 +              codec_cfg->snd_omap_alsa_playback =
 +                      &tsc2102_snd_omap_alsa_playback;
 +              codec_cfg->codec_configure_dev = tsc2102_configure;
 +              codec_cfg->codec_set_samplerate = tsc2102_set_samplerate;
 +              codec_cfg->codec_clock_setup = tsc2102_clock_setup;
 +              codec_cfg->codec_clock_on = tsc2102_clock_on;
 +              codec_cfg->codec_clock_off = tsc2102_clock_off;
 +              codec_cfg->get_default_samplerate =
 +                      tsc2102_get_default_samplerate;
 +              ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
 +      } else
 +              ret = -ENODEV;
 +
 +      return ret;
 +}
 +
 +static int snd_omap_alsa_tsc2102_remove(struct platform_device *pdev)
 +{
 +      tsc2102_dac_power(0);
 +
 +      return snd_omap_alsa_remove(pdev);
 +}
 +
 +static struct platform_driver omap_alsa_driver = {
 +      .probe          = snd_omap_alsa_tsc2102_probe,
 +      .remove         = snd_omap_alsa_tsc2102_remove,
 +      .suspend        = snd_omap_alsa_tsc2102_suspend,
 +      .resume         = snd_omap_alsa_tsc2102_resume,
 +      .driver         = {
 +              .name   = "tsc2102-alsa",
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap_alsa_tsc2102_init(void)
 +{
 +      int err;
 +
 +      ADEBUG();
 +      err = platform_driver_register(&omap_alsa_driver);
 +
 +      return err;
 +}
 +
 +static void __exit omap_alsa_tsc2102_exit(void)
 +{
 +      ADEBUG();
 +      platform_driver_unregister(&omap_alsa_driver);
 +}
 +
 +module_init(omap_alsa_tsc2102_init);
 +module_exit(omap_alsa_tsc2102_exit);
index f9293cda59cf8a070927e8176954a7b24ade7dd2,0000000000000000000000000000000000000000..45c46e2dfb1de871f0cf0eed0167cda44a3f39db
mode 100644,000000..100644
--- /dev/null
@@@ -1,591 -1,0 +1,591 @@@
- #include <asm/arch/omap-alsa.h>
 +/*
 + * sound/arm/omap-alsa.c
 + *
 + * Alsa Driver for OMAP
 + *
 + * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
 + * Written by Daniel Petrini, David Cohen, Anderson Briglia
 + *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
 + *
 + * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
 + *
 + * Based on sa11xx-uda1341.c,
 + * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
 + *
 + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the  GNU General Public License along
 + * with this program; if not, write  to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + *
 + * History:
 + *
 + * 2005-07-29   INdT Kernel Team - Alsa driver for omap osk. Creation of new
 + *                                 file omap-aic23.c
 + *
 + * 2005-12-18   Dirk Behme       - Added L/R Channel Interchange fix as proposed
 + *                                 by Ajaya Babu
 + *
 + */
 +
 +#include <linux/platform_device.h>
 +#ifdef CONFIG_PM
 +#include <linux/pm.h>
 +#endif
 +#include <sound/core.h>
 +#include <sound/pcm.h>
 +
++#include <mach/omap-alsa.h>
 +#include "omap-alsa-dma.h"
 +
 +MODULE_AUTHOR("Mika Laitio");
 +MODULE_AUTHOR("Daniel Petrini");
 +MODULE_AUTHOR("David Cohen");
 +MODULE_AUTHOR("Anderson Briglia");
 +
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("OMAP driver for ALSA");
 +MODULE_ALIAS("omap_alsa_mcbsp.1");
 +
 +static char *id;
 +static struct snd_card_omap_codec     *alsa_codec;
 +static struct omap_alsa_codec_config  *alsa_codec_config;
 +
 +/* FIXME: Please change to use omap asoc framework instead, this can be racy */
 +static dma_addr_t dma_start_pos;
 +
 +/*
 + * HW interface start and stop helper functions
 + */
 +static int audio_ifc_start(void)
 +{
 +      omap_mcbsp_start(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static int audio_ifc_stop(void)
 +{
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static void omap_alsa_audio_init(struct snd_card_omap_codec *omap_alsa)
 +{
 +      /* Setup DMA stuff */
 +      omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa omap out";
 +      omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
 +          SNDRV_PCM_STREAM_PLAYBACK;
 +      omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
 +          OMAP_DMA_MCBSP1_TX;
 +      omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_start =
 +          audio_ifc_start;
 +      omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_stop =
 +          audio_ifc_stop;
 +
 +      omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa omap in";
 +      omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
 +          SNDRV_PCM_STREAM_CAPTURE;
 +      omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
 +          OMAP_DMA_MCBSP1_RX;
 +      omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_start =
 +          audio_ifc_start;
 +      omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_stop =
 +          audio_ifc_stop;
 +}
 +
 +/*
 + * DMA functions
 + * Depends on omap-alsa-dma.c functions and (omap) dma.c
 + */
 +static int audio_dma_request(struct audio_stream *s,
 +                           void (*callback) (void *))
 +{
 +      int err;
 +      ADEBUG();
 +
 +      err = omap_request_alsa_sound_dma(s->dma_dev, s->id, s, &s->lch);
 +      if (err < 0)
 +              printk(KERN_ERR "Unable to grab audio dma 0x%x\n", s->dma_dev);
 +      return err;
 +}
 +
 +static int audio_dma_free(struct audio_stream *s)
 +{
 +      int err = 0;
 +      ADEBUG();
 +
 +      err = omap_free_alsa_sound_dma(s, &s->lch);
 +      if (err < 0)
 +              printk(KERN_ERR "Unable to free audio dma channels!\n");
 +      return err;
 +}
 +
 +/*
 + *  This function should calculate the current position of the dma in the
 + *  buffer. It will help alsa middle layer to continue update the buffer.
 + *  Its correctness is crucial for good functioning.
 + */
 +static u_int audio_get_dma_pos(struct audio_stream *s)
 +{
 +      struct snd_pcm_substream *substream = s->stream;
 +      struct snd_pcm_runtime *runtime = substream->runtime;
 +      unsigned int offset;
 +      unsigned long flags;
 +      dma_addr_t count;
 +      ADEBUG();
 +
 +      /* this must be called w/ interrupts locked as requested in dma.c */
 +      spin_lock_irqsave(&s->dma_lock, flags);
 +
 +      /* For the current period let's see where we are */
 +      count = omap_get_dma_src_pos(s->lch[s->dma_q_head]) - dma_start_pos;
 +
 +      spin_unlock_irqrestore(&s->dma_lock, flags);
 +
 +      /* Now, the position related to the end of that period */
 +      offset = bytes_to_frames(runtime, s->offset) -
 +                      bytes_to_frames(runtime, count);
 +
 +      if (offset >= runtime->buffer_size)
 +              offset = 0;
 +
 +      return offset;
 +}
 +
 +/*
 + * this stops the dma and clears the dma ptrs
 + */
 +static void audio_stop_dma(struct audio_stream *s)
 +{
 +      unsigned long flags;
 +      ADEBUG();
 +
 +      spin_lock_irqsave(&s->dma_lock, flags);
 +      s->active = 0;
 +      s->period = 0;
 +      s->periods = 0;
 +
 +      /* this stops the dma channel and clears the buffer ptrs */
 +      omap_stop_alsa_sound_dma(s);
 +
 +      omap_clear_alsa_sound_dma(s);
 +
 +      spin_unlock_irqrestore(&s->dma_lock, flags);
 +}
 +
 +/*
 + *  Main dma routine, requests dma according where you are in main alsa buffer
 + */
 +static void audio_process_dma(struct audio_stream *s)
 +{
 +      struct snd_pcm_substream *substream = s->stream;
 +      struct snd_pcm_runtime *runtime;
 +      unsigned int dma_size;
 +      unsigned int offset;
 +      int ret;
 +
 +      ADEBUG();
 +      runtime = substream->runtime;
 +      if (s->active) {
 +              dma_size = frames_to_bytes(runtime, runtime->period_size);
 +              offset = dma_size * s->period;
 +              snd_assert(dma_size <= DMA_BUF_SIZE, return);
 +              /*
 +               * On omap1510 based devices, we need to call the stop_dma
 +               * before calling the start_dma or we will not receive the
 +               * irq from DMA after the first transfered/played buffer.
 +               * (invocation of callback_omap_alsa_sound_dma() method).
 +               */
 +              if (cpu_is_omap1510())
 +                      omap_stop_alsa_sound_dma(s);
 +
 +              dma_start_pos = (dma_addr_t)runtime->dma_area + offset;
 +              ret = omap_start_alsa_sound_dma(s, dma_start_pos, dma_size);
 +              if (ret) {
 +                      printk(KERN_ERR "audio_process_dma: cannot"
 +                                      " queue DMA buffer (%i)\n", ret);
 +                      return;
 +              }
 +
 +              s->period++;
 +              s->period %= runtime->periods;
 +              s->periods++;
 +              s->offset = offset;
 +      }
 +}
 +
 +/*
 + *  This is called when dma IRQ occurs at the end of each transmited block
 + */
 +void callback_omap_alsa_sound_dma(void *data)
 +{
 +      struct audio_stream *s = data;
 +
 +      ADEBUG();
 +      /*
 +       * If we are getting a callback for an active stream then we inform
 +       * the PCM middle layer we've finished a period
 +       */
 +      if (s->active)
 +              snd_pcm_period_elapsed(s->stream);
 +
 +      spin_lock(&s->dma_lock);
 +      if (s->periods > 0)
 +              s->periods--;
 +
 +      audio_process_dma(s);
 +      spin_unlock(&s->dma_lock);
 +}
 +
 +/*
 + * Alsa section
 + * PCM settings and callbacks
 + */
 +static int snd_omap_alsa_trigger(struct snd_pcm_substream *substream, int cmd)
 +{
 +      struct snd_card_omap_codec *chip =
 +          snd_pcm_substream_chip(substream);
 +      int stream_id = substream->pstr->stream;
 +      struct audio_stream *s = &chip->s[stream_id];
 +      int err = 0;
 +
 +      ADEBUG();
 +      /* note local interrupts are already disabled in the midlevel code */
 +      spin_lock(&s->dma_lock);
 +      switch (cmd) {
 +      case SNDRV_PCM_TRIGGER_START:
 +              /* requested stream startup */
 +              s->active = 1;
 +              audio_process_dma(s);
 +              break;
 +      case SNDRV_PCM_TRIGGER_STOP:
 +              /* requested stream shutdown */
 +              audio_stop_dma(s);
 +              break;
 +      default:
 +              err = -EINVAL;
 +              break;
 +      }
 +      spin_unlock(&s->dma_lock);
 +
 +      return err;
 +}
 +
 +static int snd_omap_alsa_prepare(struct snd_pcm_substream *substream)
 +{
 +      struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
 +      struct snd_pcm_runtime *runtime = substream->runtime;
 +      struct audio_stream *s = &chip->s[substream->pstr->stream];
 +
 +      ADEBUG();
 +      /* set requested samplerate */
 +      alsa_codec_config->codec_set_samplerate(runtime->rate);
 +      chip->samplerate = runtime->rate;
 +
 +      s->period = 0;
 +      s->periods = 0;
 +
 +      return 0;
 +}
 +
 +static snd_pcm_uframes_t
 +snd_omap_alsa_pointer(struct snd_pcm_substream *substream)
 +{
 +      struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
 +
 +      ADEBUG();
 +      return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
 +}
 +
 +static int snd_card_omap_alsa_open(struct snd_pcm_substream *substream)
 +{
 +      struct snd_card_omap_codec *chip =
 +          snd_pcm_substream_chip(substream);
 +      struct snd_pcm_runtime *runtime = substream->runtime;
 +      int stream_id = substream->pstr->stream;
 +      int err;
 +
 +      ADEBUG();
 +      chip->s[stream_id].stream = substream;
 +      alsa_codec_config->codec_clock_on();
 +      if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
 +              runtime->hw = *(alsa_codec_config->snd_omap_alsa_playback);
 +      else
 +              runtime->hw = *(alsa_codec_config->snd_omap_alsa_capture);
 +
 +      err = snd_pcm_hw_constraint_integer(runtime,
 +                                              SNDRV_PCM_HW_PARAM_PERIODS);
 +      if (err < 0)
 +              return err;
 +
 +      err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 +                              alsa_codec_config->hw_constraints_rates);
 +      if (err < 0)
 +              return err;
 +
 +      return 0;
 +}
 +
 +static int snd_card_omap_alsa_close(struct snd_pcm_substream *substream)
 +{
 +      struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
 +
 +      ADEBUG();
 +      alsa_codec_config->codec_clock_off();
 +      chip->s[substream->pstr->stream].stream = NULL;
 +
 +      return 0;
 +}
 +
 +/* HW params & free */
 +static int snd_omap_alsa_hw_params(struct snd_pcm_substream *substream,
 +                                      struct snd_pcm_hw_params *hw_params)
 +{
 +      return snd_pcm_lib_malloc_pages(substream,
 +                                      params_buffer_bytes(hw_params));
 +}
 +
 +static int snd_omap_alsa_hw_free(struct snd_pcm_substream *substream)
 +{
 +      return snd_pcm_lib_free_pages(substream);
 +}
 +
 +/* pcm operations */
 +static struct snd_pcm_ops snd_card_omap_alsa_playback_ops = {
 +      .open =         snd_card_omap_alsa_open,
 +      .close =        snd_card_omap_alsa_close,
 +      .ioctl =        snd_pcm_lib_ioctl,
 +      .hw_params =    snd_omap_alsa_hw_params,
 +      .hw_free =      snd_omap_alsa_hw_free,
 +      .prepare =      snd_omap_alsa_prepare,
 +      .trigger =      snd_omap_alsa_trigger,
 +      .pointer =      snd_omap_alsa_pointer,
 +};
 +
 +static struct snd_pcm_ops snd_card_omap_alsa_capture_ops = {
 +      .open =         snd_card_omap_alsa_open,
 +      .close =        snd_card_omap_alsa_close,
 +      .ioctl =        snd_pcm_lib_ioctl,
 +      .hw_params =    snd_omap_alsa_hw_params,
 +      .hw_free =      snd_omap_alsa_hw_free,
 +      .prepare =      snd_omap_alsa_prepare,
 +      .trigger =      snd_omap_alsa_trigger,
 +      .pointer =      snd_omap_alsa_pointer,
 +};
 +
 +/*
 + *  Alsa init and exit section
 + *  Inits pcm alsa structures, allocate the alsa buffer, suspend, resume
 + */
 +static int __init snd_card_omap_alsa_pcm(struct snd_card_omap_codec *omap_alsa,
 +                                      int device)
 +{
 +      struct snd_pcm *pcm;
 +      int err;
 +
 +      ADEBUG();
 +      err = snd_pcm_new(omap_alsa->card, "OMAP PCM", device, 1, 1, &pcm);
 +      if (err < 0)
 +              return err;
 +
 +      /* sets up initial buffer with continuous allocation */
 +      snd_pcm_lib_preallocate_pages_for_all(pcm,
 +                                            SNDRV_DMA_TYPE_CONTINUOUS,
 +                                            snd_dma_continuous_data
 +                                            (GFP_KERNEL),
 +                                            128 * 1024, 128 * 1024);
 +
 +      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 +                      &snd_card_omap_alsa_playback_ops);
 +      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 +                      &snd_card_omap_alsa_capture_ops);
 +      pcm->private_data = omap_alsa;
 +      pcm->info_flags = 0;
 +      strcpy(pcm->name, "omap alsa pcm");
 +
 +      omap_alsa_audio_init(omap_alsa);
 +
 +      /* setup DMA controller */
 +      audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK],
 +                        callback_omap_alsa_sound_dma);
 +      audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE],
 +                        callback_omap_alsa_sound_dma);
 +
 +      omap_alsa->pcm = pcm;
 +
 +      return 0;
 +}
 +
 +
 +#ifdef CONFIG_PM
 +/*
 + * Driver suspend/resume - calls alsa functions. Some hints from aaci.c
 + */
 +int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct snd_card_omap_codec *chip;
 +      struct snd_card *card = platform_get_drvdata(pdev);
 +
 +      if (card->power_state != SNDRV_CTL_POWER_D3hot) {
 +              chip = card->private_data;
 +              if (chip->card->power_state != SNDRV_CTL_POWER_D3hot) {
 +                      snd_power_change_state(chip->card,
 +                                              SNDRV_CTL_POWER_D3hot);
 +                      snd_pcm_suspend_all(chip->pcm);
 +                      /* Mutes and turn clock off */
 +                      alsa_codec_config->codec_clock_off();
 +                      snd_omap_suspend_mixer();
 +              }
 +      }
 +      return 0;
 +}
 +
 +int snd_omap_alsa_resume(struct platform_device *pdev)
 +{
 +      struct snd_card_omap_codec *chip;
 +      struct snd_card *card = platform_get_drvdata(pdev);
 +
 +      if (card->power_state != SNDRV_CTL_POWER_D0) {
 +              chip = card->private_data;
 +              if (chip->card->power_state != SNDRV_CTL_POWER_D0) {
 +                      snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
 +                      alsa_codec_config->codec_clock_on();
 +                      snd_omap_resume_mixer();
 +              }
 +      }
 +      return 0;
 +}
 +
 +#endif        /* CONFIG_PM */
 +
 +void snd_omap_alsa_free(struct snd_card *card)
 +{
 +      struct snd_card_omap_codec *chip = card->private_data;
 +      ADEBUG();
 +
 +      /*
 +       * Turn off codec after it is done.
 +       * Can't do it immediately, since it may still have
 +       * buffered data.
 +       */
 +      schedule_timeout_interruptible(2);
 +
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      omap_mcbsp_free(AUDIO_MCBSP);
 +
 +      audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
 +      audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
 +}
 +
 +/* module init & exit */
 +
 +/*
 + * Inits alsa soudcard structure.
 + * Called by the probe method in codec after function pointers has been set.
 + */
 +int snd_omap_alsa_post_probe(struct platform_device *pdev,
 +                              struct omap_alsa_codec_config *config)
 +{
 +      int err = 0;
 +      int def_rate;
 +      struct snd_card *card;
 +
 +      ADEBUG();
 +      alsa_codec_config       = config;
 +
 +      alsa_codec_config->codec_clock_setup();
 +      alsa_codec_config->codec_clock_on();
 +
 +      omap_mcbsp_request(AUDIO_MCBSP);
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      omap_mcbsp_config(AUDIO_MCBSP, alsa_codec_config->mcbsp_regs_alsa);
 +      omap_mcbsp_start(AUDIO_MCBSP);
 +
 +      if (alsa_codec_config && alsa_codec_config->codec_configure_dev)
 +              alsa_codec_config->codec_configure_dev();
 +
 +      alsa_codec_config->codec_clock_off();
 +
 +      /* register the soundcard */
 +      card = snd_card_new(-1, id, THIS_MODULE, sizeof(alsa_codec));
 +      if (card == NULL)
 +              goto nodev1;
 +
 +      alsa_codec = kcalloc(1, sizeof(*alsa_codec), GFP_KERNEL);
 +      if (alsa_codec == NULL)
 +              goto nodev2;
 +
 +      card->private_data = (void *)alsa_codec;
 +      card->private_free = snd_omap_alsa_free;
 +
 +      alsa_codec->card        = card;
 +      def_rate                = alsa_codec_config->get_default_samplerate();
 +      alsa_codec->samplerate  = def_rate;
 +
 +      spin_lock_init(&alsa_codec->s[0].dma_lock);
 +      spin_lock_init(&alsa_codec->s[1].dma_lock);
 +
 +      /* mixer */
 +      err = snd_omap_mixer(alsa_codec);
 +      if (err < 0)
 +              goto nodev3;
 +
 +      /* PCM */
 +      err = snd_card_omap_alsa_pcm(alsa_codec, 0);
 +      if (err < 0)
 +              goto nodev3;
 +
 +      strcpy(card->driver, "OMAP_ALSA");
 +      strcpy(card->shortname, alsa_codec_config->name);
 +      sprintf(card->longname, alsa_codec_config->name);
 +
 +      snd_omap_init_mixer();
 +      snd_card_set_dev(card, &pdev->dev);
 +
 +      err = snd_card_register(card);
 +      if (err == 0) {
 +              printk(KERN_INFO "audio support initialized\n");
 +              platform_set_drvdata(pdev, card);
 +              return 0;
 +      }
 +
 +nodev3:
 +      kfree(alsa_codec);
 +nodev2:
 +      snd_card_free(card);
 +nodev1:
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      omap_mcbsp_free(AUDIO_MCBSP);
 +
 +      return err;
 +}
 +
 +int snd_omap_alsa_remove(struct platform_device *pdev)
 +{
 +      struct snd_card *card = platform_get_drvdata(pdev);
 +      struct snd_card_omap_codec *chip = card->private_data;
 +
 +      snd_card_free(card);
 +
 +      alsa_codec = NULL;
 +      card->private_data = NULL;
 +      kfree(chip);
 +
 +      platform_set_drvdata(pdev, NULL);
 +
 +      return 0;
 +}
index 0ecb2f77c6796649553b08eaf0d948945de79414,0000000000000000000000000000000000000000..c603aaa18d524839335193d9a3094d01506fa939
mode 100644,000000..100644
--- /dev/null
@@@ -1,754 -1,0 +1,754 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/sound/oss/omap-audio-aic23.c
 + *
 + * Glue audio driver for TI TLV320AIC23 codec
 + *
 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
 + * Copyright (C) 2001, Steve Johnson <stevej@ridgerun.com>
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + * Copyright (C) 2005 Dirk Behme <dirk.behme@de.bosch.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 + * NO EVENT SHALL THE 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.
 + *
 + * You should have received a copy of the  GNU General Public License along
 + * with this program; if not, write  to the Free Software Foundation, Inc.,
 + * 675 Mass Ave, Cambridge, MA 02139, USA.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/types.h>
 +#include <linux/delay.h>
 +#include <linux/pm.h>
 +#include <linux/errno.h>
 +#include <linux/sound.h>
 +#include <linux/soundcard.h>
 +#include <linux/clk.h>
 +#include <linux/mutex.h>
 +
 +#include <asm/uaccess.h>
- #include <asm/arch/mcbsp.h>
- #include <asm/arch/fpga.h>
- #include <asm/arch/aic23.h>
- #include <asm/arch/clock.h>
++#include <mach/hardware.h>
 +#include <asm/io.h>
 +#include <asm/mach-types.h>
 +
++#include <mach/mcbsp.h>
++#include <mach/fpga.h>
++#include <mach/aic23.h>
++#include <mach/clock.h>
 +
 +#include "omap-audio.h"
 +#include "omap-audio-dma-intfc.h"
 +
 +#ifdef CONFIG_PROC_FS
 +#include <linux/proc_fs.h>
 +#define PROC_START_FILE "driver/aic23-audio-start"
 +#define PROC_STOP_FILE  "driver/aic23-audio-stop"
 +#endif
 +
 +//#define DEBUG
 +
 +#ifdef DEBUG
 +#define DPRINTK(ARGS...)  printk("<%s>: ",__FUNCTION__);printk(ARGS)
 +#else
 +#define DPRINTK( x... )
 +#endif
 +
 +#define CODEC_NAME             "AIC23"
 +
 +#if CONFIG_MACH_OMAP_OSK
 +#define PLATFORM_NAME            "OMAP OSK"
 +#elif CONFIG_MACH_OMAP_INNOVATOR
 +#define PLATFORM_NAME            "OMAP INNOVATOR"
 +#else
 +#error "Unsupported plattform"
 +#endif
 +
 +/* Define to set the AIC23 as the master w.r.t McBSP */
 +#define AIC23_MASTER
 +
 +#define CODEC_CLOCK                   12000000
 +
 +/*
 + * AUDIO related MACROS
 + */
 +#define DEFAULT_BITPERSAMPLE          16
 +#define AUDIO_RATE_DEFAULT          44100
 +
 +/* Select the McBSP For Audio */
 +#define AUDIO_MCBSP                   OMAP_MCBSP1
 +
 +#define REC_MASK                    (SOUND_MASK_LINE | SOUND_MASK_MIC)
 +#define DEV_MASK                    (REC_MASK | SOUND_MASK_VOLUME)
 +
 +#define SET_VOLUME                  1
 +#define SET_LINE                    2
 +
 +#define DEFAULT_OUTPUT_VOLUME         93
 +#define DEFAULT_INPUT_VOLUME          0       /* 0 ==> mute line in */
 +
 +#define OUTPUT_VOLUME_MIN             LHV_MIN
 +#define OUTPUT_VOLUME_MAX             LHV_MAX
 +#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
 +#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
 +
 +#define INPUT_VOLUME_MIN            LIV_MIN
 +#define INPUT_VOLUME_MAX            LIV_MAX
 +#define INPUT_VOLUME_RANGE          (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
 +#define INPUT_VOLUME_MASK           INPUT_VOLUME_MAX
 +
 +#define NUMBER_SAMPLE_RATES_SUPPORTED 9
 +
 +/*
 + * HW interface start and stop helper functions
 + */
 +static int audio_ifc_start(void)
 +{
 +      omap_mcbsp_start(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static int audio_ifc_stop(void)
 +{
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static audio_stream_t output_stream = {
 +        .id              = "AIC23 out",
 +        .dma_dev         = OMAP_DMA_MCBSP1_TX,
 +      .input_or_output = FMODE_WRITE,
 +      .hw_start       = audio_ifc_start,
 +      .hw_stop         = audio_ifc_stop
 +};
 +
 +static audio_stream_t input_stream = {
 +        .id              = "AIC23 in",
 +        .dma_dev         = OMAP_DMA_MCBSP1_RX,
 +      .input_or_output = FMODE_READ,
 +      .hw_start       = audio_ifc_start,
 +      .hw_stop         = audio_ifc_stop
 +};
 +
 +static struct clk *aic23_mclk = 0;
 +
 +static int audio_dev_id, mixer_dev_id;
 +
 +static struct aic23_local_info {
 +        u8  volume;
 +        u16 volume_reg;
 +        u8  line;
 +        u8  mic;
 +        u16 input_volume_reg;
 +        int mod_cnt;
 +} aic23_local;
 +
 +struct sample_rate_reg_info {
 +        u32 sample_rate;
 +        u8  control;            /* SR3, SR2, SR1, SR0 and BOSR */
 +        u8  divider;          /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
 +};
 +
 +/* To Store the default sample rate */
 +static long audio_samplerate = AUDIO_RATE_DEFAULT;
 +
 +/* DAC USB-mode sampling rates (MCLK = 12 MHz) */
 +static const struct sample_rate_reg_info
 +reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
 +        {96000, 0x0E, 0},
 +        {88200, 0x1F, 0},
 +        {48000, 0x00, 0},
 +        {44100, 0x11, 0},
 +        {32000, 0x0C, 0},
 +        {24000, 0x00, 1},
 +        {16000, 0x0C, 1},
 +        { 8000, 0x06, 0},
 +        { 4000, 0x06, 1},
 +};
 +
 +static struct omap_mcbsp_reg_cfg initial_config = {
 +        .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
 +        .spcr1 = RINTM(3) | RRST,
 +        .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
 +      RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
 +        .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
 +        .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
 +        XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
 +        .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
 +        .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
 +        .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
 +#ifndef AIC23_MASTER
 +        /* configure McBSP to be the I2S master */
 +        .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
 +#else
 +        /* configure McBSP to be the I2S slave */
 +        .pcr0  = CLKXP | CLKRP,
 +#endif /* AIC23_MASTER */
 +};
 +
 +static void omap_aic23_initialize(void *dummy);
 +static void omap_aic23_shutdown(void *dummy);
 +static int  omap_aic23_ioctl(struct inode *inode, struct file *file,
 +                             uint cmd, ulong arg);
 +static int  omap_aic23_probe(void);
 +#ifdef MODULE
 +static void omap_aic23_remove(void);
 +#endif
 +static int  omap_aic23_suspend(void);
 +static int  omap_aic23_resume(void);
 +static inline void aic23_configure(void);
 +static int  mixer_open(struct inode *inode, struct file *file);
 +static int  mixer_release(struct inode *inode, struct file *file);
 +static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
 +                        ulong arg);
 +
 +#ifdef CONFIG_PROC_FS
 +static int codec_start(char *buf, char **start, off_t offset, int count,
 +                       int *eof, void *data);
 +static int codec_stop(char *buf, char **start, off_t offset, int count,
 +                      int *eof, void *data);
 +#endif
 +
 +
 +/* File Op structure for mixer */
 +static struct file_operations omap_mixer_fops = {
 +        .open           = mixer_open,
 +        .release        = mixer_release,
 +        .ioctl          = mixer_ioctl,
 +        .owner          = THIS_MODULE
 +};
 +
 +/* To store characteristic info regarding the codec for the audio driver */
 +static audio_state_t aic23_state = {
 +        .output_stream  = &output_stream,
 +        .input_stream   = &input_stream,
 +/*    .need_tx_for_rx = 1, //Once the Full Duplex works  */
 +        .need_tx_for_rx = 0,
 +        .hw_init        = omap_aic23_initialize,
 +        .hw_shutdown    = omap_aic23_shutdown,
 +        .client_ioctl   = omap_aic23_ioctl,
 +        .hw_probe       = omap_aic23_probe,
 +        .hw_remove      =  __exit_p(omap_aic23_remove),
 +        .hw_suspend     = omap_aic23_suspend,
 +        .hw_resume      = omap_aic23_resume,
 +};
 +
 +/* This will be defined in the audio.h */
 +static struct file_operations *omap_audio_fops;
 +
 +extern int aic23_write_value(u8 reg, u16 value);
 +
 +/* TLV320AIC23 is a write only device */
 +static __inline__ void audio_aic23_write(u8 address, u16 data)
 +{
 +        aic23_write_value(address, data);
 +}
 +
 +static int aic23_update(int flag, int val)
 +{
 +        u16 volume;
 +
 +        /* Ignore separate left/right channel for now,
 +           even the codec does support it. */
 +        val &= 0xff;
 +
 +        if (val < 0 || val > 100) {
 +                printk(KERN_ERR "Trying a bad volume value(%d)!\n",val);
 +                return -EPERM;
 +        }
 +
 +        switch (flag) {
 +        case SET_VOLUME:
 +                // Convert 0 -> 100 volume to 0x00 (LHV_MIN) -> 0x7f (LHV_MAX) 
 +                // volume range
 +                volume = ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
 +                
 +                // R/LHV[6:0] 1111111 (+6dB) to 0000000 (-73dB) in 1db steps,
 +                // default 1111001 (0dB)
 +                aic23_local.volume_reg &= ~OUTPUT_VOLUME_MASK;
 +                aic23_local.volume_reg |= volume;
 +                audio_aic23_write(LEFT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
 +                audio_aic23_write(RIGHT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
 +                break;
 +
 +        case SET_LINE:
 +                // Convert 0 -> 100 volume to 0x0 (LIV_MIN) -> 0x1f (LIV_MAX) 
 +                // volume range
 +                volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
 +
 +                // R/LIV[4:0] 11111 (+12dB) to 00000 (-34.5dB) in 1.5dB steps,
 +                // default 10111 (0dB)
 +                aic23_local.input_volume_reg &= ~INPUT_VOLUME_MASK;
 +                aic23_local.input_volume_reg |= volume;
 +                audio_aic23_write(LEFT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
 +                audio_aic23_write(RIGHT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
 +                break;
 +        }
 +        return 0;
 +}
 +
 +static int mixer_open(struct inode *inode, struct file *file)
 +{
 +        /* Any mixer specific initialization */
 +
 +        return 0;
 +}
 +
 +static int mixer_release(struct inode *inode, struct file *file)
 +{
 +        /* Any mixer specific Un-initialization */
 +
 +        return 0;
 +}
 +
 +static int
 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 +{
 +        int val;
 +        int ret = 0;
 +        int nr = _IOC_NR(cmd);
 +
 +        /*
 +         * We only accept mixer (type 'M') ioctls.
 +         */
 +        if (_IOC_TYPE(cmd) != 'M')
 +                return -EINVAL;
 +
 +        DPRINTK(" 0x%08x\n", cmd);
 +
 +        if (cmd == SOUND_MIXER_INFO) {
 +                struct mixer_info mi;
 +
 +                strncpy(mi.id, "AIC23", sizeof(mi.id));
 +                strncpy(mi.name, "TI AIC23", sizeof(mi.name));
 +                mi.modify_counter = aic23_local.mod_cnt;
 +                return copy_to_user((void *)arg, &mi, sizeof(mi));
 +        }
 +
 +        if (_IOC_DIR(cmd) & _IOC_WRITE) {
 +                ret = get_user(val, (int *)arg);
 +                if (ret)
 +                        goto out;
 +
 +        
 +                switch (nr) {
 +                case SOUND_MIXER_VOLUME:
 +                        aic23_local.volume = val;
 +                        aic23_local.mod_cnt++;
 +                        ret = aic23_update(SET_VOLUME, val);
 +                        break;
 +
 +                case SOUND_MIXER_LINE:
 +                        aic23_local.line = val;
 +                        aic23_local.mod_cnt++;
 +                        ret = aic23_update(SET_LINE, val);
 +                        break;
 +
 +                case SOUND_MIXER_MIC:
 +                        aic23_local.mic = val;
 +                        aic23_local.mod_cnt++;
 +                        ret = aic23_update(SET_LINE, val);
 +                        break;
 +
 +                case SOUND_MIXER_RECSRC:
 +                        break;
 +
 +                default:
 +                        ret = -EINVAL;
 +                }
 +        }
 +
 +        if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
 +                ret = 0;
 +
 +                switch (nr) {
 +                case SOUND_MIXER_VOLUME:
 +                        val = aic23_local.volume;
 +                        break;
 +                case SOUND_MIXER_LINE:
 +                        val = aic23_local.line;
 +                        break;
 +                case SOUND_MIXER_MIC:
 +                        val = aic23_local.mic;
 +                        break;
 +                case SOUND_MIXER_RECSRC:
 +                        val = REC_MASK;
 +                        break;
 +                case SOUND_MIXER_RECMASK:
 +                        val = REC_MASK;
 +                        break;
 +                case SOUND_MIXER_DEVMASK:
 +                        val = DEV_MASK;
 +                        break;
 +                case SOUND_MIXER_CAPS:
 +                        val = 0;
 +                        break;
 +                case SOUND_MIXER_STEREODEVS:
 +                        val = 0;
 +                        break;
 +                default:
 +                        val = 0;
 +                        ret = -EINVAL;
 +                        break;
 +                }
 +
 +                if (ret == 0)
 +                        ret = put_user(val, (int *)arg);
 +        }
 +out:
 +        return ret;
 +
 +}
 +
 +int omap_set_samplerate(long sample_rate)
 +{
 +        u8 count = 0;
 +        u16 data = 0;
 +        /* wait for any frame to complete */
 +        udelay(125);
 +
 +        /* Search for the right sample rate */
 +        while ((reg_info[count].sample_rate != sample_rate) &&
 +               (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
 +                count++;
 +        }
 +        if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
 +                printk(KERN_ERR "Invalid Sample Rate %d requested\n",
 +                       (int)sample_rate);
 +                return -EPERM;
 +        }
 +
 +        if (machine_is_omap_innovator()) {
 +                /* set the CODEC clock input source to 12.000MHz */
 +                fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~0x01, 
 +                           OMAP1510_FPGA_POWER);
 +        }
 +
 +        data = (reg_info[count].divider << CLKIN_SHIFT) | 
 +                (reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
 +
 +        audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
 +
 +        audio_samplerate = sample_rate;
 +
 +#ifndef AIC23_MASTER
 +        {
 +                int clkgdv = 0;
 +                /* 
 +                   Set Sample Rate at McBSP
 +
 +                   Formula : 
 +                   Codec System Clock = CODEC_CLOCK, or half if clock_divider = 1;
 +                   clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1);
 +
 +                   FWID = BitsPerSample - 1;
 +                   FPER = (BitsPerSample * 2) - 1;
 +                */  
 +                if (reg_info[count].divider)
 +                        clkgdv = CODEC_CLOCK / 2;
 +                else 
 +                        clkgdv = CODEC_CLOCK;
 +
 +                clkgdv = (clkgdv / (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1;
 +
 +                initial_config.srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +
 +                initial_config.srgr2 =
 +                        (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
 +
 +                omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
 +        }
 +#endif /* AIC23_MASTER */
 +
 +        return 0;
 +}
 +
 +static void omap_aic23_initialize(void *dummy)
 +{
 +        DPRINTK("entry\n");
 +
 +        /* initialize with default sample rate */
 +        audio_samplerate = AUDIO_RATE_DEFAULT;
 +
 +        omap_mcbsp_request(AUDIO_MCBSP);
 +
 +        /* if configured, then stop mcbsp */
 +        omap_mcbsp_stop(AUDIO_MCBSP);
 +
 +        omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
 +        omap_mcbsp_start(AUDIO_MCBSP);
 +        aic23_configure();
 +
 +        DPRINTK("exit\n");
 +}
 +
 +static void omap_aic23_shutdown(void *dummy)
 +{
 +        /*
 +          Turn off codec after it is done.
 +          Can't do it immediately, since it may still have
 +          buffered data.
 +
 +          Wait 20ms (arbitrary value) and then turn it off.
 +        */
 +
 +        set_current_state(TASK_INTERRUPTIBLE);
 +        schedule_timeout(2);
 +
 +        omap_mcbsp_stop(AUDIO_MCBSP);
 +        omap_mcbsp_free(AUDIO_MCBSP);
 +
 +        audio_aic23_write(RESET_CONTROL_ADDR, 0);
 +        audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0xff);
 +}
 +
 +static inline void aic23_configure()
 +{
 +        /* Reset codec */
 +        audio_aic23_write(RESET_CONTROL_ADDR, 0);
 +
 +        /* Initialize the AIC23 internal state */
 +
 +        /* Left/Right line input volume control */
 +        aic23_local.line = DEFAULT_INPUT_VOLUME;
 +        aic23_local.mic = DEFAULT_INPUT_VOLUME;
 +        aic23_update(SET_LINE, DEFAULT_INPUT_VOLUME);
 +
 +        /* Left/Right headphone channel volume control */
 +        /* Zero-cross detect on */
 +        aic23_local.volume_reg = LZC_ON;
 +        aic23_update(SET_VOLUME, aic23_local.volume);
 +
 +        /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
 +        audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DAC_SELECTED | INSEL_MIC);
 +
 +        /* Digital audio path control, de-emphasis control 44.1kHz */
 +        audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
 +
 +        /* Power control, everything is on */
 +        audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0);
 +
 +        /* Digital audio interface, master/slave mode, I2S, 16 bit */
 +#ifdef AIC23_MASTER
 +        audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, MS_MASTER | IWL_16 | FOR_DSP);
 +#else
 +        audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
 +#endif /* AIC23_MASTER */
 +
 +        /* Enable digital interface */
 +        audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
 +
 +        /* clock configuration */
 +        omap_set_samplerate(audio_samplerate);
 +}
 +
 +static int
 +omap_aic23_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 +{
 +        long val;
 +        int ret = 0;
 +
 +        DPRINTK(" 0x%08x\n", cmd);
 +
 +        /*
 +         * These are platform dependent ioctls which are not handled by the
 +         * generic omap-audio module.
 +         */
 +        switch (cmd) {
 +        case SNDCTL_DSP_STEREO:
 +                ret = get_user(val, (int *)arg);
 +                if (ret)
 +                        return ret;
 +                /* the AIC23 is stereo only */
 +                ret = (val == 0) ? -EINVAL : 1;
 +                return put_user(ret, (int *)arg);
 +
 +        case SNDCTL_DSP_CHANNELS:
 +        case SOUND_PCM_READ_CHANNELS:
 +                /* the AIC23 is stereo only */
 +                return put_user(2, (long *)arg);
 +
 +        case SNDCTL_DSP_SPEED:
 +                ret = get_user(val, (long *)arg);
 +                if (ret)
 +                        break;
 +                ret = omap_set_samplerate(val);
 +                if (ret)
 +                        break;
 +                /* fall through */
 +
 +        case SOUND_PCM_READ_RATE:
 +                return put_user(audio_samplerate, (long *)arg);
 +
 +        case SOUND_PCM_READ_BITS:
 +        case SNDCTL_DSP_SETFMT:
 +        case SNDCTL_DSP_GETFMTS:
 +                /* we can do 16-bit only */
 +                return put_user(AFMT_S16_LE, (long *)arg);
 +
 +        default:
 +                /* Maybe this is meant for the mixer (As per OSS Docs) */
 +                return mixer_ioctl(inode, file, cmd, arg);
 +        }
 +
 +        return ret;
 +}
 +
 +static int omap_aic23_probe(void)
 +{
 +        /* Get the fops from audio oss driver */
 +        if (!(omap_audio_fops = audio_get_fops())) {
 +                printk(KERN_ERR "Unable to get the file operations for AIC23 OSS driver\n");
 +                audio_unregister_codec(&aic23_state);
 +                return -EPERM;
 +        }
 +
 +        aic23_local.volume = DEFAULT_OUTPUT_VOLUME;
 +
 +        /* register devices */
 +        audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
 +        mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
 +
 +#ifdef CONFIG_PROC_FS
 +        create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
 +                               NULL /* parent dir */ ,
 +                               codec_start, NULL /* client data */ );
 +
 +        create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
 +                               NULL /* parent dir */ ,
 +                               codec_stop, NULL /* client data */ );
 +#endif
 +
 +        /* Announcement Time */
 +        printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
 +               " audio support initialized\n");
 +        return 0;
 +}
 +
 +#ifdef MODULE
 +static void __exit omap_aic23_remove(void)
 +{
 +        /* Un-Register the codec with the audio driver */
 +        unregister_sound_dsp(audio_dev_id);
 +        unregister_sound_mixer(mixer_dev_id);
 +
 +#ifdef CONFIG_PROC_FS
 +        remove_proc_entry(PROC_START_FILE, NULL);
 +        remove_proc_entry(PROC_STOP_FILE, NULL);
 +#endif
 +}
 +#endif /* MODULE */
 +
 +static int omap_aic23_suspend(void)
 +{
 +        /* Empty for the moment */
 +        return 0;
 +}
 +
 +static int omap_aic23_resume(void)
 +{
 +        /* Empty for the moment */
 +        return 0;
 +}
 +
 +static int __init audio_aic23_init(void)
 +{
 +
 +        int err = 0;
 +
 +      if (machine_is_omap_h2() || machine_is_omap_h3())
 +              return -ENODEV;
 +
 +      mutex_init(&aic23_state.mutex);
 +
 +        if (machine_is_omap_osk()) {
 +                /* Set MCLK to be clock input for AIC23 */
 +                aic23_mclk = clk_get(0, "mclk");
 +            
 +                if(clk_get_rate( aic23_mclk) != CODEC_CLOCK){
 +                        /* MCLK ist not at CODEC_CLOCK */
 +                        if( clk_get_usecount(aic23_mclk) > 0 ){
 +                                /* MCLK is already in use */
 +                                printk(KERN_WARNING "MCLK in use at %d Hz. We change it to %d Hz\n",
 +                                       (uint)clk_get_rate( aic23_mclk), CODEC_CLOCK);
 +                        }
 +                        if( clk_set_rate( aic23_mclk, CODEC_CLOCK ) ){
 +                                printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
 +                                return -ECANCELED;
 +                      }
 +              }
 +
 +                clk_enable( aic23_mclk );
 +
 +                DPRINTK("MCLK = %d [%d], usecount = %d\n",(uint)clk_get_rate( aic23_mclk ), 
 +                        CODEC_CLOCK, clk_get_usecount( aic23_mclk));
 +        }
 +
 +        if (machine_is_omap_innovator()) {
 +                u8 fpga;
 +                /*
 +                  Turn on chip select for CODEC (shared with touchscreen).  
 +                  Don't turn it back off, in case touch screen needs it.
 +                */                           
 +                fpga = fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
 +                fpga |= 0x4;
 +                fpga_write(fpga, OMAP1510_FPGA_TOUCHSCREEN);
 +        }
 +
 +        /* register the codec with the audio driver */
 +        if ((err = audio_register_codec(&aic23_state))) {
 +                printk(KERN_ERR
 +                       "Failed to register AIC23 driver with Audio OSS Driver\n");
 +        }
 +
 +        return err;
 +}
 +
 +static void __exit audio_aic23_exit(void)
 +{
 +        (void)audio_unregister_codec(&aic23_state);
 +        return;
 +}
 +
 +#ifdef CONFIG_PROC_FS
 +static int codec_start(char *buf, char **start, off_t offset, int count,
 +                       int *eof, void *data)
 +{
 +        void *foo = NULL;
 +
 +        omap_aic23_initialize(foo);
 +
 +        printk("AIC23 codec initialization done.\n");
 +        return 0;
 +}
 +static int codec_stop(char *buf, char **start, off_t offset, int count,
 +                      int *eof, void *data)
 +{
 +        void *foo = NULL;
 +
 +        omap_aic23_shutdown(foo);
 +
 +        printk("AIC23 codec shutdown.\n");
 +        return 0;
 +}
 +#endif /* CONFIG_PROC_FS */
 +
 +module_init(audio_aic23_init);
 +module_exit(audio_aic23_exit);
 +
 +MODULE_AUTHOR("Dirk Behme <dirk.behme@de.bosch.com>");
 +MODULE_DESCRIPTION("Glue audio driver for the TI AIC23 codec.");
 +MODULE_LICENSE("GPL");
index d568582604b8ef99a4638cd11b3a88db6853381a,0000000000000000000000000000000000000000..c6a61369eab924e82cbe03c0cc62b50ea0b81fee
mode 100644,000000..100644
--- /dev/null
@@@ -1,985 -1,0 +1,985 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/sound/oss/omap-audio-dma-intfc.c
 + *
 + * Common audio DMA handling for the OMAP processors
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + * History:
 + *
 + * 2004-06-07 Sriram Kannan   - Created new file from omap_audio_dma_intfc.c. This file
 + *                              will contain only the DMA interface and buffer handling of OMAP
 + *                              audio driver.
 + *
 + * 2004-06-22 Sriram Kannan   - removed legacy code (auto-init). Self-linking of DMA logical channel.
 + *
 + * 2004-08-12   Nishanth Menon  - Modified to integrate Audio requirements on 1610,1710 platforms
 + *
 + * 2004-11-01   Nishanth Menon  - 16xx platform code base modified to support multi channel chaining.
 + *
 + * 2004-12-15   Nishanth Menon  - Improved 16xx platform channel logic introduced - tasklets, queue handling updated
 + *
 + * 2005-12-10   Dirk Behme      - Added L/R Channel Interchange fix as proposed by Ajaya Babu
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/types.h>
 +#include <linux/fs.h>
 +#include <linux/mm.h>
 +#include <linux/slab.h>
 +#include <linux/sched.h>
 +#include <linux/poll.h>
 +#include <linux/pm.h>
 +#include <linux/errno.h>
 +#include <linux/sound.h>
 +#include <linux/soundcard.h>
 +#include <linux/sysrq.h>
 +#include <linux/interrupt.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/completion.h>
 +
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
- #include <asm/arch/dma.h>
++#include <mach/hardware.h>
 +#include <asm/semaphore.h>
 +
- #include <asm/arch/mcbsp.h>
++#include <mach/dma.h>
 +#include "omap-audio-dma-intfc.h"
 +
++#include <mach/mcbsp.h>
 +
 +#include "omap-audio.h"
 +
 +#undef DEBUG
 +//#define DEBUG
 +#ifdef DEBUG
 +#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
 +#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
 +#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
 +#else
 +
 +#define DPRINTK( x... )
 +#define FN_IN
 +#define FN_OUT(x)
 +#endif
 +
 +#define ERR(ARGS...) printk(KERN_ERR "{%s}-ERROR: ", __FUNCTION__);printk(ARGS);
 +
 +#define AUDIO_NAME            "omap-audio"
 +#define AUDIO_NBFRAGS_DEFAULT 8
 +#define AUDIO_FRAGSIZE_DEFAULT        8192
 +
 +#define AUDIO_ACTIVE(state)   ((state)->rd_ref || (state)->wr_ref)
 +
 +#define SPIN_ADDR             (dma_addr_t)0
 +#define SPIN_SIZE             2048
 +
 +/* Channel Queue Handling macros
 + * tail always points to the current free entry
 + * Head always points to the current entry being used
 + * end is either head or tail
 + */
 +
 +#define AUDIO_QUEUE_INIT(s) s->dma_q_head = s->dma_q_tail = s->dma_q_count = 0;
 +#define AUDIO_QUEUE_FULL(s) (nr_linked_channels == s->dma_q_count)
 +#define AUDIO_QUEUE_LAST(s) (1 == s->dma_q_count)
 +#define AUDIO_QUEUE_EMPTY(s) (0 == s->dma_q_count)
 +#define __AUDIO_INCREMENT_QUEUE(end) ((end)=((end)+1) % nr_linked_channels)
 +#define AUDIO_INCREMENT_HEAD(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_head); s->dma_q_count--;
 +#define AUDIO_INCREMENT_TAIL(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_tail); s->dma_q_count++;
 +
 +/* DMA buffer fragmentation sizes */
 +#define MAX_DMA_SIZE           0x1000000
 +#define CUT_DMA_SIZE           0x1000
 +/* TODO: To be moved to more appropriate location */
 +#define DCSR_ERROR           0x3
 +#define DCSR_SYNC_SET        (1 << 6)
 +
 +#define DCCR_FS              (1 << 5)
 +#define DCCR_PRIO            (1 << 6)
 +#define DCCR_AI              (1 << 8)
 +#define DCCR_REPEAT          (1 << 9)
 +/* if 0 the channel works in 3.1 compatible mode*/
 +#define DCCR_N31COMP         (1 << 10)
 +#define DCCR_EP              (1 << 11)
 +#define DCCR_SRC_AMODE_BIT   12
 +#define DCCR_SRC_AMODE_MASK  (0x3<<12)
 +#define DCCR_DST_AMODE_BIT   14
 +#define DCCR_DST_AMODE_MASK  (0x3<<14)
 +#define AMODE_CONST          0x0
 +#define AMODE_POST_INC       0x1
 +#define AMODE_SINGLE_INDEX   0x2
 +#define AMODE_DOUBLE_INDEX   0x3
 +
 +/**************************** DATA STRUCTURES *****************************************/
 +
 +static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
 +
 +struct audio_isr_work_item {
 +      int current_lch;
 +      u16 ch_status;
 +      audio_stream_t *s;
 +};
 +
 +static char work_item_running = 0;
 +static char nr_linked_channels = 1;
 +static struct audio_isr_work_item work1, work2;
 +
 +
 +/*********************************** MODULE SPECIFIC FUNCTIONS PROTOTYPES *************/
 +
 +static void audio_dsr_handler(unsigned long);
 +static DECLARE_TASKLET(audio_isr_work1, audio_dsr_handler,
 +              (unsigned long)&work1);
 +static DECLARE_TASKLET(audio_isr_work2, audio_dsr_handler,
 +              (unsigned long)&work2);
 +
 +static void sound_dma_irq_handler(int lch, u16 ch_status, void *data);
 +static void audio_dma_callback(int lch, u16 ch_status, void *data);
 +static int omap_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
 +                              u_int size);
 +static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
 +                                   u_int dma_size);
 +static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
 +                                      u_int dma_size);
 +static int audio_start_dma_chain(audio_stream_t * s);
 +
 +/*********************************** GLOBAL FUNCTIONS DEFINTIONS ***********************/
 +
 +/***************************************************************************************
 + *
 + * Buffer creation/destruction
 + *
 + **************************************************************************************/
 +int audio_setup_buf(audio_stream_t * s)
 +{
 +      int frag;
 +      int dmasize = 0;
 +      char *dmabuf = NULL;
 +      dma_addr_t dmaphys = 0;
 +      FN_IN;
 +      if (s->buffers) {
 +              FN_OUT(1);
 +              return -EBUSY;
 +      }
 +      s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
 +      if (!s->buffers)
 +              goto err;
 +      memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
 +      for (frag = 0; frag < s->nbfrags; frag++) {
 +              audio_buf_t *b = &s->buffers[frag];
 +              /*
 +               * Let's allocate non-cached memory for DMA buffers.
 +               * We try to allocate all memory at once.
 +               * If this fails (a common reason is memory fragmentation),
 +               * then we allocate more smaller buffers.
 +               */
 +              if (!dmasize) {
 +                      dmasize = (s->nbfrags - frag) * s->fragsize;
 +                      do {
 +                              dmabuf =
 +                                  dma_alloc_coherent(NULL, dmasize, &dmaphys,
 +                                                     0);
 +                              if (!dmabuf)
 +                                      dmasize -= s->fragsize;
 +                      }
 +                      while (!dmabuf && dmasize);
 +                      if (!dmabuf)
 +                              goto err;
 +                      b->master = dmasize;
 +                      memzero(dmabuf, dmasize);
 +              }
 +              b->data = dmabuf;
 +              b->dma_addr = dmaphys;
 +              dmabuf += s->fragsize;
 +              dmaphys += s->fragsize;
 +              dmasize -= s->fragsize;
 +      }
 +      s->usr_head = s->dma_head = s->dma_tail = 0;
 +      AUDIO_QUEUE_INIT(s);
 +      s->started = 0;
 +      s->bytecount = 0;
 +      s->fragcount = 0;
 +      init_completion(&s->wfc);
 +      s->wfc.done = s->nbfrags;
 +      FN_OUT(0);
 +      return 0;
 +      err:
 +      audio_discard_buf(s);
 +      FN_OUT(1);
 +      return -ENOMEM;
 +}
 +
 +void audio_discard_buf(audio_stream_t * s)
 +{
 +      FN_IN;
 +      /* ensure DMA isn't using those buffers */
 +      audio_reset(s);
 +      if (s->buffers) {
 +              int frag;
 +              for (frag = 0; frag < s->nbfrags; frag++) {
 +                      if (!s->buffers[frag].master)
 +                              continue;
 +                      dma_free_coherent(NULL,
 +                                        s->buffers[frag].master,
 +                                        s->buffers[frag].data,
 +                                        s->buffers[frag].dma_addr);
 +              }
 +              kfree(s->buffers);
 +              s->buffers = NULL;
 +      }
 +      FN_OUT(0);
 +}
 +
 +/***************************************************************************************
 + *
 + * DMA channel requests
 + *
 + **************************************************************************************/
 +static void omap_sound_dma_link_lch(void *data)
 +{
 +      audio_stream_t *s = (audio_stream_t *) data;
 +      int *chan = s->lch;
 +      int i;
 +
 +      FN_IN;
 +      if (s->linked) {
 +              FN_OUT(1);
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              int nex_chan =
 +                  ((nr_linked_channels - 1 ==
 +                    i) ? chan[0] : chan[i + 1]);
 +              omap_dma_link_lch(cur_chan, nex_chan);
 +      }
 +      s->linked = 1;
 +      FN_OUT(0);
 +}
 +
 +int
 +omap_request_sound_dma(int device_id, const char *device_name, void *data,
 +                     int **channels)
 +{
 +      int i, err = 0;
 +      int *chan = NULL;
 +      FN_IN;
 +      if (unlikely((NULL == channels) || (NULL == device_name))) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      /* Try allocate memory for the num channels */
 +      *channels =
 +          (int *)kmalloc(sizeof(int) * nr_linked_channels,
 +                         GFP_KERNEL);
 +      chan = *channels;
 +      if (NULL == chan) {
 +              ERR("No Memory for channel allocs!\n");
 +              FN_OUT(-ENOMEM);
 +              return -ENOMEM;
 +      }
 +      spin_lock(&dma_list_lock);
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              err =
 +                  omap_request_dma(device_id, device_name,
 +                                   sound_dma_irq_handler, data, &chan[i]);
 +              /* Handle Failure condition here */
 +              if (err < 0) {
 +                      int j;
 +                      for (j = 0; j < i; j++) {
 +                              omap_free_dma(chan[j]);
 +                      }
 +                      spin_unlock(&dma_list_lock);
 +                      kfree(chan);
 +                      *channels = NULL;
 +                      ERR("Error in requesting channel %d=0x%x\n", i, err);
 +                      FN_OUT(err);
 +                      return err;
 +              }
 +      }
 +
 +      /* Chain the channels together */
 +      if (!cpu_is_omap15xx())
 +              omap_sound_dma_link_lch(data);
 +
 +      spin_unlock(&dma_list_lock);
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/***************************************************************************************
 + *
 + * DMA channel requests Freeing
 + *
 + **************************************************************************************/
 +static void omap_sound_dma_unlink_lch(void *data)
 +{
 +      audio_stream_t *s = (audio_stream_t *) data;
 +      int *chan = s->lch;
 +      int i;
 +
 +      FN_IN;
 +      if (!s->linked) {
 +              FN_OUT(1);
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              int nex_chan =
 +                  ((nr_linked_channels - 1 ==
 +                    i) ? chan[0] : chan[i + 1]);
 +              omap_dma_unlink_lch(cur_chan, nex_chan);
 +      }
 +      s->linked = 0;
 +      FN_OUT(0);
 +}
 +
 +int omap_free_sound_dma(void *data, int **channels)
 +{
 +      int i;
 +      int *chan = NULL;
 +      FN_IN;
 +      if (unlikely(NULL == channels)) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      if (unlikely(NULL == *channels)) {
 +              BUG();
 +              return -EPERM;
 +      }
 +      chan = (*channels);
 +
 +      if (!cpu_is_omap15xx())
 +              omap_sound_dma_unlink_lch(data);
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              omap_stop_dma(cur_chan);
 +              omap_free_dma(cur_chan);
 +      }
 +      kfree(*channels);
 +      *channels = NULL;
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/***************************************************************************************
 + *
 + * Process DMA requests - This will end up starting the transfer. Proper fragments of
 + * Transfers will be initiated.
 + *
 + **************************************************************************************/
 +int audio_process_dma(audio_stream_t * s)
 +{
 +      int ret = 0;
 +      unsigned long flags;
 +      FN_IN;
 +
 +      /* Dont let the ISR over ride touching the in_use flag */
 +      local_irq_save(flags);
 +      if (1 == s->in_use) {
 +              local_irq_restore(flags);
 +              ERR("Called again while In Use\n");
 +              return 0;
 +      }
 +      s->in_use = 1;
 +      local_irq_restore(flags);
 +
 +      if (s->stopped)
 +              goto spin;
 +
 +      if (s->dma_spinref > 0 && s->pending_frags) {
 +              s->dma_spinref = 0;
 +              DMA_CLEAR(s);
 +      }
 +      while (s->pending_frags) {
 +              audio_buf_t *b = &s->buffers[s->dma_head];
 +              u_int dma_size = s->fragsize - b->offset;
 +              if (dma_size > MAX_DMA_SIZE)
 +                      dma_size = CUT_DMA_SIZE;
 +              ret =
 +                  omap_start_sound_dma(s, b->dma_addr + b->offset, dma_size);
 +              if (ret) {
 +                      goto process_out;
 +              }
 +              b->dma_ref++;
 +              b->offset += dma_size;
 +              if (b->offset >= s->fragsize) {
 +                      s->pending_frags--;
 +                      if (++s->dma_head >= s->nbfrags)
 +                              s->dma_head = 0;
 +              }
 +      }
 +      spin:
 +      if (s->spin_idle) {
 +              int spincnt = 0;
 +              ERR("we are spinning\n");
 +              while (omap_start_sound_dma(s, SPIN_ADDR, SPIN_SIZE) == 0)
 +                      spincnt++;
 +              /*
 +               * Note: if there is still a data buffer being
 +               * processed then the ref count is negative.  This
 +               * allows for the DMA termination to be accounted in
 +               * the proper order.  Of course dma_spinref can't be
 +               * greater than 0 if dma_ref is not 0 since we kill
 +               * the spinning above as soon as there is real data to process.
 +               */
 +              if (s->buffers && s->buffers[s->dma_tail].dma_ref)
 +                      spincnt = -spincnt;
 +              s->dma_spinref += spincnt;
 +      }
 +
 +      process_out:
 +      s->in_use = 0;
 +
 +      FN_OUT(ret);
 +      return ret;
 +}
 +
 +/***************************************************************************************
 + *
 + * Prime Rx - Since the recieve buffer has no time limit as to when it would arrive,
 + *            we need to prime it
 + *            
 + **************************************************************************************/
 +void audio_prime_rx(audio_state_t * state)
 +{
 +      audio_stream_t *is = state->input_stream;
 +
 +      FN_IN;
 +      if (state->need_tx_for_rx) {
 +              /*
 +               * With some codecs like the Philips UDA1341 we must ensure
 +               * there is an output stream at any time while recording since
 +               * this is how the UDA1341 gets its clock from the SA1100.
 +               * So while there is no playback data to send, the output DMA
 +               * will spin with all zeroes.  We use the cache flush special
 +               * area for that.
 +               */
 +              state->output_stream->spin_idle = 1;
 +              audio_process_dma(state->output_stream);
 +      }
 +      is->pending_frags = is->nbfrags;
 +      init_completion(&is->wfc);
 +      is->wfc.done = 0;
 +
 +      is->active = 1;
 +      audio_process_dma(is);
 +
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/***************************************************************************************
 + *
 + * set the fragment size
 + *
 + **************************************************************************************/
 +int audio_set_fragments(audio_stream_t * s, int val)
 +{
 +      FN_IN;
 +      if (s->active)
 +              return -EBUSY;
 +      if (s->buffers)
 +              audio_discard_buf(s);
 +      s->nbfrags = (val >> 16) & 0x7FFF;
 +      val &= 0xFFFF;
 +      if (val < 4)
 +              val = 4;
 +      if (val > 15)
 +              val = 15;
 +      s->fragsize = 1 << val;
 +      if (s->nbfrags < 2)
 +              s->nbfrags = 2;
 +      if (s->nbfrags * s->fragsize > 128 * 1024)
 +              s->nbfrags = 128 * 1024 / s->fragsize;
 +      FN_OUT(0);
 +      if (audio_setup_buf(s))
 +              return -ENOMEM;
 +      return val | (s->nbfrags << 16);
 +
 +}
 +
 +/***************************************************************************************
 + *
 + * Sync up the buffers before we shutdown, else under-run errors will happen
 + *
 + **************************************************************************************/
 +int audio_sync(struct file *file)
 +{
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *s = state->output_stream;
 +      audio_buf_t *b;
 +      u_int shiftval = 0;
 +      unsigned long flags;
 +
 +      DECLARE_WAITQUEUE(wait, current);
 +
 +      FN_IN;
 +
 +      if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) {
 +              FN_OUT(1);
 +              return 0;
 +      }
 +
 +      /*
 +       * Send current buffer if it contains data.  Be sure to send
 +       * a full sample count.
 +       */
 +      b = &s->buffers[s->usr_head];
 +      if (b->offset &= ~3) {
 +              /* Wait for a buffer to become free */
 +              if (wait_for_completion_interruptible(&s->wfc))
 +                      return 0;
 +              /*
 +               * HACK ALERT !
 +               * To avoid increased complexity in the rest of the code
 +               * where full fragment sizes are assumed, we cheat a little
 +               * with the start pointer here and don't forget to restore
 +               * it later.
 +               */
 +              
 +              /* As this is a last frag we need only one dma channel
 +               * to complete. So it's need to unlink dma channels
 +               * to avoid empty dma work.
 +               */
 +              if (!cpu_is_omap15xx() && AUDIO_QUEUE_EMPTY(s))
 +                      omap_sound_dma_unlink_lch(s);
 +
 +              shiftval = s->fragsize - b->offset;
 +              b->offset = shiftval;
 +              b->dma_addr -= shiftval;
 +              b->data -= shiftval;
 +              local_irq_save(flags);
 +              s->bytecount -= shiftval;
 +              if (++s->usr_head >= s->nbfrags)
 +                      s->usr_head = 0;
 +
 +              s->pending_frags++;
 +              audio_process_dma(s);
 +              local_irq_restore(flags);
 +      }
 +
 +      /* Let's wait for all buffers to complete */
 +      set_current_state(TASK_INTERRUPTIBLE);
 +      add_wait_queue(&s->wq, &wait);
 +      while ((s->pending_frags || (s->wfc.done < s->nbfrags))
 +             && !signal_pending(current)) {
 +              schedule();
 +              set_current_state(TASK_INTERRUPTIBLE);
 +      }
 +      set_current_state(TASK_RUNNING);
 +      remove_wait_queue(&s->wq, &wait);
 +
 +      /* undo the pointer hack above */
 +      if (shiftval) {
 +              local_irq_save(flags);
 +              b->dma_addr += shiftval;
 +              b->data += shiftval;
 +              /* ensure sane DMA code behavior if not yet processed */
 +              if (b->offset != 0)
 +                      b->offset = s->fragsize;
 +              local_irq_restore(flags);
 +      }
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/***************************************************************************************
 + *
 + * Stop all the DMA channels of the stream
 + *
 + **************************************************************************************/
 +void audio_stop_dma(audio_stream_t * s)
 +{
 +      int *chan = s->lch;
 +      int i;
 +      FN_IN;
 +      if (unlikely(NULL == chan)) {
 +              BUG();
 +              return;
 +      }
 +      for (i = 0; i < nr_linked_channels; i++) {
 +              int cur_chan = chan[i];
 +              omap_stop_dma(cur_chan);
 +      }
 +      s->started = 0;
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/***************************************************************************************
 + *
 + * Get the dma posn
 + *
 + **************************************************************************************/
 +u_int audio_get_dma_pos(audio_stream_t * s)
 +{
 +      audio_buf_t *b = &s->buffers[s->dma_tail];
 +      u_int offset;
 +
 +      FN_IN;
 +      if (b->dma_ref) {
 +              offset = omap_get_dma_src_pos(s->lch[s->dma_q_head]) - b->dma_addr;
 +              if (offset >= s->fragsize)
 +                      offset = s->fragsize - 4;
 +      } else if (s->pending_frags) {
 +              offset = b->offset;
 +      } else {
 +              offset = 0;
 +      }
 +      FN_OUT(offset);
 +      return offset;
 +}
 +
 +/***************************************************************************************
 + *
 + * Reset the audio buffers
 + *
 + **************************************************************************************/
 +void audio_reset(audio_stream_t * s)
 +{
 +      FN_IN;
 +      if (s->buffers) {
 +              audio_stop_dma(s);
 +              s->buffers[s->dma_head].offset = 0;
 +              s->buffers[s->usr_head].offset = 0;
 +              s->usr_head = s->dma_head;
 +              s->pending_frags = 0;
 +              init_completion(&s->wfc);
 +              s->wfc.done = s->nbfrags;
 +      }
 +      s->active = 0;
 +      s->stopped = 0;
 +      s->started = 0;
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/***************************************************************************************
 + *
 + * Clear any pending transfers
 + *
 + **************************************************************************************/
 +void omap_clear_sound_dma(audio_stream_t * s)
 +{
 +      FN_IN;
 +      omap_clear_dma(s->lch[s->dma_q_head]);
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/***************************************************************************************
 + *
 + * DMA related functions
 + *
 + **************************************************************************************/
 +static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
 +                                   u_int dma_size)
 +{
 +      int dt = 0x1;           /* data type 16 */
 +      int cen = 32;           /* Stereo */
 +      int cfn = dma_size / (2 * cen);
 +      unsigned long dest_start;
 +      int dest_port = 0;
 +      int sync_dev = 0;
 +
 +      FN_IN;
 +
 +      if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 +              dest_start = AUDIO_MCBSP_DATAWRITE;
 +              dest_port = OMAP_DMA_PORT_MPUI;
 +      }
 +      if (cpu_is_omap24xx()) {
 +              dest_start = AUDIO_MCBSP_DATAWRITE;
 +              sync_dev = AUDIO_DMA_TX;
 +      }
 +
 +      omap_set_dma_dest_params(channel, dest_port, OMAP_DMA_AMODE_CONSTANT, dest_start, 0, 0);
 +      omap_set_dma_src_params(channel, 0, OMAP_DMA_AMODE_POST_INC, dma_ptr, 0, 0);
 +      omap_set_dma_transfer_params(channel, dt, cen, cfn, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0);
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
 +                                      u_int dma_size)
 +{
 +      int dt = 0x1;           /* data type 16 */
 +      int cen = 16;           /* mono */
 +      int cfn = dma_size / (2 * cen);
 +      unsigned long src_start;
 +      int src_port = 0;
 +      int sync_dev = 0;
 +      int src_sync = 0;
 +
 +      FN_IN;
 +
 +      if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 +              src_start = AUDIO_MCBSP_DATAREAD;
 +              src_port = OMAP_DMA_PORT_MPUI;
 +      }
 +      if (cpu_is_omap24xx()) {
 +              src_start = AUDIO_MCBSP_DATAREAD;
 +              sync_dev = AUDIO_DMA_RX;
 +              src_sync = 1;
 +      }
 +
 +      omap_set_dma_src_params(channel, src_port, OMAP_DMA_AMODE_CONSTANT, src_start, 0, 0);
 +      omap_set_dma_dest_params(channel, 0, OMAP_DMA_AMODE_POST_INC, dma_ptr, 0, 0);
 +      omap_set_dma_transfer_params(channel, dt, cen, cfn, OMAP_DMA_SYNC_ELEMENT, sync_dev, src_sync);
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +static int audio_start_dma_chain(audio_stream_t * s)
 +{
 +      int channel = s->lch[s->dma_q_head];
 +      FN_IN;
 +      if (!s->started) {
 +              s->hw_stop();           /* stops McBSP Interface */
 +              omap_start_dma(channel);
 +              s->started = 1;
 +              s->hw_start();          /* start McBSP interface */
 +      }
 +      /* else the dma itself will progress forward with out our help */
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/* Start DMA -
 + * Do the initial set of work to initialize all the channels as required.
 + * We shall then initate a transfer
 + */
 +static int omap_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
 +                              u_int dma_size)
 +{
 +      int ret = -EPERM;
 +
 +      FN_IN;
 +      if (unlikely(dma_size > MAX_DMA_SIZE)) {
 +              ERR("DmaSoundDma: Start: overflowed %d-%d\n", dma_size,
 +                  MAX_DMA_SIZE);
 +              return -EOVERFLOW;
 +      }
 +
 +      if (AUDIO_QUEUE_FULL(s)) {
 +              ret = -2;
 +              goto sound_out;
 +      }
 +      
 +      if (s->input_or_output == FMODE_WRITE)
 +              /*playback */
 +      {
 +              ret =
 +                  audio_set_dma_params_play(s->lch[s->dma_q_tail], dma_ptr,
 +                                            dma_size);
 +      } else {
 +              ret =
 +                  audio_set_dma_params_capture(s->lch[s->dma_q_tail], dma_ptr,
 +                                               dma_size);
 +      }
 +      if (ret != 0) {
 +              ret = -2;       /* indicate queue full */
 +              goto sound_out;
 +      }
 +      AUDIO_INCREMENT_TAIL(s);
 +      ret = audio_start_dma_chain(s);
 +      if (ret) {
 +              ERR("dma start failed");
 +      }
 +      sound_out:
 +      FN_OUT(ret);
 +      return ret;
 +
 +}
 +
 +/***************************************************************************************
 + *
 + * ISR related functions
 + *
 + **************************************************************************************/
 +/* The work item handler */
 +static void audio_dsr_handler(unsigned long inData)
 +{
 +      void *data = (void *)inData;
 +      struct audio_isr_work_item *work = data;
 +      audio_stream_t *s = (work->s);
 +      int sound_curr_lch = work->current_lch;
 +      u16 ch_status = work->ch_status;
 +
 +      FN_IN;
 +      DPRINTK("lch=%d,status=0x%x, data=%p as=%p\n", sound_curr_lch,
 +              ch_status, data, s);
 +      if (AUDIO_QUEUE_EMPTY(s)) {
 +              ERR("Interrupt(%d)  for empty queue(h=%d, T=%d)???\n",
 +                  sound_curr_lch, s->dma_q_head, s->dma_q_tail);
 +              ERR("nbfrag=%d,pendfrags=%d,USR-H=%d, QH-%d QT-%d\n",
 +                  s->nbfrags, s->pending_frags, s->usr_head, s->dma_head,
 +                  s->dma_tail);
 +              FN_OUT(-1);
 +              return;
 +      }
 +
 +      AUDIO_INCREMENT_HEAD(s);        /* Empty the queue */
 +
 +      /* Try to fill again */
 +      audio_dma_callback(sound_curr_lch, ch_status, s);
 +      FN_OUT(0);
 +
 +}
 +
 +/* Macro to trace the IRQ calls - checks for multi-channel irqs */
 +//#define IRQ_TRACE
 +#ifdef IRQ_TRACE
 +#define MAX_UP 10
 +static char xyz[MAX_UP] = { 0 };
 +static int h = 0;
 +#endif
 +
 +/* ISRs have to be short and smart.. So we transfer every heavy duty stuff to the 
 + * work item
 + */
 +static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status, void *data)
 +{
 +      int dma_status = ch_status;
 +      audio_stream_t *s = (audio_stream_t *) data;
 +      FN_IN;
 +#ifdef IRQ_TRACE
 +      xyz[h++] = '0' + sound_curr_lch;
 +      if (h == MAX_UP - 1) {
 +              printk("%s-", xyz);
 +              h = 0;
 +      }
 +#endif
 +      DPRINTK("lch=%d,status=0x%x, dma_status=%d, data=%p\n", sound_curr_lch,
 +              ch_status, dma_status, data);
 +
 +      if (dma_status & (DCSR_ERROR)) {
 +              if (cpu_is_omap15xx() || cpu_is_omap16xx())
 +                      omap_stop_dma(sound_curr_lch);
 +              ERR("DCSR_ERROR!\n");
 +              FN_OUT(-1);
 +              return;
 +      }
 +
 +      if (AUDIO_QUEUE_LAST(s))
 +              audio_stop_dma(s);
 +
 +      /* Start the work item  - we ping pong the work items */
 +      if (!work_item_running) {
 +              work1.current_lch = sound_curr_lch;
 +              work1.ch_status = ch_status;
 +              work1.s = s;
 +              /* schedule tasklet 1 */
 +              tasklet_schedule(&audio_isr_work1);
 +              work_item_running = 1;
 +      } else {
 +              work2.current_lch = sound_curr_lch;
 +              work2.ch_status = ch_status;
 +              work2.s = s;
 +              /* schedule tasklet 2 */
 +              tasklet_schedule(&audio_isr_work2);
 +              work_item_running = 0;
 +      }
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/* The call back that handles buffer stuff */
 +static void audio_dma_callback(int lch, u16 ch_status, void *data)
 +{
 +      audio_stream_t *s = data;
 +      audio_buf_t *b = &s->buffers[s->dma_tail];
 +      FN_IN;
 +
 +      if (s->dma_spinref > 0) {
 +              s->dma_spinref--;
 +      } else if (!s->buffers) {
 +              printk(KERN_CRIT
 +                     "omap_audio: received DMA IRQ for non existent buffers!\n");
 +              return;
 +      } else if (b->dma_ref && --b->dma_ref == 0 && b->offset >= s->fragsize) {
 +              /* This fragment is done */
 +              b->offset = 0;
 +              s->bytecount += s->fragsize;
 +              s->fragcount++;
 +              s->dma_spinref = -s->dma_spinref;
 +
 +              if (++s->dma_tail >= s->nbfrags)
 +                      s->dma_tail = 0;
 +
 +              if (!s->mapped)
 +                      complete(&s->wfc);
 +              else
 +                      s->pending_frags++;
 +
 +              wake_up(&s->wq);
 +      }
 +
 +      audio_process_dma(s);
 +      
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_get_dma_callback(): return the dma interface call back function
 + *
 + *********************************************************************************/
 +dma_callback_t audio_get_dma_callback(void)
 +{
 +      FN_IN;
 +      FN_OUT(0);
 +      return audio_dma_callback;
 +}
 +
 +static int __init audio_dma_init(void)
 +{
 +      if (!cpu_is_omap15xx())
 +              nr_linked_channels = 2;
 +
 +      return 0;
 +}
 +
 +static void __exit audio_dma_exit(void)
 +{
 +      /* Nothing */
 +}
 +
 +module_init(audio_dma_init);
 +module_exit(audio_dma_exit);
 +
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION("Common DMA handling for Audio driver on OMAP processors");
 +MODULE_LICENSE("GPL");
 +
 +EXPORT_SYMBOL(omap_clear_sound_dma);
 +EXPORT_SYMBOL(omap_request_sound_dma);
 +EXPORT_SYMBOL(omap_free_sound_dma);
 +
 +EXPORT_SYMBOL(audio_get_dma_callback);
 +EXPORT_SYMBOL(audio_setup_buf);
 +EXPORT_SYMBOL(audio_process_dma);
 +EXPORT_SYMBOL(audio_prime_rx);
 +EXPORT_SYMBOL(audio_set_fragments);
 +EXPORT_SYMBOL(audio_sync);
 +EXPORT_SYMBOL(audio_stop_dma);
 +EXPORT_SYMBOL(audio_get_dma_pos);
 +EXPORT_SYMBOL(audio_reset);
 +EXPORT_SYMBOL(audio_discard_buf);
index cbabcf59ad97ec5de0eed1704c4adbd25e268584,0000000000000000000000000000000000000000..9cbb0e821399deeee62219f7ae05c6a8c5fbe4ac
mode 100644,000000..100644
--- /dev/null
@@@ -1,1238 -1,0 +1,1238 @@@
- #include <asm/hardware.h>
- #include <asm/arch/dma.h>
 +/*
 + * linux/sound/oss/omap-audio-tsc2101.c
 + *
 + * Glue driver for TSC2101 for OMAP processors
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + * History:
 + *  -------
 + *  2004-08-12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms.
 + *  2004-09-14 Sriram Kannan - Added /proc support for asynchronous starting/stopping the codec
 + *            (without affecting the normal driver flow).
 + *  2004-11-04 Nishanth Menon - Support for power management
 + *  2004-11-07 Nishanth Menon - Support for Common TSC access b/w Touchscreen and audio drivers
 + */
 +
 +/***************************** INCLUDES ************************************/
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/types.h>
 +#include <linux/fs.h>
 +#include <linux/delay.h>
 +#include <linux/pm.h>
 +#include <linux/errno.h>
 +#include <linux/sound.h>
 +#include <linux/soundcard.h>
 +#include <linux/mutex.h>
 +
 +#include <asm/uaccess.h>
- #include <asm/hardware.h>
++#include <mach/hardware.h>
++#include <mach/dma.h>
 +#include <asm/io.h>
- #include <asm/arch/mux.h>
- #include <asm/arch/io.h>
++#include <mach/hardware.h>
 +
- #include <asm/arch/mcbsp.h>
++#include <mach/mux.h>
++#include <mach/io.h>
 +#include <asm/mach-types.h>
 +
 +#include "omap-audio.h"
 +#include "omap-audio-dma-intfc.h"
- #include <asm/arch/dsp_common.h>
++#include <mach/mcbsp.h>
 +#ifdef CONFIG_ARCH_OMAP16XX
 +#include <../drivers/ssi/omap-uwire.h>
++#include <mach/dsp_common.h>
 +#elif defined(CONFIG_ARCH_OMAP24XX)
 +#else
 +#error "Unsupported configuration"
 +#endif
 +
 +#include <asm/hardware/tsc2101.h>
 +#include <../drivers/ssi/omap-tsc2101.h>
 +
 +/***************************** MACROS ************************************/
 +
 +#define PROC_SUPPORT
 +
 +#ifdef PROC_SUPPORT
 +#include <linux/proc_fs.h>
 +#define PROC_START_FILE "driver/tsc2101-audio-start"
 +#define PROC_STOP_FILE  "driver/tsc2101-audio-stop"
 +#endif
 +
 +#define CODEC_NAME             "TSC2101"
 +
 +#ifdef CONFIG_ARCH_OMAP16XX
 +#define PLATFORM_NAME "OMAP16XX"
 +#elif defined(CONFIG_ARCH_OMAP24XX)
 +#define PLATFORM_NAME "OMAP2"
 +#endif
 +
 +/* Define to set the tsc as the master w.r.t McBSP */
 +#define TSC_MASTER
 +
 +/*
 + * AUDIO related MACROS
 + */
 +#define DEFAULT_BITPERSAMPLE          16
 +#define AUDIO_RATE_DEFAULT              44100
 +#define PAGE2_AUDIO_CODEC_REGISTERS   (2)
 +#define LEAVE_CS                                0x80
 +
 +/* Select the McBSP For Audio */
 +/* 16XX is MCBSP1 and 24XX is MCBSP2*/
 +/* see include/asm-arm/arch-omap/mcbsp.h */
 +#ifndef AUDIO_MCBSP
 +#error "UnSupported Configuration"
 +#endif
 +
 +#define REC_MASK                                (SOUND_MASK_LINE | SOUND_MASK_MIC)
 +#define DEV_MASK                                (REC_MASK | SOUND_MASK_VOLUME)
 +
 +#define SET_VOLUME                              1
 +#define SET_LINE                                2
 +#define SET_MIC             3
 +#define SET_RECSRC          4
 +
 +#define DEFAULT_VOLUME                93
 +#define DEFAULT_INPUT_VOLUME    20    /* An minimal volume */
 +
 +/* Tsc Audio Specific */
 +#define NUMBER_SAMPLE_RATES_SUPPORTED 16
 +#define OUTPUT_VOLUME_MIN 0x7F
 +#define OUTPUT_VOLUME_MAX 0x32
 +#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
 +#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MIN
 +#define DEFAULT_VOLUME_LEVEL          OUTPUT_VOLUME_MAX
 +
 +/* use input vol of 75 for 0dB gain */
 +#define INPUT_VOLUME_MIN                    0x0
 +#define INPUT_VOLUME_MAX       0x7D
 +#define INPUT_VOLUME_RANGE                  (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
 +#define INPUT_VOLUME_MASK                   INPUT_VOLUME_MAX
 +
 +/*********** Debug Macros ********/
 +/* To Generate a rather shrill tone -test the entire path */
 +//#define TONE_GEN
 +/* To Generate a tone for each keyclick - test the tsc,spi paths*/
 +//#define TEST_KEYCLICK
 +/* To dump the tsc registers for debug */
 +//#define TSC_DUMP_REGISTERS
 +
 +#ifdef DPRINTK
 +#undef DPRINTK
 +#endif
 +#undef DEBUG
 +
 +//#define DEBUG
 +#ifdef DEBUG
 +#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
 +#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
 +#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
 +#else
 +#define DPRINTK( x... )
 +#define FN_IN
 +#define FN_OUT(n)
 +#endif
 +
 +/***************************** Data Structures **********************************/
 +
 +static int audio_ifc_start(void)
 +{
 +      omap_mcbsp_start(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static int audio_ifc_stop(void)
 +{
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      return 0;
 +}
 +
 +static audio_stream_t output_stream = {
 +      .id                     = "TSC2101 out",
 +      .dma_dev                = AUDIO_DMA_TX,
 +      .input_or_output        = FMODE_WRITE,
 +      .hw_start               = audio_ifc_start,
 +      .hw_stop                = audio_ifc_stop,
 +};
 +
 +static audio_stream_t input_stream = {
 +      .id                     = "TSC2101 in",
 +      .dma_dev                = AUDIO_DMA_RX,
 +      .input_or_output        = FMODE_READ,
 +      .hw_start               = audio_ifc_start,
 +      .hw_stop                = audio_ifc_stop,
 +};
 +
 +static int audio_dev_id, mixer_dev_id;
 +
 +typedef struct {
 +      u8      volume;
 +      u8      line;
 +      u8      mic;
 +      int     recsrc;
 +      int     mod_cnt;
 +} tsc2101_local_info;
 +
 +static tsc2101_local_info tsc2101_local = {
 +      volume:         DEFAULT_VOLUME,
 +      line:           DEFAULT_INPUT_VOLUME,
 +      mic:            DEFAULT_INPUT_VOLUME,
 +      recsrc:         SOUND_MASK_LINE,
 +      mod_cnt:        0
 +};
 +
 +struct sample_rate_reg_info {
 +      u16 sample_rate;
 +      u8  divisor;
 +      u8  fs_44kHz;           /* if 0 48 khz, if 1 44.1 khz fsref */
 +};
 +
 +/* To Store the default sample rate */
 +static long audio_samplerate = AUDIO_RATE_DEFAULT;
 +
 +static const struct sample_rate_reg_info
 + reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
 +      /* Div 1 */
 +      {48000, 0, 0},
 +      {44100, 0, 1},
 +      /* Div 1.5 */
 +      {32000, 1, 0},
 +      {29400, 1, 1},
 +      /* Div 2 */
 +      {24000, 2, 0},
 +      {22050, 2, 1},
 +      /* Div 3 */
 +      {16000, 3, 0},
 +      {14700, 3, 1},
 +      /* Div 4 */
 +      {12000, 4, 0},
 +      {11025, 4, 1},
 +      /* Div 5 */
 +      {9600, 5, 0},
 +      {8820, 5, 1},
 +      /* Div 5.5 */
 +      {8727, 6, 0},
 +      {8018, 6, 1},
 +      /* Div 6 */
 +      {8000, 7, 0},
 +      {7350, 7, 1},
 +};
 +
 +static struct omap_mcbsp_reg_cfg initial_config = {
 +      .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
 +      .spcr1 = RINTM(3) | RRST,
 +      .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
 +               RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
 +      .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
 +      .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
 +               XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
 +      .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
 +      .srgr1 = FWID(15),
 +      .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
 +
 +      /* platform specific initialization */
 +#ifdef CONFIG_MACH_OMAP_H2
 +      .pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
 +#elif defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H4) || defined(CONFIG_MACH_OMAP_APOLLON)
 +
 +#ifndef TSC_MASTER
 +      .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
 +#else
 +      .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
 +#endif                                /* tsc Master defs */
 +
 +#endif                                /* platform specific inits */
 +};
 +
 +/***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
 +
 +static void omap_tsc2101_initialize(void *dummy);
 +
 +static void omap_tsc2101_shutdown(void *dummy);
 +
 +static int  omap_tsc2101_ioctl(struct inode *inode, struct file *file,
 +                             uint cmd, ulong arg);
 +
 +static int  omap_tsc2101_probe(void);
 +
 +static void omap_tsc2101_remove(void);
 +
 +static int  omap_tsc2101_suspend(void);
 +
 +static int  omap_tsc2101_resume(void);
 +
 +static void tsc2101_configure(void);
 +
 +static int  mixer_open(struct inode *inode, struct file *file);
 +
 +static int  mixer_release(struct inode *inode, struct file *file);
 +
 +static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
 +                      ulong arg);
 +
 +#ifdef TEST_KEYCLICK
 +void tsc2101_testkeyclick(void);
 +#endif
 +
 +#ifdef TONE_GEN
 +void toneGen(void);
 +#endif
 +
 +#ifdef TSC_DUMP_REGISTERS
 +static void tsc2101_dumpRegisters(void);
 +#endif
 +
 +#ifdef PROC_SUPPORT
 +static int codec_start(char *buf, char **start, off_t offset, int count,
 +                     int *eof, void *data);
 +
 +static int codec_stop(char *buf, char **start, off_t offset, int count,
 +                    int *eof, void *data);
 +
 +static void tsc2101_start(void);
 +#endif
 +
 +/******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
 +
 +/* File Op structure for mixer */
 +static struct file_operations omap_mixer_fops = {
 +      .open           = mixer_open,
 +      .release        = mixer_release,
 +      .ioctl          = mixer_ioctl,
 +      .owner          = THIS_MODULE
 +};
 +
 +/* To store characteristic info regarding the codec for the audio driver */
 +static audio_state_t tsc2101_state = {
 +      .output_stream  = &output_stream,
 +      .input_stream   = &input_stream,
 +/*    .need_tx_for_rx = 1, //Once the Full Duplex works  */
 +      .need_tx_for_rx = 0,
 +      .hw_init        = omap_tsc2101_initialize,
 +      .hw_shutdown    = omap_tsc2101_shutdown,
 +      .client_ioctl   = omap_tsc2101_ioctl,
 +      .hw_probe       = omap_tsc2101_probe,
 +      .hw_remove      = omap_tsc2101_remove,
 +      .hw_suspend     = omap_tsc2101_suspend,
 +      .hw_resume      = omap_tsc2101_resume,
 +};
 +
 +/* This will be defined in the Audio.h */
 +static struct file_operations *omap_audio_fops;
 +
 +/***************************** MODULES SPECIFIC FUNCTIONs *******************************/
 +
 +/*********************************************************************************
 + *
 + * Simplified write for tsc Audio
 + *
 + *********************************************************************************/
 +static __inline__ void audio_tsc2101_write(u8 address, u16 data)
 +{
 +      omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
 +}
 +
 +/*********************************************************************************
 + *
 + * Simplified read for tsc  Audio
 + *
 + *********************************************************************************/
 +static __inline__ u16 audio_tsc2101_read(u8 address)
 +{
 +      return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
 +}
 +
 +/*********************************************************************************
 + *
 + * tsc2101_update()
 + * Volume Adj etc
 + *
 + ********************************************************************************/
 +static int tsc2101_update(int flag, int val)
 +{
 +      u16 volume;
 +      u16 data;
 +
 +      FN_IN;
 +      switch (flag) {
 +      case SET_VOLUME:
 +              if (val < 0 || val > 100) {
 +                      printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
 +                      return -EPERM;
 +              }
 +              /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
 +              volume =
 +                  ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
 +              /* invert the value for getting the proper range 0 min and 100 max */
 +              volume = OUTPUT_VOLUME_MIN - volume;
 +              data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
 +              data &=
 +                  ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
 +                    DGC_DARVL(OUTPUT_VOLUME_MIN));
 +              data |= DGC_DALVL(volume) | DGC_DARVL(volume);
 +              audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
 +              data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
 +
 +              break;
 +
 +      case SET_LINE:
 +              if (val < 0 || val > 100) {
 +                      printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
 +                      return -EPERM;
 +              }
 +              /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
 +              /* NOTE: 0 is minimum volume and not mute */
 +              volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
 +              /* Handset Input not muted, AGC for Handset In off */
 +              audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
 +      HGC_ADPGA_HED(volume));
 +              break;
 +
 +      case SET_MIC:
 +              if (val < 0 || val > 100) {
 +                      printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
 +                      return -EPERM;
 +              }
 +              /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
 +              /* NOTE: 0 is minimum volume and not mute */
 +              volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
 +              /* Handset Input not muted, AGC for Handset In off */
 +              audio_tsc2101_write(TSC2101_HANDSET_GAIN_CTRL,
 +      HNGC_ADPGA_HND(volume));
 +              break;
 +
 +      case SET_RECSRC:
 +              /*
 +               * If more than one recording device selected,
 +               * disable the device that is currently in use.
 +               */
 +              if (hweight32(val) > 1)
 +                      val &= ~tsc2101_local.recsrc;
 +
 +              data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
 +              data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
 +
 +              if (val == SOUND_MASK_MIC) {
 +                      data |=  MPC_MICSEL(1);
 +                      audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
 +              }
 +              else if (val == SOUND_MASK_LINE) {
 +                      data |=  MPC_MICSEL(0);
 +                      audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
 +              }
 +              else {
 +                      printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
 +       " value specified\n");
 +                      return -EINVAL;
 +              }
 +              tsc2101_local.recsrc = val;
 +              break;
 +      default:
 +              printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
 +      "flag specified\n");
 +              break;
 +      }
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * mixer_open()
 + *
 + ********************************************************************************/
 +static int mixer_open(struct inode *inode, struct file *file)
 +{
 +      /* Any mixer specific initialization */
 +
 +      /* Initalize the tsc2101 */
 +      omap_tsc2101_enable();
 +
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * mixer_release()
 + *
 + ********************************************************************************/
 +static int mixer_release(struct inode *inode, struct file *file)
 +{
 +      /* Any mixer specific Un-initialization */
 +      omap_tsc2101_disable();
 +
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * mixer_ioctl()
 + *
 + ********************************************************************************/
 +static int
 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 +{
 +      int val;
 +      int gain;
 +      int ret = 0;
 +      int nr = _IOC_NR(cmd);
 +
 +      /*
 +       * We only accept mixer (type 'M') ioctls.
 +       */
 +      FN_IN;
 +      if (_IOC_TYPE(cmd) != 'M')
 +              return -EINVAL;
 +
 +      DPRINTK(" 0x%08x\n", cmd);
 +
 +      if (cmd == SOUND_MIXER_INFO) {
 +              struct mixer_info mi;
 +
 +              strncpy(mi.id, "TSC2101", sizeof(mi.id));
 +              strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
 +              mi.modify_counter = tsc2101_local.mod_cnt;
 +              FN_OUT(1);
 +              return copy_to_user((void __user *)arg, &mi, sizeof(mi));
 +      }
 +
 +      if (_IOC_DIR(cmd) & _IOC_WRITE) {
 +              ret = get_user(val, (int __user *)arg);
 +              if (ret)
 +                      goto out;
 +
 +              /* Ignore separate left/right channel for now,
 +               * even the codec does support it.
 +               */
 +              gain = val & 255;
 +
 +              switch (nr) {
 +              case SOUND_MIXER_VOLUME:
 +                      tsc2101_local.volume = val;
 +                      tsc2101_local.mod_cnt++;
 +                      ret = tsc2101_update(SET_VOLUME, gain);
 +                      break;
 +
 +              case SOUND_MIXER_LINE:
 +                      tsc2101_local.line = val;
 +                      tsc2101_local.mod_cnt++;
 +                      ret = tsc2101_update(SET_LINE, gain);
 +                      break;
 +
 +              case SOUND_MIXER_MIC:
 +                      tsc2101_local.mic = val;
 +                      tsc2101_local.mod_cnt++;
 +                      ret = tsc2101_update(SET_MIC, gain);
 +                      break;
 +
 +              case SOUND_MIXER_RECSRC:
 +                      if ((val & SOUND_MASK_LINE) ||
 +                          (val & SOUND_MASK_MIC)) {
 +                              if (tsc2101_local.recsrc != val) {
 +                                      tsc2101_local.mod_cnt++;
 +                                      tsc2101_update(SET_RECSRC, val);
 +                              }
 +                      }
 +                      else {
 +                              ret = -EINVAL;
 +                      }
 +                      break;
 +
 +              default:
 +                      ret = -EINVAL;
 +              }
 +      }
 +
 +      if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
 +              ret = 0;
 +
 +              switch (nr) {
 +              case SOUND_MIXER_VOLUME:
 +                      val = tsc2101_local.volume;
 +                      val = (tsc2101_local.volume << 8) |
 +        tsc2101_local.volume;
 +                      break;
 +              case SOUND_MIXER_LINE:
 +                      val = (tsc2101_local.line << 8) |
 +        tsc2101_local.line;
 +                      break;
 +              case SOUND_MIXER_MIC:
 +                      val = (tsc2101_local.mic << 8) |
 +        tsc2101_local.mic;
 +                      break;
 +              case SOUND_MIXER_RECSRC:
 +                      val = tsc2101_local.recsrc;
 +                      break;
 +              case SOUND_MIXER_RECMASK:
 +                      val = REC_MASK;
 +                      break;
 +              case SOUND_MIXER_DEVMASK:
 +                      val = DEV_MASK;
 +                      break;
 +              case SOUND_MIXER_CAPS:
 +                      val = 0;
 +                      break;
 +              case SOUND_MIXER_STEREODEVS:
 +                      val = SOUND_MASK_VOLUME;
 +                      break;
 +              default:
 +                      val = 0;
 +                      printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
 +       "read ioctl flag specified\n");
 +                      ret = -EINVAL;
 +                      break;
 +              }
 +
 +              if (ret == 0)
 +                      ret = put_user(val, (int __user *)arg);
 +      }
 +      out:
 +      FN_OUT(0);
 +      return ret;
 +
 +}
 +
 +/*********************************************************************************
 + *
 + * omap_set_samplerate()
 + *
 + ********************************************************************************/
 +static int omap_set_samplerate(long sample_rate)
 +{
 +      u8 count = 0;
 +      u16 data = 0;
 +      int clkgdv = 0;
 +      /* wait for any frame to complete */
 +      udelay(125);
 +
 +      /* Search for the right sample rate */
 +      while ((reg_info[count].sample_rate != sample_rate) &&
 +             (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
 +              count++;
 +      }
 +      if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
 +              printk(KERN_ERR "Invalid Sample Rate %d requested\n",
 +                     (int)sample_rate);
 +              return -EPERM;
 +      }
 +
 +      /* Set AC1 */
 +      data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
 +      /*Clear prev settings */
 +      data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
 +      data |=
 +          AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
 +                                                         divisor);
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
 +
 +      /* Set the AC3 */
 +      data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
 +      /*Clear prev settings */
 +      data &= ~(AC3_REFFS | AC3_SLVMS);
 +      data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
 +#ifdef TSC_MASTER
 +      data |= AC3_SLVMS;
 +#endif                                /* #ifdef TSC_MASTER */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
 +
 +      /* program the PLLs */
 +      if (reg_info[count].fs_44kHz) {
 +              /* 44.1 khz - 12 MHz Mclk */
 +              audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));    /* PVAL 1; I_VAL 7 */
 +              audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
 +      } else {
 +              /* 48 khz - 12 Mhz Mclk */
 +              audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));    /* PVAL 1; I_VAL 8 */
 +              audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
 +      }
 +
 +      audio_samplerate = sample_rate;
 +
 +      /* Set the sample rate */
 +#ifndef TSC_MASTER
 +      clkgdv =
 +          DEFAULT_MCBSP_CLOCK / (sample_rate *
 +                                 (DEFAULT_BITPERSAMPLE * 2 - 1));
 +      if (clkgdv)
 +              initial_config.srgr1 =
 +                  (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      else
 +              return (1);
 +
 +      /* Stereo Mode */
 +      initial_config.srgr2 =
 +          (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
 +#else
 +      initial_config.srgr1 =
 +          (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
 +      initial_config.srgr2 =
 +          ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
 +
 +#endif                                /* end of #ifdef TSC_MASTER */
 +      omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
 +
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * omap_tsc2101_initialize() [hw_init() ]
 + *
 + ********************************************************************************/
 +static void omap_tsc2101_initialize(void *dummy)
 +{
 +
 +      DPRINTK("omap_tsc2101_initialize entry\n");
 +
 +      /* initialize with default sample rate */
 +      audio_samplerate = AUDIO_RATE_DEFAULT;
 +
 +      omap_mcbsp_request(AUDIO_MCBSP);
 +
 +      /* if configured, then stop mcbsp */
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +
 +      omap_tsc2101_enable();
 +
 +      omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
 +      omap_mcbsp_start(AUDIO_MCBSP);
 +      tsc2101_configure();
 +
 +#ifdef TEST_KEYCLICK
 +      tsc2101_testkeyclick();
 +#endif
 +
 +#ifdef TONE_GEN
 +      toneGen();
 +#endif
 +
 +      DPRINTK("omap_tsc2101_initialize exit\n");
 +}
 +
 +/*********************************************************************************
 + *
 + * omap_tsc2101_shutdown() [hw_shutdown() ]
 + *
 + ********************************************************************************/
 +static void omap_tsc2101_shutdown(void *dummy)
 +{
 +      /*
 +         Turn off codec after it is done.
 +         Can't do it immediately, since it may still have
 +         buffered data.
 +
 +         Wait 20ms (arbitrary value) and then turn it off.
 +       */
 +
 +      FN_IN;
 +      set_current_state(TASK_INTERRUPTIBLE);
 +      schedule_timeout(2);
 +
 +      omap_mcbsp_stop(AUDIO_MCBSP);
 +      omap_mcbsp_free(AUDIO_MCBSP);
 +
 +      audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
 +                          ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
 +
 +      omap_tsc2101_disable();
 +
 +      FN_OUT(0);
 +}
 +
 +/*********************************************************************************
 + *
 + * tsc2101_configure
 + *
 + ********************************************************************************/
 +static void tsc2101_configure(void)
 +{
 +      FN_IN;
 +
 +      audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
 +
 +      /*Mute Analog Sidetone */
 +      /*Select MIC_INHED input for headset */
 +      /*Cell Phone In not connected */
 +      audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
 +                          MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
 +
 +      /* Set record source */
 +      tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
 +
 +      /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
 +      /* 1dB AGC hysteresis */
 +      /* MICes bias 2V */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
 +
 +      /* Set codec output volume */
 +      audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
 +
 +      /* DAC left and right routed to SPK2 */
 +      /* SPK1/2 unmuted */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
 +                          AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
 +                          AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
 +                          AC5_HDSCPTC);
 +
 +      /* OUT8P/N muted, CPOUT muted */
 +
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
 +                          AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
 +                          AC6_VGNDSCPTC);
 +
 +      /* Headset/Hook switch detect disabled */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
 +
 +      /* Left line input volume control */
 +      tsc2101_update(SET_LINE, tsc2101_local.line);
 +
 +      /* mic input volume control */
 +      tsc2101_update(SET_MIC, tsc2101_local.mic);
 +
 +      /* Left/Right headphone channel volume control */
 +      /* Zero-cross detect on */
 +      tsc2101_update(SET_VOLUME, tsc2101_local.volume);
 +
 +      /* clock configuration */
 +      omap_set_samplerate(audio_samplerate);
 +
 +#ifdef TSC_DUMP_REGISTERS
 +      tsc2101_dumpRegisters();
 +#endif
 +
 +      FN_OUT(0);
 +}
 +
 +#ifdef PROC_SUPPORT
 +static void tsc2101_start(void)
 +{
 +      FN_IN;
 +
 +      audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
 +
 +      /*Mute Analog Sidetone */
 +      /*Select MIC_INHED input for headset */
 +      /*Cell Phone In not connected */
 +      audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
 +                          MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
 +
 +      /* Set record source */
 +      tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
 +
 +      /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
 +      /* 1dB AGC hysteresis */
 +      /* MICes bias 2V */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
 +
 +      /* Set codec output volume */
 +      audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
 +
 +      /* DAC left and right routed to SPK2 */
 +      /* SPK1/2 unmuted */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
 +                          AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
 +                          AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
 +                          AC5_HDSCPTC);
 +
 +      /* OUT8P/N muted, CPOUT muted */
 +
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
 +                          AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
 +                          AC6_VGNDSCPTC);
 +
 +      /* Headset/Hook switch detect disabled */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
 +
 +      /* Left line input volume control */
 +      tsc2101_update(SET_LINE, tsc2101_local.line);
 +
 +      /* mic input volume control */
 +      tsc2101_update(SET_MIC, tsc2101_local.mic);
 +
 +      /* Left/Right headphone channel volume control */
 +      /* Zero-cross detect on */
 +      tsc2101_update(SET_VOLUME, tsc2101_local.volume);
 +
 +      FN_OUT(0);
 +
 +}
 +#endif
 +
 +/******************************************************************************************
 + *
 + * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
 + * routine handles some platform specific ioctl's
 + *
 + ******************************************************************************************/
 +static int
 +omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 +{
 +      long val;
 +      int ret = 0;
 +
 +      DPRINTK(" 0x%08x\n", cmd);
 +
 +      /*
 +       * These are platform dependent ioctls which are not handled by the
 +       * generic omap-audio module.
 +       */
 +      switch (cmd) {
 +      case SNDCTL_DSP_STEREO:
 +              ret = get_user(val, (int __user *)arg);
 +              if (ret)
 +                      return ret;
 +              /* the AIC23 is stereo only */
 +              ret = (val == 0) ? -EINVAL : 1;
 +              FN_OUT(1);
 +              return put_user(ret, (int __user *)arg);
 +
 +      case SNDCTL_DSP_CHANNELS:
 +      case SOUND_PCM_READ_CHANNELS:
 +              /* the AIC23 is stereo only */
 +              FN_OUT(2);
 +              return put_user(2, (long __user *)arg);
 +
 +      case SNDCTL_DSP_SPEED:
 +              ret = get_user(val, (long __user *)arg);
 +              if (ret)
 +                      break;
 +              ret = omap_set_samplerate(val);
 +              if (ret)
 +                      break;
 +              /* fall through */
 +
 +      case SOUND_PCM_READ_RATE:
 +              FN_OUT(3);
 +              return put_user(audio_samplerate, (long __user *)arg);
 +
 +      case SOUND_PCM_READ_BITS:
 +      case SNDCTL_DSP_SETFMT:
 +      case SNDCTL_DSP_GETFMTS:
 +              /* we can do 16-bit only */
 +              FN_OUT(4);
 +              return put_user(AFMT_S16_LE, (long __user *)arg);
 +
 +      default:
 +              /* Maybe this is meant for the mixer (As per OSS Docs) */
 +              FN_OUT(5);
 +              return mixer_ioctl(inode, file, cmd, arg);
 +      }
 +
 +      FN_OUT(0);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * module_probe for TSC2101
 + *
 + ********************************************************************************/
 +static int omap_tsc2101_probe(void)
 +{
 +      FN_IN;
 +
 +      /* Get the fops from audio oss driver */
 +      if (!(omap_audio_fops = audio_get_fops())) {
 +              printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
 +              audio_unregister_codec(&tsc2101_state);
 +              return -EPERM;
 +      }
 +
 +      /* register devices */
 +      audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
 +      mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
 +
 +#ifdef PROC_SUPPORT
 +      create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
 +                             NULL /* parent dir */ ,
 +                             codec_start, NULL /* client data */ );
 +
 +      create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
 +                             NULL /* parent dir */ ,
 +                             codec_stop, NULL /* client data */ );
 +#endif
 +
 +      /* Announcement Time */
 +      printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
 +             " Audio support initialized\n");
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * Module Remove for TSC2101
 + *
 + ********************************************************************************/
 +static void omap_tsc2101_remove(void)
 +{
 +      FN_IN;
 +      /* Un-Register the codec with the audio driver */
 +      unregister_sound_dsp(audio_dev_id);
 +      unregister_sound_mixer(mixer_dev_id);
 +
 +#ifdef PROC_SUPPORT
 +      remove_proc_entry(PROC_START_FILE, NULL);
 +      remove_proc_entry(PROC_STOP_FILE, NULL);
 +#endif
 +      FN_OUT(0);
 +
 +}
 +
 +/*********************************************************************************
 + *
 + * Module Suspend for TSC2101
 + *
 + ********************************************************************************/
 +static int omap_tsc2101_suspend(void)
 +{
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * Module Resume for TSC2101
 + *
 + ********************************************************************************/
 +static int omap_tsc2101_resume(void)
 +{
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * module_init for TSC2101
 + *
 + ********************************************************************************/
 +static int __init audio_tsc2101_init(void)
 +{
 +
 +      int err = 0;
 +      FN_IN;
 +
 +      if (machine_is_omap_osk() || machine_is_omap_innovator())
 +              return -ENODEV;
 +
 +      mutex_init(&tsc2101_state.mutex);
 +
 +      /* register the codec with the audio driver */
 +      if ((err = audio_register_codec(&tsc2101_state))) {
 +              printk(KERN_ERR
 +                     "Failed to register TSC driver with Audio OSS Driver\n");
 +      }
 +      FN_OUT(err);
 +      return err;
 +}
 +
 +/*********************************************************************************
 + *
 + * module_exit for TSC2101
 + *
 + ********************************************************************************/
 +static void __exit audio_tsc2101_exit(void)
 +{
 +
 +      FN_IN;
 +      (void)audio_unregister_codec(&tsc2101_state);
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/**************************** DEBUG FUNCTIONS ***********************************/
 +
 +/*********************************************************************************
 + * TEST_KEYCLICK:
 + * This is a test to generate various keyclick sound on tsc.
 + * verifies if the tsc and the spi interfaces are operational.
 + *
 + ********************************************************************************/
 +#ifdef TEST_KEYCLICK
 +void tsc2101_testkeyclick(void)
 +{
 +      u8 freq = 0;
 +      u16 old_reg_val, reg_val;
 +      u32 uDummyVal = 0;
 +      u32 uTryVal = 0;
 +
 +      old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
 +
 +      /* Keyclick active, max amplitude and longest key click len(32 period) */
 +      printk(KERN_INFO " TESTING KEYCLICK\n Listen carefully NOW....\n");
 +      printk(KERN_INFO " OLD REG VAL=0x%x\n", old_reg_val);
 +      /* try all frequencies */
 +      for (; freq < 8; freq++) {
 +              /* Keyclick active, max amplitude and longest key click len(32 period) */
 +              reg_val = old_reg_val | AC2_KCLAC(0x7) | AC2_KCLLN(0xF);
 +              uDummyVal = 0;
 +              uTryVal = 0;
 +              printk(KERN_INFO "\n\nTrying frequency %d reg val= 0x%x\n",
 +                     freq, reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
 +              audio_tsc2101_write(TSC2101_AUDIO_CTRL_2,
 +                                  reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
 +              printk("DONE. Wait 10 ms ...\n");
 +              /* wait till the kclk bit is auto cleared! time out also to be considered. */
 +              while (audio_tsc2101_read(TSC2101_AUDIO_CTRL_2) & AC2_KCLEN) {
 +                      udelay(3);
 +                      uTryVal++;
 +                      if (uTryVal > 2000) {
 +                              printk(KERN_ERR
 +                                     "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
 +                                     freq);
 +                              printk(KERN_INFO
 +                                     "uTryVal == %d: Read back new reg val= 0x%x\n",
 +                                     uTryVal,
 +                                     audio_tsc2101_read
 +                                     (TSC2101_AUDIO_CTRL_2));
 +                              /* clear */
 +                              audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
 +                              break;
 +                      }
 +              }
 +      }
 +      /* put the old value back */
 +      audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, old_reg_val);
 +      printk(KERN_INFO " KEYCLICK TEST COMPLETE\n");
 +
 +}                             /* End of tsc2101_testkeyclick */
 +
 +#endif                                /* TEST_KEYCLICK */
 +
 +/*********************************************************************************
 + * TONEGEN:
 + * This is a test to generate a rather unpleasant sound..
 + * verifies if the mcbsp is active (requires MCBSP_DIRECT_RW to be active on McBSP)
 + *
 + ********************************************************************************/
 +#ifdef TONE_GEN
 +/* Generates a shrill tone */
 +u16 tone[] = {
 +      0x0ce4, 0x0ce4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
 +      0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
 +      0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
 +      0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
 +      0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
 +      0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
 +      0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
 +      0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
 +      0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
 +      0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
 +      0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
 +      0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
 +      0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
 +      0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
 +      0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
 +      0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
 +      0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
 +      0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
 +      0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
 +      0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
 +      0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
 +      0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
 +      0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
 +      0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
 +      0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
 +      0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
 +      0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
 +      0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
 +      0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
 +      0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
 +      0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
 +      0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
 +      0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000
 +};
 +
 +void toneGen(void)
 +{
 +      int count = 0;
 +      int ret = 0;
 +      printk(KERN_INFO "TONE GEN TEST :");
 +
 +      for (count = 0; count < 5000; count++) {
 +              int bytes;
 +              for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
 +                      ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
 +                      if (ret == -1) {
 +                              /* retry */
 +                              bytes--;
 +                      } else if (ret == -2) {
 +                              printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
 +                              return;
 +                      }
 +              }
 +      }
 +      printk(KERN_INFO "SUCCESS\n");
 +}
 +
 +#endif                                /* End of TONE_GEN */
 +
 +/*********************************************************************************
 + *
 + * TSC_DUMP_REGISTERS:
 + * This will dump the entire register set of Page 2 tsc2101. 
 + * Useful for major goof ups
 + *
 + ********************************************************************************/
 +#ifdef TSC_DUMP_REGISTERS
 +static void tsc2101_dumpRegisters(void)
 +{
 +      int i = 0;
 +      u16 data = 0;
 +      printk("TSC 2101 Register dump for Page 2 \n");
 +      for (i = 0; i < 0x27; i++) {
 +              data = audio_tsc2101_read(i);
 +              printk(KERN_INFO "Register[%x]=0x%04x\n", i, data);
 +
 +      }
 +}
 +#endif                                /* End of #ifdef TSC_DUMP_REGISTERS */
 +
 +#ifdef PROC_SUPPORT
 +static int codec_start(char *buf, char **start, off_t offset, int count,
 +                     int *eof, void *data)
 +{
 +      omap_tsc2101_enable();
 +      tsc2101_start();
 +      printk("Codec initialization done.\n");
 +      return 0;
 +}
 +static int codec_stop(char *buf, char **start, off_t offset, int count,
 +                    int *eof, void *data)
 +{
 +
 +      omap_tsc2101_disable();
 +      audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
 +                          ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
 +      printk("Codec shutdown.\n");
 +      return 0;
 +}
 +#endif
 +
 +/*********************************************************************************
 + *
 + * Other misc management, registration etc
 + *
 + ********************************************************************************/
 +module_init(audio_tsc2101_init);
 +module_exit(audio_tsc2101_exit);
 +
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION
 +    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
 +MODULE_LICENSE("GPL");
index 84f544598ef07ee65812d9fdcf7c1942ba41cd5d,0000000000000000000000000000000000000000..95b5eef11847d87f705f18665bf33916a6195061
mode 100644,000000..100644
--- /dev/null
@@@ -1,1162 -1,0 +1,1162 @@@
- #include <asm/hardware.h>
 +/*
 + * linux/sound/oss/omap-audio.c
 + *
 + * Common audio handling for the OMAP processors
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + * History:
 + *
 + * 2004/08/12   Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
 + *
 + * 2004-11-01   Nishanth Menon - modified to support 16xx and 17xx 
 + *                platform multi channel chaining.
 + *
 + * 2004-11-04   Nishanth Menon - Added support for power management
 + *
 + * 2004-12-17   Nishanth Menon - Provided proper module handling support
 + */
 +
 +/***************************** INCLUDES ************************************/
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/types.h>
 +#include <linux/fs.h>
 +#include <linux/mm.h>
 +#include <linux/slab.h>
 +#include <linux/sched.h>
 +#include <linux/poll.h>
 +#include <linux/pm.h>
 +#include <linux/errno.h>
 +#include <linux/sound.h>
 +#include <linux/soundcard.h>
 +#include <linux/sysrq.h>
 +#include <linux/delay.h>
 +#include <linux/platform_device.h>
 +#include <linux/completion.h>
 +#include <linux/mutex.h>
 +
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
++#include <mach/hardware.h>
 +
 +#include "omap-audio-dma-intfc.h"
 +#include "omap-audio.h"
 +
 +/***************************** MACROS ************************************/
 +
 +#undef DEBUG
 +//#define DEBUG
 +#ifdef DEBUG
 +#define DPRINTK  printk
 +#define FN_IN printk("[omap_audio.c:[%s] start\n", __FUNCTION__)
 +#define FN_OUT(n) printk("[omap_audio.c:[%s] end(%d)\n", __FUNCTION__ , n)
 +#else
 +#define DPRINTK( x... )
 +#define FN_IN
 +#define FN_OUT(x)
 +#endif
 +
 +#define OMAP_AUDIO_NAME               "omap-audio"
 +#define AUDIO_NBFRAGS_DEFAULT 8
 +#define AUDIO_FRAGSIZE_DEFAULT        8192
 +
 +/* HACK ALERT!: These values will bave to be tuned as this is a trade off b/w
 + * Sampling Rate vs buffer size and delay we are prepared to do before giving up
 + */
 +#define MAX_QUEUE_FULL_RETRIES 1000000
 +#define QUEUE_WAIT_TIME        10
 +
 +#define AUDIO_ACTIVE(state)   ((state)->rd_ref || (state)->wr_ref)
 +
 +#define SPIN_ADDR             (dma_addr_t)0
 +#define SPIN_SIZE             2048
 +
 +/***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
 +
 +static int audio_write(struct file *file, const char __user *buffer,
 +                     size_t count, loff_t * ppos);
 +
 +static int audio_read(struct file *file, char __user *buffer, size_t count,
 +                    loff_t * ppos);
 +
 +static int audio_mmap(struct file *file, struct vm_area_struct *vma);
 +
 +static unsigned int audio_poll(struct file *file,
 +                             struct poll_table_struct *wait);
 +
 +static loff_t audio_llseek(struct file *file, loff_t offset, int origin);
 +
 +static int audio_ioctl(struct inode *inode, struct file *file, uint cmd,
 +                     ulong arg);
 +
 +static int audio_open(struct inode *inode, struct file *file);
 +
 +static int audio_release(struct inode *inode, struct file *file);
 +
 +static int audio_probe(struct platform_device *pdev);
 +
 +static int audio_remove(struct platform_device *pdev);
 +
 +static void audio_shutdown(struct platform_device *pdev);
 +
 +static int audio_suspend(struct platform_device *pdev, pm_message_t mesg);
 +
 +static int audio_resume(struct platform_device *pdev);
 +
 +static void audio_free(struct device *dev);
 +
 +/***************************** Data Structures **********************************/
 +
 +/*
 + * The function pointer set to be registered by the codec.
 + */
 +static audio_state_t audio_state = { NULL };
 +
 +/* DMA Call back function */
 +static dma_callback_t audio_dma_callback = NULL;
 +
 +/* File Ops structure */
 +static struct file_operations omap_audio_fops = {
 +      .open           = audio_open,
 +      .release        = audio_release,
 +      .write          = audio_write,
 +      .read           = audio_read,
 +      .mmap           = audio_mmap,
 +      .poll           = audio_poll,
 +      .ioctl          = audio_ioctl,
 +      .llseek         = audio_llseek,
 +      .owner          = THIS_MODULE
 +};
 +
 +/* Driver information */
 +static struct platform_driver omap_audio_driver = {
 +      .probe          = audio_probe,
 +      .remove         = audio_remove,
 +      .suspend        = audio_suspend,
 +      .shutdown       = audio_shutdown,
 +      .resume         = audio_resume,
 +      .driver         = {
 +              .name   = OMAP_AUDIO_NAME,
 +      },
 +};
 +
 +/* Device Information */
 +static struct platform_device omap_audio_device = {
 +      .name = OMAP_AUDIO_NAME,
 +      .dev = {
 +              .driver_data = &audio_state,
 +              .release = audio_free,
 +              },
 +      .id = 0,
 +};
 +
 +/***************************** GLOBAL FUNCTIONs **********************************/
 +
 +/* Power Management Functions for Linux Device Model  */
 +/* DEBUG PUPOSES ONLY! */
 +#ifdef CONFIG_PM
 +//#undef CONFIG_PM
 +#endif
 +
 +#ifdef CONFIG_PM
 +/*********************************************************************************
 + *
 + * audio_ldm_suspend(): Suspend operation
 + *
 + *********************************************************************************/
 +static int audio_ldm_suspend(void *data)
 +{
 +      audio_state_t *state = data;
 +
 +      FN_IN;
 +
 +      /* 
 +       * Reject the suspend request if we are already actively transmitting data 
 +       * Rationale: We dont want to be suspended while in the middle of a call!
 +       */
 +      if (AUDIO_ACTIVE(state) && state->hw_init) {
 +              printk(KERN_ERR "Audio device Active, Cannot Suspend");
 +              return -EPERM;
 +#if 0
 +              /* NOTE:
 +               * This Piece of code is commented out in hope
 +               * That one day we would need to suspend the device while 
 +               * audio operations are in progress and resume the operations
 +               * once the resume is done.
 +               * This is just a sample implementation of how it could be done.
 +               * Currently NOT SUPPORTED
 +               */
 +              audio_stream_t *is = state->input_stream;
 +              audio_stream_t *os = state->output_stream;
 +              int stopstate;
 +              if (is && is->buffers) {
 +                      printk("IS Suspend\n");
 +                      stopstate = is->stopped;
 +                      audio_stop_dma(is);
 +                      DMA_CLEAR(is);
 +                      is->dma_spinref = 0;
 +                      is->stopped = stopstate;
 +              }
 +              if (os && os->buffers) {
 +                      printk("OS Suspend\n");
 +                      stopstate = os->stopped;
 +                      audio_stop_dma(os);
 +                      DMA_CLEAR(os);
 +                      os->dma_spinref = 0;
 +                      os->stopped = stopstate;
 +              }
 +#endif
 +      }
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_ldm_resume(): Resume Operations
 + *
 + *********************************************************************************/
 +static int audio_ldm_resume(void *data)
 +{
 +      audio_state_t *state = data;
 +
 +      FN_IN;
 +      if (AUDIO_ACTIVE(state) && state->hw_init) {
 +              /* Should never occur - since we never suspend with active state */
 +              BUG();
 +              return -EPERM;
 +#if 0
 +              /* NOTE:
 +               * This Piece of code is commented out in hope
 +               * That one day we would need to suspend the device while 
 +               * audio operations are in progress and resume the operations
 +               * once the resume is done.
 +               * This is just a sample implementation of how it could be done.
 +               * Currently NOT SUPPORTED
 +               */
 +              audio_stream_t *is = state->input_stream;
 +              audio_stream_t *os = state->output_stream;
 +              if (os && os->buffers) {
 +                      printk("OS Resume\n");
 +                      audio_reset(os);
 +                      audio_process_dma(os);
 +              }
 +              if (is && is->buffers) {
 +                      printk("IS Resume\n");
 +                      audio_reset(is);
 +                      audio_process_dma(is);
 +              }
 +#endif
 +      }
 +      FN_OUT(0);
 +      return 0;
 +}
 +#endif                                /* End of #ifdef CONFIG_PM */
 +
 +/*********************************************************************************
 + *
 + * audio_free(): The Audio driver release function
 + * This is a dummy function required by the platform driver
 + *
 + *********************************************************************************/
 +static void audio_free(struct device *dev)
 +{
 +      /* Nothing to Release! */
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_probe(): The Audio driver probe function
 + * WARNING!!!!  : It is expected that the codec would have registered with us by now
 + *
 + *********************************************************************************/
 +static int audio_probe(struct platform_device *pdev)
 +{
 +      int ret;
 +      FN_IN;
 +      if (!audio_state.hw_probe) {
 +              printk(KERN_ERR "Probe Function Not Registered\n");
 +              return -ENODEV;
 +      }
 +      ret = audio_state.hw_probe();
 +      FN_OUT(ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_remove() Function to handle removal operations
 + *
 + *********************************************************************************/
 +static int audio_remove(struct platform_device *pdev)
 +{
 +      FN_IN;
 +      if (audio_state.hw_remove) {
 +              audio_state.hw_remove();
 +      }
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_shutdown(): Function to handle shutdown operations
 + *
 + *********************************************************************************/
 +static void audio_shutdown(struct platform_device *pdev)
 +{
 +      FN_IN;
 +      if (audio_state.hw_cleanup) {
 +              audio_state.hw_cleanup();
 +      }
 +      FN_OUT(0);
 +      return;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_suspend(): Function to handle suspend operations 
 + *
 + *********************************************************************************/
 +static int audio_suspend(struct platform_device *pdev, pm_message_t mesg)
 +{
 +      int ret = 0;
 +
 +#ifdef CONFIG_PM
 +      void *data = pdev->dev.driver_data;
 +      FN_IN;
 +      if (audio_state.hw_suspend) {
 +              ret = audio_ldm_suspend(data);
 +              if (ret == 0)
 +                      ret = audio_state.hw_suspend();
 +      }
 +      if (ret) {
 +              printk(KERN_INFO "Audio Suspend Failed \n");
 +      } else {
 +              printk(KERN_INFO "Audio Suspend Success \n");
 +      }
 +#endif                                /* CONFIG_PM */
 +
 +      FN_OUT(ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_resume(): Function to handle resume operations
 + *
 + *********************************************************************************/
 +static int audio_resume(struct platform_device *pdev)
 +{
 +      int ret = 0;
 +
 +#ifdef        CONFIG_PM
 +      void *data = pdev->dev.driver_data;
 +      FN_IN;
 +      if (audio_state.hw_resume) {
 +              ret = audio_ldm_resume(data);
 +              if (ret == 0)
 +                      ret = audio_state.hw_resume();
 +      }
 +      if (ret) {
 +              printk(KERN_INFO " Audio Resume Failed \n");
 +      } else {
 +              printk(KERN_INFO " Audio Resume Success \n");
 +      }
 +#endif                                /* CONFIG_PM */
 +
 +      FN_OUT(ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_get_fops(): Return the fops required to get the function pointers of 
 + *                   OMAP Audio Driver
 + *
 + *********************************************************************************/
 +struct file_operations *audio_get_fops(void)
 +{
 +      FN_IN;
 +      FN_OUT(0);
 +      return &omap_audio_fops;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_register_codec(): Register a Codec fn points using this function
 + * WARNING!!!!!          : Codecs should ensure that they do so! no sanity checks
 + *                         during runtime is done due to obvious performance 
 + *                         penalties.
 + *
 + *********************************************************************************/
 +int audio_register_codec(audio_state_t * codec_state)
 +{
 +      int ret;
 +      FN_IN;
 +
 +      /* We dont handle multiple codecs now */
 +      if (audio_state.hw_init) {
 +              printk(KERN_ERR " Codec Already registered\n");
 +              return -EPERM;
 +      }
 +
 +      /* Grab the dma Callback */
 +      audio_dma_callback = audio_get_dma_callback();
 +      if (!audio_dma_callback) {
 +              printk(KERN_ERR "Unable to get call back function\n");
 +              return -EPERM;
 +      }
 +
 +      /* Sanity checks */
 +      if (!codec_state) {
 +              printk(KERN_ERR "NULL ARGUMENT!\n");
 +              return -EPERM;
 +      }
 +
 +      if (!codec_state->hw_probe || !codec_state->hw_init
 +          || !codec_state->hw_shutdown || !codec_state->client_ioctl) {
 +              printk(KERN_ERR
 +                     "Required Fn Entry point Missing probe=%p init=%p,down=%p,ioctl=%p!\n",
 +                     codec_state->hw_probe, codec_state->hw_init,
 +                     codec_state->hw_shutdown, codec_state->client_ioctl);
 +              return -EPERM;
 +      }
 +
 +      memcpy(&audio_state, codec_state, sizeof(audio_state_t));
 +      mutex_init(&audio_state.mutex);
 +
 +      ret = platform_device_register(&omap_audio_device);
 +      if (ret != 0) {
 +              printk(KERN_ERR "Platform dev_register failed =%d\n", ret);
 +              ret = -ENODEV;
 +              goto register_out;
 +      }
 +
 +      ret = platform_driver_register(&omap_audio_driver);
 +      if (ret != 0) {
 +              printk(KERN_ERR "Device Register failed =%d\n", ret);
 +              ret = -ENODEV;
 +              platform_device_unregister(&omap_audio_device);
 +              goto register_out;
 +      }
 +
 +      register_out:
 +
 +      FN_OUT(ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_unregister_codec(): Un-Register a Codec using this function
 + *
 + *********************************************************************************/
 +int audio_unregister_codec(audio_state_t * codec_state)
 +{
 +      FN_IN;
 +
 +      /* We dont handle multiple codecs now */
 +      if (!audio_state.hw_init) {
 +              printk(KERN_ERR " No Codec registered\n");
 +              return -EPERM;
 +      }
 +      /* Security check */
 +      if (audio_state.hw_init != codec_state->hw_init) {
 +              printk(KERN_ERR
 +                     " Attempt to unregister codec which was not registered with us\n");
 +              return -EPERM;
 +      }
 +
 +      platform_driver_unregister(&omap_audio_driver);
 +      platform_device_unregister(&omap_audio_device);
 +
 +      memset(&audio_state, 0, sizeof(audio_state_t));
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/***************************** MODULES SPECIFIC FUNCTION *************************/
 +
 +/*********************************************************************************
 + *
 + * audio_write(): Exposed to write() call
 + *
 + *********************************************************************************/
 +static int
 +audio_write(struct file *file, const char __user *buffer,
 +              size_t count, loff_t * ppos)
 +{
 +      const char __user *buffer0 = buffer;
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *s = state->output_stream;
 +      int chunksize, ret = 0;
 +
 +      DPRINTK("audio_write: count=%d\n", count);
 +      if (*ppos != file->f_pos) {
 +              printk("FPOS not ppos ppos=0x%x fpos =0x%x\n", (u32) * ppos,
 +                     (u32) file->f_pos);
 +              return -ESPIPE;
 +      }
 +      if (s->mapped) {
 +              printk("s already mapped\n");
 +              return -ENXIO;
 +      }
 +      if (!s->buffers && audio_setup_buf(s)) {
 +              printk("NO MEMORY\n");
 +              return -ENOMEM;
 +      }
 +
 +      while (count > 0) {
 +              audio_buf_t *b = &s->buffers[s->usr_head];
 +
 +              /* Wait for a buffer to become free */
 +              if (file->f_flags & O_NONBLOCK) {
 +                      ret = -EAGAIN;
 +                      if (!s->wfc.done)
 +                              break;
 +              }
 +              ret = -ERESTARTSYS;
 +              if (wait_for_completion_interruptible(&s->wfc))
 +                      break;
 +
 +              /* Feed the current buffer */
 +              chunksize = s->fragsize - b->offset;
 +              if (chunksize > count)
 +                      chunksize = count;
 +              DPRINTK("write %d to %d\n", chunksize, s->usr_head);
 +              if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
 +                      printk(KERN_ERR "Audio: CopyFrom User failed \n");
 +                      complete(&s->wfc);
 +                      return -EFAULT;
 +              }
 +
 +              buffer += chunksize;
 +              count -= chunksize;
 +              b->offset += chunksize;
 +
 +              if (b->offset < s->fragsize) {
 +                      complete(&s->wfc);
 +                      break;
 +              }
 +
 +              /* Update pointers and send current fragment to DMA */
 +              b->offset = 0;
 +              if (++s->usr_head >= s->nbfrags)
 +                      s->usr_head = 0;
 +              /* Add the num of frags pending */
 +              s->pending_frags++;
 +              s->active = 1;
 +
 +              audio_process_dma(s);
 +
 +      }
 +
 +      if ((buffer - buffer0))
 +              ret = buffer - buffer0;
 +      DPRINTK("audio_write: return=%d\n", ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_read(): Exposed as read() function
 + *
 + *********************************************************************************/
 +static int
 +audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
 +{
 +      char __user *buffer0 = buffer;
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *s = state->input_stream;
 +      int chunksize, ret = 0;
 +      unsigned long flags;
 +
 +      DPRINTK("audio_read: count=%d\n", count);
 +
 +      if (*ppos != file->f_pos) {
 +              printk("AudioRead - FPOS not ppos ppos=0x%x fpos =0x%x\n",
 +                     (u32) * ppos, (u32) file->f_pos);
 +              return -ESPIPE;
 +      }
 +      if (s->mapped) {
 +              printk("AudioRead - s already mapped\n");
 +              return -ENXIO;
 +      }
 +
 +      if (!s->active) {
 +              if (!s->buffers && audio_setup_buf(s)) {
 +                      printk("AudioRead - No Memory\n");
 +                      return -ENOMEM;
 +              }
 +              audio_prime_rx(state);
 +      }
 +
 +      while (count > 0) {
 +              audio_buf_t *b = &s->buffers[s->usr_head];
 +
 +              /* Wait for a buffer to become full */
 +              if (file->f_flags & O_NONBLOCK) {
 +                      ret = -EAGAIN;
 +                      if (!s->wfc.done)
 +                              break;
 +              }
 +              ret = -ERESTARTSYS;
 +              if (wait_for_completion_interruptible(&s->wfc))
 +                      break;
 +
 +              /* Grab data from the current buffer */
 +              chunksize = s->fragsize - b->offset;
 +              if (chunksize > count)
 +                      chunksize = count;
 +              DPRINTK("read %d from %d\n", chunksize, s->usr_head);
 +              if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
 +                      complete(&s->wfc);
 +                      return -EFAULT;
 +              }
 +              buffer += chunksize;
 +              count -= chunksize;
 +              b->offset += chunksize;
 +              if (b->offset < s->fragsize) {
 +                      complete(&s->wfc);
 +                      break;
 +              }
 +
 +              /* Update pointers and return current fragment to DMA */
 +              local_irq_save(flags);
 +              b->offset = 0;
 +              if (++s->usr_head >= s->nbfrags)
 +                      s->usr_head = 0;
 +
 +              s->pending_frags++;
 +              local_irq_restore(flags);
 +              audio_process_dma(s);
 +
 +      }
 +
 +      if ((buffer - buffer0))
 +              ret = buffer - buffer0;
 +      DPRINTK("audio_read: return=%d\n", ret);
 +      return ret;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_mmap(): Exposed as mmap Function
 + * !!WARNING: Still under development
 + *
 + *********************************************************************************/
 +static int audio_mmap(struct file *file, struct vm_area_struct *vma)
 +{
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *s;
 +      unsigned long size, vma_addr;
 +      int i, ret;
 +
 +      FN_IN;
 +      if (vma->vm_pgoff != 0)
 +              return -EINVAL;
 +
 +      if (vma->vm_flags & VM_WRITE) {
 +              if (!state->wr_ref)
 +                      return -EINVAL;;
 +              s = state->output_stream;
 +      } else if (vma->vm_flags & VM_READ) {
 +              if (!state->rd_ref)
 +                      return -EINVAL;
 +              s = state->input_stream;
 +      } else
 +              return -EINVAL;
 +
 +      if (s->mapped)
 +              return -EINVAL;
 +      size = vma->vm_end - vma->vm_start;
 +      if (size != s->fragsize * s->nbfrags)
 +              return -EINVAL;
 +      if (!s->buffers && audio_setup_buf(s))
 +              return -ENOMEM;
 +      vma_addr = vma->vm_start;
 +      for (i = 0; i < s->nbfrags; i++) {
 +              audio_buf_t *buf = &s->buffers[i];
 +              if (!buf->master)
 +                      continue;
 +              ret =
 +                  remap_pfn_range(vma, vma_addr, buf->dma_addr >> PAGE_SHIFT,
 +                                  buf->master, vma->vm_page_prot);
 +              if (ret)
 +                      return ret;
 +              vma_addr += buf->master;
 +      }
 +      s->mapped = 1;
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_poll(): Exposed as poll function
 + *
 + *********************************************************************************/
 +static unsigned int
 +audio_poll(struct file *file, struct poll_table_struct *wait)
 +{
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *is = state->input_stream;
 +      audio_stream_t *os = state->output_stream;
 +      unsigned int mask = 0;
 +
 +      DPRINTK("audio_poll(): mode=%s%s\n",
 +              (file->f_mode & FMODE_READ) ? "r" : "",
 +              (file->f_mode & FMODE_WRITE) ? "w" : "");
 +
 +      if (file->f_mode & FMODE_READ) {
 +              /* Start audio input if not already active */
 +              if (!is->active) {
 +                      if (!is->buffers && audio_setup_buf(is))
 +                              return -ENOMEM;
 +                      audio_prime_rx(state);
 +              }
 +              poll_wait(file, &is->wq, wait);
 +      }
 +
 +      if (file->f_mode & FMODE_WRITE) {
 +              if (!os->buffers && audio_setup_buf(os))
 +                      return -ENOMEM;
 +              poll_wait(file, &os->wq, wait);
 +      }
 +
 +      if (file->f_mode & FMODE_READ)
 +              if ((is->mapped && is->bytecount > 0) ||
 +                  (!is->mapped && is->wfc.done > 0))
 +                      mask |= POLLIN | POLLRDNORM;
 +
 +      if (file->f_mode & FMODE_WRITE)
 +              if ((os->mapped && os->bytecount > 0) ||
 +                  (!os->mapped && os->wfc.done > 0))
 +                      mask |= POLLOUT | POLLWRNORM;
 +
 +      DPRINTK("audio_poll() returned mask of %s%s\n",
 +              (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
 +
 +      FN_OUT(mask);
 +      return mask;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_llseek(): Exposed as lseek() function.
 + *
 + *********************************************************************************/
 +static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
 +{
 +      FN_IN;
 +      FN_OUT(0);
 +      return -ESPIPE;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_ioctl(): Handles generic ioctls. If there is a request for something this
 + * fn cannot handle, its then given to client specific ioctl routine, that will take
 + * up platform specific requests
 + *
 + *********************************************************************************/
 +static int
 +audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 +{
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *os = state->output_stream;
 +      audio_stream_t *is = state->input_stream;
 +      long val;
 +
 +      DPRINTK(__FILE__ " audio_ioctl 0x%08x\n", cmd);
 +
 +      /* dispatch based on command */
 +      switch (cmd) {
 +      case OSS_GETVERSION:
 +              return put_user(SOUND_VERSION, (int __user *)arg);
 +
 +      case SNDCTL_DSP_GETBLKSIZE:
 +              if (file->f_mode & FMODE_WRITE)
 +                      return put_user(os->fragsize, (int __user *)arg);
 +              else
 +                      return put_user(is->fragsize, (int __user *)arg);
 +
 +      case SNDCTL_DSP_GETCAPS:
 +              val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
 +              if (is && os)
 +                      val |= DSP_CAP_DUPLEX;
 +              FN_OUT(1);
 +              return put_user(val, (int __user *)arg);
 +
 +      case SNDCTL_DSP_SETFRAGMENT:
 +              if (get_user(val, (long __user *)arg)) {
 +                      FN_OUT(2);
 +                      return -EFAULT;
 +              }
 +              if (file->f_mode & FMODE_READ) {
 +                      int ret = audio_set_fragments(is, val);
 +                      if (ret < 0) {
 +                              FN_OUT(3);
 +                              return ret;
 +                      }
 +                      ret = put_user(ret, (int __user *)arg);
 +                      if (ret) {
 +                              FN_OUT(4);
 +                              return ret;
 +                      }
 +              }
 +              if (file->f_mode & FMODE_WRITE) {
 +                      int ret = audio_set_fragments(os, val);
 +                      if (ret < 0) {
 +                              FN_OUT(5);
 +                              return ret;
 +                      }
 +                      ret = put_user(ret, (int __user *)arg);
 +                      if (ret) {
 +                              FN_OUT(6);
 +                              return ret;
 +                      }
 +              }
 +              FN_OUT(7);
 +              return 0;
 +
 +      case SNDCTL_DSP_SYNC:
 +              FN_OUT(8);
 +              return audio_sync(file);
 +
 +      case SNDCTL_DSP_SETDUPLEX:
 +              FN_OUT(9);
 +              return 0;
 +
 +      case SNDCTL_DSP_POST:
 +              FN_OUT(10);
 +              return 0;
 +
 +      case SNDCTL_DSP_GETTRIGGER:
 +              val = 0;
 +              if (file->f_mode & FMODE_READ && is->active && !is->stopped)
 +                      val |= PCM_ENABLE_INPUT;
 +              if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
 +                      val |= PCM_ENABLE_OUTPUT;
 +              FN_OUT(11);
 +              return put_user(val, (int __user *)arg);
 +
 +      case SNDCTL_DSP_SETTRIGGER:
 +              if (get_user(val, (int __user *)arg)) {
 +                      FN_OUT(12);
 +                      return -EFAULT;
 +              }
 +              if (file->f_mode & FMODE_READ) {
 +                      if (val & PCM_ENABLE_INPUT) {
 +                              unsigned long flags;
 +                              if (!is->active) {
 +                                      if (!is->buffers && audio_setup_buf(is)) {
 +                                              FN_OUT(13);
 +                                              return -ENOMEM;
 +                                      }
 +                                      audio_prime_rx(state);
 +                              }
 +                              local_irq_save(flags);
 +                              is->stopped = 0;
 +                              local_irq_restore(flags);
 +                              audio_process_dma(is);
 +
 +                      } else {
 +                              audio_stop_dma(is);
 +                      }
 +              }
 +              if (file->f_mode & FMODE_WRITE) {
 +                      if (val & PCM_ENABLE_OUTPUT) {
 +                              unsigned long flags;
 +                              if (!os->buffers && audio_setup_buf(os)) {
 +                                      FN_OUT(14);
 +                                      return -ENOMEM;
 +                              }
 +                              local_irq_save(flags);
 +                              if (os->mapped && !os->pending_frags) {
 +                                      os->pending_frags = os->nbfrags;
 +                                      init_completion(&os->wfc);
 +                                      os->wfc.done = 0;
 +                                      os->active = 1;
 +                              }
 +                              os->stopped = 0;
 +                              local_irq_restore(flags);
 +                              audio_process_dma(os);
 +
 +                      } else {
 +                              audio_stop_dma(os);
 +                      }
 +              }
 +              FN_OUT(15);
 +              return 0;
 +
 +      case SNDCTL_DSP_GETOPTR:
 +      case SNDCTL_DSP_GETIPTR:
 +              {
 +                      count_info inf = { 0, };
 +                      audio_stream_t *s =
 +                          (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
 +                      int bytecount, offset;
 +                      unsigned long flags;
 +
 +                      if ((s == is && !(file->f_mode & FMODE_READ)) ||
 +                          (s == os && !(file->f_mode & FMODE_WRITE))) {
 +                              FN_OUT(16);
 +                              return -EINVAL;
 +                      }
 +                      if (s->active) {
 +                              local_irq_save(flags);
 +                              offset = audio_get_dma_pos(s);
 +                              inf.ptr = s->dma_tail * s->fragsize + offset;
 +                              bytecount = s->bytecount + offset;
 +                              s->bytecount = -offset;
 +                              inf.blocks = s->fragcount;
 +                              s->fragcount = 0;
 +                              local_irq_restore(flags);
 +                              if (bytecount < 0)
 +                                      bytecount = 0;
 +                              inf.bytes = bytecount;
 +                      }
 +                      FN_OUT(17);
 +                      return copy_to_user((void __user *)arg, &inf, sizeof(inf));
 +              }
 +
 +      case SNDCTL_DSP_GETOSPACE:
 +      case SNDCTL_DSP_GETISPACE:
 +              {
 +                      audio_buf_info inf = { 0, };
 +                      audio_stream_t *s =
 +                          (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
 +
 +                      if ((s == is && !(file->f_mode & FMODE_READ)) ||
 +                          (s == os && !(file->f_mode & FMODE_WRITE))) {
 +                              FN_OUT(18);
 +                              return -EINVAL;
 +                      }
 +                      if (!s->buffers && audio_setup_buf(s)) {
 +                              FN_OUT(19);
 +                              return -ENOMEM;
 +                      }
 +                      inf.bytes = s->wfc.done * s->fragsize;
 +
 +                      inf.fragments = inf.bytes / s->fragsize;
 +                      inf.fragsize = s->fragsize;
 +                      inf.fragstotal = s->nbfrags;
 +                      FN_OUT(20);
 +                      return copy_to_user((void __user *)arg, &inf, sizeof(inf));
 +              }
 +
 +      case SNDCTL_DSP_NONBLOCK:
 +              file->f_flags |= O_NONBLOCK;
 +              FN_OUT(21);
 +              return 0;
 +
 +      case SNDCTL_DSP_RESET:
 +              if (file->f_mode & FMODE_READ) {
 +                      audio_reset(is);
 +                      if (state->need_tx_for_rx) {
 +                              unsigned long flags;
 +                              local_irq_save(flags);
 +                              os->spin_idle = 0;
 +                              local_irq_restore(flags);
 +                      }
 +              }
 +              if (file->f_mode & FMODE_WRITE) {
 +                      audio_reset(os);
 +              }
 +              FN_OUT(22);
 +              return 0;
 +
 +      default:
 +              /*
 +               * Let the client of this module handle the
 +               * non generic ioctls
 +               */
 +              FN_OUT(23);
 +              return state->client_ioctl(inode, file, cmd, arg);
 +      }
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_open(): Exposed as open() function
 + *
 + *********************************************************************************/
 +static int audio_open(struct inode *inode, struct file *file)
 +{
 +      audio_state_t *state = (&audio_state);
 +      audio_stream_t *os = state->output_stream;
 +      audio_stream_t *is = state->input_stream;
 +      int err, need_tx_dma;
 +      static unsigned char tsc2101_init_flag = 0;
 +
 +      FN_IN;
 +
 +      /* Lock the module */
 +      if (!try_module_get(THIS_MODULE)) {
 +              printk(KERN_CRIT "Failed to get module\n");
 +              return -ESTALE;
 +      }
 +      /* Lock the codec module */
 +      if (!try_module_get(state->owner)) {
 +              printk(KERN_CRIT "Failed to get codec module\n");
 +              module_put(THIS_MODULE);
 +              return -ESTALE;
 +      }
 +
 +      mutex_lock(&state->mutex);
 +
 +      /* access control */
 +      err = -ENODEV;
 +      if ((file->f_mode & FMODE_WRITE) && !os)
 +              goto out;
 +      if ((file->f_mode & FMODE_READ) && !is)
 +              goto out;
 +      err = -EBUSY;
 +      if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
 +              goto out;
 +      if ((file->f_mode & FMODE_READ) && state->rd_ref)
 +              goto out;
 +      err = -EINVAL;
 +      if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !os)
 +              goto out;
 +
 +      /* request DMA channels */
 +      need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
 +                     ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
 +      if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
 +              need_tx_dma = 0;
 +      if (need_tx_dma) {
 +              DMA_REQUEST(err, os, audio_dma_callback);
 +              if (err < 0)
 +                      goto out;
 +      }
 +      if (file->f_mode & FMODE_READ) {
 +              DMA_REQUEST(err, is, audio_dma_callback);
 +              if (err < 0) {
 +                      if (need_tx_dma)
 +                              DMA_FREE(os);
 +                      goto out;
 +              }
 +      }
 +
 +      /* now complete initialisation */
 +      if (!AUDIO_ACTIVE(state)) {
 +              if (state->hw_init && !tsc2101_init_flag) {
 +                      state->hw_init(state->data);
 +                      tsc2101_init_flag = 0;
 +
 +              }
 +
 +      }
 +
 +      if ((file->f_mode & FMODE_WRITE)) {
 +              state->wr_ref = 1;
 +              audio_reset(os);
 +              os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
 +              os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
 +              os->mapped = 0;
 +              init_waitqueue_head(&os->wq);
 +      }
 +
 +      if (file->f_mode & FMODE_READ) {
 +              state->rd_ref = 1;
 +              audio_reset(is);
 +              is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
 +              is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
 +              is->mapped = 0;
 +              init_waitqueue_head(&is->wq);
 +      }
 +
 +      file->private_data = state;
 +      err = 0;
 +
 +      out:
 +      mutex_unlock(&state->mutex);
 +      if (err) {
 +              module_put(state->owner);
 +              module_put(THIS_MODULE);
 +      }
 +      FN_OUT(err);
 +      return err;
 +}
 +
 +/*********************************************************************************
 + *
 + * audio_release(): Exposed as release function()
 + *
 + *********************************************************************************/
 +static int audio_release(struct inode *inode, struct file *file)
 +{
 +      audio_state_t *state = file->private_data;
 +      audio_stream_t *os = state->output_stream;
 +      audio_stream_t *is = state->input_stream;
 +
 +      FN_IN;
 +
 +      mutex_lock(&state->mutex);
 +
 +      if (file->f_mode & FMODE_READ) {
 +              audio_discard_buf(is);
 +              DMA_FREE(is);
 +              is->dma_spinref = 0;
 +              if (state->need_tx_for_rx) {
 +                      os->spin_idle = 0;
 +                      if (!state->wr_ref) {
 +                              DMA_FREE(os);
 +                              os->dma_spinref = 0;
 +                      }
 +              }
 +              state->rd_ref = 0;
 +      }
 +
 +      if (file->f_mode & FMODE_WRITE) {
 +              audio_sync(file);
 +              audio_discard_buf(os);
 +              if (!state->need_tx_for_rx || !state->rd_ref) {
 +                      DMA_FREE(os);
 +                      os->dma_spinref = 0;
 +              }
 +              state->wr_ref = 0;
 +      }
 +
 +      if (!AUDIO_ACTIVE(state)) {
 +              if (state->hw_shutdown)
 +                      state->hw_shutdown(state->data);
 +      }
 +
 +      mutex_unlock(&state->mutex);
 +
 +      module_put(state->owner);
 +      module_put(THIS_MODULE);
 +
 +      FN_OUT(0);
 +      return 0;
 +}
 +
 +EXPORT_SYMBOL(audio_register_codec);
 +EXPORT_SYMBOL(audio_unregister_codec);
 +EXPORT_SYMBOL(audio_get_fops);
 +
 +MODULE_AUTHOR("Texas Instruments");
 +MODULE_DESCRIPTION("Common audio handling for OMAP processors");
 +MODULE_LICENSE("GPL");
index c039dee3b148c184dc0e14b539197012925792c4,0000000000000000000000000000000000000000..895d8031d7c61c5dbdbafd8ad0144b9ce6b3c065
mode 100644,000000..100644
--- /dev/null
@@@ -1,125 -1,0 +1,125 @@@
- #include <asm/arch/dma.h>
 +/*
 + * linux/sound/oss/omap-audio.h
 + *
 + * Common audio handling for the OMAP processors
 + *
 + * Copyright (C) 2004 Texas Instruments, Inc.
 + *
 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
 + *
 + * This package is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + *
 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + *  History
 + *  -------
 + *  2004/08/12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
 + *
 + *  2004/04/04 Nishanth menon - Added hooks for power management
 + *
 + *  2005/12/10 Dirk Behme     - Added L/R Channel Interchange fix as proposed by Ajaya Babu
 + */
 +
 +#ifndef __OMAP_AUDIO_H
 +#define __OMAP_AUDIO_H
 +
 +/* Requires dma.h */
++#include <mach/dma.h>
 +
 +/*
 + * Buffer Management
 + */
 +typedef struct {
 +      int offset;             /* current offset */
 +      char *data;             /* points to actual buffer */
 +      dma_addr_t dma_addr;    /* physical buffer address */
 +      int dma_ref;            /* DMA refcount */
 +      int master;             /* owner for buffer allocation, contain size when true */
 +} audio_buf_t;
 +
 +/*
 + * Structure describing the data stream related information
 + */
 +typedef struct {
 +      char *id;               /* identification string */
 +      audio_buf_t *buffers;   /* pointer to audio buffer structures */
 +      u_int usr_head;         /* user fragment index */
 +      u_int dma_head;         /* DMA fragment index to go */
 +      u_int dma_tail;         /* DMA fragment index to complete */
 +      u_int fragsize;         /* fragment i.e. buffer size */
 +      u_int nbfrags;          /* nbr of fragments i.e. buffers */
 +      u_int pending_frags;    /* Fragments sent to DMA */
 +      int dma_dev;            /* device identifier for DMA */
 +
 +#ifdef OMAP_DMA_CHAINING_SUPPORT
 +      lch_chain *dma_chain;
 +      dma_regs_t *dma_regs;   /* points to our DMA registers */
 +#else
 +      char started;           /* to store if the chain was started or not */
 +      int dma_q_head;         /* DMA Channel Q Head */
 +      int dma_q_tail;         /* DMA Channel Q Tail */
 +      char dma_q_count;       /* DMA Channel Q Count */
 +      char in_use;            /*  Is this is use? */
 +      int *lch;               /*  Chain of channels this stream is linked to */
 +#endif
 +      int input_or_output;    /* Direction of this data stream */
 +      int bytecount;          /* nbr of processed bytes */
 +      int fragcount;          /* nbr of fragment transitions */
 +      struct completion wfc;  /* wait for "nbfrags" fragment completion */
 +      wait_queue_head_t wq;   /* for poll */
 +      int dma_spinref;        /* DMA is spinning */
 +      unsigned mapped:1;      /* mmap()'ed buffers */
 +      unsigned active:1;      /* actually in progress */
 +      unsigned stopped:1;     /* might be active but stopped */
 +      unsigned spin_idle:1;   /* have DMA spin on zeros when idle */
 +      unsigned linked:1;      /* dma channels linked */
 +      int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
 +      int (*hw_stop)(void);   /* interface to stop HW interface, e.g. McBSP */
 +} audio_stream_t;
 +
 +/*
 + * State structure for one instance
 + */
 +typedef struct {
 +      struct module *owner;   /* Codec module ID */
 +      audio_stream_t *output_stream;
 +      audio_stream_t *input_stream;
 +      unsigned rd_ref:1;      /* open reference for recording */
 +      unsigned wr_ref:1;      /* open reference for playback */
 +      unsigned need_tx_for_rx:1; /* if data must be sent while receiving */
 +      void *data;
 +      void (*hw_init) (void *);
 +      void (*hw_shutdown) (void *);
 +      int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
 +      int (*hw_probe) (void);
 +      void (*hw_remove) (void);
 +      void (*hw_cleanup) (void);
 +      int (*hw_suspend) (void);
 +      int (*hw_resume) (void);
 +      struct pm_dev *pm_dev;
 +      struct mutex mutex;     /* to protect against races in attach() */
 +} audio_state_t;
 +
 +#ifdef AUDIO_PM
 +void audio_ldm_suspend(void *data);
 +
 +void audio_ldm_resume(void *data);
 +
 +#endif
 +
 +/* Register a Codec using this function */
 +extern int audio_register_codec(audio_state_t * codec_state);
 +/* Un-Register a Codec using this function */
 +extern int audio_unregister_codec(audio_state_t * codec_state);
 +/* Function to provide fops of omap audio driver */
 +extern struct file_operations *audio_get_fops(void);
 +/* Function to initialize the device info for audio driver */
 +extern int audio_dev_init(void);
 +/* Function to un-initialize the device info for audio driver */
 +void audio_dev_uninit(void);
 +
 +#endif                                /* End of #ifndef __OMAP_AUDIO_H */