summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/OMAP/DSS317
-rwxr-xr-xTI_OMAP4_Kernel_Release_Notes_L24.x.txt479
-rwxr-xr-xTI_OMAP4_Syslink_Release_Notes_L24.x.txt626
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/configs/omap3_pandora_defconfig2
-rw-r--r--arch/arm/configs/omap_3430sdp_defconfig2
-rw-r--r--arch/arm/configs/omap_4430sdp_defconfig145
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c2
-rw-r--r--arch/arm/mach-omap2/Makefile19
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c6
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c14
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c481
-rw-r--r--arch/arm/mach-omap2/board-ldp.c12
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c6
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c10
-rw-r--r--arch/arm/mach-omap2/board-overo.c8
-rw-r--r--arch/arm/mach-omap2/clock.c547
-rw-r--r--arch/arm/mach-omap2/clock.h16
-rw-r--r--arch/arm/mach-omap2/clock24xx.c8
-rw-r--r--arch/arm/mach-omap2/clock34xx.c524
-rw-r--r--arch/arm/mach-omap2/clock34xx.h5
-rw-r--r--arch/arm/mach-omap2/clock44xx.c257
-rw-r--r--arch/arm/mach-omap2/clock44xx.h1787
-rw-r--r--arch/arm/mach-omap2/clockdomain.c69
-rw-r--r--arch/arm/mach-omap2/clockdomains.h253
-rw-r--r--arch/arm/mach-omap2/cm.h270
-rw-r--r--arch/arm/mach-omap2/cm1-regbits-44xx.h325
-rw-r--r--arch/arm/mach-omap2/cm2-regbits-44xx.h584
-rw-r--r--arch/arm/mach-omap2/control.c6
-rw-r--r--arch/arm/mach-omap2/devices.c139
-rw-r--r--arch/arm/mach-omap2/dspbridge.c76
-rw-r--r--arch/arm/mach-omap2/id.c7
-rw-r--r--arch/arm/mach-omap2/io.c11
-rw-r--r--arch/arm/mach-omap2/iommu2.c8
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-omap2/mailbox.c164
-rw-r--r--arch/arm/mach-omap2/mcbsp.c46
-rw-r--r--arch/arm/mach-omap2/mmc-twl4030.c124
-rw-r--r--arch/arm/mach-omap2/mux.c215
-rw-r--r--arch/arm/mach-omap2/omap4-iommu.c112
-rw-r--r--arch/arm/mach-omap2/pm-debug.c18
-rw-r--r--arch/arm/mach-omap2/pm24xx.c5
-rw-r--r--arch/arm/mach-omap2/pm34xx.c38
-rw-r--r--arch/arm/mach-omap2/powerdomain.c155
-rw-r--r--arch/arm/mach-omap2/powerdomains.h53
-rw-r--r--arch/arm/mach-omap2/powerdomains24xx.h18
-rw-r--r--arch/arm/mach-omap2/powerdomains34xx.h18
-rw-r--r--arch/arm/mach-omap2/powerdomains44xx.h258
-rw-r--r--arch/arm/mach-omap2/prcm-common.h28
-rw-r--r--arch/arm/mach-omap2/prcm.c17
-rw-r--r--arch/arm/mach-omap2/prm-regbits-44xx.h1141
-rw-r--r--arch/arm/mach-omap2/prm.h323
-rw-r--r--arch/arm/mach-omap2/serial.c236
-rw-r--r--arch/arm/mach-omap2/sleep34xx.S2
-rw-r--r--arch/arm/plat-omap/Kconfig6
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/clock.c26
-rw-r--r--arch/arm/plat-omap/common.c2
-rwxr-xr-x[-rw-r--r--]arch/arm/plat-omap/devices.c64
-rw-r--r--arch/arm/plat-omap/dma.c303
-rw-r--r--arch/arm/plat-omap/fb.c30
-rw-r--r--arch/arm/plat-omap/gpio.c157
-rw-r--r--arch/arm/plat-omap/i2c.c21
-rwxr-xr-xarch/arm/plat-omap/include/dspbridge/_chnl_sm.h218
-rw-r--r--arch/arm/plat-omap/include/dspbridge/_dcd.h187
-rw-r--r--arch/arm/plat-omap/include/dspbridge/brddefs.h54
-rw-r--r--arch/arm/plat-omap/include/dspbridge/cfg.h339
-rw-r--r--arch/arm/plat-omap/include/dspbridge/cfgdefs.h120
-rw-r--r--arch/arm/plat-omap/include/dspbridge/chnl.h170
-rw-r--r--arch/arm/plat-omap/include/dspbridge/chnl_sm.h168
-rw-r--r--arch/arm/plat-omap/include/dspbridge/chnldefs.h92
-rw-r--r--arch/arm/plat-omap/include/dspbridge/chnlpriv.h136
-rw-r--r--arch/arm/plat-omap/include/dspbridge/clk.h155
-rw-r--r--arch/arm/plat-omap/include/dspbridge/cmm.h420
-rw-r--r--arch/arm/plat-omap/include/dspbridge/cmmdefs.h135
-rw-r--r--arch/arm/plat-omap/include/dspbridge/cod.h433
-rw-r--r--arch/arm/plat-omap/include/dspbridge/csl.h135
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbc.h66
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbdcd.h388
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbdcddef.h94
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbdefs.h583
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbg.h110
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbl.h354
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbldefs.h155
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbll.h70
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dblldefs.h509
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbof.h117
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbreg.h113
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dbtype.h103
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dehdefs.h42
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dev.h785
-rw-r--r--arch/arm/plat-omap/include/dspbridge/devdefs.h35
-rw-r--r--arch/arm/plat-omap/include/dspbridge/disp.h236
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dispdefs.h45
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dmm.h85
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dpc.h167
-rw-r--r--arch/arm/plat-omap/include/dspbridge/drv.h496
-rw-r--r--arch/arm/plat-omap/include/dspbridge/drvdefs.h34
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dspdrv.h106
-rw-r--r--arch/arm/plat-omap/include/dspbridge/dynamic_loader.h505
-rw-r--r--arch/arm/plat-omap/include/dspbridge/errbase.h509
-rw-r--r--arch/arm/plat-omap/include/dspbridge/gb.h85
-rw-r--r--arch/arm/plat-omap/include/dspbridge/getsection.h118
-rw-r--r--arch/arm/plat-omap/include/dspbridge/gh.h37
-rw-r--r--arch/arm/plat-omap/include/dspbridge/gs.h64
-rw-r--r--arch/arm/plat-omap/include/dspbridge/gt.h315
-rw-r--r--arch/arm/plat-omap/include/dspbridge/host_os.h96
-rw-r--r--arch/arm/plat-omap/include/dspbridge/io.h132
-rw-r--r--arch/arm/plat-omap/include/dspbridge/io_sm.h338
-rw-r--r--arch/arm/plat-omap/include/dspbridge/iodefs.h45
-rw-r--r--arch/arm/plat-omap/include/dspbridge/kfile.h216
-rw-r--r--arch/arm/plat-omap/include/dspbridge/ldr.h51
-rw-r--r--arch/arm/plat-omap/include/dspbridge/list.h296
-rw-r--r--arch/arm/plat-omap/include/dspbridge/mbx_sh.h213
-rw-r--r--arch/arm/plat-omap/include/dspbridge/mem.h340
-rw-r--r--arch/arm/plat-omap/include/dspbridge/memdefs.h52
-rw-r--r--arch/arm/plat-omap/include/dspbridge/mgr.h234
-rw-r--r--arch/arm/plat-omap/include/dspbridge/mgrpriv.h55
-rw-r--r--arch/arm/plat-omap/include/dspbridge/msg.h106
-rw-r--r--arch/arm/plat-omap/include/dspbridge/msgdefs.h43
-rw-r--r--arch/arm/plat-omap/include/dspbridge/nldr.h81
-rw-r--r--arch/arm/plat-omap/include/dspbridge/nldrdefs.h307
-rw-r--r--arch/arm/plat-omap/include/dspbridge/node.h619
-rw-r--r--arch/arm/plat-omap/include/dspbridge/nodedefs.h40
-rw-r--r--arch/arm/plat-omap/include/dspbridge/nodepriv.h202
-rw-r--r--arch/arm/plat-omap/include/dspbridge/ntfy.h146
-rw-r--r--arch/arm/plat-omap/include/dspbridge/proc.h648
-rw-r--r--arch/arm/plat-omap/include/dspbridge/procpriv.h35
-rw-r--r--arch/arm/plat-omap/include/dspbridge/pwr.h129
-rw-r--r--arch/arm/plat-omap/include/dspbridge/pwr_sh.h41
-rw-r--r--arch/arm/plat-omap/include/dspbridge/reg.h257
-rw-r--r--arch/arm/plat-omap/include/dspbridge/resourcecleanup.h88
-rw-r--r--arch/arm/plat-omap/include/dspbridge/rmm.h199
-rw-r--r--arch/arm/plat-omap/include/dspbridge/rms_sh.h125
-rw-r--r--arch/arm/plat-omap/include/dspbridge/rmstypes.h40
-rw-r--r--arch/arm/plat-omap/include/dspbridge/services.h63
-rw-r--r--arch/arm/plat-omap/include/dspbridge/std.h143
-rw-r--r--arch/arm/plat-omap/include/dspbridge/strm.h441
-rw-r--r--arch/arm/plat-omap/include/dspbridge/strmdefs.h57
-rw-r--r--arch/arm/plat-omap/include/dspbridge/sync.h340
-rw-r--r--arch/arm/plat-omap/include/dspbridge/util.h122
-rw-r--r--arch/arm/plat-omap/include/dspbridge/utildefs.h51
-rw-r--r--arch/arm/plat-omap/include/dspbridge/uuidutil.h74
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wcd.h61
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wcdioctl.h519
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmd.h1193
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmdchnl.h90
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmddeh.h66
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmdio.h53
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmdioctl.h91
-rw-r--r--arch/arm/plat-omap/include/dspbridge/wmdmsg.h70
-rw-r--r--arch/arm/plat-omap/include/mach/clock.h5
-rw-r--r--arch/arm/plat-omap/include/mach/clockdomain.h6
-rw-r--r--arch/arm/plat-omap/include/mach/common.h1
-rw-r--r--arch/arm/plat-omap/include/mach/control.h3
-rw-r--r--arch/arm/plat-omap/include/mach/cpu.h4
-rw-r--r--arch/arm/plat-omap/include/mach/display.h600
-rwxr-xr-xarch/arm/plat-omap/include/mach/dma.h143
-rw-r--r--arch/arm/plat-omap/include/mach/irqs.h18
-rw-r--r--arch/arm/plat-omap/include/mach/mailbox.h21
-rw-r--r--arch/arm/plat-omap/include/mach/mcbsp.h8
-rw-r--r--arch/arm/plat-omap/include/mach/mcspi.h16
-rw-r--r--arch/arm/plat-omap/include/mach/mmc.h9
-rw-r--r--arch/arm/plat-omap/include/mach/mux.h85
-rw-r--r--arch/arm/plat-omap/include/mach/omap-serial.h156
-rw-r--r--arch/arm/plat-omap/include/mach/omap44xx.h10
-rw-r--r--arch/arm/plat-omap/include/mach/powerdomain.h10
-rw-r--r--arch/arm/plat-omap/include/mach/vram.h34
-rw-r--r--arch/arm/plat-omap/include/mach/vrfb.h51
-rwxr-xr-xarch/arm/plat-omap/include/syslink/GlobalTypes.h154
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MBXAccInt.h550
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MBXRegAcM.h3027
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MLBAccInt.h132
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MLBRegAcM.h206
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MMUAccInt.h179
-rwxr-xr-xarch/arm/plat-omap/include/syslink/MMURegAcM.h427
-rw-r--r--arch/arm/plat-omap/include/syslink/_sysmgr.h50
-rwxr-xr-xarch/arm/plat-omap/include/syslink/atomic_linux.h105
-rw-r--r--arch/arm/plat-omap/include/syslink/ducatienabler.h291
-rw-r--r--arch/arm/plat-omap/include/syslink/gate_remote.h34
-rwxr-xr-xarch/arm/plat-omap/include/syslink/gatepeterson.h167
-rwxr-xr-xarch/arm/plat-omap/include/syslink/gatepeterson_ioctl.h193
-rw-r--r--arch/arm/plat-omap/include/syslink/gt.h320
-rwxr-xr-xarch/arm/plat-omap/include/syslink/heap.h91
-rwxr-xr-xarch/arm/plat-omap/include/syslink/heapbuf.h152
-rwxr-xr-xarch/arm/plat-omap/include/syslink/heapbuf_ioctl.h215
-rwxr-xr-xarch/arm/plat-omap/include/syslink/host_os.h72
-rwxr-xr-xarch/arm/plat-omap/include/syslink/hw_defs.h63
-rwxr-xr-xarch/arm/plat-omap/include/syslink/hw_mbox.h447
-rwxr-xr-xarch/arm/plat-omap/include/syslink/hw_mmu.h169
-rwxr-xr-xarch/arm/plat-omap/include/syslink/hw_ocp.h60
-rwxr-xr-xarch/arm/plat-omap/include/syslink/ipc_ioctl.h92
-rw-r--r--arch/arm/plat-omap/include/syslink/listmp.h267
-rw-r--r--arch/arm/plat-omap/include/syslink/listmp_sharedmemory.h289
-rw-r--r--arch/arm/plat-omap/include/syslink/listmp_sharedmemory_ioctl.h258
-rw-r--r--arch/arm/plat-omap/include/syslink/messageq.h464
-rw-r--r--arch/arm/plat-omap/include/syslink/messageq_ioctl.h237
-rw-r--r--arch/arm/plat-omap/include/syslink/messageq_transportshm.h283
-rw-r--r--arch/arm/plat-omap/include/syslink/messageq_transportshm_ioctl.h160
-rwxr-xr-xarch/arm/plat-omap/include/syslink/multiproc.h83
-rwxr-xr-xarch/arm/plat-omap/include/syslink/multiproc_ioctl.h94
-rw-r--r--arch/arm/plat-omap/include/syslink/nameserver.h131
-rw-r--r--arch/arm/plat-omap/include/syslink/nameserver_ioctl.h230
-rwxr-xr-xarch/arm/plat-omap/include/syslink/nameserver_remote.h39
-rwxr-xr-xarch/arm/plat-omap/include/syslink/nameserver_remotenotify.h100
-rwxr-xr-xarch/arm/plat-omap/include/syslink/nameserver_remotenotify_ioctl.h163
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify.h267
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_dispatcher.h158
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_driver.h44
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_driverdefs.h440
-rw-r--r--arch/arm/plat-omap/include/syslink/notify_ducatidriver.h200
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_ducatidriver_defs.h152
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_shmdriver.h108
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notify_tesladriver.h219
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notifydefs.h25
-rwxr-xr-xarch/arm/plat-omap/include/syslink/notifyerr.h198
-rw-r--r--arch/arm/plat-omap/include/syslink/platform.h45
-rwxr-xr-xarch/arm/plat-omap/include/syslink/platform_mem.h137
-rwxr-xr-xarch/arm/plat-omap/include/syslink/procmgr.h280
-rwxr-xr-xarch/arm/plat-omap/include/syslink/sharedregion.h110
-rwxr-xr-xarch/arm/plat-omap/include/syslink/sharedregion_ioctl.h181
-rw-r--r--arch/arm/plat-omap/include/syslink/sysmemmgr.h179
-rw-r--r--arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h130
-rw-r--r--arch/arm/plat-omap/include/syslink/sysmgr.h182
-rw-r--r--arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h100
-rw-r--r--arch/arm/plat-omap/iommu.c12
-rw-r--r--arch/arm/plat-omap/mailbox.c246
-rw-r--r--arch/arm/plat-omap/mcbsp.c30
-rw-r--r--arch/arm/plat-omap/mux.c3
-rw-r--r--arch/arm/plat-omap/vram.c632
-rw-r--r--arch/arm/plat-omap/vrfb.c282
-rw-r--r--drivers/Makefile8
-rw-r--r--drivers/dsp/bridge/Kbuild39
-rw-r--r--drivers/dsp/bridge/Kconfig37
-rw-r--r--drivers/dsp/bridge/dynload/cload.c1854
-rw-r--r--drivers/dsp/bridge/dynload/dlclasses_hdr.h41
-rw-r--r--drivers/dsp/bridge/dynload/dload_internal.h237
-rw-r--r--drivers/dsp/bridge/dynload/doff.h347
-rw-r--r--drivers/dsp/bridge/dynload/getsection.c412
-rw-r--r--drivers/dsp/bridge/dynload/header.h59
-rw-r--r--drivers/dsp/bridge/dynload/module_list.h161
-rw-r--r--drivers/dsp/bridge/dynload/params.h231
-rw-r--r--drivers/dsp/bridge/dynload/reloc.c425
-rw-r--r--drivers/dsp/bridge/dynload/reloc_table.h102
-rw-r--r--drivers/dsp/bridge/dynload/reloc_table_c6000.c258
-rw-r--r--drivers/dsp/bridge/gen/_gt_para.c107
-rw-r--r--drivers/dsp/bridge/gen/gb.c182
-rw-r--r--drivers/dsp/bridge/gen/gh.c191
-rw-r--r--drivers/dsp/bridge/gen/gs.c108
-rw-r--r--drivers/dsp/bridge/gen/gt.c348
-rw-r--r--drivers/dsp/bridge/gen/uuidutil.c238
-rw-r--r--drivers/dsp/bridge/hw/EasiGlobal.h42
-rw-r--r--drivers/dsp/bridge/hw/GlobalTypes.h325
-rw-r--r--drivers/dsp/bridge/hw/IPIAccInt.h41
-rw-r--r--drivers/dsp/bridge/hw/IVA2RegAcM.h28
-rw-r--r--drivers/dsp/bridge/hw/MLBAccInt.h132
-rw-r--r--drivers/dsp/bridge/hw/MLBRegAcM.h201
-rw-r--r--drivers/dsp/bridge/hw/MMUAccInt.h76
-rw-r--r--drivers/dsp/bridge/hw/MMURegAcM.h253
-rw-r--r--drivers/dsp/bridge/hw/PRCMAccInt.h463
-rw-r--r--drivers/dsp/bridge/hw/PRCMRegAcM.h1187
-rw-r--r--drivers/dsp/bridge/hw/hw_defs.h73
-rw-r--r--drivers/dsp/bridge/hw/hw_dspssC64P.c56
-rw-r--r--drivers/dsp/bridge/hw/hw_dspssC64P.h48
-rw-r--r--drivers/dsp/bridge/hw/hw_mbox.c245
-rw-r--r--drivers/dsp/bridge/hw/hw_mbox.h323
-rw-r--r--drivers/dsp/bridge/hw/hw_mmu.c599
-rw-r--r--drivers/dsp/bridge/hw/hw_mmu.h177
-rw-r--r--drivers/dsp/bridge/hw/hw_prcm.c368
-rw-r--r--drivers/dsp/bridge/hw/hw_prcm.h284
-rw-r--r--drivers/dsp/bridge/pmgr/chnl.c260
-rw-r--r--drivers/dsp/bridge/pmgr/chnlobj.h71
-rw-r--r--drivers/dsp/bridge/pmgr/cmm.c1291
-rw-r--r--drivers/dsp/bridge/pmgr/cod.c683
-rw-r--r--drivers/dsp/bridge/pmgr/dbl.c1385
-rw-r--r--drivers/dsp/bridge/pmgr/dbll.c1587
-rw-r--r--drivers/dsp/bridge/pmgr/dev.c1476
-rw-r--r--drivers/dsp/bridge/pmgr/dmm.c692
-rw-r--r--drivers/dsp/bridge/pmgr/io.c205
-rw-r--r--drivers/dsp/bridge/pmgr/ioobj.h52
-rw-r--r--drivers/dsp/bridge/pmgr/msg.c173
-rw-r--r--drivers/dsp/bridge/pmgr/msgobj.h52
-rw-r--r--drivers/dsp/bridge/pmgr/wcd.c1651
-rw-r--r--drivers/dsp/bridge/rmgr/dbdcd.c1573
-rw-r--r--drivers/dsp/bridge/rmgr/disp.c916
-rwxr-xr-xdrivers/dsp/bridge/rmgr/drv.c1936
-rw-r--r--drivers/dsp/bridge/rmgr/drv_interface.c760
-rw-r--r--drivers/dsp/bridge/rmgr/drv_interface.h40
-rw-r--r--drivers/dsp/bridge/rmgr/dspdrv.c276
-rw-r--r--drivers/dsp/bridge/rmgr/mgr.c491
-rw-r--r--drivers/dsp/bridge/rmgr/nldr.c1967
-rw-r--r--drivers/dsp/bridge/rmgr/node.c3550
-rwxr-xr-xdrivers/dsp/bridge/rmgr/proc.c2111
-rw-r--r--drivers/dsp/bridge/rmgr/pwr.c184
-rw-r--r--drivers/dsp/bridge/rmgr/rmm.c604
-rw-r--r--drivers/dsp/bridge/rmgr/strm.c1066
-rw-r--r--drivers/dsp/bridge/services/cfg.c483
-rw-r--r--drivers/dsp/bridge/services/clk.c375
-rw-r--r--drivers/dsp/bridge/services/csl.c173
-rw-r--r--drivers/dsp/bridge/services/dbg.c119
-rw-r--r--drivers/dsp/bridge/services/dpc.c274
-rw-r--r--drivers/dsp/bridge/services/kfile.c338
-rw-r--r--drivers/dsp/bridge/services/list.c285
-rw-r--r--drivers/dsp/bridge/services/mem.c599
-rw-r--r--drivers/dsp/bridge/services/ntfy.c329
-rw-r--r--drivers/dsp/bridge/services/reg.c196
-rw-r--r--drivers/dsp/bridge/services/regsup.c368
-rw-r--r--drivers/dsp/bridge/services/regsup.h58
-rw-r--r--drivers/dsp/bridge/services/services.c206
-rw-r--r--drivers/dsp/bridge/services/sync.c602
-rw-r--r--drivers/dsp/bridge/wmd/_cmm.h59
-rw-r--r--drivers/dsp/bridge/wmd/_deh.h47
-rw-r--r--drivers/dsp/bridge/wmd/_msg_sm.h158
-rw-r--r--drivers/dsp/bridge/wmd/_tiomap.h418
-rw-r--r--drivers/dsp/bridge/wmd/_tiomap_mmu.h53
-rw-r--r--drivers/dsp/bridge/wmd/_tiomap_pwr.h102
-rw-r--r--drivers/dsp/bridge/wmd/_tiomap_util.h46
-rw-r--r--drivers/dsp/bridge/wmd/chnl_sm.c1100
-rwxr-xr-xdrivers/dsp/bridge/wmd/io_sm.c2136
-rw-r--r--drivers/dsp/bridge/wmd/mmu_fault.c172
-rw-r--r--drivers/dsp/bridge/wmd/mmu_fault.h45
-rw-r--r--drivers/dsp/bridge/wmd/msg_sm.c643
-rw-r--r--drivers/dsp/bridge/wmd/tiomap3430.c2238
-rw-r--r--drivers/dsp/bridge/wmd/tiomap3430_pwr.c738
-rwxr-xr-xdrivers/dsp/bridge/wmd/tiomap_io.c434
-rw-r--r--drivers/dsp/bridge/wmd/tiomap_io.h112
-rw-r--r--drivers/dsp/bridge/wmd/tiomap_sm.c257
-rw-r--r--drivers/dsp/bridge/wmd/ue_deh.c385
-rwxr-xr-xdrivers/dsp/syslink/Kconfig60
-rw-r--r--drivers/dsp/syslink/multicore_ipc/Kbuild25
-rw-r--r--drivers/dsp/syslink/multicore_ipc/_listmp.h48
-rw-r--r--drivers/dsp/syslink/multicore_ipc/gate_remote.c40
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/gatepeterson.c961
-rw-r--r--drivers/dsp/syslink/multicore_ipc/gatepeterson_ioctl.c386
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/heap.c101
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/heapbuf.c1171
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/heapbuf_ioctl.c479
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/ipc_drv.c242
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/ipc_ioctl.c80
-rw-r--r--drivers/dsp/syslink/multicore_ipc/listmp.c440
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/listmp_sharedmemory.c1473
-rw-r--r--drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c689
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/messageq.c1575
-rw-r--r--drivers/dsp/syslink/multicore_ipc/messageq_ioctl.c484
-rw-r--r--drivers/dsp/syslink/multicore_ipc/messageq_transportshm.c778
-rw-r--r--drivers/dsp/syslink/multicore_ipc/messageq_transportshm_ioctl.c330
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/multiproc.c242
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/multiproc_ioctl.c164
-rw-r--r--drivers/dsp/syslink/multicore_ipc/nameserver.c1003
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/nameserver_ioctl.c592
-rw-r--r--drivers/dsp/syslink/multicore_ipc/nameserver_remote.c49
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/nameserver_remotenotify.c713
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/nameserver_remotenotify_ioctl.c339
-rw-r--r--drivers/dsp/syslink/multicore_ipc/platform.c1420
-rw-r--r--drivers/dsp/syslink/multicore_ipc/platform_mem.c288
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/platformcfg.c91
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/sharedregion.c775
-rwxr-xr-xdrivers/dsp/syslink/multicore_ipc/sharedregion_ioctl.c349
-rw-r--r--drivers/dsp/syslink/multicore_ipc/sysmemmgr.c459
-rw-r--r--drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c223
-rw-r--r--drivers/dsp/syslink/multicore_ipc/sysmgr.c815
-rw-r--r--drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c143
-rw-r--r--drivers/dsp/syslink/notify_dispatcher/Kbuild19
-rw-r--r--drivers/dsp/syslink/notify_dispatcher/hw_mbox.c374
-rw-r--r--drivers/dsp/syslink/notify_dispatcher/hw_ocp.c85
-rw-r--r--drivers/dsp/syslink/notify_dispatcher/notify_dispatcher.c448
-rw-r--r--drivers/dsp/syslink/notify_ducatidriver/Kbuild19
-rw-r--r--drivers/dsp/syslink/notify_ducatidriver/drv_ducati.c348
-rw-r--r--drivers/dsp/syslink/notify_ducatidriver/notify_ducati.c1249
-rw-r--r--drivers/dsp/syslink/notify_tesladriver/Kbuild18
-rwxr-xr-xdrivers/dsp/syslink/notify_tesladriver/drv_tesla.c79
-rw-r--r--drivers/dsp/syslink/notify_tesladriver/notify_tesla.c1108
-rwxr-xr-xdrivers/dsp/syslink/omap_notify/Kbuild19
-rwxr-xr-xdrivers/dsp/syslink/omap_notify/drv_notify.c918
-rwxr-xr-xdrivers/dsp/syslink/omap_notify/notify.c548
-rwxr-xr-xdrivers/dsp/syslink/omap_notify/notify_driver.c172
-rwxr-xr-xdrivers/dsp/syslink/procmgr/Kbuild10
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/Kbuild10
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/dmm4430.c355
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/dmm4430.h50
-rw-r--r--drivers/dsp/syslink/procmgr/proc4430/ducatienabler.c1332
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/hw_mmu.c643
-rw-r--r--drivers/dsp/syslink/procmgr/proc4430/proc4430.c1021
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/proc4430.h147
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/proc4430_drv.c400
-rwxr-xr-xdrivers/dsp/syslink/procmgr/proc4430/proc4430_drvdefs.h169
-rwxr-xr-xdrivers/dsp/syslink/procmgr/procdefs.h203
-rwxr-xr-xdrivers/dsp/syslink/procmgr/processor.c398
-rwxr-xr-xdrivers/dsp/syslink/procmgr/processor.h84
-rwxr-xr-xdrivers/dsp/syslink/procmgr/procmgr.c957
-rwxr-xr-xdrivers/dsp/syslink/procmgr/procmgr_drv.c757
-rwxr-xr-xdrivers/dsp/syslink/procmgr/procmgr_drvdefs.h541
-rw-r--r--drivers/gpio/twl4030-gpio.c26
-rw-r--r--drivers/i2c/busses/i2c-omap.c73
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/omap-keypad.c111
-rw-r--r--drivers/media/Kconfig2
-rw-r--r--drivers/media/video/Kconfig12
-rw-r--r--drivers/media/video/Makefile2
-rw-r--r--drivers/media/video/omap/Kconfig27
-rw-r--r--drivers/media/video/omap/Makefile3
-rw-r--r--drivers/media/video/omap/omap_vout.c3078
-rw-r--r--drivers/media/video/omap/omap_voutdef.h160
-rw-r--r--drivers/media/video/omap/omap_voutlib.c257
-rw-r--r--drivers/media/video/omap/omap_voutlib.h34
-rwxr-xr-xdrivers/media/video/tiler/dmm_hl_drv.c1
-rw-r--r--drivers/media/video/v4l2-common.c9
-rw-r--r--drivers/media/video/v4l2-ioctl.c24
-rw-r--r--drivers/mfd/Kconfig21
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/twl-core.c (renamed from drivers/mfd/twl4030-core.c)372
-rw-r--r--drivers/mfd/twl4030-irq.c20
-rw-r--r--drivers/mfd/twl6030-gpadc.c444
-rw-r--r--drivers/mfd/twl6030-irq.c303
-rw-r--r--drivers/mmc/host/Kconfig6
-rw-r--r--drivers/mmc/host/omap_hsmmc.c203
-rw-r--r--drivers/power/twl6030_bci_battery.c570
-rw-r--r--drivers/regulator/Kconfig4
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/twl-regulator.c (renamed from drivers/regulator/twl4030-regulator.c)281
-rw-r--r--drivers/rtc/Kconfig8
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-twl.c (renamed from drivers/rtc/rtc-twl4030.c)149
-rw-r--r--drivers/serial/Kconfig117
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/omap-serial.c1728
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/omap2_mcspi.c433
-rw-r--r--drivers/usb/otg/twl4030-usb.c42
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/omap/Kconfig5
-rw-r--r--drivers/video/omap/blizzard.c2
-rw-r--r--drivers/video/omap/dispc.c52
-rw-r--r--drivers/video/omap/hwa742.c2
-rw-r--r--drivers/video/omap/lcd_4430sdp.c128
-rw-r--r--drivers/video/omap/lcd_h3.c2
-rw-r--r--drivers/video/omap/lcd_h4.c3
-rw-r--r--drivers/video/omap/lcd_inn1510.c2
-rw-r--r--drivers/video/omap/lcd_inn1610.c2
-rw-r--r--drivers/video/omap/lcd_osk.c2
-rw-r--r--drivers/video/omap/lcd_palmte.c2
-rw-r--r--drivers/video/omap/lcd_palmtt.c2
-rw-r--r--drivers/video/omap/lcd_palmz71.c3
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/rfbi.c3
-rw-r--r--drivers/video/omap/sossi.c2
-rw-r--r--drivers/video/omap2/Kconfig3
-rw-r--r--drivers/video/omap2/Makefile4
-rw-r--r--drivers/video/omap2/displays/Kconfig49
-rw-r--r--drivers/video/omap2/displays/Makefile11
-rw-r--r--drivers/video/omap2/displays/ctrl-blizzard.c279
-rw-r--r--drivers/video/omap2/displays/lcd_4430sdp.c126
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c712
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.h9
-rw-r--r--drivers/video/omap2/displays/panel-generic.c104
-rw-r--r--drivers/video/omap2/displays/panel-n800.c435
-rw-r--r--drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c113
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c153
-rw-r--r--drivers/video/omap2/displays/panel-taal.c905
-rw-r--r--drivers/video/omap2/dss/Kconfig90
-rw-r--r--drivers/video/omap2/dss/Makefile6
-rw-r--r--drivers/video/omap2/dss/core.c925
-rw-r--r--drivers/video/omap2/dss/dispc.c4131
-rw-r--r--drivers/video/omap2/dss/display.c668
-rw-r--r--drivers/video/omap2/dss/dpi.c407
-rw-r--r--drivers/video/omap2/dss/dsi.c3517
-rw-r--r--drivers/video/omap2/dss/dss.c373
-rw-r--r--drivers/video/omap2/dss/dss.h377
-rw-r--r--drivers/video/omap2/dss/manager.c1551
-rw-r--r--drivers/video/omap2/dss/overlay.c769
-rw-r--r--drivers/video/omap2/dss/rfbi.c1315
-rw-r--r--drivers/video/omap2/dss/sdi.c381
-rw-r--r--drivers/video/omap2/dss/venc.c782
-rw-r--r--drivers/video/omap2/omapfb/Kconfig35
-rw-r--r--drivers/video/omap2/omapfb/Makefile2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c709
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c2143
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c506
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h153
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/omap_wdt.c25
-rw-r--r--include/linux/i2c/twl.h (renamed from include/linux/i2c/twl4030.h)254
-rw-r--r--include/linux/i2c/twl6030-gpadc.h110
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/omapfb.h (renamed from arch/arm/plat-omap/include/mach/omapfb.h)53
-rw-r--r--include/linux/videodev2.h21
-rw-r--r--include/media/v4l2-ioctl.h5
-rw-r--r--include/sound/soc-dai.h1
-rw-r--r--kernel/irq/chip.c14
-rw-r--r--kernel/irq/manage.c49
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/abe-twl6030.c1377
-rw-r--r--sound/soc/codecs/abe-twl6030.h32
-rw-r--r--sound/soc/codecs/abe/C_ABE_FW.CM1638
-rw-r--r--sound/soc/codecs/abe/C_ABE_FW.PM2048
-rw-r--r--sound/soc/codecs/abe/C_ABE_FW.SM323712
-rw-r--r--sound/soc/codecs/abe/C_ABE_FW.lDM4096
-rw-r--r--sound/soc/codecs/abe/C_ABE_FW_SIZE.h14
-rw-r--r--sound/soc/codecs/abe/Makefile9
-rw-r--r--sound/soc/codecs/abe/abe_api.c2023
-rw-r--r--sound/soc/codecs/abe/abe_api.h1081
-rw-r--r--sound/soc/codecs/abe/abe_cm_addr.h320
-rw-r--r--sound/soc/codecs/abe/abe_cof.h9
-rw-r--r--sound/soc/codecs/abe/abe_dat.h1212
-rw-r--r--sound/soc/codecs/abe/abe_dbg.c99
-rw-r--r--sound/soc/codecs/abe/abe_dbg.h167
-rw-r--r--sound/soc/codecs/abe/abe_def.h450
-rw-r--r--sound/soc/codecs/abe/abe_define.h54
-rw-r--r--sound/soc/codecs/abe/abe_dm_addr.h234
-rw-r--r--sound/soc/codecs/abe/abe_ext.c118
-rw-r--r--sound/soc/codecs/abe/abe_ext.h34
-rw-r--r--sound/soc/codecs/abe/abe_functionsId.h75
-rw-r--r--sound/soc/codecs/abe/abe_fw.h479
-rw-r--r--sound/soc/codecs/abe/abe_ini.c674
-rw-r--r--sound/soc/codecs/abe/abe_initxxx_labels.h258
-rw-r--r--sound/soc/codecs/abe/abe_irq.c53
-rw-r--r--sound/soc/codecs/abe/abe_lib.c703
-rw-r--r--sound/soc/codecs/abe/abe_lib.h108
-rw-r--r--sound/soc/codecs/abe/abe_main.c95
-rw-r--r--sound/soc/codecs/abe/abe_main.h53
-rw-r--r--sound/soc/codecs/abe/abe_ref.h108
-rw-r--r--sound/soc/codecs/abe/abe_seq.c248
-rw-r--r--sound/soc/codecs/abe/abe_seq.h127
-rw-r--r--sound/soc/codecs/abe/abe_sm_addr.h398
-rw-r--r--sound/soc/codecs/abe/abe_sys.h9
-rw-r--r--sound/soc/codecs/abe/abe_taskId.h111
-rw-r--r--sound/soc/codecs/abe/abe_test.c104
-rw-r--r--sound/soc/codecs/abe/abe_test.h25
-rw-r--r--sound/soc/codecs/abe/abe_typ.h630
-rw-r--r--sound/soc/codecs/abe/abe_typedef.h354
-rw-r--r--sound/soc/codecs/abe/abehal.dsp246
-rw-r--r--sound/soc/codecs/abe/abehal.dsw33
-rw-r--r--sound/soc/codecs/twl4030.c18
-rw-r--r--sound/soc/codecs/twl6030.h138
-rw-r--r--sound/soc/omap/Kconfig18
-rw-r--r--sound/soc/omap/Makefile6
-rw-r--r--sound/soc/omap/mcpdm.c491
-rw-r--r--sound/soc/omap/mcpdm.h156
-rw-r--r--sound/soc/omap/omap-abe.c330
-rw-r--r--sound/soc/omap/omap-abe.h35
-rw-r--r--sound/soc/omap/omap-hdmi.c159
-rw-r--r--sound/soc/omap/omap-hdmi.h29
-rw-r--r--sound/soc/omap/omap-mcbsp.c4
-rw-r--r--sound/soc/omap/omap-mcpdm.c246
-rw-r--r--sound/soc/omap/omap-mcpdm.h29
-rw-r--r--sound/soc/omap/omap-pcm.c13
-rw-r--r--sound/soc/omap/omap-pcm.h3
-rw-r--r--sound/soc/omap/sdp4430.c278
551 files changed, 177156 insertions, 1709 deletions
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
new file mode 100644
index 000000000000..0af0e9eed5d6
--- /dev/null
+++ b/Documentation/arm/OMAP/DSS
@@ -0,0 +1,317 @@
+OMAP2/3 Display Subsystem
+-------------------------
+
+This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
+(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
+TV-out and multiple display support, but there are lots of small improvements
+also.
+
+The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
+panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
+currently side by side, you can choose which one to use.
+
+Features
+--------
+
+Working and tested features include:
+
+- MIPI DPI (parallel) output
+- MIPI DSI output in command mode
+- MIPI DBI (RFBI) output
+- SDI output
+- TV output
+- All pieces can be compiled as a module or inside kernel
+- Use DISPC to update any of the outputs
+- Use CPU to update RFBI or DSI output
+- OMAP DISPC planes
+- RGB16, RGB24 packed, RGB24 unpacked
+- YUV2, UYVY
+- Scaling
+- Adjusting DSS FCK to find a good pixel clock
+- Use DSI DPLL to create DSS FCK
+
+Tested boards include:
+- OMAP3 SDP board
+- Beagle board
+- N810
+
+omapdss driver
+--------------
+
+The DSS driver does not itself have any support for Linux framebuffer, V4L or
+such like the current ones, but it has an internal kernel API that upper level
+drivers can use.
+
+The DSS driver models OMAP's overlays, overlay managers and displays in a
+flexible way to enable non-common multi-display configuration. In addition to
+modelling the hardware overlays, omapdss supports virtual overlays and overlay
+managers. These can be used when updating a display with CPU or system DMA.
+
+Panel and controller drivers
+----------------------------
+
+The drivers implement panel or controller specific functionality and are not
+usually visible to users except through omapfb driver. They register
+themselves to the DSS driver.
+
+omapfb driver
+-------------
+
+The omapfb driver implements arbitrary number of standard linux framebuffers.
+These framebuffers can be routed flexibly to any overlays, thus allowing very
+dynamic display architecture.
+
+The driver exports some omapfb specific ioctls, which are compatible with the
+ioctls in the old driver.
+
+The rest of the non standard features are exported via sysfs. Whether the final
+implementation will use sysfs, or ioctls, is still open.
+
+V4L2 drivers
+------------
+
+V4L2 is being implemented in TI.
+
+From omapdss point of view the V4L2 drivers should be similar to framebuffer
+driver.
+
+Architecture
+--------------------
+
+Some clarification what the different components do:
+
+ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
+ pixel data for the image. Framebuffer has width and height and color
+ depth.
+ - Overlay defines where the pixels are read from and where they go on the
+ screen. The overlay may be smaller than framebuffer, thus displaying only
+ part of the framebuffer. The position of the overlay may be changed if
+ the overlay is smaller than the display.
+ - Overlay manager combines the overlays in to one image and feeds them to
+ display.
+ - Display is the actual physical display device.
+
+A framebuffer can be connected to multiple overlays to show the same pixel data
+on all of the overlays. Note that in this case the overlay input sizes must be
+the same, but, in case of video overlays, the output size can be different. Any
+framebuffer can be connected to any overlay.
+
+An overlay can be connected to one overlay manager. Also DISPC overlays can be
+connected only to DISPC overlay managers, and virtual overlays can be only
+connected to virtual overlays.
+
+An overlay manager can be connected to one display. There are certain
+restrictions which kinds of displays an overlay manager can be connected:
+
+ - DISPC TV overlay manager can be only connected to TV display.
+ - Virtual overlay managers can only be connected to DBI or DSI displays.
+ - DISPC LCD overlay manager can be connected to all displays, except TV
+ display.
+
+Sysfs
+-----
+The sysfs interface is mainly used for testing. I don't think sysfs
+interface is the best for this in the final version, but I don't quite know
+what would be the best interfaces for these things.
+
+The sysfs interface is divided to two parts: DSS and FB.
+
+/sys/class/graphics/fb? directory:
+mirror 0=off, 1=on
+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
+rotate_type 0 = DMA rotation, 1 = VRFB rotation
+overlays List of overlay numbers to which framebuffer pixels go
+phys_addr Physical address of the framebuffer
+virt_addr Virtual address of the framebuffer
+size Size of the framebuffer
+
+/sys/devices/platform/omapdss/overlay? directory:
+enabled 0=off, 1=on
+input_size width,height (ie. the framebuffer size)
+manager Destination overlay manager name
+name
+output_size width,height
+position x,y
+screen_width width
+global_alpha global alpha 0-255 0=transparent 255=opaque
+
+/sys/devices/platform/omapdss/manager? directory:
+display Destination display
+name
+alpha_blending_enabled 0=off, 1=on
+trans_key_enabled 0=off, 1=on
+trans_key_type gfx-destination, video-source
+trans_key_value transparency color key (RGB24)
+default_color default background color (RGB24)
+
+/sys/devices/platform/omapdss/display? directory:
+ctrl_name Controller name
+mirror 0=off, 1=on
+update_mode 0=off, 1=auto, 2=manual
+enabled 0=off, 1=on
+name
+rotate Rotation 0-3 for 0, 90, 180, 270 degrees
+timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
+ When writing, two special timings are accepted for tv-out:
+ "pal" and "ntsc"
+panel_name
+tear_elim Tearing elimination 0=off, 1=on
+
+There are also some debugfs files at <debugfs>/omapdss/ which show information
+about clocks and registers.
+
+Examples
+--------
+
+The following definitions have been made for the examples below:
+
+ovl0=/sys/devices/platform/omapdss/overlay0
+ovl1=/sys/devices/platform/omapdss/overlay1
+ovl2=/sys/devices/platform/omapdss/overlay2
+
+mgr0=/sys/devices/platform/omapdss/manager0
+mgr1=/sys/devices/platform/omapdss/manager1
+
+lcd=/sys/devices/platform/omapdss/display0
+dvi=/sys/devices/platform/omapdss/display1
+tv=/sys/devices/platform/omapdss/display2
+
+fb0=/sys/class/graphics/fb0
+fb1=/sys/class/graphics/fb1
+fb2=/sys/class/graphics/fb2
+
+Default setup on OMAP3 SDP
+--------------------------
+
+Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
+and TV-out are not in use. The columns from left to right are:
+framebuffers, overlays, overlay managers, displays. Framebuffers are
+handled by omapfb, and the rest by the DSS.
+
+FB0 --- GFX -\ DVI
+FB1 --- VID1 --+- LCD ---- LCD
+FB2 --- VID2 -/ TV ----- TV
+
+Example: Switch from LCD to DVI
+----------------------
+
+w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
+h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
+
+echo "0" > $lcd/enabled
+echo "" > $mgr0/display
+fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
+# at this point you have to switch the dvi/lcd dip-switch from the omap board
+echo "dvi" > $mgr0/display
+echo "1" > $dvi/enabled
+
+After this the configuration looks like:
+
+FB0 --- GFX -\ -- DVI
+FB1 --- VID1 --+- LCD -/ LCD
+FB2 --- VID2 -/ TV ----- TV
+
+Example: Clone GFX overlay to LCD and TV
+-------------------------------
+
+w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
+h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
+
+echo "0" > $ovl0/enabled
+echo "0" > $ovl1/enabled
+
+echo "" > $fb1/overlays
+echo "0,1" > $fb0/overlays
+
+echo "$w,$h" > $ovl1/output_size
+echo "tv" > $ovl1/manager
+
+echo "1" > $ovl0/enabled
+echo "1" > $ovl1/enabled
+
+echo "1" > $tv/enabled
+
+After this the configuration looks like (only relevant parts shown):
+
+FB0 +-- GFX ---- LCD ---- LCD
+ \- VID1 ---- TV ---- TV
+
+Misc notes
+----------
+
+OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
+
+Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
+of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
+
+Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
+does not support mirroring.
+
+VRFB rotation requires much more memory than non-rotated framebuffer, so you
+probably need to increase your vram setting before using VRFB rotation. Also,
+many applications may not work with VRFB if they do not pay attention to all
+framebuffer parameters.
+
+Kernel boot arguments
+---------------------
+
+vram=<size>
+ - Amount of total VRAM to preallocate. For example, "10M". omapfb
+ allocates memory for framebuffers from VRAM.
+
+omapfb.mode=<display>:<mode>[,...]
+ - Default video mode for specified displays. For example,
+ "dvi:800x400MR-24@60". See drivers/video/modedb.c.
+ There are also two special modes: "pal" and "ntsc" that
+ can be used to tv out.
+
+omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
+ - VRAM allocated for a framebuffer. Normally omapfb allocates vram
+ depending on the display size. With this you can manually allocate
+ more or define the physical address of each framebuffer. For example,
+ "1:4M" to allocate 4M for fb1.
+
+omapfb.debug=<y|n>
+ - Enable debug printing. You have to have OMAPFB debug support enabled
+ in kernel config.
+
+omapfb.test=<y|n>
+ - Draw test pattern to framebuffer whenever framebuffer settings change.
+ You need to have OMAPFB debug support enabled in kernel config.
+
+omapfb.vrfb=<y|n>
+ - Use VRFB rotation for all framebuffers.
+
+omapfb.rotate=<angle>
+ - Default rotation applied to all framebuffers.
+ 0 - 0 degree rotation
+ 1 - 90 degree rotation
+ 2 - 180 degree rotation
+ 3 - 270 degree rotation
+
+omapfb.mirror=<y|n>
+ - Default mirror for all framebuffers. Only works with DMA rotation.
+
+omapdss.def_disp=<display>
+ - Name of default display, to which all overlays will be connected.
+ Common examples are "lcd" or "tv".
+
+omapdss.debug=<y|n>
+ - Enable debug printing. You have to have DSS debug support enabled in
+ kernel config.
+
+TODO
+----
+
+DSS locking
+
+Error checking
+- Lots of checks are missing or implemented just as BUG()
+
+System DMA update for DSI
+- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
+ to skip the empty byte?)
+
+OMAP1 support
+- Not sure if needed
+
diff --git a/TI_OMAP4_Kernel_Release_Notes_L24.x.txt b/TI_OMAP4_Kernel_Release_Notes_L24.x.txt
new file mode 100755
index 000000000000..2ed20a7e19e6
--- /dev/null
+++ b/TI_OMAP4_Kernel_Release_Notes_L24.x.txt
@@ -0,0 +1,479 @@
+Release notes for the Linux kernel for L24.0.13
+----------------------------------------------
+
+22 October 2009
+
+Copyright (C) 2009 Texas Instruments Incorporated. All rights reserved.
+
+
+1. Introduction
+----------------
+This document accompanies OMAP(TM) Software Release L24.0.13 for Linux 2.6.31
+on OMAP4430 VPOM4430_1.09a_Patch33. The document specifies:
+ - Instructions for unpacking the release
+ - New features and features the release supports
+ - Planned future features
+ - Postponed features
+
+
+2. Release Summary
+------------------
+This is a Linux Baseport Release for SDP4430 on Virtio.
+The kernel is based on Linux-omap version 2.6.31 from open source.
+U-boot is based on open-source version 1.1.4.
+
+The u-boot source can be obtained via GIT from:
+ http://git.omapzoom.org/?p=repo/u-boot.git;a=shortlog;h=refs/heads/omap4_dev
+
+The kernel source can be obtained via GIT from:
+ http://dev.omapzoom.org/?p=integration/kernel-omap4.git;a=summary
+ L24.0.13 branch
+Virtio version used: VPOM4430_1.09a + VPOM4430_1.09a_Patch33.var
+
+All drivers planned for this release are working as expected and
+overall platform stability is good.
+
+Current L24.0.13 support:
+ UART with DMA support,SMP OS Kernel boot-up on with UART, GPTimers, McBSP,
+ McSPI, I2c, GPIO, WATCHDOG, Keypad, Phoenix PM IC, RTC, ALSA AUDIO, Neon,
+ PM - Clock framework, Clock Domain framework, Power Domain framework,
+ Shared Resource Framework, Tick suppression.
+ U-boot USB support.
+Code has been added for following drivers, but cannot be tested on Virtio:
+ Phoenix - General Purpose ADC, Battery charging.
+
+3. Instructions
+----------------
+
+3.1 Virtio Setup
+
+This release works on VPOM4430_1.09a_Patch33.
+
+
+3.2 Virtio Installation Instructions
+
+a. Install to C:\Virtio
+b. Once installation for virtio is started, you will be prompted for
+ installation
+ for virtual serial port. Say yes to it and give a port number (say 5 or 6).
+ Multiple serial ports can also be installed.
+c. Install C:\Virtio\Shared\Disassembler\Setup\VirtioDisassembler.exe.
+ This is to enable debugging using virtio.
+d. License for virtio has to be set in the environment variables
+ LM_LICENSE_FILE.
+e. Install VPOM4430_1.09a_Patch33.
+
+
+3.3 Virtio Configuration Instructions
+
+Run virtio and if modify the following parameters
+
+a. On some versions SSM is generating error due to illegal instruction fetch.
+ To workaround this you can disable SsmDisableSecurity user parameter.
+ Params->User Parameters-> SsmDisableSecurity = yes
+ Right click on SsmDisableSecurity parameter and change properties to editable
+ mode. Then you can set this parameter to Yes. Default value is no.
+b. If IVAHD is enabled the image boot up takes lot of time. If IVAHD component
+ is not required it can be disabled.
+ Browse to VPOM4430::SDP::OMAP4430::TIOMAP4CORES and disable all the enabled
+ components under it
+c. Open the Params tab and look at the User Parameters. Set the UARTx_COM_PORT
+ to the virtual port number you had provided while installation.
+d. Both CPU cores support has been enabled.
+e. L2 Cache is not enabled in software. This requires the cache to be turned
+ off in the Virtio parameter list too. For this browse to
+ VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1 and set the CacheDisabled parameter
+ to true. Browse to VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_2 and set the
+ CacheDisabled parameter to true.Also browse to
+ VPOM4430::SDP::OMAP4430::CPU_SS::pl310_cache and set the CacheDisabled
+ parameter to true.
+f. Once booted with two CPU, you can see two penguins on LCD instead on one.
+ Linux kernel shows one penguin per CPU.
+
+3.4 Compiling U-Boot
+
+Set the environment variable PATH such that cross compile binaries point to the
+needed tool chain. Refer to section 5 for tool chain information.
+
+To select the default configuration for U-Boot type:
+ # make CROSS_COMPILE=arm-none-linux-gnueabi- omap4430sdp_config
+
+To build the U-Boot image type:
+ # make CROSS_COMPILE=arm-none-linux-gnueabi-
+
+3.5 Compiling X-Loader
+
+Not yet supported
+
+3.6 Compiling the Kernel
+
+Set the environment variable PATH such that cross-compile binaries point to the
+needed tool chain. Refer to section 5 for tool chain information.
+
+The default configuration file for Virtio4430 is present at
+arch/arm/configs/omap_4430sdp_defconfig.
+
+To work with the default configuration file, run following commands:
+ # make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
+ omap_4430sdp_defconfig
+
+Build kernel with:
+ # make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
+
+NOTE: The above steps will create arch/arm/boot/uImage in the kernel directory
+ which is the binary used for booting.
+
+Filesystem:
+NFS file system is not yet supported. Use ramdisk instead.
+The default configuration for ramdisk is in the 4430 defconfig.
+ Load address = 0x81600000
+ Default size = 20MB
+
+
+3.7 Running U-Boot boot loader on RAM
+
+Go to the design tab. Open Scripts-> configs/Native Apps/Native Apps.script.
+Replace it as shown below.
+Then launch HyperTerminal and connect to the virtual serial port installed.
+(e.g. COM5).
+Now choose Native Apps in the configuration tabs at the top and select run.
+The SDP4430 U-Boot prompt will appear in your terminal emulation program.
+
+----------------------- [start of Native Apps.script]--------------------------
+
+[VPOM4430::SDP::OMAP4430::L3FW_GPMC] bypass on
+[VPOM4430::SDP::OMAP4430::L3FW_EMIF] bypass on
+g #10
+
+cc VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1
+
+# Configure DMM to allow SDRAM accesses during ELF load.
+# DMM_LISA_MAP[0]: 0x80000000 mapped to 0x0 on SDRC0 (128MiB, no interleaving)
+d 0x4E000100=0x80301000
+
+#load up the u-boot,kernel and file system
+[VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1]l 0x80300000 -bin <uImage PATH>
+[VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1]l 0x81600000 -bin <ramfs PATH>
+[VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1]l 0x88e80000 -bin <u-boot.bin PATH>
+
+
+# PRCM setup
+# WKUP Domain
+dp 0x4a307800 = 0x3
+dp 0x4a307830 = 0x2
+dp 0x4a307838 = 0x102
+dp 0x4a307840 = 0x01000002
+dp 0x4a307858 = 0x2
+dp 0x4a307878 = 0x2
+dp 0x4a307880 = 0x1
+
+# ABE Domain
+dp 0x4A004500 = 0x3
+dp 0x4A004528 = 0x2
+dp 0x4A004530 = 0x2
+dp 0x4A004538 = 0x2
+dp 0x4A004540 = 0x2
+dp 0x4A004548 = 0x2
+dp 0x4A004550 = 0x2
+dp 0x4A004558 = 0x2
+dp 0x4A004560 = 0xf02
+dp 0x4A004568 = 0x2
+dp 0x4A004570 = 0x2
+dp 0x4A004578 = 0x2
+dp 0x4A004580 = 0x2
+dp 0x4A004588 = 0x2
+
+# CORE Domain
+# WakeUp Module domains
+dp 0x4A008900 = 0x2
+dp 0x4A008a00 = 0x2
+dp 0x4A008b00 = 0x2
+dp 0x4A008c00 = 0x2
+dp 0x4A008900 = 0x3
+
+# SDMA No Sleep!!
+dp 0x4A008a00 = 0x0
+dp 0x4A008b00 = 0x3
+dp 0x4A008c00 = 0x3
+dp 0x4A008828 = 0x1
+dp 0x4A008920 = 0x1
+
+# IVAHD Domain
+dp 0x4A008F00 = 0x2
+dp 0x4A008F00 = 0x3
+dp 0x4A008F20 = 0x1
+dp 0x4A008F28 = 0x1
+
+# CAM Domain
+dp 0x4A009000 = 0x2
+dp 0x4A009000 = 0x3
+dp 0x4A009020 = 0x102
+dp 0x4A009028 = 0x2
+
+# DSS Domain
+dp 0x4A009100 = 0x2
+dp 0x4A009100 = 0x3
+dp 0x4A009120 = 0xf02
+dp 0x4A009128 = 0x2
+
+# GFX Domain
+dp 0x4A009200 = 0x2
+dp 0x4A009200 = 0x3
+dp 0x4A009220 = 0x2
+
+# L3INT Domain
+dp 0x4A009300 = 0x3
+dp 0x4A009328 = 0x2
+dp 0x4A009330 = 0x2
+dp 0x4A009338 = 0x2
+dp 0x4A009340 = 0x102
+dp 0x4A009358 = 0xff02
+dp 0x4A009360 = 0x102
+dp 0x4A009368 = 0x712
+dp 0x4A009380 = 0x2
+dp 0x4A009388 = 0x2
+dp 0x4A009390 = 0x2
+dp 0x4A009398 = 0x2
+dp 0x4A0093A8 = 0x2
+dp 0x4A0093C0 = 0x2
+dp 0x4A0093C8 = 0x2
+dp 0x4A0093D0 = 0x2
+dp 0x4A0093E0 = 0x2
+
+# L4PER Domain
+dp 0x4A009400 = 0x2
+dp 0x4A009580 = 0x2
+dp 0x4A009400 = 0x3
+dp 0x4A009580 = 0x3
+dp 0x4A009420 = 0x2
+dp 0x4A009428 = 0x2
+dp 0x4A009430 = 0x2
+dp 0x4A009438 = 0x2
+dp 0x4A009440 = 0x2
+dp 0x4A009448 = 0x2
+dp 0x4A009450 = 0x2
+dp 0x4A009458 = 0x2
+dp 0x4A009460 = 0x102
+dp 0x4A009468 = 0x102
+dp 0x4A009470 = 0x102
+dp 0x4A009478 = 0x102
+dp 0x4A009480 = 0x102
+dp 0x4A009488 = 0x2
+dp 0x4A009490 = 0x2
+dp 0x4A009498 = 0x2
+dp 0x4A0094A0 = 0x2
+dp 0x4A0094A8 = 0x2
+dp 0x4A0094B0 = 0x2
+dp 0x4A0094B8 = 0x2
+dp 0x4A0094D0 = 0x2
+dp 0x4A0094D8 = 0x2
+dp 0x4A0094E0 = 0x2
+dp 0x4A0094E8 = 0x2
+dp 0x4A0094F0 = 0x2
+dp 0x4A0094F8 = 0x2
+dp 0x4A009500 = 0x2
+dp 0x4A009508 = 0x2
+dp 0x4A009520 = 0x2
+dp 0x4A009528 = 0x2
+dp 0x4A009530 = 0x2
+dp 0x4A009538 = 0x702
+dp 0x4A009540 = 0x2
+dp 0x4A009548 = 0x2
+dp 0x4A009550 = 0x2
+dp 0x4A009558 = 0x2
+dp 0x4A009560 = 0x2
+dp 0x4A0095A0 = 0x2
+dp 0x4A0095A8 = 0x2
+dp 0x4A0095B0 = 0x2
+dp 0x4A0095B8 = 0x2
+dp 0x4A0095C0 = 0x2
+dp 0x4A0095C8 = 0x2
+
+#Route UART1 signals
+dp 0x4a10013C = 0x00010001
+
+#Mux configuration for Keypad
+dp 0x4A100188 = 0x01010101
+dp 0x4A10018C = 0x01010101
+dp 0x4A100190 = 0x01010101
+
+dp 0x4A10017C = 0x01010101
+dp 0x4A100180 = 0x01010101
+dp 0x4A100184 = 0x01010101
+
+#Route GPIO11 for Phoenix AudioCodec PowerUp
+dp 0x4a31E084 = 0x01080003
+
+# EMIF firewall bypass mode can now be turned off
+[VPOM4430::SDP::OMAP4430::L3FW_EMIF] bypass off
+
+# Open up the EMIF and OCMRAM firewalls to all accessors before anything runs
+d 0x4a20c08c=0xffffffff
+d 0x4a21208c=0xffffffff
+d 0x4a22808c=0xffffffff
+
+[VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_1]r r15=0x88e80000
+[VPOM4430::SDP::OMAP4430::CPU_SS::Cortex_2]r r15=0x88e80000
+g
+
+------------------------- [End of Native Apps.script]---------------------------
+
+3.8 Running Linux kernel
+
+The kernel binary used will be arch/arm/boot/uImage.
+
+
+3.8.1 Loading the kernel image via Virtio
+Note that the new NativeApp.script can load the kernel image & file sytem
+image.
+
+Just give below command on u-boot prompt.
+ bootm 0x80300000
+You should see the kernel booting and ramdisk getting loaded in a few seconds
+
+3.8.2 Loading the kernel image via Trace32
+
+Launch the T32. If console window is already running t32.cmm script is
+automatically run and you will be attached to the system. If not you will have
+to manually run t32.cmm script file.
+Break the system through t32
+Use the following commands from T32 window to load up the kernel image and
+file system
+ Data.load.binary <your Image path>/Image 0x80300000
+ Data.load.binary <your ramdisk path> 0x81600000
+ r r15=0x80e80054
+
+Select 'go' in the T32 window
+Go to the hyper terminal and execute the following
+
+>bootm 0x80300000
+
+You should see the kernel booting and ramdisk getting loaded in a few seconds
+
+NOTE: The kernel binary used is arch/arm/boot/uImage and
+ not arch/arm/boot/Image.
+
+
+4. Features
+-----------
+
+4.1 New Features
+
+4.2 Supported Features
+
+- Boot-loader:
+ U-boot from RAM,
+ U-boot USB support.
+
+- OS Kernel
+ SMP Kernel with GIC, LOCAL timer support.
+ GP-Timers
+ 32 KHz Sync timer
+ Watchdog timer
+ I2C
+ DMA
+ GPIO
+ McBSP
+ McSPI
+ Console UART (Uart 1, Uart 2, Uart 3,Uart 4)
+ Phoenix Regulator
+ Phoenix core
+ RTC
+ KEYPAD
+ MMC/eMMC/SD
+ Tiler
+ Neon
+
+ Code has been added for following drivers, but cannot be tested on Virtio:
+ Phoenix - General Purpose ADC, Battery charging.
+
+- Power related
+ Clock nodes in PRM/CM1/CM2 modules modelled.
+ Clock nodes for ABE/PER/CORE/MPU/DSP/UNIPRO DPLL's modelled.
+ Not present:
+ USB DPLL not modelled
+ None of the DPLL set_rate and recalc functions are implemented.
+ Shared Resource Framework
+ Tick suppression enabled.
+
+
+-Audio
+ Added Audio Backend playback support with MM interface
+ Added TWL6030 ALSA SoC codec driver
+ Support for Low Power and High Performance modes of TWL6030 codec
+ Basic support for audio interrupt: power-up sequence completion
+ Added McPDM base and SoC platform drivers
+ Added SDP4430 ALSA SoC machine driver
+ Additional Comments:
+ - Supported 44.1/48 kHz signed 32-bits LE format
+ - twl6030 i2c bus 1 speed was reduced to 400 kbits/s to match codec
+ requirements
+ NOTE: Audio support is disabled in SDP4430 kernel defconfig due to the
+ requirement of an additional license for dMACe component in Virtio,
+ which is used as a part of Audio Backend.
+
+-Video
+ Basic Frame Buffer support.
+
+-Display
+ Tiler
+
+4.3 Postponed Features
+
+None
+
+
+4.4 Future Planned Features
+
+Refer to Program schedule.
+
+
+4.5 Defects Fixed in This Release
+
+None
+
+4.6 Open Defects
+
+None
+
+
+4.7 Open Change Requests
+
+None
+
+
+4.8 Rejected Defects
+
+None
+
+
+4.9 Postponed Defects
+
+None
+
+4.10 Limitations
+
+None
+
+
+5. Tool Chain
+-------------
+The toolchain used to build the code can be obtained from CodeSourcery at the
+following URL:
+ http://www.codesourcery.com/gnu_toolchains/arm/portal/release644
+
+The tool chain version is Sourcery G++ Lite 2008q3-72 for ARM GNU/Linux.
+
+The tool chain requires glibc 2.3.0 or higher to compile the source code on
+the host machine.
+
+
+--------------------------------------------------------------------------------
+
+OMAP(TM) is a Trademark of Texas Instruments Incorporated
+Innovator(TM) is a Trademark of Texas Instruments Incorporated
+Code Composer Studio(TM) is a Trademark of Texas Instruments Incorporated
+DSP/BIOS(TM) is a Trademark of Texas Instruments Incorporated
+
+All other trademarks are the property of the respective owner.
+
diff --git a/TI_OMAP4_Syslink_Release_Notes_L24.x.txt b/TI_OMAP4_Syslink_Release_Notes_L24.x.txt
new file mode 100755
index 000000000000..609ded631803
--- /dev/null
+++ b/TI_OMAP4_Syslink_Release_Notes_L24.x.txt
@@ -0,0 +1,626 @@
+================================================================================
+OMAP4 Syslink List Handoff
+================================================================================
+
+Author : Ramesh Gupta G / Suman Anna
+Date : June 30 2009
+
+===========
+Summary:
+===========
+OMAP4 Syslink consists of required set of drivers for Multi Core
+communication. The communication is mainly divided into Chiron to Tesla and
+Chiron to Ducati processors. Below sections provide details on the components
+in detail.
+
+=================
+Tesla MPU Bridge
+=================
+Tesla MPU bridge is the communication driver between the Chiron and
+Tesla processor.
+
+=============
+Syslink IPC
+=============
+Syslink IPC is the communication driver between the Chiron and Ducati cores.
+
+==============
+Proc manager
+==============
+ - Implemented initial version of Proc module. Proc module controls Ducati
+ Processors and supports IPC mechanism. Ducati enabler is now part of Proc
+ module.
+ - DMM support for Ducati memory.
+
+===============
+Notify module
+===============
+ Notify module provides an abstraction to underlying communiation layer,
+ notify clients(e.g notify_tesladriver & notify_ducatidriver) would register
+ with notify driver(omap_notify) with the supported set of functions
+ and the notify users (syslink ipc, tesla bridgedriver) use
+ notify driver to use client functionalities.
+
+=============
+Sources:
+=============
+All the above module sources are available along with the
+linux-omap4 kernel sources hosted in
+
+http://dev.omapzoom.org/?p=integration/kernel-omap4.git;a=summary
+
+Tesla Bridge api and sample sources are available in omapzoom.org in below link
+
+https://omapzoom.org/gf/project/omapbridge/frs/
+?action=FrsReleaseBrowse&frs_package_id=2
+
+For syslink ipc, Notify and proc manager apis/ samples please
+contact TI counter part.
+
+=======
+Setup:
+=======
+Virtio : VPOM4430_1.09a + patch3
+CCS: Version 3.3 with VPOM simulator. For more information on CCS availability
+please contact TI.
+CCSv4 with VPOM simulator is also supported.
+
+=====================
+Build Instructions:
+=====================
+
+Building the Linux Kernel and syslink components.
+
+All syslink component sources are now available along with Kernel sources under
+the drivers/dsp folders, They can be built as modules by below steps.
+
+Tesla Bridge driver sources available in folder drivers/dsp/bridge
+
+Syslink IPC component enables communication between Chiron and Ducati cores. The
+sources for Syslink components are available in folder drivers/dsp/syslink
+
+Proc manager driver initializes and programs
+MMU page table entries which is required for Ducati image loading.
+
+Please follow the below steps to build all the drivers.
+
+From the Kernel sources run below commands.
+
+ 1. export PATH varible to arm codesourcey cross compiler.
+
+ 2. export ARCH=arm
+
+ 3. make distclean
+
+ 4. make CROSS_COMPILE=arm-none-linux-gnueabi- omap_4430sdp_defconfig
+
+ 5. Run make menuconfig
+
+ 6. Select drivers under
+ Deivice Drivers -->Sys_Link --->
+ <M> OMAP IPC Module
+ <M> OMAP Notify Module
+ <M> Mailbox Dispatcher
+ <M> OMAP Notify Tesla Module
+ <M> OMAP Notify Ducati Module
+ <M> Syslink Procmgr
+ <M> Proc 4430
+ Device Drivers --><M> DSP Bridge driver-->
+ [M] DSP Bridge Debug Support
+
+ Select DSP Bridge Debug Support option as above.
+ 7. Save Configuration
+
+ 8. Build the kernel by running below commands.
+
+ 9. Add mkimage path to the PATH variable (for uImage building).
+
+ 10. make CROSS_COMPILE=arm-none-linux-gnueabi- uImage
+
+ 11. On successful uImage is built under arch/arm/boot, use this uImage
+ to boot Virtio.
+
+ 12. Building the modules by below commands.
+
+ 13. Run below command once the kernel is built.
+
+ 14. Make CROSS_COMPILE=arm-none-linux-gnueabi- modules. This command
+ is applicable only if we select the required drivers as modules.
+ if all the drivers are selected as part of the kernel steps
+ from 14 to 23 can be ignored.
+
+ 15. Bridgedriver module (bridgedriver.ko) is built under folder
+ drivers/dsp/bridge/ dspbridge module(dspbridge.ko) is built
+ under folder arch/arm/plat-omap2 which is required for bridge
+ driver.
+
+ 16. Notify module (omap_notify.ko) is built under folder
+ drivers/dsp/syslink/omap_notify/
+
+ 17. notify dispatcher is (notify_disp.ko) is built under folder
+ drivers/dsp/syslink/notify_dispatcher
+
+ 18. notify tesla driver (notify_tesladriver.ko) is built under folder
+ drivers/dsp/syslink/notify_tesladriver
+
+ 19. notify dispatcher is (notify_ducatidriver.ko) is built under folder
+ drivers/dsp/syslink/notify_ducatidriver
+
+ 20. syslink proc4430 module for ducati(syslink_proci4430.ko) is built under folder
+ drivers/dsp/syslink/procmgr/proc4430/
+
+ 21. syslink proc module (syslink_proc.ko) is built under folder
+ drivers/dsp/syslink/procmgr/
+
+ 22. syslink ipc module for ducati (syslink_ipc.ko) is built under folder
+ drivers/dsp/syslink/multicore_ipc/
+
+ 23. copy all these drivers to the target file system
+ (ram disk file system)along with the tesla binaries
+
+ 24. To build all of the above drivers as part of the Kernel,
+ select the drivers and run "make uImage"
+
+=================================================================================
+Important Notes:
+ 1.bridgedriver depends on dspbridge driver, omap_notify
+ notify_tesladriver and notify_dispatcher drivers
+ 2. notify_ducatidriver depends on
+ omap_notify,notify_dispatcher and syslink_proc4430 drivers.
+ 3. syslink_ipc driver depends on omap_notify, notify_dispatcher,
+ notify_ducatidriver, syslink_proc and syslink_proc4430 drivers.
+=================================================================================
+
+=======================================
+Building Bridge API library and samples
+=======================================
+
+Build tesla bridge libraries by running below commands.
+
+ 1. Copy the pthread libraries from arm cross compiler tool chain into
+ dspbridge/target/lib folder
+
+ 2. cd into api folder cd /dspbridge/mpu_api
+
+ 3. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder> clean
+
+ 4. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder>
+
+ 5. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder> install
+
+ 6. On successful build libbridge.so, libbridge.so.2 are installed in
+ dspbridge/target/lib/ folder.
+
+Build the samples by running below commands.
+
+ 1. Copy the bridge libraries libbridge.so* to folder dspbridge/samples/mpu/lib/
+
+ 2. Cd dspbridge/samples/mpu/src
+
+ Run make command as below.
+
+ 3. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder> clean
+
+ 4. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder>
+
+ 5. make PREFIX=<path to dspbridge folder> TGTROOT=<path to dspbridge folder> install
+
+Build ducati syslink libraries by running below commands.
+
+ 1. Copy the pthread and librt libraries from arm cross compiler tool chain into
+ dspbridge/target/lib folder. Also copy the libgcc.a file.
+
+ 2. cd into api src folder cd /syslink/api/src
+
+ 3. make PREFIX=<path to syslink folder> TGTROOT=<path to syslink folder> clean
+
+ 4. make PREFIX=<path to syslink folder> TGTROOT=<path to syslink folder>
+
+ 5. make PREFIX=<path to syslink folder> TGTROOT=<path to syslink folder> install
+
+ 6. On successful build, libutils.so, libutils.so.0, libnotify.so,
+ libipc.so, libnotify.so.2, libprocmgr.so, libprocmgr.so.2, libipc.so,
+ libipc.so.0, librcm.so, librcm.so.0 are installed in
+ syslink/target/lib/ folder.
+
+Build the syslink samples by running below commands.
+
+ 1. cd syslink/samples
+
+ Run make command as below.
+
+ 2. make PREFIX=<path to syslink folder> TGTROOT=<path to syslink folder>
+ KRNLSRC=<kernel sources > clean
+
+ 3. make PREFIX=<path to syslink folder> TGTROOT=<path to syslink folder>
+ KRNLSRC=<kernel sources >
+
+ 4. The sample .out files are build in the respective source directories
+ underneath syslink/samples folder.
+ 5. The kernel sample procmgr_app.ko is built under
+ syslink/samples/proc_sample/krnl
+ 6. make sure to build the samples from the same session from which the
+ kernel is built or export ARCH and PATH variables as mentioned
+ in above in kernel building.
+
+========================================
+Building Tesla images and Ducati samples
+========================================
+ 1. Install the CCS and get the CGtools for Tesla and ARM (for Ducati)
+ 2. Upgrade the BIOS to the latest from T.I website
+ 3. https://www-a.ti.com/downloads/sds_support/targetcontent/index.html
+ 4. Follow the DSP Application guide to build DSP samples.
+ 5. Framework components present in the tarball that is uploaded and also
+ on TI website where BIOS is found.
+ 6. Contact TI representative for Tesla/Ducati images.
+
+
+=======================
+Running Tesla Samples
+=======================
+
+ 1. Boot the kernel with Ramdisk consisting all the drivers and Tesla
+ images, samples, API libraries.
+
+ 2. Once kernel is booted, cd into the folder where all the binaries are
+ placed.
+
+ 3. install all the drivers in the sequence as below, this step is
+ required only if the drivers are build as modules,
+ if all the drivers are build as part of the kernel one can
+ ignore steps 3 and 4
+
+ insmod omap_notify.ko
+
+ insmod notify_disp.ko
+
+ insmod notify_tesladriver.ko
+
+ insmod dspbridge.ko
+
+ insmod bridgedriver.ko
+
+ 4. Create device node for bridgedriver accordingly
+ by checking the /proc/devices.
+
+ e.g: mknod /dev/DspBridge c 253 0
+
+ 5.Load the image using cexec.out
+
+ ./cexec.out ddspbase_tiomap4430.dof64T
+
+ 6. This loads image and waits the sync mask to be cleared by DSP.
+ DSP Start address is displayed as below.
+
+ - - - DSP Start Address [0x2104b000]- - -
+
+
+ 7. Copy the above start address (0x2104b000), Go to Virtio IDE and break
+ the system by typing 'y' in the virtio console.
+
+ 8. Open the Code Composer Studio, select Open Tesla.
+
+ 9. Open the register window and modify the PC with the DSP Start
+ address (0x2104b000).
+
+ 10. In CCS hit F11 key for several times (at least 5-10 times) and then
+ press F5.
+
+ 11. Go back to Teraterm where cexec completes and DSP is started. Now we
+ are ready to run dsp samples, below are the commands for running
+ samples.
+
+ ./scale.out 10
+ ./zerocopymsg.out
+ ./strmcopy.out 0 install_bridge out-strm-file.
+ ./ping.out 10
+ ./dmmcopy.out inoustall_bridge out-dmm-file
+
+
+Running Bridge Samples in Dynamic loading mode:
+
+ 1. Boot Virtio
+
+ 2. Install all the 3 driver using the script as mentioned in above section.
+ This step is not required if all the drivers are build as part of the
+ kernel.
+
+ 3. load dynbase image.
+ ./cexec.out dynbase_tiomap4430.dof64T
+
+ 4. Follow same procedure as above in Section to start DSP. With CCS
+
+ 5. Register the required dll as below.
+ ./dynreg.out -r strmcopydyn_4430.dll64T
+
+ 6. Run the strmcopy sample.
+ ./strmcopy.out 0 install_bridge out-strm
+
+================================================================================
+Important Note3: Due to some limitations we cannot run 2 different samples at
+one time in dynamic loading mode. One needs to reboot Virtio for running other
+sample.
+================================================================================
+
+=======================
+Running Syslink Samples
+=======================
+
+ 1. Boot the kernel with ramdisk consisting all the drivers and Syslink
+ samples, API libraries. Ducati images need not be part of the ramdisk.
+
+ 2. Once kernel is booted, cd into the folder where all the binaries are
+ placed.
+
+ 3. install all the drivers in the sequence as below, this step is
+ required only if the drivers are build as modules,
+ if all the drivers are build as part of the kernel one can
+ ignore steps 3 and 4
+
+ insmod omap_notify.ko
+
+ insmod notify_disp.ko
+
+ insmod notify_ducatidriver.ko
+
+ insmod syslink_proc.ko
+
+ insmod syslink_proc4430.ko
+
+ insmod syslink_ipc.ko
+
+ 4. Create device node for syslink components accordingly
+ by checking the /proc/devices.
+
+ mknod /dev/ipcnotify c 232 0
+
+ mknod /dev/notifyducatidrv c 234 0
+
+ mkdir /dev/syslinkipc
+
+ mknod /dev/syslinkipc/ProcMgr c 254 0
+
+ mknod /dev/syslink-proc4430 c 253 0
+
+ mknod /dev/syslink_ipc c 252 0
+
+ 5. Configure the Proc module by running the following command. This
+ sets up the drivers for running the syslink samples.
+
+ insmod procmgr_app.ko
+
+ 6. Run the samples by running the corresponding .out files
+
+ eg: ./messagequ.out
+
+ 7. Load the Ducati baseimage when prompted using CCS.
+
+
+==============================
+Validating the Ducati Driver
+==============================
+
+One can validate the Ducati enabler driver by running below steps.
+-------------------------------------------------------------------------------
+Important Note4: CCS need to be configured for "VPOMAP 4 Platform Simulator"
+
+Remove the IVAHD-iCONT1, IVAHD-iCONT2, and Modena.
+
+The System Configuration must have only Tesla and Duati-ARM-M3-1, Ducati-ARM-M3-2
+-------------------------------------------------------------------------------
+
+Two baseimages Bios6Boot.xem3 and Bios6Boot_Core1.xem3 can be used to validate
+the BIOS6 boot validation on each of the cores respectively.
+
+Please contact TI representative for these images.
+
+The following steps detail the boot on Core0. Similar procedure can be followed
+to boot the Core1 as well.
+
+ 1. Boot the Virtio as usual.
+
+ 2. Break the platform by typing 'y' in the Virtio Console after the bash
+ shell prompt appears.
+
+ 3. install all the drivers in the sequence as below, this step is
+ required only if the drivers are build as modules,
+ if all the drivers are build as part of the kernel one can
+ ignore this step
+
+ insmod omap_notify.ko
+
+ insmod notify_disp.ko
+
+ insmod syslink_proc4430.ko
+
+ insmod notify_ducatidriver.ko
+
+ 4. The syslink_proc4430 driver programs MMU and
+ updates page table entries.
+ 5. Break the Virtio by typing y in console.
+
+ 6. Open CCS and select Ducati core.
+
+ 7. Load the base image into Ducati core0.
+
+ 8. In Virtio design , browse to
+ VPOM4430->SDP->OMAP4430-> InitValue_DUCATI_SYS_1.
+ Right click and open.
+ Right click on Signal (InitValue) and select
+ Send Signal To Platform.
+ Send 1 and press OK. This resets the core.
+
+ 9. Press F11 once to have the Reset release become effective.
+ Note that the PC does not change here and the SP is updated.
+ Press F11 couple more times to make sure Ducati is executing
+ and thereafter you can press F5.
+
+Running Notify ping sample on Ducati:
+-------------------------------------
+ 1. Boot Vartio as usual.
+ 2. Follow the same steps as above install required drivers (step 3
+ above), this step is required only if the drivers
+ are build as modules, if all the drivers are build
+ as part of the kernel one can ignore this step
+ 3. create nodes for ipcnotify and notifyducatidrv accordinngly.
+ e.g: mknod /dev/ipcnotify c 232 0
+ mknod /dev/notifyducatidrv c 234 0
+ 4. run notifyping.out sample.
+
+ 5. The sample keeps in a loop while sending events and
+ checking for ducati side initialization.
+
+ 6. Break the Virtio by typing y in console.
+
+ 7. Open CCS and select Ducati-ARM-M3-1 core.
+
+ 6. Load ducati image (notifyxfer_bios6.xem3) image.
+
+ 7. Open source file notifyxfer_bios6.c file and add some breakpoints
+ in the main function.
+
+ 8. Press F11 once to have the Reset release become effective.
+ Note that the PC does not change here and the SP is updated.
+ Press F11 couple more times to make sure Ducati is executing
+ and thereafter you can press F5.
+ 9. One can observe Ducati receiving the events from Chiron
+ calling the call back function and sending event back to Chiron.
+
+ 10. The Notifyping sample running on the Chiron shows event messages
+ and call back function messages.
+
+Loading ducati images using the userspace loader:
+------------------------------------------------
+ 1. On successful ducati sample build user space binary loader
+ ducati_load.out is build underi folder
+ syslink/samples/samples/procmgr/ducati_load/
+ 2. One can load the ducati image on to SYSM3 or APPM3 using the
+ userspace binary loader as below.
+ ./ducati_load.out <image_name>
+ 3. on successful load the loader displays the entry point for
+ the image at the end.
+
+ ------snip----
+ loaded_program: 0xea19
+ Completed Loading Image ..... notifyxfer_bios6.xem3
+ entry_point is 0xea19
+ Hit any key to terminate cexec.
+ --------------
+ 4. Due to Virtio issues we cannot start SYSM3/APPM3 from the
+ MPU side, one has to use CCS for SYSM3/APPM3 start by
+ following below step.
+ 5. Break Virtio and open CCS, Select the processor on which
+ image is loaded.
+ 6. Open the PC registers.
+ 7. Set the PC value to the entry point displayed from the loading
+ step.
+ 8. Run couple of times step run.
+ 9. Run the Processor.
+
+loading images on both SYSM3/APPM3 processors
+---------------------------------------------
+
+Follow below procedure to load images on both SYSM3/APPM3 using
+user space loader
+
+ 1. SYSM3 should be reached main() before loading the APPM3 image.
+ 2. SYSM3 should be in running state to load APPM3 from MPU using
+ user space loader. Otherwise MPU will not respond.
+ 3. Because of the above reasons, one need to introduce a continuos
+ while loop in both the SYSM3/APPM3 programs immediately in the main()
+ function at the first place. e.g:
+
+ while(flag)
+ ;
+ 4. Load the SYSM3 image using the loader, set the PC using CCS and tun the
+ SYSM3 processor. Now SYSM3 executing the while(flag) loop.
+ 5. Load the APPM3 using the loader, set the PC using the CCS and run the
+ APPM3 processor, now the APPM3 is executing the while(flag) loop.
+ 6. Stop APPM3 processor.
+ 7. Stop SYSM3 processor.
+ 8. Bring SYSM3 out of while loop by changing the variable flag to 0 on the
+ fly.
+ 9. Bring APP3 out of while loop by changing the variable flag to 0 on the
+ fly.
+ 10. Run SYSM3 and Run APPM3.
+
+================================================================================
+Highlights / Important Notes
+================================================================================
+
+==============
+Tesla Bridge
+==============
+Features Introduced
+--------------------------
+- Fixed checkpatch errors and warnings for all modules under syslink.
+- Dynamic Loading Support has been added.
+- Bridge Trace Support has been added.
+- All basic bridge features, messaging, processor copy streaming, dmmcopy,
+ zerocopy messaging in static and dynamic loading are validated.
+
+==============
+Syslink
+==============
+- RCM server and client works on Chiron, Ducati SYSM3 and APPM3.
+- Added load support by Proc manager.
+- All modules can be built along with the Kernel.
+- All modules are working as expected.
+- Userspace binary image loader utility is implemented for loading images on
+ Ducati.
+
+Ducati Bridge
+==============
+- Elf Image support.
+- Ducati MMU Programming.
+- Page table entries updation.
+- Loading and running a Ducati image.
+- Validation using notify ping sample
+- BIOS30 and XDC39 Support.
+- IPC33 and FC36-RCM alignment.
+
+
+Important Notes
+--------------------
+ - Set the bootargs to use only 54M, this is required for Ducati testing.
+ Run below command in u-boot prompt.
+
+ set bootargs root=/dev/ram0 rw mem=54M console=ttyS0,115200n8
+ initrd=0x81600000,20M ramdisk_size=20480
+
+ - One need to have CCS to start the Ducati processors as the Virtio doesn't have
+ the PRCM support to reset Ducati processors.
+ - Code Composer Studio is required to write the Start DSP Address to the
+ PC register
+ * CCS_v3.3_SR9_79.exe or CCS_v3.3_SR10_80.exe or CCS_v3.3_SR11
+ * Install ccs_VPOMAP4_1.00.02.zip located at
+ C:\Virtio\Platforms\VPOM4430\CCS
+ * Use Tesla - VPOMAP 4 Platform Simulator.
+ * Please contact your TI representative for further information on
+ Code Composer Studio (CCS)
+
+ - Basic Validation for Tesla Bridge was done with samples in
+ Static and dynamic mode:
+ Dmmcopy, Zcmsg, Strmcopy, Scale and Ping
+ - Basic validation for Ducati image with loading ducati imeges
+ and Notify ping sample.
+
+==================================
+Issues Resolved
+==================================
+ - NONE
+
+==================================
+Known Issues
+==================================
+ 1. Running dynamic samples second time failing, one has to restart
+ Virtio for running another dyncamic sample.
+ 2. Due to mailbox changes in Virtio1.06a version, Bridge 24.0.8 release
+ is not backward compatible with Virtio versions < 1.06a.
+ 3. Notipy ping sample some times not working because of timing issues.
+ Need to have break points in Ducati side.
+ 4. CCS is required to start Ducati processors (SYSM3/APPM3), as the
+ current Virtio doesn't have the PRCM support to reset Ducati Processors.
+ 5. ping sample is not working in dynamic mode in Tesla due to dependant
+ library issue this is been tracked by internal tracking number id:
+ OMAPS00202802
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1c58b4ad5272..93232d87579f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1479,6 +1479,10 @@ source "drivers/staging/Kconfig"
source "drivers/media/video/tiler/Kconfig"
+source "drivers/dsp/syslink/Kconfig"
+
+source "drivers/dsp/bridge/Kconfig"
+
endmenu
source "fs/Kconfig"
diff --git a/arch/arm/configs/omap3_pandora_defconfig b/arch/arm/configs/omap3_pandora_defconfig
index b54ad2e2da36..3c962be8b8e3 100644
--- a/arch/arm/configs/omap3_pandora_defconfig
+++ b/arch/arm/configs/omap3_pandora_defconfig
@@ -1049,7 +1049,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
-CONFIG_RTC_DRV_TWL4030=y
+CONFIG_RTC_DRV_TWL=y
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig
index 23df1fe7573f..4942ab1d0ff3 100644
--- a/arch/arm/configs/omap_3430sdp_defconfig
+++ b/arch/arm/configs/omap_3430sdp_defconfig
@@ -1632,7 +1632,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
-CONFIG_RTC_DRV_TWL4030=y
+CONFIG_RTC_DRV_TWL=y
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig
index 321de5515949..f47a2f78638f 100644
--- a/arch/arm/configs/omap_4430sdp_defconfig
+++ b/arch/arm/configs/omap_4430sdp_defconfig
@@ -110,6 +110,9 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_MMC_OMAP_HS=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -183,9 +186,9 @@ CONFIG_ARCH_OMAP4=y
# OMAP Feature Selections
#
# CONFIG_OMAP_RESET_CLOCKS is not set
-# CONFIG_OMAP_MUX is not set
-# CONFIG_OMAP_MCBSP is not set
-# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MCBSP=y
+CONFIG_OMAP_MBOX_FWK=y
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
@@ -374,7 +377,8 @@ CONFIG_INPUT_EVDEV=y
#
# Input Device Drivers
#
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_OMAP=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -415,6 +419,7 @@ CONFIG_SERIAL_8250_RSA=y
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
+#CONFIG_SERIAL_OMAP is not set
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
@@ -425,10 +430,14 @@ CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
-# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_SPI=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
# CONFIG_DEBUG_GPIO is not set
# CONFIG_GPIO_SYSFS is not set
@@ -439,7 +448,9 @@ CONFIG_GPIOLIB=y
#
# I2C GPIO expanders:
#
-
+CONFIG_I2C_OMAP=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_MASTER=y
#
# PCI GPIO expanders:
#
@@ -452,13 +463,14 @@ CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
+CONFIG_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
+CONFIG_SSB_POSSIBLE=y
#
# Multifunction device drivers
@@ -472,20 +484,54 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_T7L66XB is not set
# CONFIG_MFD_TC6387XB is not set
# CONFIG_MFD_TC6393XB is not set
+CONFIG_TWL6030_CORE=y
#
# Multimedia devices
#
-
+CONFIG_MEDIA_SUPPORT=y
#
# Multimedia core support
#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_MEDIA=y
#
# Multimedia drivers
#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP_VIDEOLIB=y
+CONFIG_VIDEO_OMAP_VIDEOOUT=y
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_TEA5764 is not set
CONFIG_DAB=y
#
@@ -493,7 +539,57 @@ CONFIG_DAB=y
#
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=4
+# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set
+# CONFIG_OMAP2_DSS_RFBI is not set
+# CONFIG_OMAP2_DSS_VENC is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+
+#
+# OMAP2/3 Display Device Drivers
+#
+# CONFIG_PANEL_GENERIC is not set
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_LCD_4430SDP=y
+# CONFIG_PANEL_4430SDP_TAAL is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=1
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -506,15 +602,34 @@ CONFIG_DAB=y
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
# CONFIG_MEMSTICK is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_NEW_LEDS is not set
CONFIG_RTC_LIB=y
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TWL=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_REGULATOR is not set
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index ed2a48a9ce74..45fc2ae2d2a6 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -19,6 +19,7 @@
#include <linux/spi/ads7846.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/omapfb.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -32,7 +33,6 @@
#include <mach/keypad.h>
#include <mach/common.h>
#include <mach/dsp_common.h>
-#include <mach/omapfb.h>
#include <mach/hwa742.h>
#include <mach/lcd_mipid.h>
#include <mach/mmc.h>
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 735bae5b0dec..969be10ed2bc 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,14 +3,15 @@
#
# Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o clock.o prcm.o
omap-2-3-common = irq.o sdrc.o
-prcm-common = prcm.o powerdomain.o
-clock-common = clock.o clockdomain.o
+prcm-common = powerdomain.o
+clock-common = clockdomain.o
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common)
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) $(clock-common)
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
@@ -38,10 +39,15 @@ endif
# Clock framework
obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+obj-$(CONFIG_ARCH_OMAP4) += clock44xx.o
+
+# MAILBOX
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+mailbox_mach-objs := mailbox.o
iommu-y += iommu2.o
iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o
-
+iommu-$(CONFIG_ARCH_OMAP4) += omap4-iommu.o
obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)
# Specific board support
@@ -70,8 +76,8 @@ obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
mmc-twl4030.o \
board-zoom-debugboard.o
-obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o
-
+obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \
+ mmc-twl4030.o
# Platform specific device init code
obj-y += usb-musb.o
@@ -80,3 +86,4 @@ obj-y += $(onenand-m) $(onenand-y)
smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o
obj-y += $(smc91x-m) $(smc91x-y)
+obj-$(CONFIG_MPU_BRIDGE) += dspbridge.o
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 8ec2a132904d..64bfce998f6e 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -19,7 +19,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -156,13 +156,13 @@ static struct omap_board_config_kernel sdp2430_config[] = {
};
-static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
+static struct twl_gpio_platform_data sdp2430_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
};
-static struct twl4030_platform_data sdp2430_twldata = {
+static struct twl_platform_data sdp2430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ac262cd74503..cd86114f2092 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -19,7 +19,7 @@
#include <linux/input.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/regulator/machine.h>
#include <linux/io.h>
#include <linux/gpio.h>
@@ -88,7 +88,7 @@ static int sdp3430_keymap[] = {
0
};
-static struct twl4030_keypad_data sdp3430_kp_data = {
+static struct twl_keypad_data sdp3430_kp_data = {
.rows = 5,
.cols = 6,
.keymap = sdp3430_keymap,
@@ -198,7 +198,7 @@ static int sdp3430_batt_table[] = {
4040, 3910, 3790, 3670, 3550
};
-static struct twl4030_bci_platform_data sdp3430_bci_data = {
+static struct twl_bci_platform_data sdp3430_bci_data = {
.battery_tmp_tbl = sdp3430_batt_table,
.tblsize = ARRAY_SIZE(sdp3430_batt_table),
};
@@ -260,7 +260,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
return 0;
}
-static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
+static struct twl_gpio_platform_data sdp3430_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
@@ -269,11 +269,11 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
.setup = sdp3430_twl_gpio_setup,
};
-static struct twl4030_usb_data sdp3430_usb_data = {
+static struct twl_usb_data sdp3430_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
-static struct twl4030_madc_platform_data sdp3430_madc_data = {
+static struct twl_madc_platform_data sdp3430_madc_data = {
.irq_line = 1,
};
@@ -409,7 +409,7 @@ static struct regulator_init_data sdp3430_vpll2 = {
.consumer_supplies = &sdp3430_vdvi_supply,
};
-static struct twl4030_platform_data sdp3430_twldata = {
+static struct twl_platform_data sdp3430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 16296530e3ce..6f3745cd683a 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -17,34 +17,167 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <mach/keypad.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <mach/mux.h>
+#include <mach/display.h>
+#include <mach/mcspi.h>
#include <mach/board.h>
#include <mach/common.h>
#include <mach/control.h>
#include <mach/timer-gp.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
+#include <linux/i2c/twl.h>
+#include "mmc-twl4030.h"
+#include <linux/regulator/machine.h>
-static struct platform_device sdp4430_lcd_device = {
- .name = "sdp4430_lcd",
+#define OMAP4_KBDOCP_BASE 0x4A31C000
+
+static int ts_gpio;
+
+static int omap_keymap[] = {
+ KEY(6, 6, KEY_Q),
+ KEY(4, 0, KEY_W),
+ KEY(0, 0, KEY_E),
+ KEY(0, 1, KEY_R),
+ KEY(0, 2, KEY_T),
+ KEY(4, 1, KEY_Y),
+ KEY(4, 2, KEY_U),
+ KEY(0, 6, KEY_I),
+ KEY(3, 6, KEY_O),
+ KEY(6, 6, KEY_P),
+ KEY(6, 1, KEY_A),
+ KEY(5, 0, KEY_S),
+ KEY(1, 0, KEY_D),
+ KEY(1, 1, KEY_F),
+ KEY(1, 2, KEY_G),
+ KEY(5, 1, KEY_H),
+ KEY(5, 2, KEY_J),
+ KEY(1, 6, KEY_K),
+ KEY(4, 6, KEY_L),
+ KEY(6, 4, KEY_BACKSPACE),
+ KEY(2, 7, KEY_CAPSLOCK),
+ KEY(3, 0, KEY_Z),
+ KEY(2, 0, KEY_X),
+ KEY(2, 1, KEY_C),
+ KEY(2, 2, KEY_V),
+ KEY(3, 2, KEY_B),
+ KEY(6, 2, KEY_N),
+ KEY(2, 6, KEY_M),
+ KEY(5, 6, KEY_DOT),
+ KEY(1, 7, KEY_ENTER),
+ KEY(3, 3, KEY_EMAIL),
+ KEY(3, 1, KEY_KPPLUS),
+ KEY(3, 7, KEY_SPACE),
+ KEY(7, 4, KEY_CAMERA),
+ KEY(4, 4, KEY_VOLUMEUP),
+ KEY(5, 5, KEY_VOLUMEDOWN),
+ KEY(7, 4, KEY_UP),
+ KEY(7, 5, KEY_DOWN),
+ KEY(7, 6, KEY_LEFT),
+ KEY(7, 7, KEY_RIGHT),
+ 0,
+};
+
+static struct resource omap_kp_resources[] = {
+ [0] = {
+ .start = OMAP4_KBDOCP_BASE,
+ .end = OMAP4_KBDOCP_BASE,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct omap_kp_platform_data omap_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = omap_keymap,
+ .keymapsize = ARRAY_SIZE(omap_keymap),
+ .delay = 4,
+ .rep = 1,
+};
+
+static struct platform_device omap_kp_device = {
+ .name = "omap-keypad",
.id = -1,
+ .dev = {
+ .platform_data = &omap_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(omap_kp_resources),
+ .resource = omap_kp_resources,
};
-static struct platform_device *sdp4430_devices[] __initdata = {
- &sdp4430_lcd_device,
+static struct omap2_mcspi_device_config tsc2046_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
};
-static struct omap_uart_config sdp4430_uart_config __initdata = {
- .enabled_uarts = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
+static struct omap2_mcspi_device_config dummy1_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+#ifdef CONFIG_SPI_TI_OMAP_TEST
+static struct omap2_mcspi_device_config dummy2_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 0, /* 0: slave, 1: master */
};
+#endif
static struct omap_lcd_config sdp4430_lcd_config __initdata = {
- .ctrl_name = "internal",
+ .ctrl_name = "internal",
+};
+
+static int sdp4430_panel_enable_lcd(void) {
+ return 0;
+}
+
+static int sdp4430_panel_disable_lcd(void) {
+ return 0;
+}
+
+static void __init sdp4430_display_init(void) {
+ return;
+}
+static struct omap_dss_device sdp4430_lcd_device = {
+ .name = "sdp4430_lcd",
+ .driver_name = "sdp4430_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 16,
+ .platform_enable = sdp4430_panel_enable_lcd,
+ .platform_disable = sdp4430_panel_disable_lcd,
+};
+
+static struct omap_dss_device *sdp4430_dss_devices[] = {
+ &sdp4430_lcd_device,
+};
+static struct omap_dss_board_info sdp4430_dss_data = {
+ .num_devices = ARRAY_SIZE(sdp4430_dss_devices),
+ .devices = sdp4430_dss_devices,
+ .default_device = &sdp4430_lcd_device,
+};
+static struct platform_device sdp4430_dss_device = {
+ .name = "omapdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &sdp4430_dss_data,
+ },
+};
+
+static struct platform_device *sdp4430_devices[] __initdata = {
+ &sdp4430_dss_device,
+ &omap_kp_device,
+};
+
+static struct omap_uart_config sdp4430_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
};
static struct omap_board_config_kernel sdp4430_config[] __initdata = {
@@ -58,6 +191,107 @@ static void __init gic_init_irq(void)
gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE));
}
+static struct spi_board_info sdp4430_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "spitst",
+ .bus_num = 1,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ },
+ [1] = {
+ .modalias = "ads7846",
+ .bus_num = 1,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ },
+#ifdef CONFIG_SPI_TI_OMAP_TEST
+ [2] = {
+ .modalias = "spidev",
+ .bus_num = 3,
+ .chip_select = 0,
+ .max_speed_hz = 6000000,
+ .controller_data = &dummy2_mcspi_config, /* Slave */
+ },
+ [3] = {
+ .modalias = "dummydevice1",
+ .bus_num = 2,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ .controller_data = &dummy1_mcspi_config, /*Master */
+ },
+#endif
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+ {
+ .mmc = 1,
+ /* 8 bits (default) requires S6.3 == ON,
+ * so the SIM card isn't used; else 4 bits.
+ */
+ .wires = 8,
+ .gpio_wp = 4,
+ },
+ {
+ .mmc = 2,
+ .wires = 8,
+ .gpio_wp = 7,
+ },
+ {
+ .mmc = 3,
+ .wires = 8,
+ .gpio_wp = 4,
+ },
+ {
+ .mmc = 4,
+ .wires = 8,
+ .gpio_wp = 4,
+ },
+ {
+ .mmc = 5,
+ .wires = 8,
+ .gpio_wp = 4,
+ },
+ {} /* Terminator */
+};
+
+static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
+ {
+ .supply = "vmmc",
+ },
+ {
+ .supply = "vmmc",
+ },
+ {
+ .supply = "vmmc",
+ },
+ {
+ .supply = "vmmc",
+ },
+ {
+ .supply = "vmmc",
+ },
+};
+
+static int __init sdp4430_mmc_init(void)
+{
+ /* Hard Coding Values for testing */
+ mmc[0].gpio_cd = 373;
+ mmc[1].gpio_cd = 0;
+ mmc[2].gpio_cd = 1;
+ mmc[3].gpio_cd = 2;
+ mmc[4].gpio_cd = 3;
+ twl4030_mmc_init(mmc);
+ /* link regulators to MMC adapters ... we "know" the
+ * regulators will be set up only *after* we return.
+ */
+ sdp4430_vmmc_supply[0].dev = mmc[0].dev;
+ sdp4430_vmmc_supply[1].dev = mmc[1].dev;
+ sdp4430_vmmc_supply[2].dev = mmc[2].dev;
+ sdp4430_vmmc_supply[3].dev = mmc[3].dev;
+ sdp4430_vmmc_supply[4].dev = mmc[4].dev;
+ return 0;
+}
+
static void __init omap_4430sdp_init_irq(void)
{
omap2_init_common_hw(NULL, NULL);
@@ -68,6 +302,228 @@ static void __init omap_4430sdp_init_irq(void)
omap_gpio_init();
}
+#ifdef CONFIG_TWL6030_CORE
+static struct regulator_init_data sdp4430_vaux1 = {
+ .constraints = {
+ .min_uV = 1000000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vaux2 = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vaux3 = {
+ .constraints = {
+ .min_uV = 1000000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* VMMC1 for MMC1 card */
+static struct regulator_init_data sdp4430_vmmc = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 5,
+ .consumer_supplies = &sdp4430_vmmc_supply,
+};
+
+static struct regulator_init_data sdp4430_vpp = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 2500000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vusim = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2900000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vana = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vcxio = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data sdp4430_vusb = {
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct twl_madc_platform_data sdp4430_gpadc_data = {
+ .irq_line = 1,
+};
+
+static struct twl_codec_data twl6030_codec = {
+ .audpwron_gpio = 127,
+ .naudint_irq = INT_44XX_SYS_NIRQ2,
+};
+
+static struct twl_platform_data sdp4430_twldata = {
+ .irq_base = TWL6030_IRQ_BASE,
+ .irq_end = TWL6030_IRQ_END,
+
+ /* Regulators */
+ .vmmc = &sdp4430_vmmc,
+ .vpp = &sdp4430_vpp,
+ .vusim = &sdp4430_vusim,
+ .vana = &sdp4430_vana,
+ .vcxio = &sdp4430_vcxio,
+ .vdac = &sdp4430_vdac,
+ .vusb = &sdp4430_vusb,
+ .vaux1 = &sdp4430_vaux1,
+ .vaux2 = &sdp4430_vaux2,
+ .vaux3 = &sdp4430_vaux3,
+ .madc = &sdp4430_gpadc_data,
+
+ /* children */
+ .codec = &twl6030_codec,
+};
+#endif
+
+static struct i2c_board_info __initdata sdp4430_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl6030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .irq = INT_44XX_SYS_NIRQ,
+#ifdef CONFIG_TWL6030_CORE
+ .platform_data = &sdp4430_twldata,
+#endif
+ },
+};
+
+static int __init omap4_i2c_init(void)
+{
+ omap_register_i2c_bus(1, 400, sdp4430_i2c_boardinfo,
+ ARRAY_SIZE(sdp4430_i2c_boardinfo));
+ omap_register_i2c_bus(2, 400, NULL, 0);
+ omap_register_i2c_bus(3, 400, NULL, 0);
+ return 0;
+}
+static void omap_mcbsp_init(void)
+{
+ omap_cfg_reg(AA3_4430_McBSP1_CLK);
+ omap_cfg_reg(Y3_4430_McBSP1_DR);
+ omap_cfg_reg(Y2_4430_McBSP1_DX);
+ omap_cfg_reg(Y4_4430_McBSP1_FSX);
+}
+void omap_kp_init(void)
+{
+ omap_cfg_reg(PAD0_4430_UNIPRO_TX0);
+ omap_cfg_reg(PAD1_4430_UNIPRO_TY0);
+ omap_cfg_reg(PAD0_4430_UNIPRO_TX1);
+ omap_cfg_reg(PAD1_4430_UNIPRO_TY1);
+ omap_cfg_reg(PAD0_4430_UNIPRO_TX2);
+ omap_cfg_reg(PAD1_4430_UNIPRO_TY2);
+
+ omap_cfg_reg(PAD0_4430_UNIPRO_RX0);
+ omap_cfg_reg(PAD1_4430_UNIPRO_RY0);
+ omap_cfg_reg(PAD0_4430_UNIPRO_RX1);
+ omap_cfg_reg(PAD1_4430_UNIPRO_RY1);
+ omap_cfg_reg(PAD0_4430_UNIPRO_RX2);
+ omap_cfg_reg(PAD1_4430_UNIPRO_RY2);
+}
+
+static void omap_abe_init(void)
+{
+ /* mcpdm */
+ omap_cfg_reg(AG25_4430_ABE_PDM_UL_DATA);
+ omap_cfg_reg(AF25_4430_ABE_PDM_DL_DATA);
+ omap_cfg_reg(AE25_4430_ABE_PDM_FRAME);
+ omap_cfg_reg(AF26_4430_ABE_PDM_LB_CLK);
+ omap_cfg_reg(AH26_4430_ABE_PDM_CLKS);
+}
+
+static void omap_phoenix_init(void)
+{
+ /* twl6030 audio power-on */
+ omap_cfg_reg(AA27_4430_GPIO_127);
+
+ omap_cfg_reg(PAD1_4430_SYS_NIRQ1);
+ omap_cfg_reg(PAD0_4430_SYS_NIRQ2);
+}
static void __init omap_4430sdp_init(void)
{
@@ -81,10 +537,21 @@ static void __init omap_4430sdp_init(void)
* Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
l2x0_init(l2cache_base, 0x02520000, 0xc0000fff);
#endif
+ omap4_i2c_init();
platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
omap_board_config = sdp4430_config;
omap_board_config_size = ARRAY_SIZE(sdp4430_config);
omap_serial_init();
+ sdp4430_spi_board_info[0].irq = OMAP_GPIO_IRQ(ts_gpio);
+ spi_register_board_info(sdp4430_spi_board_info,
+ ARRAY_SIZE(sdp4430_spi_board_info));
+ omap_mcbsp_init();
+ sdp4430_mmc_init();
+ sdp4430_display_init();
+ omap_kp_init();
+ omap_phoenix_init();
+ omap_abe_init();
+
}
static void __init omap_4430sdp_map_io(void)
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index ea383f88cb1b..18353ef82a45 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -23,7 +23,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/io.h>
#include <linux/smsc911x.h>
@@ -101,7 +101,7 @@ static int ldp_twl4030_keymap[] = {
0
};
-static struct twl4030_keypad_data ldp_kp_twl4030_data = {
+static struct twl_keypad_data ldp_kp_twl4030_data = {
.rows = 6,
.cols = 6,
.keymap = ldp_twl4030_keymap,
@@ -294,17 +294,17 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
{ OMAP_TAG_LCD, &ldp_lcd_config },
};
-static struct twl4030_usb_data ldp_usb_data = {
+static struct twl_usb_data ldp_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
-static struct twl4030_gpio_platform_data ldp_gpio_data = {
+static struct twl_gpio_platform_data ldp_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
};
-static struct twl4030_madc_platform_data ldp_madc_data = {
+static struct twl_madc_platform_data ldp_madc_data = {
.irq_line = 1,
};
@@ -327,7 +327,7 @@ static struct regulator_init_data ldp_vmmc1 = {
.consumer_supplies = &ldp_vmmc1_supply,
};
-static struct twl4030_platform_data ldp_twldata = {
+static struct twl_platform_data ldp_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index e00ba128cece..d3b7164facd6 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -29,7 +29,7 @@
#include <linux/mtd/nand.h>
#include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -169,7 +169,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
return 0;
}
-static struct twl4030_gpio_platform_data beagle_gpio_data = {
+static struct twl_gpio_platform_data beagle_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
@@ -249,7 +249,7 @@ static struct regulator_init_data beagle_vpll2 = {
.consumer_supplies = &beagle_vdvi_supply,
};
-static struct twl4030_platform_data beagle_twldata = {
+static struct twl_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 864ee3d021f7..e0d080974e93 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -24,7 +24,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/leds.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
@@ -180,7 +180,7 @@ static int pandora_keypad_map[] = {
KEY(5, 2, KEY_FN),
};
-static struct twl4030_keypad_data pandora_kp_data = {
+static struct twl_keypad_data pandora_kp_data = {
.rows = 8,
.cols = 6,
.keymap = pandora_keypad_map,
@@ -240,7 +240,7 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,
return 0;
}
-static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
+static struct twl_gpio_platform_data omap3pandora_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
@@ -277,11 +277,11 @@ static struct regulator_init_data pandora_vmmc2 = {
.consumer_supplies = &pandora_vmmc2_supply,
};
-static struct twl4030_usb_data omap3pandora_usb_data = {
+static struct twl_usb_data omap3pandora_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
-static struct twl4030_platform_data omap3pandora_twldata = {
+static struct twl_platform_data omap3pandora_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
.gpio = &omap3pandora_gpio_data,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 6bce23004aa4..e6b1f5d0faa1 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -26,7 +26,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/regulator/machine.h>
#include <linux/mtd/mtd.h>
@@ -307,14 +307,14 @@ static int overo_twl_gpio_setup(struct device *dev,
return 0;
}
-static struct twl4030_gpio_platform_data overo_gpio_data = {
+static struct twl_gpio_platform_data overo_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
.setup = overo_twl_gpio_setup,
};
-static struct twl4030_usb_data overo_usb_data = {
+static struct twl_usb_data overo_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -334,7 +334,7 @@ static struct regulator_init_data overo_vmmc1 = {
/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
-static struct twl4030_platform_data overo_twldata = {
+static struct twl_platform_data overo_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
.gpio = &overo_gpio_data,
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 456e2ad5f621..b53bc9344987 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -46,6 +46,12 @@
/* Possible error results from _dpll_test_mult */
#define DPLL_MULT_UNDERFLOW -1
+/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
+#define DPLL_AUTOIDLE_DISABLE 0x0
+#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1
+
+#define MAX_DPLL_WAIT_TRIES 1000000
+
/*
* Scale factor to mitigate roundoff errors in DPLL rate rounding.
* The higher the scale factor, the greater the risk of arithmetic overflow,
@@ -70,9 +76,41 @@
u8 cpu_mask;
/*-------------------------------------------------------------------------
- * OMAP2/3 specific clock functions
+ * OMAP2/3/4 specific clock functions
*-------------------------------------------------------------------------*/
+void omap2_init_dpll_parent(struct clk *clk)
+{
+ u32 v;
+ struct dpll_data *dd;
+
+ dd = clk->dpll_data;
+ if (!dd)
+ return;
+
+ /* Return bypass rate if DPLL is bypassed */
+ v = __raw_readl(dd->control_reg);
+ v &= dd->enable_mask;
+ v >>= __ffs(dd->enable_mask);
+
+ /* Reparent in case the dpll is in bypass */
+ if (cpu_is_omap24xx()) {
+ if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
+ v == OMAP2XXX_EN_DPLL_FRBYPASS)
+ clk_reparent(clk, dd->clk_bypass);
+ } else if (cpu_is_omap34xx()) {
+ if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
+ v == OMAP3XXX_EN_DPLL_FRBYPASS)
+ clk_reparent(clk, dd->clk_bypass);
+ } else if (cpu_is_omap44xx()) {
+ if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
+ v == OMAP4XXX_EN_DPLL_FRBYPASS ||
+ v == OMAP4XXX_EN_DPLL_MNBYPASS)
+ clk_reparent(clk, dd->clk_bypass);
+ }
+ return;
+}
+
/**
* _omap2xxx_clk_commit - commit clock parent/rate changes in hardware
* @clk: struct clk *
@@ -149,6 +187,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
* clockdomain pointer, and save it into the struct clk. Intended to be
* called during clk_register(). No return value.
*/
+#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
void omap2_init_clk_clkdm(struct clk *clk)
{
struct clockdomain *clkdm;
@@ -166,6 +205,7 @@ void omap2_init_clk_clkdm(struct clk *clk)
"clkdm %s\n", clk->name, clk->clkdm_name);
}
}
+#endif
/**
* omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
@@ -247,6 +287,11 @@ u32 omap2_get_dpll_rate(struct clk *clk)
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
return dd->clk_bypass->rate;
+ } else if (cpu_is_omap44xx()) {
+ if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
+ v == OMAP4XXX_EN_DPLL_FRBYPASS ||
+ v == OMAP4XXX_EN_DPLL_MNBYPASS)
+ return dd->clk_bypass->rate;
}
v = __raw_readl(dd->mult_div1_reg);
@@ -437,8 +482,10 @@ void omap2_clk_disable(struct clk *clk)
_omap2_clk_disable(clk);
if (clk->parent)
omap2_clk_disable(clk->parent);
+#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_disable(clk->clkdm, clk);
+#endif
}
}
@@ -448,8 +495,10 @@ int omap2_clk_enable(struct clk *clk)
int ret = 0;
if (clk->usecount++ == 0) {
+#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_enable(clk->clkdm, clk);
+#endif
if (clk->parent) {
ret = omap2_clk_enable(clk->parent);
@@ -468,8 +517,10 @@ int omap2_clk_enable(struct clk *clk)
return ret;
err:
+#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_disable(clk->clkdm, clk);
+#endif
clk->usecount--;
return ret;
}
@@ -1023,6 +1074,500 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
}
/*-------------------------------------------------------------------------
+ * OMAP3/4 specific clock functions
+ *-------------------------------------------------------------------------*/
+
+/**
+ * omap3_dpll_recalc - recalculate DPLL rate
+ * @clk: DPLL struct clk
+ *
+ * Recalculate and propagate the DPLL rate.
+ */
+unsigned long omap3_dpll_recalc(struct clk *clk)
+{
+ return omap2_get_dpll_rate(clk);
+}
+
+/**
+ * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
+ * @clk: DPLL output struct clk
+ *
+ * Using parent clock DPLL data, look up DPLL state. If locked, set our
+ * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
+ */
+unsigned long omap3_clkoutx2_recalc(struct clk *clk)
+{
+ const struct dpll_data *dd;
+ unsigned long rate;
+ u32 v;
+ struct clk *pclk;
+
+ /* Walk up the parents of clk, looking for a DPLL */
+ pclk = clk->parent;
+ while (pclk && !pclk->dpll_data)
+ pclk = pclk->parent;
+
+ /* clk does not have a DPLL as a parent? */
+ WARN_ON(!pclk);
+
+ dd = pclk->dpll_data;
+
+ WARN_ON(!dd->enable_mask);
+
+ v = __raw_readl(dd->control_reg) & dd->enable_mask;
+ v >>= __ffs(dd->enable_mask);
+ if (v != OMAP3XXX_EN_DPLL_LOCKED)
+ rate = clk->parent->rate;
+ else
+ rate = clk->parent->rate * 2;
+ return rate;
+}
+
+/**
+ * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
+ * @clk: struct clk * of the DPLL to read
+ *
+ * Return the DPLL's autoidle bits, shifted down to bit 0. Returns
+ * -EINVAL if passed a null pointer or if the struct clk does not
+ * appear to refer to a DPLL.
+ */
+static u32 omap3_dpll_autoidle_read(struct clk *clk)
+{
+ const struct dpll_data *dd;
+ u32 v;
+
+ if (!clk || !clk->dpll_data)
+ return -EINVAL;
+
+ dd = clk->dpll_data;
+
+ v = __raw_readl(dd->autoidle_reg);
+ v &= dd->autoidle_mask;
+ v >>= __ffs(dd->autoidle_mask);
+
+ return v;
+}
+
+/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
+static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
+{
+ const struct dpll_data *dd;
+ u32 v;
+
+ dd = clk->dpll_data;
+
+ v = __raw_readl(dd->control_reg);
+ v &= ~dd->enable_mask;
+ v |= clken_bits << __ffs(dd->enable_mask);
+ __raw_writel(v, dd->control_reg);
+}
+
+/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
+static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
+{
+ const struct dpll_data *dd;
+ int i = 0;
+ int ret = -EINVAL;
+
+ dd = clk->dpll_data;
+
+ state <<= __ffs(dd->idlest_mask);
+
+ while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
+ i < MAX_DPLL_WAIT_TRIES) {
+ i++;
+ udelay(1);
+ }
+
+ if (i == MAX_DPLL_WAIT_TRIES) {
+ printk(KERN_ERR "clock: %s failed transition to '%s'\n",
+ clk->name, (state) ? "locked" : "bypassed");
+ } else {
+ pr_debug("clock: %s transition to '%s' in %d loops\n",
+ clk->name, (state) ? "locked" : "bypassed", i);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * omap3_dpll_allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control. This automatic idle mode
+ * switching takes effect only when the DPLL is locked, at least on
+ * OMAP3430. The DPLL will enter low-power stop when its downstream
+ * clocks are gated. No return value.
+ */
+static void omap3_dpll_allow_idle(struct clk *clk)
+{
+ const struct dpll_data *dd;
+ u32 v;
+
+ if (!clk || !clk->dpll_data)
+ return;
+
+ dd = clk->dpll_data;
+
+ /*
+ * REVISIT: CORE DPLL can optionally enter low-power bypass
+ * by writing 0x5 instead of 0x1. Add some mechanism to
+ * optionally enter this mode.
+ */
+ v = __raw_readl(dd->autoidle_reg);
+ v &= ~dd->autoidle_mask;
+ v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
+ __raw_writel(v, dd->autoidle_reg);
+}
+
+/**
+ * omap3_dpll_deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control. No return value.
+ */
+static void omap3_dpll_deny_idle(struct clk *clk)
+{
+ const struct dpll_data *dd;
+ u32 v;
+
+ if (!clk || !clk->dpll_data)
+ return;
+
+ dd = clk->dpll_data;
+
+ v = __raw_readl(dd->autoidle_reg);
+ v &= ~dd->autoidle_mask;
+ v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
+ __raw_writel(v, dd->autoidle_reg);
+}
+
+/*
+ * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power bypass mode. In
+ * bypass mode, the DPLL's rate is set equal to its parent clock's
+ * rate. Waits for the DPLL to report readiness before returning.
+ * Will save and restore the DPLL's autoidle state across the enable,
+ * per the CDP code. If the DPLL entered bypass mode successfully,
+ * return 0; if the DPLL did not enter bypass in the time allotted, or
+ * DPLL3 was passed in, or the DPLL does not support low-power bypass,
+ * return -EINVAL.
+ */
+static int _omap3_noncore_dpll_bypass(struct clk *clk)
+{
+ int r;
+ u8 ai;
+
+ if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
+ return -EINVAL;
+
+ pr_debug("clock: configuring DPLL %s for low-power bypass\n",
+ clk->name);
+
+ ai = omap3_dpll_autoidle_read(clk);
+
+ _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
+
+ r = _omap3_wait_dpll_status(clk, 0);
+
+ if (ai)
+ omap3_dpll_allow_idle(clk);
+ else
+ omap3_dpll_deny_idle(clk);
+
+ return r;
+}
+
+/* From 3430 TRM ES2 4.7.6.2 */
+static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
+{
+ unsigned long fint;
+ u16 f = 0;
+
+ fint = clk->dpll_data->clk_ref->rate / (n + 1);
+
+ pr_debug("clock: fint is %lu\n", fint);
+
+ if (fint >= 750000 && fint <= 1000000)
+ f = 0x3;
+ else if (fint > 1000000 && fint <= 1250000)
+ f = 0x4;
+ else if (fint > 1250000 && fint <= 1500000)
+ f = 0x5;
+ else if (fint > 1500000 && fint <= 1750000)
+ f = 0x6;
+ else if (fint > 1750000 && fint <= 2100000)
+ f = 0x7;
+ else if (fint > 7500000 && fint <= 10000000)
+ f = 0xB;
+ else if (fint > 10000000 && fint <= 12500000)
+ f = 0xC;
+ else if (fint > 12500000 && fint <= 15000000)
+ f = 0xD;
+ else if (fint > 15000000 && fint <= 17500000)
+ f = 0xE;
+ else if (fint > 17500000 && fint <= 21000000)
+ f = 0xF;
+ else
+ pr_debug("clock: unknown freqsel setting for %d\n", n);
+
+ return f;
+}
+
+/*
+ * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report
+ * readiness before returning. Will save and restore the DPLL's
+ * autoidle state across the enable, per the CDP code. If the DPLL
+ * locked successfully, return 0; if the DPLL did not lock in the time
+ * allotted, or DPLL3 was passed in, return -EINVAL.
+ */
+static int _omap3_noncore_dpll_lock(struct clk *clk)
+{
+ u8 ai;
+ int r;
+
+ pr_debug("clock: locking DPLL %s\n", clk->name);
+
+ ai = omap3_dpll_autoidle_read(clk);
+
+ omap3_dpll_deny_idle(clk);
+
+ _omap3_dpll_write_clken(clk, DPLL_LOCKED);
+
+ r = _omap3_wait_dpll_status(clk, 1);
+
+ if (ai)
+ omap3_dpll_allow_idle(clk);
+
+ return r;
+}
+
+
+/*
+ * omap3_noncore_dpll_program - set non-core DPLL M,N values directly
+ * @clk: struct clk * of DPLL to set
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ * @freqsel: FREQSEL value to set
+ *
+ * Program the DPLL with the supplied M, N values, and wait for the DPLL to
+ * lock.. Returns -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
+{
+ struct dpll_data *dd = clk->dpll_data;
+ u32 v;
+
+ /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
+ _omap3_noncore_dpll_bypass(clk);
+
+ if (!cpu_is_omap44xx()) {
+ /* Set jitter correction */
+ v = __raw_readl(dd->control_reg);
+ v &= ~dd->freqsel_mask;
+ v |= freqsel << __ffs(dd->freqsel_mask);
+ __raw_writel(v, dd->control_reg);
+ }
+
+ /* Set DPLL multiplier, divider */
+ v = __raw_readl(dd->mult_div1_reg);
+ v &= ~(dd->mult_mask | dd->div1_mask);
+ v |= m << __ffs(dd->mult_mask);
+ v |= (n - 1) << __ffs(dd->div1_mask);
+ __raw_writel(v, dd->mult_div1_reg);
+
+ /* We let the clock framework set the other output dividers later */
+
+ /* REVISIT: Set ramp-up delay? */
+
+ _omap3_noncore_dpll_lock(clk);
+
+ return 0;
+}
+
+/**
+ * omap3_noncore_dpll_set_rate - set non-core DPLL rate
+ * @clk: struct clk * of DPLL to set
+ * @rate: rounded target rate
+ *
+ * Set the DPLL CLKOUT to the target rate. If the DPLL can enter
+ * low-power bypass, and the target rate is the bypass source clock
+ * rate, then configure the DPLL for bypass. Otherwise, round the
+ * target rate if it hasn't been done already, then program and lock
+ * the DPLL. Returns -EINVAL upon error, or 0 upon success.
+ */
+int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *new_parent = NULL;
+ u16 freqsel;
+ struct dpll_data *dd;
+ int ret;
+
+ if (!clk || !rate)
+ return -EINVAL;
+
+ dd = clk->dpll_data;
+ if (!dd)
+ return -EINVAL;
+
+ if (rate == omap2_get_dpll_rate(clk))
+ return 0;
+
+ /*
+ * Ensure both the bypass and ref clocks are enabled prior to
+ * doing anything; we need the bypass clock running to reprogram
+ * the DPLL.
+ */
+ omap2_clk_enable(dd->clk_bypass);
+ omap2_clk_enable(dd->clk_ref);
+
+ if (dd->clk_bypass->rate == rate &&
+ (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+ pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
+
+ ret = _omap3_noncore_dpll_bypass(clk);
+ if (!ret)
+ new_parent = dd->clk_bypass;
+ } else {
+ if (dd->last_rounded_rate != rate)
+ omap2_dpll_round_rate(clk, rate);
+
+ if (dd->last_rounded_rate == 0)
+ return -EINVAL;
+
+ /* No freqsel on OMAP4 */
+ if (!cpu_is_omap44xx()) {
+ freqsel = _omap3_dpll_compute_freqsel(clk,
+ dd->last_rounded_n);
+ if (!freqsel)
+ WARN_ON(1);
+ }
+
+ pr_debug("clock: %s: set rate: locking rate to %lu.\n",
+ clk->name, rate);
+
+ ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
+ dd->last_rounded_n, freqsel);
+ if (!ret)
+ new_parent = dd->clk_ref;
+ }
+ if (!ret) {
+ /*
+ * Switch the parent clock in the heirarchy, and make sure
+ * that the new parent's usecount is correct. Note: we
+ * enable the new parent before disabling the old to avoid
+ * any unnecessary hardware disable->enable transitions.
+ */
+ if (clk->usecount) {
+ omap2_clk_enable(new_parent);
+ omap2_clk_disable(clk->parent);
+ }
+ clk_reparent(clk, new_parent);
+ clk->rate = rate;
+ }
+ omap2_clk_disable(dd->clk_ref);
+ omap2_clk_disable(dd->clk_bypass);
+
+ return 0;
+}
+
+/*
+ * _omap3_noncore_dpll_stop - instruct a DPLL to stop
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power stop. Will save and
+ * restore the DPLL's autoidle state across the stop, per the CDP
+ * code. If DPLL3 was passed in, or the DPLL does not support
+ * low-power stop, return -EINVAL; otherwise, return 0.
+ */
+static int _omap3_noncore_dpll_stop(struct clk *clk)
+{
+ u8 ai;
+
+ if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
+ return -EINVAL;
+
+ pr_debug("clock: stopping DPLL %s\n", clk->name);
+
+ ai = omap3_dpll_autoidle_read(clk);
+
+ _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
+
+ if (ai)
+ omap3_dpll_allow_idle(clk);
+ else
+ omap3_dpll_deny_idle(clk);
+
+ return 0;
+}
+
+/**
+ * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
+ * The choice of modes depends on the DPLL's programmed rate: if it is
+ * the same as the DPLL's parent clock, it will enter bypass;
+ * otherwise, it will enter lock. This code will wait for the DPLL to
+ * indicate readiness before returning, unless the DPLL takes too long
+ * to enter the target state. Intended to be used as the struct clk's
+ * enable function. If DPLL3 was passed in, or the DPLL does not
+ * support low-power stop, or if the DPLL took too long to enter
+ * bypass or lock, return -EINVAL; otherwise, return 0.
+ */
+int omap3_noncore_dpll_enable(struct clk *clk)
+{
+ int r;
+ struct dpll_data *dd;
+
+ dd = clk->dpll_data;
+ if (!dd)
+ return -EINVAL;
+
+ if (clk->rate == dd->clk_bypass->rate) {
+ WARN_ON(clk->parent != dd->clk_bypass);
+ r = _omap3_noncore_dpll_bypass(clk);
+ } else {
+ WARN_ON(clk->parent != dd->clk_ref);
+ r = _omap3_noncore_dpll_lock(clk);
+ }
+ /* FIXME: this is dubious - if clk->rate has changed, what about propagating? */
+ if (!r)
+ clk->rate = omap2_get_dpll_rate(clk);
+
+ return r;
+}
+
+/**
+ * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
+ * The choice of modes depends on the DPLL's programmed rate: if it is
+ * the same as the DPLL's parent clock, it will enter bypass;
+ * otherwise, it will enter lock. This code will wait for the DPLL to
+ * indicate readiness before returning, unless the DPLL takes too long
+ * to enter the target state. Intended to be used as the struct clk's
+ * enable function. If DPLL3 was passed in, or the DPLL does not
+ * support low-power stop, or if the DPLL took too long to enter
+ * bypass or lock, return -EINVAL; otherwise, return 0.
+ */
+void omap3_noncore_dpll_disable(struct clk *clk)
+{
+ _omap3_noncore_dpll_stop(clk);
+}
+
+
+/* Non-CORE DPLL rate set code */
+
+/*-------------------------------------------------------------------------
* Omap2 clock reset and init functions
*-------------------------------------------------------------------------*/
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 9ae7540f8af2..325aee689770 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -36,6 +36,17 @@
#define OMAP3XXX_EN_DPLL_FRBYPASS 0x6
#define OMAP3XXX_EN_DPLL_LOCKED 0x7
+/* OMAP4xxx CM_CLKMODE_DPLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */
+#define OMAP4XXX_EN_DPLL_MNBYPASS 0x4
+#define OMAP4XXX_EN_DPLL_LPBYPASS 0x5
+#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6
+#define OMAP4XXX_EN_DPLL_LOCKED 0x7
+
+/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
+#define DPLL_LOW_POWER_STOP 0x1
+#define DPLL_LOW_POWER_BYPASS 0x5
+#define DPLL_LOCKED 0x7
+
int omap2_clk_init(void);
int omap2_clk_enable(struct clk *clk);
void omap2_clk_disable(struct clk *clk);
@@ -63,10 +74,13 @@ unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
u32 omap2_get_dpll_rate(struct clk *clk);
+void omap2_init_dpll_parent(struct clk *clk);
int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
void omap2_clk_prepare_for_reboot(void);
int omap2_dflt_clk_enable(struct clk *clk);
void omap2_dflt_clk_disable(struct clk *clk);
+int omap3_noncore_dpll_enable(struct clk *clk);
+void omap3_noncore_dpll_disable(struct clk *clk);
void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
u8 *other_bit);
void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
@@ -80,11 +94,13 @@ extern u8 cpu_mask;
/* clksel_rate data common to 24xx/343x */
static const struct clksel_rate gpt_32k_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
{ .div = 0 }
};
static const struct clksel_rate gpt_sys_rates[] = {
{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
{ .div = 0 }
};
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index bc5d3ac66611..7e6eea5cd54a 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = {
CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
/* DSS domain clocks */
- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X),
- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
+ LK("omapdss", "ick", &dss_ick, CK_243X | CK_242X),
+ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
+ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
+ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
/* L3 domain clocks */
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X),
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X),
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index cd7819cc0c9e..97561e0f0e9f 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -235,13 +235,13 @@ static struct omap_clk omap34xx_clks[] = {
CLK("omap_rng", "ick", &rng_ick, CK_343X),
CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
CLK(NULL, "des1_ick", &des1_ick, CK_343X),
- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X),
- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X),
- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X),
- CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1),
- CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2),
+ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
+ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
+ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
+ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
+ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
+ CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
+ CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2),
CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
CLK(NULL, "cam_ick", &cam_ick, CK_343X),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
@@ -315,12 +315,6 @@ static struct omap_clk omap34xx_clks[] = {
CLK(NULL, "wdt1_fck", &wdt1_fck, CK_343X),
};
-/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
-#define DPLL_AUTOIDLE_DISABLE 0x0
-#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1
-
-#define MAX_DPLL_WAIT_TRIES 1000000
-
#define MIN_SDRC_DLL_LOCK_FREQ 83000000
#define CYCLES_PER_MHZ 1000000
@@ -337,8 +331,7 @@ static struct omap_clk omap34xx_clks[] = {
*/
#define SDRC_MPURATE_LOOPS 96
-/**
- * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
+/* omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
* @clk: struct clk * being enabled
* @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
* @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
@@ -404,394 +397,6 @@ static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
*idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
}
-/**
- * omap3_dpll_recalc - recalculate DPLL rate
- * @clk: DPLL struct clk
- *
- * Recalculate and propagate the DPLL rate.
- */
-static unsigned long omap3_dpll_recalc(struct clk *clk)
-{
- return omap2_get_dpll_rate(clk);
-}
-
-/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
-static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
-{
- const struct dpll_data *dd;
- u32 v;
-
- dd = clk->dpll_data;
-
- v = __raw_readl(dd->control_reg);
- v &= ~dd->enable_mask;
- v |= clken_bits << __ffs(dd->enable_mask);
- __raw_writel(v, dd->control_reg);
-}
-
-/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
-static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
-{
- const struct dpll_data *dd;
- int i = 0;
- int ret = -EINVAL;
-
- dd = clk->dpll_data;
-
- state <<= __ffs(dd->idlest_mask);
-
- while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
- i < MAX_DPLL_WAIT_TRIES) {
- i++;
- udelay(1);
- }
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- printk(KERN_ERR "clock: %s failed transition to '%s'\n",
- clk->name, (state) ? "locked" : "bypassed");
- } else {
- pr_debug("clock: %s transition to '%s' in %d loops\n",
- clk->name, (state) ? "locked" : "bypassed", i);
-
- ret = 0;
- }
-
- return ret;
-}
-
-/* From 3430 TRM ES2 4.7.6.2 */
-static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
-{
- unsigned long fint;
- u16 f = 0;
-
- fint = clk->dpll_data->clk_ref->rate / (n + 1);
-
- pr_debug("clock: fint is %lu\n", fint);
-
- if (fint >= 750000 && fint <= 1000000)
- f = 0x3;
- else if (fint > 1000000 && fint <= 1250000)
- f = 0x4;
- else if (fint > 1250000 && fint <= 1500000)
- f = 0x5;
- else if (fint > 1500000 && fint <= 1750000)
- f = 0x6;
- else if (fint > 1750000 && fint <= 2100000)
- f = 0x7;
- else if (fint > 7500000 && fint <= 10000000)
- f = 0xB;
- else if (fint > 10000000 && fint <= 12500000)
- f = 0xC;
- else if (fint > 12500000 && fint <= 15000000)
- f = 0xD;
- else if (fint > 15000000 && fint <= 17500000)
- f = 0xE;
- else if (fint > 17500000 && fint <= 21000000)
- f = 0xF;
- else
- pr_debug("clock: unknown freqsel setting for %d\n", n);
-
- return f;
-}
-
-/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
-
-/*
- * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report
- * readiness before returning. Will save and restore the DPLL's
- * autoidle state across the enable, per the CDP code. If the DPLL
- * locked successfully, return 0; if the DPLL did not lock in the time
- * allotted, or DPLL3 was passed in, return -EINVAL.
- */
-static int _omap3_noncore_dpll_lock(struct clk *clk)
-{
- u8 ai;
- int r;
-
- if (clk == &dpll3_ck)
- return -EINVAL;
-
- pr_debug("clock: locking DPLL %s\n", clk->name);
-
- ai = omap3_dpll_autoidle_read(clk);
-
- omap3_dpll_deny_idle(clk);
-
- _omap3_dpll_write_clken(clk, DPLL_LOCKED);
-
- r = _omap3_wait_dpll_status(clk, 1);
-
- if (ai)
- omap3_dpll_allow_idle(clk);
-
- return r;
-}
-
-/*
- * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enter low-power bypass mode. In
- * bypass mode, the DPLL's rate is set equal to its parent clock's
- * rate. Waits for the DPLL to report readiness before returning.
- * Will save and restore the DPLL's autoidle state across the enable,
- * per the CDP code. If the DPLL entered bypass mode successfully,
- * return 0; if the DPLL did not enter bypass in the time allotted, or
- * DPLL3 was passed in, or the DPLL does not support low-power bypass,
- * return -EINVAL.
- */
-static int _omap3_noncore_dpll_bypass(struct clk *clk)
-{
- int r;
- u8 ai;
-
- if (clk == &dpll3_ck)
- return -EINVAL;
-
- if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
- return -EINVAL;
-
- pr_debug("clock: configuring DPLL %s for low-power bypass\n",
- clk->name);
-
- ai = omap3_dpll_autoidle_read(clk);
-
- _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
-
- r = _omap3_wait_dpll_status(clk, 0);
-
- if (ai)
- omap3_dpll_allow_idle(clk);
- else
- omap3_dpll_deny_idle(clk);
-
- return r;
-}
-
-/*
- * _omap3_noncore_dpll_stop - instruct a DPLL to stop
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enter low-power stop. Will save and
- * restore the DPLL's autoidle state across the stop, per the CDP
- * code. If DPLL3 was passed in, or the DPLL does not support
- * low-power stop, return -EINVAL; otherwise, return 0.
- */
-static int _omap3_noncore_dpll_stop(struct clk *clk)
-{
- u8 ai;
-
- if (clk == &dpll3_ck)
- return -EINVAL;
-
- if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
- return -EINVAL;
-
- pr_debug("clock: stopping DPLL %s\n", clk->name);
-
- ai = omap3_dpll_autoidle_read(clk);
-
- _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
-
- if (ai)
- omap3_dpll_allow_idle(clk);
- else
- omap3_dpll_deny_idle(clk);
-
- return 0;
-}
-
-/**
- * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
- * The choice of modes depends on the DPLL's programmed rate: if it is
- * the same as the DPLL's parent clock, it will enter bypass;
- * otherwise, it will enter lock. This code will wait for the DPLL to
- * indicate readiness before returning, unless the DPLL takes too long
- * to enter the target state. Intended to be used as the struct clk's
- * enable function. If DPLL3 was passed in, or the DPLL does not
- * support low-power stop, or if the DPLL took too long to enter
- * bypass or lock, return -EINVAL; otherwise, return 0.
- */
-static int omap3_noncore_dpll_enable(struct clk *clk)
-{
- int r;
- struct dpll_data *dd;
-
- if (clk == &dpll3_ck)
- return -EINVAL;
-
- dd = clk->dpll_data;
- if (!dd)
- return -EINVAL;
-
- if (clk->rate == dd->clk_bypass->rate) {
- WARN_ON(clk->parent != dd->clk_bypass);
- r = _omap3_noncore_dpll_bypass(clk);
- } else {
- WARN_ON(clk->parent != dd->clk_ref);
- r = _omap3_noncore_dpll_lock(clk);
- }
- /* FIXME: this is dubious - if clk->rate has changed, what about propagating? */
- if (!r)
- clk->rate = omap2_get_dpll_rate(clk);
-
- return r;
-}
-
-/**
- * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
- * @clk: pointer to a DPLL struct clk
- *
- * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
- * The choice of modes depends on the DPLL's programmed rate: if it is
- * the same as the DPLL's parent clock, it will enter bypass;
- * otherwise, it will enter lock. This code will wait for the DPLL to
- * indicate readiness before returning, unless the DPLL takes too long
- * to enter the target state. Intended to be used as the struct clk's
- * enable function. If DPLL3 was passed in, or the DPLL does not
- * support low-power stop, or if the DPLL took too long to enter
- * bypass or lock, return -EINVAL; otherwise, return 0.
- */
-static void omap3_noncore_dpll_disable(struct clk *clk)
-{
- if (clk == &dpll3_ck)
- return;
-
- _omap3_noncore_dpll_stop(clk);
-}
-
-
-/* Non-CORE DPLL rate set code */
-
-/*
- * omap3_noncore_dpll_program - set non-core DPLL M,N values directly
- * @clk: struct clk * of DPLL to set
- * @m: DPLL multiplier to set
- * @n: DPLL divider to set
- * @freqsel: FREQSEL value to set
- *
- * Program the DPLL with the supplied M, N values, and wait for the DPLL to
- * lock.. Returns -EINVAL upon error, or 0 upon success.
- */
-static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
-{
- struct dpll_data *dd = clk->dpll_data;
- u32 v;
-
- /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
- _omap3_noncore_dpll_bypass(clk);
-
- /* Set jitter correction */
- v = __raw_readl(dd->control_reg);
- v &= ~dd->freqsel_mask;
- v |= freqsel << __ffs(dd->freqsel_mask);
- __raw_writel(v, dd->control_reg);
-
- /* Set DPLL multiplier, divider */
- v = __raw_readl(dd->mult_div1_reg);
- v &= ~(dd->mult_mask | dd->div1_mask);
- v |= m << __ffs(dd->mult_mask);
- v |= (n - 1) << __ffs(dd->div1_mask);
- __raw_writel(v, dd->mult_div1_reg);
-
- /* We let the clock framework set the other output dividers later */
-
- /* REVISIT: Set ramp-up delay? */
-
- _omap3_noncore_dpll_lock(clk);
-
- return 0;
-}
-
-/**
- * omap3_noncore_dpll_set_rate - set non-core DPLL rate
- * @clk: struct clk * of DPLL to set
- * @rate: rounded target rate
- *
- * Set the DPLL CLKOUT to the target rate. If the DPLL can enter
- * low-power bypass, and the target rate is the bypass source clock
- * rate, then configure the DPLL for bypass. Otherwise, round the
- * target rate if it hasn't been done already, then program and lock
- * the DPLL. Returns -EINVAL upon error, or 0 upon success.
- */
-static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *new_parent = NULL;
- u16 freqsel;
- struct dpll_data *dd;
- int ret;
-
- if (!clk || !rate)
- return -EINVAL;
-
- dd = clk->dpll_data;
- if (!dd)
- return -EINVAL;
-
- if (rate == omap2_get_dpll_rate(clk))
- return 0;
-
- /*
- * Ensure both the bypass and ref clocks are enabled prior to
- * doing anything; we need the bypass clock running to reprogram
- * the DPLL.
- */
- omap2_clk_enable(dd->clk_bypass);
- omap2_clk_enable(dd->clk_ref);
-
- if (dd->clk_bypass->rate == rate &&
- (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
- pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
-
- ret = _omap3_noncore_dpll_bypass(clk);
- if (!ret)
- new_parent = dd->clk_bypass;
- } else {
- if (dd->last_rounded_rate != rate)
- omap2_dpll_round_rate(clk, rate);
-
- if (dd->last_rounded_rate == 0)
- return -EINVAL;
-
- freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
- if (!freqsel)
- WARN_ON(1);
-
- pr_debug("clock: %s: set rate: locking rate to %lu.\n",
- clk->name, rate);
-
- ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
- dd->last_rounded_n, freqsel);
- if (!ret)
- new_parent = dd->clk_ref;
- }
- if (!ret) {
- /*
- * Switch the parent clock in the heirarchy, and make sure
- * that the new parent's usecount is correct. Note: we
- * enable the new parent before disabling the old to avoid
- * any unnecessary hardware disable->enable transitions.
- */
- if (clk->usecount) {
- omap2_clk_enable(new_parent);
- omap2_clk_disable(clk->parent);
- }
- clk_reparent(clk, new_parent);
- clk->rate = rate;
- }
- omap2_clk_disable(dd->clk_ref);
- omap2_clk_disable(dd->clk_bypass);
-
- return 0;
-}
-
static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
{
/*
@@ -807,7 +412,6 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
return omap3_noncore_dpll_set_rate(clk, rate);
}
-
/*
* CORE DPLL (DPLL3) rate programming functions
*
@@ -907,120 +511,8 @@ static const struct clkops clkops_noncore_dpll_ops = {
/* DPLL autoidle read/set code */
-/**
- * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
- * @clk: struct clk * of the DPLL to read
- *
- * Return the DPLL's autoidle bits, shifted down to bit 0. Returns
- * -EINVAL if passed a null pointer or if the struct clk does not
- * appear to refer to a DPLL.
- */
-static u32 omap3_dpll_autoidle_read(struct clk *clk)
-{
- const struct dpll_data *dd;
- u32 v;
-
- if (!clk || !clk->dpll_data)
- return -EINVAL;
-
- dd = clk->dpll_data;
-
- v = __raw_readl(dd->autoidle_reg);
- v &= dd->autoidle_mask;
- v >>= __ffs(dd->autoidle_mask);
-
- return v;
-}
-
-/**
- * omap3_dpll_allow_idle - enable DPLL autoidle bits
- * @clk: struct clk * of the DPLL to operate on
- *
- * Enable DPLL automatic idle control. This automatic idle mode
- * switching takes effect only when the DPLL is locked, at least on
- * OMAP3430. The DPLL will enter low-power stop when its downstream
- * clocks are gated. No return value.
- */
-static void omap3_dpll_allow_idle(struct clk *clk)
-{
- const struct dpll_data *dd;
- u32 v;
-
- if (!clk || !clk->dpll_data)
- return;
-
- dd = clk->dpll_data;
-
- /*
- * REVISIT: CORE DPLL can optionally enter low-power bypass
- * by writing 0x5 instead of 0x1. Add some mechanism to
- * optionally enter this mode.
- */
- v = __raw_readl(dd->autoidle_reg);
- v &= ~dd->autoidle_mask;
- v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
- __raw_writel(v, dd->autoidle_reg);
-}
-
-/**
- * omap3_dpll_deny_idle - prevent DPLL from automatically idling
- * @clk: struct clk * of the DPLL to operate on
- *
- * Disable DPLL automatic idle control. No return value.
- */
-static void omap3_dpll_deny_idle(struct clk *clk)
-{
- const struct dpll_data *dd;
- u32 v;
-
- if (!clk || !clk->dpll_data)
- return;
-
- dd = clk->dpll_data;
-
- v = __raw_readl(dd->autoidle_reg);
- v &= ~dd->autoidle_mask;
- v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
- __raw_writel(v, dd->autoidle_reg);
-}
-
/* Clock control for DPLL outputs */
-/**
- * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
- * @clk: DPLL output struct clk
- *
- * Using parent clock DPLL data, look up DPLL state. If locked, set our
- * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
- */
-static unsigned long omap3_clkoutx2_recalc(struct clk *clk)
-{
- const struct dpll_data *dd;
- unsigned long rate;
- u32 v;
- struct clk *pclk;
-
- /* Walk up the parents of clk, looking for a DPLL */
- pclk = clk->parent;
- while (pclk && !pclk->dpll_data)
- pclk = pclk->parent;
-
- /* clk does not have a DPLL as a parent? */
- WARN_ON(!pclk);
-
- dd = pclk->dpll_data;
-
- WARN_ON(!dd->enable_mask);
-
- v = __raw_readl(dd->control_reg) & dd->enable_mask;
- v >>= __ffs(dd->enable_mask);
- if (v != OMAP3XXX_EN_DPLL_LOCKED)
- rate = clk->parent->rate;
- else
- rate = clk->parent->rate * 2;
- return rate;
-}
-
/* Common clock code */
/*
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 57cc2725b923..2f18bde517b3 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -54,11 +54,6 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
static struct clk dpll1_fck;
static struct clk dpll2_fck;
-/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
-#define DPLL_LOW_POWER_STOP 0x1
-#define DPLL_LOW_POWER_BYPASS 0x5
-#define DPLL_LOCKED 0x7
-
/* PRM CLOCKS */
/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
diff --git a/arch/arm/mach-omap2/clock44xx.c b/arch/arm/mach-omap2/clock44xx.c
new file mode 100644
index 000000000000..5c91c208232a
--- /dev/null
+++ b/arch/arm/mach-omap2/clock44xx.c
@@ -0,0 +1,257 @@
+/*
+ * OMAP4-specific clock framework functions
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Written by Rajendra Nayak (rnayak@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 <linux/limits.h>
+#include <linux/bitops.h>
+
+#include <mach/clock.h>
+#include <mach/sram.h>
+#include <asm/div64.h>
+#include <asm/clkdev.h>
+
+#include <mach/sdrc.h>
+#include "clock.h"
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+#include "cm.h"
+#include "cm1-regbits-44xx.h"
+#include "cm2-regbits-44xx.h"
+
+static const struct clkops clkops_noncore_dpll_ops;
+
+#include "clock44xx.h"
+
+struct omap_clk {
+ u32 cpu;
+ struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck, cp) \
+ { \
+ .cpu = cp, \
+ .lk = { \
+ .dev_id = dev, \
+ .con_id = con, \
+ .clk = ck, \
+ }, \
+ }
+
+#define CK_443X (1 << 0)
+
+static struct omap_clk omap44xx_clks[] = {
+ CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_443X),
+ CLK(NULL, "pad_cks", &pad_cks, CK_443X),
+ CLK(NULL, "slimbus_ck", &slimbus_ck, CK_443X),
+ CLK(NULL, "phy_clkout_ck", &phy_clkout_ck, CK_443X),
+ CLK(NULL, "xclk_60m_otg_ck", &xclk_60m_otg_ck, CK_443X),
+ CLK(NULL, "xclk_60m_hsp1_ck", &xclk_60m_hsp1_ck, CK_443X),
+ CLK(NULL, "xclk_60m_hsp2_ck", &xclk_60m_hsp2_ck, CK_443X),
+ CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_443X),
+ CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_443X),
+ CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_443X),
+ CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_443X),
+ CLK(NULL, "virt_27m_ck", &virt_27m_ck, CK_443X),
+ CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_443X),
+ CLK(NULL, "sys_ck", &sys_ck, CK_443X),
+ CLK(NULL, "abe_dss_sys_ck", &abe_dss_sys_ck, CK_443X),
+ CLK(NULL, "dpll_sys_ref_ck", &dpll_sys_ref_ck, CK_443X),
+ CLK(NULL, "abe_dpll_alwon_ck", &abe_dpll_alwon_ck, CK_443X),
+ CLK(NULL, "gpt1_fck", &gpt1_fck, CK_443X),
+ CLK(NULL, "gpt2_fck", &gpt2_fck, CK_443X),
+ CLK(NULL, "gpt3_fck", &gpt3_fck, CK_443X),
+ CLK(NULL, "gpt4_fck", &gpt4_fck, CK_443X),
+ CLK(NULL, "gpt9_fck", &gpt9_fck, CK_443X),
+ CLK(NULL, "gpt10_fck", &gpt10_fck, CK_443X),
+ CLK(NULL, "gpt11_fck", &gpt11_fck, CK_443X),
+ CLK(NULL, "gpmc_fck", &gpmc_fck, CK_443X),
+ CLK(NULL, "dpll_abe_ck", &dpll_abe_ck, CK_443X),
+ CLK(NULL, "dpll_abe_x2_ck", &dpll_abe_x2_ck, CK_443X),
+ CLK(NULL, "dpll_abe_m2_ck", &dpll_abe_m2_ck, CK_443X),
+ CLK(NULL, "dpll_abe_x2m2_ck", &dpll_abe_x2m2_ck, CK_443X),
+ CLK(NULL, "dpll_abe_x2m3_ck", &dpll_abe_x2m3_ck, CK_443X),
+ CLK(NULL, "per_abe_x1_fck", &per_abe_x1_fck, CK_443X),
+ CLK(NULL, "dpll_abe_x2_fck", &dpll_abe_x2_fck, CK_443X),
+ CLK(NULL, "core_dpll_hs_ck", &core_dpll_hs_ck, CK_443X),
+ CLK(NULL, "per_dpll_hs_ck", &per_dpll_hs_ck, CK_443X),
+ CLK(NULL, "usb_dpll_hs_ck", &usb_dpll_hs_ck, CK_443X),
+ CLK(NULL, "abe_ck", &abe_ck, CK_443X),
+ CLK(NULL, "aess_fck", &aess_fck, CK_443X),
+ CLK(NULL, "abe_lp_ck", &abe_lp_ck, CK_443X),
+ CLK(NULL, "abe_24m_fck", &abe_24m_fck, CK_443X),
+ CLK(NULL, "abe_gpt5_fck", &abe_gpt5_fck, CK_443X),
+ CLK(NULL, "abe_gpt6_fck", &abe_gpt6_fck, CK_443X),
+ CLK(NULL, "abe_gpt7_fck", &abe_gpt7_fck, CK_443X),
+ CLK(NULL, "abe_gpt8_fck", &abe_gpt8_fck, CK_443X),
+ CLK(NULL, "mcbsp1_int_fck", &mcbsp1_int_fck, CK_443X),
+ CLK(NULL, "mcbsp2_int_fck", &mcbsp2_int_fck, CK_443X),
+ CLK(NULL, "mcbsp3_int_fck", &mcbsp3_int_fck, CK_443X),
+ CLK(NULL, "mcasp1_int_fck", &mcasp1_int_fck, CK_443X),
+ CLK(NULL, "dmic_abe_int_fck", &dmic_abe_int_fck, CK_443X),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_443X),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_443X),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_443X),
+ CLK(NULL, "mcasp1_fck", &mcasp1_fck, CK_443X),
+ CLK(NULL, "dmic_abe_fck", &dmic_abe_fck, CK_443X),
+ CLK(NULL, "per_hsd_byp_ck", &per_hsd_byp_ck, CK_443X),
+ CLK(NULL, "dpll_per_ck", &dpll_per_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2_ck", &dpll_per_x2_ck, CK_443X),
+ CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m2_ck", &dpll_per_x2m2_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m3_ck", &dpll_per_x2m3_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m4_ck", &dpll_per_x2m4_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m5_ck", &dpll_per_x2m5_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m6_ck", &dpll_per_x2m6_ck, CK_443X),
+ CLK(NULL, "dpll_per_x2m7_ck", &dpll_per_x2m7_ck, CK_443X),
+ CLK(NULL, "omap_96m_alwon_ck", &omap_96m_alwon_ck, CK_443X),
+ CLK(NULL, "omap_192m_fck", &omap_192m_fck, CK_443X),
+ CLK(NULL, "per_dpll_scrm_ck", &per_dpll_scrm_ck, CK_443X),
+ CLK(NULL, "omap_128m_fck", &omap_128m_fck, CK_443X),
+ CLK(NULL, "dss_fck", &dss_fck, CK_443X),
+ CLK(NULL, "per_mpu_m3", &per_mpu_m3, CK_443X),
+ CLK(NULL, "per_dpll_emu_ck", &per_dpll_emu_ck, CK_443X),
+ CLK(NULL, "core_phy_hsd_byp_ck", &core_phy_hsd_byp_ck, CK_443X),
+ CLK(NULL, "dpll_core_ck", &dpll_core_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck, CK_443X),
+ CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2m3_ck", &dpll_core_x2m3_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2m4_ck", &dpll_core_x2m4_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2m5_ck", &dpll_core_x2m5_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2m6_ck", &dpll_core_x2m6_ck, CK_443X),
+ CLK(NULL, "dpll_core_x2m7_ck", &dpll_core_x2m7_ck, CK_443X),
+ CLK(NULL, "phy_root_ck", &phy_root_ck, CK_443X),
+ CLK(NULL, "core_dpll_scrm_ck", &core_dpll_scrm_ck, CK_443X),
+ CLK(NULL, "dpll_x2_ck", &dpll_x2_ck, CK_443X),
+ CLK(NULL, "core_x2_ck", &core_x2_ck, CK_443X),
+ CLK(NULL, "core_dpll_emu_ck", &core_dpll_emu_ck, CK_443X),
+ CLK(NULL, "core_sgx_fck", &core_sgx_fck, CK_443X),
+ CLK(NULL, "mpu_dpll_hs_ck", &mpu_dpll_hs_ck, CK_443X),
+ CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X),
+ CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X),
+ CLK(NULL, "mpu_dpll_ck", &mpu_dpll_ck, CK_443X),
+ CLK(NULL, "iva_dpll_hs_ck", &iva_dpll_hs_ck, CK_443X),
+ CLK(NULL, "dpll_iva_ck", &dpll_iva_ck, CK_443X),
+ CLK(NULL, "dpll_iva_x2_ck", &dpll_iva_x2_ck, CK_443X),
+ CLK(NULL, "dpll_iva_x2m4_ck", &dpll_iva_x2m4_ck, CK_443X),
+ CLK(NULL, "dpll_iva_x2m5_ck", &dpll_iva_x2m5_ck, CK_443X),
+ CLK(NULL, "dsp_root_ck", &dsp_root_ck, CK_443X),
+ CLK(NULL, "ivahd_ck", &ivahd_ck, CK_443X),
+ CLK(NULL, "dpll_unipro_ck", &dpll_unipro_ck, CK_443X),
+ CLK(NULL, "dpll_unipro_x2_ck", &dpll_unipro_x2_ck, CK_443X),
+ CLK(NULL, "dpll_unipro_x2m2_ck", &dpll_unipro_x2m2_ck, CK_443X),
+ CLK(NULL, "unipro1_phy_fck", &unipro1_phy_fck, CK_443X),
+ CLK(NULL, "dpll_usb_ck", &dpll_usb_ck, CK_443X),
+ CLK(NULL, "dpll_usb_m2_ck", &dpll_usb_m2_ck, CK_443X),
+ CLK(NULL, "init_480m_fck", &init_480m_fck, CK_443X),
+ CLK(NULL, "dpll_usb_clkdcoldo", &dpll_usb_clkdcoldo, CK_443X),
+ CLK(NULL, "init_960m_fck", &init_960m_fck, CK_443X),
+ CLK(NULL, "init_60m_fck", &init_60m_fck, CK_443X),
+ CLK(NULL, "utmi_p3_fck", &utmi_p3_fck, CK_443X),
+ CLK(NULL, "init_60m_p1_fck", &init_60m_p1_fck, CK_443X),
+ CLK(NULL, "init_60m_p2_fck", &init_60m_p2_fck, CK_443X),
+ CLK(NULL, "utmi_root_gfck", &utmi_root_gfck, CK_443X),
+ CLK(NULL, "tll_ch0_fck", &tll_ch0_fck, CK_443X),
+ CLK(NULL, "tll_ch1_fck", &tll_ch1_fck, CK_443X),
+ CLK(NULL, "tll_ch2_fck", &tll_ch2_fck, CK_443X),
+ CLK(NULL, "hsic_p1_480m_fck", &hsic_p1_480m_fck, CK_443X),
+ CLK(NULL, "hsic_p2_480m_fck", &hsic_p2_480m_fck, CK_443X),
+ CLK(NULL, "otg_60m_fck", &otg_60m_fck, CK_443X),
+ CLK(NULL, "utmi_p1_fck", &utmi_p1_fck, CK_443X),
+ CLK(NULL, "utmi_p2_fck", &utmi_p2_fck, CK_443X),
+ CLK(NULL, "core_ck", &core_ck, CK_443X),
+ CLK(NULL, "l3_ick", &l3_ick, CK_443X),
+ CLK(NULL, "l4_root_ck", &l4_root_ck, CK_443X),
+ CLK(NULL, "per_24m_fck", &per_24m_fck, CK_443X),
+ CLK(NULL, "fdif_fck", &fdif_fck, CK_443X),
+ CLK(NULL, "hsi_fck", &hsi_fck, CK_443X),
+ CLK(NULL, "mpu_m3_iss_ck", &mpu_m3_iss_ck, CK_443X),
+};
+
+static struct clk_functions omap2_clk_functions = {
+ .clk_enable = omap2_clk_enable,
+ .clk_disable = omap2_clk_disable,
+ .clk_round_rate = omap2_clk_round_rate,
+ .clk_set_rate = omap2_clk_set_rate,
+ .clk_set_parent = omap2_clk_set_parent,
+ .clk_disable_unused = omap2_clk_disable_unused,
+};
+
+static const struct clkops clkops_noncore_dpll_ops = {
+ .enable = &omap3_noncore_dpll_enable,
+ .disable = &omap3_noncore_dpll_disable,
+};
+
+void omap2_clk_prepare_for_reboot(void)
+{
+ return;
+}
+
+static int __init omap2_clk_arch_init(void)
+{
+ if (!mpurate)
+ return -EINVAL;
+
+ recalculate_root_clocks();
+ return 0;
+}
+arch_initcall(omap2_clk_arch_init);
+
+int __init omap2_clk_init(void)
+{
+ /* struct prcm_config *prcm; */
+ struct omap_clk *c;
+ /* u32 clkrate; */
+ u32 cpu_clkflg;
+
+ /*
+ * FIXME: This is needed only on Virtio.
+ * set the sysclk speed to 38.4Mhz.
+ */
+ __raw_writel(0x6, OMAP4430_CM_SYS_CLKSEL);
+
+ if (cpu_is_omap44xx()) {
+ cpu_mask = RATE_IN_443X;
+ cpu_clkflg = CK_443X;
+ }
+
+ clk_init(&omap2_clk_functions);
+
+ for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks); c++)
+ clk_preinit(c->lk.clk);
+
+ for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks); c++)
+ if (c->cpu & cpu_clkflg) {
+ clkdev_add(&c->lk);
+ clk_register(c->lk.clk);
+ /* TODO
+ omap2_init_clk_clkdm(c->lk.clk);
+ */
+ }
+
+ recalculate_root_clocks();
+
+ /*
+ * Only enable those clocks we will need, let the drivers
+ * enable other clocks as necessary
+ */
+ clk_enable_init_clocks();
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
new file mode 100644
index 000000000000..58f569c29749
--- /dev/null
+++ b/arch/arm/mach-omap2/clock44xx.h
@@ -0,0 +1,1787 @@
+/*
+ * OMAP4 clock framework
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Written by Rajendra Nayak (rnayak@ti.com)
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
+
+#include <mach/control.h>
+
+#include "clock.h"
+#include "cm.h"
+#include "cm1-regbits-44xx.h"
+#include "cm2-regbits-44xx.h"
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+
+unsigned long omap3_dpll_recalc(struct clk *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk *clk);
+int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
+
+/* Maximum DPLL multiplier, divider values for OMAP4 */
+#define OMAP4_MAX_DPLL_MULT 2048
+#define OMAP4_MAX_DPLL_DIV 128
+
+/* PRM CLOCKS */
+
+static struct clk omap_32k_fck = {
+ .name = "omap_32k_fck",
+ .ops = &clkops_null,
+ .rate = 32768,
+ .flags = RATE_FIXED,
+};
+
+static struct clk secure_32k_fck = {
+ .name = "secure_32k_fck",
+ .ops = &clkops_null,
+ .rate = 32768,
+ .flags = RATE_FIXED,
+};
+
+static struct clk pad_cks = {
+ .name = "pad_cks",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk slimbus_ck = {
+ .name = "slimbus_ck",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk phy_clkout_ck = {
+ .name = "phy_clkout_ck",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk xclk_60m_otg_ck = {
+ .name = "xclk_60m_otg_ck",
+ .ops = &clkops_null,
+ .rate = 60000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk xclk_60m_hsp1_ck = {
+ .name = "xclk_60m_hsp1_ck",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk xclk_60m_hsp2_ck = {
+ .name = "xclk_60m_hsp2_ck",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_12m_ck = {
+ .name = "virt_12m_ck",
+ .ops = &clkops_null,
+ .rate = 12000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_13m_ck = {
+ .name = "virt_13m_ck",
+ .ops = &clkops_null,
+ .rate = 13000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_19_2m_ck = {
+ .name = "virt_19_2m_ck",
+ .ops = &clkops_null,
+ .rate = 19200000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_26m_ck = {
+ .name = "virt_26m_ck",
+ .ops = &clkops_null,
+ .rate = 26000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_27m_ck = {
+ .name = "virt_27m_ck",
+ .ops = &clkops_null,
+ .rate = 27000000,
+ .flags = RATE_FIXED,
+};
+
+static struct clk virt_38_4m_ck = {
+ .name = "virt_38_4m_ck",
+ .ops = &clkops_null,
+ .rate = 38400000,
+ .flags = RATE_FIXED,
+};
+
+static const struct clksel_rate sys_clk_12m_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_clk_13m_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_clk_19_2m_rates[] = {
+ { .div = 1, .val = 3, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_clk_26m_rates[] = {
+ { .div = 1, .val = 4, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_clk_27m_rates[] = {
+ { .div = 1, .val = 5, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_clk_38_4m_rates[] = {
+ { .div = 1, .val = 6, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel sys_clk_clksel[] = {
+ { .parent = &virt_12m_ck, .rates = sys_clk_12m_rates },
+ { .parent = &virt_13m_ck, .rates = sys_clk_13m_rates },
+ { .parent = &virt_19_2m_ck, .rates = sys_clk_19_2m_rates },
+ { .parent = &virt_26m_ck, .rates = sys_clk_26m_rates },
+ { .parent = &virt_27m_ck, .rates = sys_clk_27m_rates },
+ { .parent = &virt_38_4m_ck, .rates = sys_clk_38_4m_rates },
+ { .parent = NULL },
+};
+
+/* sys_clk clock */
+/* 12, 13, 19.2, 26, 27 or 38.4 MHz */
+static struct clk sys_ck = {
+ .name = "sys_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .clksel_reg = OMAP4430_CM_SYS_CLKSEL,
+ .clksel_mask = OMAP4430_SYS_CLKSEL_MASK,
+ .clksel = sys_clk_clksel,
+ .flags = RATE_FIXED,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate div2_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 1, .flags = RATE_IN_443X },
+ { .div = 0 }
+};
+
+static const struct clksel abe_dss_sys_ck_clksel[] = {
+ { .parent = &sys_ck, .rates = div2_rates },
+ { .parent = NULL }
+};
+
+static struct clk abe_dss_sys_ck = {
+ .name = "abe_dss_sys_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &sys_ck,
+ .clksel_reg = OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = abe_dss_sys_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel dpll_sys_ref_ck_clksel[] = {
+ { .parent = &sys_ck, .rates = div2_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_sys_ref_ck = {
+ .name = "dpll_sys_ref_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &sys_ck,
+ .clksel_reg = OMAP4430_CM_DPLL_SYS_REF_CLKSEL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = dpll_sys_ref_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate dpll_sys_ref_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate omap_32k_fck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel abe_dpll_alwon_ck_clksel[] = {
+ { .parent = &dpll_sys_ref_ck, .rates = dpll_sys_ref_ck_rates },
+ { .parent = &omap_32k_fck, .rates = omap_32k_fck_rates },
+ { .parent = NULL }
+};
+
+static struct clk abe_dpll_alwon_ck = {
+ .name = "abe_dpll_alwon_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &omap_32k_fck,
+ .clksel_reg = OMAP4430_CM_ABE_PLL_REF_CLKSEL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = abe_dpll_alwon_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel omap443x_gpt_clksel[] = {
+ { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
+ { .parent = &sys_ck, .rates = gpt_sys_rates },
+ { .parent = NULL}
+};
+
+static struct clk gpt1_fck = {
+ .name = "gpt1_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_WKUP_GPTIMER1_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_WKUP_GPTIMER1_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt2_fck = {
+ .name = "gpt2_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER2_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER2_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt3_fck = {
+ .name = "gpt3_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER3_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER3_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt4_fck = {
+ .name = "gpt4_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER4_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER4_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt9_fck = {
+ .name = "gpt9_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER9_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER9_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt10_fck = {
+ .name = "gpt10_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER10_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER10_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk gpt11_fck = {
+ .name = "gpt11_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM_L4PER_GPTIMER11_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM_L4PER_GPTIMER11_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+/* TODO:Dummy clock node still needed to boot on Omap4, remove later */
+static struct clk gpmc_fck = {
+ .name = "gpmc_fck",
+ .ops = &clkops_null,
+};
+
+/* DPLL's */
+
+#define DPLL_LOW_POWER_STOP 0x1
+#define DPLL_LOW_POWER_BYPASS 0x5
+#define DPLL_LOCKED 0x7
+
+static const struct clksel_rate div_mx_dpll_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 2, .flags = RATE_IN_443X },
+ { .div = 3, .val = 3, .flags = RATE_IN_443X },
+ { .div = 4, .val = 4, .flags = RATE_IN_443X },
+ { .div = 5, .val = 5, .flags = RATE_IN_443X },
+ { .div = 6, .val = 6, .flags = RATE_IN_443X },
+ { .div = 7, .val = 7, .flags = RATE_IN_443X },
+ { .div = 8, .val = 8, .flags = RATE_IN_443X },
+ { .div = 9, .val = 9, .flags = RATE_IN_443X },
+ { .div = 10, .val = 10, .flags = RATE_IN_443X },
+ { .div = 11, .val = 11, .flags = RATE_IN_443X },
+ { .div = 12, .val = 12, .flags = RATE_IN_443X },
+ { .div = 13, .val = 13, .flags = RATE_IN_443X },
+ { .div = 14, .val = 14, .flags = RATE_IN_443X },
+ { .div = 15, .val = 15, .flags = RATE_IN_443X },
+ { .div = 16, .val = 16, .flags = RATE_IN_443X },
+ { .div = 17, .val = 17, .flags = RATE_IN_443X },
+ { .div = 18, .val = 18, .flags = RATE_IN_443X },
+ { .div = 19, .val = 19, .flags = RATE_IN_443X },
+ { .div = 20, .val = 20, .flags = RATE_IN_443X },
+ { .div = 21, .val = 21, .flags = RATE_IN_443X },
+ { .div = 22, .val = 22, .flags = RATE_IN_443X },
+ { .div = 23, .val = 23, .flags = RATE_IN_443X },
+ { .div = 24, .val = 24, .flags = RATE_IN_443X },
+ { .div = 25, .val = 25, .flags = RATE_IN_443X },
+ { .div = 26, .val = 26, .flags = RATE_IN_443X },
+ { .div = 27, .val = 27, .flags = RATE_IN_443X },
+ { .div = 28, .val = 28, .flags = RATE_IN_443X },
+ { .div = 29, .val = 29, .flags = RATE_IN_443X },
+ { .div = 30, .val = 30, .flags = RATE_IN_443X },
+ { .div = 31, .val = 31, .flags = RATE_IN_443X },
+ { .div = 0 }
+};
+
+/* DPLL ABE */
+
+static struct dpll_data dpll_abe_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_ABE,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &sys_ck,
+ .clk_ref = &abe_dpll_alwon_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_ABE,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_ABE,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_ABE,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_abe_ck = {
+ .name = "dpll_abe_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_dpll_parent,
+ .parent = &abe_dpll_alwon_ck,
+ .dpll_data = &dpll_abe_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_abe_x2_ck = {
+ .name = "dpll_abe_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_ck,
+ .recalc = &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_abe_m2_clksel[] = {
+ { .parent = &dpll_abe_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_abe_m2_ck = {
+ .name = "dpll_abe_m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_abe_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_abe_m2_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel dpll_abe_x2mx_clksel[] = {
+ { .parent = &dpll_abe_x2_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_abe_x2m2_ck = {
+ .name = "dpll_abe_x2m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_abe_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_abe_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_abe_x2m3_ck = {
+ .name = "dpll_abe_x2m3_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_abe_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_ABE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_abe_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk per_abe_x1_fck = {
+ .name = "per_abe_x1_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dpll_abe_x2_fck = {
+ .name = "dpll_abe_x2_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk core_dpll_hs_ck = {
+ .name = "core_dpll_hs_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk per_dpll_hs_ck = {
+ .name = "per_dpll_hs_ck",
+ .ops = &clkops_null,
+ .parent = &core_dpll_hs_ck,
+ .fixed_div = 2,
+ .recalc = &omap2_fixed_divisor_recalc,
+};
+
+static struct clk usb_dpll_hs_ck = {
+ .name = "usb_dpll_hs_ck",
+ .ops = &clkops_null,
+ .parent = &core_dpll_hs_ck,
+ .fixed_div = 2,
+ .recalc = &omap2_fixed_divisor_recalc,
+};
+
+/* CM1_ABE clocks */
+
+static const struct clksel_rate dpll_abe_x2_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 1, .flags = RATE_IN_443X },
+ { .div = 4, .val = 2, .flags = RATE_IN_443X },
+ { .div = 0 },
+};
+
+static const struct clksel abe_ck_clksel[] = {
+ { .parent = &dpll_abe_x2_ck, .rates = dpll_abe_x2_ck_rates },
+ { .parent = NULL },
+};
+
+static struct clk abe_ck = {
+ .name = "abe_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_abe_x2_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_ABE,
+ .clksel_mask = OMAP4430_CLKSEL_OPP_MASK,
+ .clksel = abe_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate abe_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 1, .flags = RATE_IN_443X },
+ { .div = 0 },
+};
+
+static const struct clksel aess_fck_clksel[] = {
+ { .parent = &abe_ck, .rates = abe_ck_rates },
+ { .parent = NULL },
+};
+
+static struct clk aess_fck = {
+ .name = "aess_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_ck,
+ .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
+ .clksel = aess_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk abe_lp_ck = {
+ .name = "abe_lp_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_x2_ck,
+ .fixed_div = 16,
+ .recalc = &omap2_fixed_divisor_recalc,
+};
+
+static struct clk abe_24m_fck = {
+ .name = "abe_24m_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_abe_x2_ck,
+ .fixed_div = 16,
+ .recalc = &omap2_fixed_divisor_recalc,
+};
+
+static struct clk abe_gpt5_fck = {
+ .name = "abe_gpt5_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+ .clksel_mask = OMAP4430_GPTIMER_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk abe_gpt6_fck = {
+ .name = "abe_gpt6_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+ .clksel_mask = OMAP4430_GPTIMER_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk abe_gpt7_fck = {
+ .name = "abe_gpt7_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+ .clksel_mask = OMAP4430_GPTIMER_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk abe_gpt8_fck = {
+ .name = "abe_gpt8_fck",
+ .ops = &clkops_omap2_dflt_wait,
+ .parent = &sys_ck,
+ .init = &omap2_init_clksel_parent,
+ .enable_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ .enable_bit = OMAP4430_EN_GPT_SHIFT,
+ .clksel_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+ .clksel_mask = OMAP4430_GPTIMER_CLKSEL_MASK,
+ .clksel = omap443x_gpt_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk per_24m_fck;
+
+static const struct clksel_rate abe_24m_fck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate sys_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate per_24m_fck_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel mcbsp_int_fck_clksel[] = {
+ { .parent = &abe_24m_fck, .rates = abe_24m_fck_rates },
+ { .parent = &sys_ck, .rates = sys_ck_rates },
+ { .parent = &per_24m_fck, .rates = per_24m_fck_rates },
+ { .parent = NULL },
+};
+
+static const struct clksel mcasp_int_fck_clksel[] = {
+ { .parent = &abe_24m_fck, .rates = abe_24m_fck_rates },
+ { .parent = &sys_ck, .rates = sys_ck_rates },
+ { .parent = &per_24m_fck, .rates = per_24m_fck_rates },
+ { .parent = NULL },
+};
+
+static const struct clksel dmic_abe_int_fck_clksel[] = {
+ { .parent = &abe_24m_fck, .rates = abe_24m_fck_rates },
+ { .parent = &sys_ck, .rates = sys_ck_rates },
+ { .parent = &per_24m_fck, .rates = per_24m_fck_rates },
+ { .parent = NULL },
+};
+
+static struct clk mcbsp1_int_fck = {
+ .name = "mcbsp1_int_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_24m_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ .clksel_mask = OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE,
+ .clksel = mcbsp_int_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcbsp2_int_fck = {
+ .name = "mcbsp2_int_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_24m_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ .clksel_mask = OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE,
+ .clksel = mcbsp_int_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcbsp3_int_fck = {
+ .name = "mcbsp3_int_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_24m_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ .clksel_mask = OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE,
+ .clksel = mcbsp_int_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcasp1_int_fck = {
+ .name = "mcasp1_int_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_24m_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ .clksel_mask = OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE,
+ .clksel = mcasp_int_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dmic_abe_int_fck = {
+ .name = "dmic_abe_int_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &abe_24m_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ .clksel_mask = OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE,
+ .clksel = dmic_abe_int_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate int_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate pad_cks_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate slimbus_ck_rates[] = {
+ { .div = 1, .val = 2, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel mcbsp1_fck_clksel[] = {
+ { .parent = &mcbsp1_int_fck, .rates = int_ck_rates },
+ { .parent = &pad_cks, .rates = pad_cks_rates },
+ { .parent = &slimbus_ck, .rates = slimbus_ck_rates },
+ { .parent = NULL },
+};
+
+static const struct clksel mcbsp2_fck_clksel[] = {
+ { .parent = &mcbsp2_int_fck, .rates = int_ck_rates },
+ { .parent = &pad_cks, .rates = pad_cks_rates },
+ { .parent = &slimbus_ck, .rates = slimbus_ck_rates },
+ { .parent = NULL },
+};
+static const struct clksel mcbsp3_fck_clksel[] = {
+ { .parent = &mcbsp3_int_fck, .rates = int_ck_rates },
+ { .parent = &pad_cks, .rates = pad_cks_rates },
+ { .parent = &slimbus_ck, .rates = slimbus_ck_rates },
+ { .parent = NULL },
+};
+static const struct clksel mcasp1_fck_clksel[] = {
+ { .parent = &mcasp1_int_fck, .rates = int_ck_rates },
+ { .parent = &pad_cks, .rates = pad_cks_rates },
+ { .parent = &slimbus_ck, .rates = slimbus_ck_rates },
+ { .parent = NULL },
+};
+static const struct clksel dmic_abe_fck_clksel[] = {
+ { .parent = &dmic_abe_int_fck, .rates = int_ck_rates },
+ { .parent = &pad_cks, .rates = pad_cks_rates },
+ { .parent = &slimbus_ck, .rates = slimbus_ck_rates },
+ { .parent = NULL },
+};
+
+static struct clk mcbsp1_fck = {
+ .name = "mcbsp1_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &mcbsp1_int_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_SOURCE,
+ .clksel = mcbsp1_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcbsp2_fck = {
+ .name = "mcbsp2_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &mcbsp2_int_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_SOURCE,
+ .clksel = mcbsp2_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcbsp3_fck = {
+ .name = "mcbsp3_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &mcbsp3_int_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_SOURCE,
+ .clksel = mcbsp3_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mcasp1_fck = {
+ .name = "mcasp1_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &mcasp1_int_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_SOURCE,
+ .clksel = mcasp1_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dmic_abe_fck = {
+ .name = "dmic_abe_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dmic_abe_int_fck,
+ .clksel_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_SOURCE,
+ .clksel = dmic_abe_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+/* DPLL PER */
+
+static const struct clksel_rate per_dpll_hs_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel per_hsd_byp_ck_clksel[] = {
+ { .parent = &dpll_sys_ref_ck, .rates = dpll_sys_ref_ck_rates },
+ { .parent = &per_dpll_hs_ck, .rates = per_dpll_hs_ck_rates },
+ { .parent = NULL }
+};
+
+static struct clk per_hsd_byp_ck = {
+ .name = "per_hsd_byp_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_sys_ref_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK,
+ .clksel = per_hsd_byp_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct dpll_data dpll_per_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_PER,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &per_dpll_hs_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .clk_hsd_bypass = &per_hsd_byp_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_PER,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_PER,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_PER,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_per_ck = {
+ .name = "dpll_per_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_dpll_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_per_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_per_x2_ck = {
+ .name = "dpll_per_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_ck,
+ .recalc = &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_per_m2_clksel[] = {
+ { .parent = &dpll_per_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_per_m2_ck = {
+ .name = "dpll_per_m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_per_m2_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel dpll_per_x2mx_clksel[] = {
+ { .parent = &dpll_per_x2_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_per_x2m2_ck = {
+ .name = "dpll_per_x2m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_per_x2m3_ck = {
+ .name = "dpll_per_x2m3_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_per_x2m4_ck = {
+ .name = "dpll_per_x2m4_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_per_x2m5_ck = {
+ .name = "dpll_per_x2m5_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_per_x2m6_ck = {
+ .name = "dpll_per_x2m6_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_per_x2m7_ck = {
+ .name = "dpll_per_x2m7_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_per_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_PER,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_per_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk omap_96m_alwon_ck = {
+ .name = "omap_96m_alwon_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk omap_192m_fck = {
+ .name = "omap_192m_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk per_dpll_scrm_ck = {
+ .name = "per_dpll_scrm_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m3_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk omap_128m_fck = {
+ .name = "omap_128m_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m4_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dss_fck = {
+ .name = "dss_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m5_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk per_mpu_m3 = {
+ .name = "per_mpu_m3",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m6_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk per_dpll_emu_ck = {
+ .name = "per_dpll_emu_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_per_x2m7_ck,
+ .recalc = &followparent_recalc,
+};
+
+/* DPLL CORE */
+static const struct clksel_rate core_dpll_hs_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel core_phy_hsd_byp_ck_clksel[] = {
+ { .parent = &dpll_sys_ref_ck, .rates = dpll_sys_ref_ck_rates },
+ { .parent = &core_dpll_hs_ck, .rates = core_dpll_hs_ck_rates },
+ { .parent = NULL }
+};
+
+static struct clk core_phy_hsd_byp_ck = {
+ .name = "core_phy_hsd_byp_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_sys_ref_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_BYP_CLKSEL_MASK,
+ .clksel = core_phy_hsd_byp_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct dpll_data dpll_core_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_CORE,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &core_dpll_hs_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .clk_hsd_bypass = &core_phy_hsd_byp_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_CORE,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_CORE,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_core_ck = {
+ .name = "dpll_core_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_dpll_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_core_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_core_x2_ck = {
+ .name = "dpll_core_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_ck,
+ .recalc = &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_core_m2_clksel[] = {
+ { .parent = &dpll_core_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_core_m2_ck = {
+ .name = "dpll_core_m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_core_m2_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel dpll_core_x2mx_clksel[] = {
+ { .parent = &dpll_core_x2_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_core_x2m3_ck = {
+ .name = "dpll_core_x2m3_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_core_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_core_x2m4_ck = {
+ .name = "dpll_core_x2m4_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_core_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_core_x2m5_ck = {
+ .name = "dpll_core_x2m5_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_core_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_core_x2m6_ck = {
+ .name = "dpll_core_x2m6_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_core_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_core_x2m7_ck = {
+ .name = "dpll_core_x2m7_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_core_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_CORE,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_core_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk phy_root_ck = {
+ .name = "phy_root_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk core_dpll_scrm_ck = {
+ .name = "core_dpll_scrm_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_x2m3_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dpll_x2_ck = {
+ .name = "dpll_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_x2m4_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk core_x2_ck = {
+ .name = "core_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_x2m5_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk core_dpll_emu_ck = {
+ .name = "core_dpll_emu_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_x2m6_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk core_sgx_fck = {
+ .name = "core_sgx_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_core_x2m7_ck,
+ .recalc = &followparent_recalc,
+};
+
+/* MPU DPLL */
+
+static const struct clksel_rate div4_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 1, .flags = RATE_IN_443X },
+ { .div = 4, .val = 2, .flags = RATE_IN_443X },
+ { .div = 8, .val = 3, .flags = RATE_IN_443X },
+ { .div = 0 }
+};
+
+static const struct clksel mpu_dpll_hs_ck_clksel[] = {
+ { .parent = &core_x2_ck, .rates = div4_rates },
+ { .parent = NULL }
+};
+
+static struct clk mpu_dpll_hs_ck = {
+ .name = "mpu_dpll_hs_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_x2_ck,
+ .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_MPU,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = mpu_dpll_hs_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct dpll_data dpll_mpu_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_MPU,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &mpu_dpll_hs_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_MPU,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_MPU,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_mpu_ck = {
+ .name = "dpll_mpu_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_dpll_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_mpu_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static const struct clksel dpll_mpu_m2_clksel[] = {
+ { .parent = &dpll_mpu_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_mpu_m2_ck = {
+ .name = "dpll_mpu_m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_mpu_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU,
+ .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_mpu_m2_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk mpu_dpll_ck = {
+ .name = "mpu_dpll_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_mpu_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+/* IVA DPLL */
+
+static const struct clksel iva_dpll_hs_ck_clksel[] = {
+ { .parent = &core_x2_ck, .rates = div4_rates },
+ { .parent = NULL }
+};
+
+static struct clk iva_dpll_hs_ck = {
+ .name = "iva_dpll_hs_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_x2_ck,
+ .clksel_reg = OMAP4430_CM_BYPCLK_DPLL_IVA,
+ .clksel_mask = OMAP4430_CLKSEL_MASK,
+ .clksel = iva_dpll_hs_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct dpll_data dpll_iva_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_IVA,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &iva_dpll_hs_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_IVA,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_IVA,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_iva_ck = {
+ .name = "dpll_iva_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_iva_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_iva_x2_ck = {
+ .name = "dpll_iva_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_iva_ck,
+ .recalc = &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_iva_x2mx_clksel[] = {
+ { .parent = &dpll_iva_x2_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_iva_x2m4_ck = {
+ .name = "dpll_iva_x2m4_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_iva_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_IVA,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_iva_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dpll_iva_x2m5_ck = {
+ .name = "dpll_iva_x2m5_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_iva_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_IVA,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_iva_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk dsp_root_ck = {
+ .name = "dsp_root_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_iva_x2m4_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk ivahd_ck = {
+ .name = "ivahd_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_iva_x2m5_ck,
+ .recalc = &followparent_recalc,
+};
+
+/* UNIPRO DPLL */
+
+static struct dpll_data dpll_unipro_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
+ .mult_mask = OMAP4430_CM2_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_DPLL_DIV_MASK,
+ .clk_bypass = &dpll_sys_ref_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_UNIPRO,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_unipro_ck = {
+ .name = "dpll_unipro_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_dpll_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_unipro_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_unipro_x2_ck = {
+ .name = "dpll_unipro_x2_ck",
+ .ops = &clkops_null,
+ .parent = &dpll_unipro_ck,
+ .recalc = &omap3_clkoutx2_recalc,
+};
+
+static const struct clksel dpll_unipro_x2mx_clksel[] = {
+ { .parent = &dpll_unipro_x2_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_unipro_x2m2_ck = {
+ .name = "dpll_unipro_x2m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_unipro_x2_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
+ .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+ .clksel = dpll_unipro_x2mx_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk unipro1_phy_fck = {
+ .name = "unipro1_phy_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_unipro_x2m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+/* USB DPLL */
+
+static struct dpll_data dpll_usb_dd = {
+ .mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_USB,
+ .mult_mask = OMAP4430_CM2_USB_DPLL_MULT_MASK,
+ .div1_mask = OMAP4430_CM2_USB_DPLL_DIV_MASK,
+ .clk_bypass = &usb_dpll_hs_ck,
+ .clk_ref = &dpll_sys_ref_ck,
+ .control_reg = OMAP4430_CM_CLKMODE_DPLL_USB,
+ .enable_mask = OMAP4430_DPLL_EN_MASK,
+ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+ .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB,
+ .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
+ .idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB,
+ .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .max_multiplier = OMAP4_MAX_DPLL_MULT,
+ .min_divider = 1,
+ .max_divider = OMAP4_MAX_DPLL_DIV,
+};
+
+static struct clk dpll_usb_ck = {
+ .name = "dpll_usb_ck",
+ .ops = &clkops_noncore_dpll_ops,
+ .init = &omap2_init_dpll_parent,
+ .parent = &dpll_sys_ref_ck,
+ .dpll_data = &dpll_usb_dd,
+ .round_rate = &omap2_dpll_round_rate,
+ .set_rate = &omap3_noncore_dpll_set_rate,
+ .recalc = &omap3_dpll_recalc,
+};
+
+static const struct clksel dpll_usb_m2_clksel[] = {
+ { .parent = &dpll_usb_ck, .rates = div_mx_dpll_rates },
+ { .parent = NULL }
+};
+
+static struct clk dpll_usb_m2_ck = {
+ .name = "dpll_usb_m2_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &dpll_usb_ck,
+ .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_USB,
+ .clksel_mask = OMAP4430_USB_DPLL_CLKOUT_DIV_MASK,
+ .clksel = dpll_usb_m2_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk init_480m_fck = {
+ .name = "init_480m_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_usb_m2_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dpll_usb_clkdcoldo = {
+ .name = "dpll_usb_clkdcoldo",
+ .ops = &clkops_null,
+ .parent = &dpll_usb_ck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk init_960m_fck = {
+ .name = "init_960m_fck",
+ .ops = &clkops_null,
+ .parent = &dpll_usb_clkdcoldo,
+ .recalc = &followparent_recalc,
+};
+
+/* CM1_USB nodes */
+
+static const struct clksel_rate init_480m_fck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X },
+ { .div = 8, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE},
+ { .div = 0 }
+};
+
+static const struct clksel init_60m_fck_clksel[] = {
+ { .parent = &init_480m_fck, .rates = init_480m_fck_rates },
+ { .parent = NULL }
+};
+
+static struct clk init_60m_fck = {
+ .name = "init_60m_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_USB_60MHZ,
+ .clksel_mask = OMAP4430_USB_60MHZ_CLKSEL_MASK,
+ .clksel = init_60m_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk utmi_p3_fck = {
+ .name = "utmi_p3_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk init_60m_p1_fck = {
+ .name = "init_60m_p1_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk init_60m_p2_fck = {
+ .name = "init_60m_p2_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk utmi_root_gfck = {
+ .name = "utmi_root_gfck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk tll_ch0_fck = {
+ .name = "tll_ch0_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk tll_ch1_fck = {
+ .name = "tll_ch1_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk tll_ch2_fck = {
+ .name = "tll_ch2_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk hsic_p1_480m_fck = {
+ .name = "hsic_p1_480m_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk hsic_p2_480m_fck = {
+ .name = "hsic_p2_480m_fck",
+ .ops = &clkops_null,
+ .parent = &init_480m_fck,
+ .recalc = &followparent_recalc,
+};
+
+static const struct clksel_rate phy_clkout_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate xclk_60m_otg_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel otg_60m_fck_clksel[] = {
+ { .parent = &phy_clkout_ck, .rates = phy_clkout_ck_rates },
+ { .parent = &xclk_60m_otg_ck, .rates = xclk_60m_otg_ck_rates },
+ { .parent = NULL }
+};
+
+static struct clk otg_60m_fck = {
+ .name = "otg_60m_fck",
+ .ops = &clkops_null,
+ .parent = &phy_clkout_ck,
+ .clksel_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_60M_MASK,
+ .clksel = otg_60m_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate init_60m_p1_fck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate xclk_60m_hsp1_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel utmi_p1_fck_clksel[] = {
+ { .parent = &init_60m_p1_fck, .rates = init_60m_p1_fck_rates },
+ { .parent = &xclk_60m_hsp1_ck, .rates = xclk_60m_hsp1_ck_rates },
+ { .parent = NULL }
+};
+
+static struct clk utmi_p1_fck = {
+ .name = "utmi_p1_fck",
+ .ops = &clkops_null,
+ .parent = &init_60m_p1_fck,
+ .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_UTMI_P1_MASK,
+ .clksel = utmi_p1_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate init_60m_p2_fck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate xclk_60m_hsp2_ck_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel utmi_p2_fck_clksel[] = {
+ { .parent = &init_60m_p2_fck, .rates = init_60m_p2_fck_rates },
+ { .parent = &xclk_60m_hsp2_ck, .rates = xclk_60m_hsp2_ck_rates },
+ { .parent = NULL }
+};
+
+static struct clk utmi_p2_fck = {
+ .name = "utmi_p2_fck",
+ .ops = &clkops_null,
+ .parent = &init_60m_p2_fck,
+ .clksel_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_UTMI_P2_MASK,
+ .clksel = utmi_p2_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+/* CM1 nodes */
+
+static const struct clksel core_ck_clksel[] = {
+ { .parent = &core_x2_ck, .rates = div2_rates },
+ { .parent = NULL }
+};
+
+static struct clk core_ck = {
+ .name = "core_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_x2_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
+ .clksel_mask = OMAP4430_CLKSEL_CORE_MASK,
+ .clksel = core_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel l3_ick_clksel[] = {
+ { .parent = &core_ck, .rates = div2_rates },
+ { .parent = NULL }
+};
+
+static struct clk l3_ick = {
+ .name = "l3_ick",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
+ .clksel_mask = OMAP4430_CM_CLKSEL_CORE_RESTORE_CLKSEL_L3_MASK,
+ .clksel = l3_ick_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel l4_root_ck_clksel[] = {
+ { .parent = &core_ck, .rates = div2_rates },
+ { .parent = NULL }
+};
+
+static struct clk l4_root_ck = {
+ .name = "l4_root_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_CORE,
+ .clksel_mask = OMAP4430_CLKSEL_L4_MASK,
+ .clksel = l4_root_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static struct clk per_24m_fck = {
+ .name = "per_24m_fck",
+ .ops = &clkops_null,
+ .parent = &omap_96m_alwon_ck,
+ .fixed_div = 4,
+ .recalc = &omap2_fixed_divisor_recalc,
+};
+
+/* CM2 nodes */
+
+static const struct clksel_rate div124_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 2, .val = 1, .flags = RATE_IN_443X },
+ { .div = 4, .val = 2, .flags = RATE_IN_443X },
+ { .div = 0 }
+};
+
+static const struct clksel fdif_fck_clksel[] = {
+ { .parent = &omap_128m_fck, .rates = div124_rates },
+ { .parent = NULL }
+};
+
+static struct clk fdif_fck = {
+ .name = "fdif_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &omap_128m_fck,
+ .clksel_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL,
+ .clksel_mask = OMAP4430_CLKSEL_FCLK_MASK,
+ .clksel = fdif_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel hsi_fck_clksel[] = {
+ { .parent = &omap_192m_fck, .rates = div124_rates },
+ { .parent = NULL }
+};
+
+static struct clk hsi_fck = {
+ .name = "hsi_fck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &omap_192m_fck,
+ .clksel_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+ .clksel_mask = OMAP4430_HSI_CLKSEL_MASK,
+ .clksel = hsi_fck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate core_ck_rates[] = {
+ { .div = 1, .val = 0, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel_rate per_mpu_m3_rates[] = {
+ { .div = 1, .val = 1, .flags = RATE_IN_443X | DEFAULT_RATE },
+ { .div = 0 }
+};
+
+static const struct clksel mpu_m3_iss_ck_clksel[] = {
+ { .parent = &core_ck, .rates = core_ck_rates },
+ { .parent = &per_mpu_m3, .rates = per_mpu_m3_rates },
+ { .parent = NULL }
+};
+
+static struct clk mpu_m3_iss_ck = {
+ .name = "mpu_m3_iss_ck",
+ .ops = &clkops_null,
+ .init = &omap2_init_clksel_parent,
+ .parent = &core_ck,
+ .clksel_reg = OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT,
+ .clksel_mask = OMAP4430_MPU_M3_ISS_ROOT_CLKSEL_MASK,
+ .clksel = mpu_m3_iss_ck_clksel,
+ .recalc = &omap2_clksel_recalc,
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 0e7d501865b6..475d59026004 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -6,6 +6,8 @@
*
* Written by Paul Walmsley and Jouni Högander
*
+ * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@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.
@@ -352,7 +354,12 @@ static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
if (!clkdm)
return -EINVAL;
- v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs,
+ OMAP2_CM_CLKSTCTRL);
+ if (cpu_is_omap44xx())
+ v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs,
+ OMAP4_CM_CLKSTCTRL);
v &= clkdm->clktrctrl_mask;
v >>= __ffs(clkdm->clktrctrl_mask);
@@ -384,16 +391,19 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm)
if (cpu_is_omap24xx()) {
cm_set_mod_reg_bits(OMAP24XX_FORCESTATE,
- clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
+ clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
- } else if (cpu_is_omap34xx()) {
+ } else if (cpu_is_omap34xx() | cpu_is_omap44xx()) {
u32 v = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
__ffs(clkdm->clktrctrl_mask));
+ if (cpu_is_omap34xx())
cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
- clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
-
+ clkdm->pwrdm.ptr->prcm_offs, OMAP2_CM_CLKSTCTRL);
+ if (cpu_is_omap44xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
+ clkdm->pwrdm.ptr->prcm_offs, OMAP4_CM_CLKSTCTRL);
} else {
BUG();
};
@@ -426,16 +436,19 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
if (cpu_is_omap24xx()) {
cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE,
- clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
+ clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
- } else if (cpu_is_omap34xx()) {
+ } else if (cpu_is_omap34xx() | cpu_is_omap44xx()) {
u32 v = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
__ffs(clkdm->clktrctrl_mask));
+ if (cpu_is_omap34xx())
cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
- clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
-
+ clkdm->pwrdm.ptr->prcm_offs, OMAP2_CM_CLKSTCTRL);
+ if (cpu_is_omap44xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
+ clkdm->pwrdm.ptr->prcm_offs, OMAP4_CM_CLKSTCTRL);
} else {
BUG();
};
@@ -474,16 +487,21 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
if (cpu_is_omap24xx())
v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
- else if (cpu_is_omap34xx())
+ else if (cpu_is_omap34xx() | cpu_is_omap44xx())
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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+ v << __ffs(clkdm->clktrctrl_mask),
+ clkdm->pwrdm.ptr->prcm_offs,
+ OMAP2_CM_CLKSTCTRL);
+ if (cpu_is_omap44xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+ v << __ffs(clkdm->clktrctrl_mask),
+ clkdm->pwrdm.ptr->prcm_offs,
+ OMAP4_CM_CLKSTCTRL);
}
/**
@@ -513,14 +531,19 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
if (cpu_is_omap24xx())
v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
- else if (cpu_is_omap34xx())
+ else if (cpu_is_omap34xx() | cpu_is_omap44xx())
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 (cpu_is_omap24xx() | cpu_is_omap34xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+ v << __ffs(clkdm->clktrctrl_mask),
+ clkdm->pwrdm.ptr->prcm_offs, OMAP2_CM_CLKSTCTRL);
+ if (cpu_is_omap44xx())
+ cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+ v << __ffs(clkdm->clktrctrl_mask),
+ clkdm->pwrdm.ptr->prcm_offs, OMAP4_CM_CLKSTCTRL);
if (atomic_read(&clkdm->usecount) > 0)
_clkdm_del_autodeps(clkdm);
@@ -565,8 +588,9 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
v = omap2_clkdm_clktrctrl_read(clkdm);
- if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
- (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
+ if (((cpu_is_omap34xx() | cpu_is_omap44xx()) \
+ && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) \
+ || (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
_clkdm_add_autodeps(clkdm);
else
omap2_clkdm_wakeup(clkdm);
@@ -618,7 +642,8 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
v = omap2_clkdm_clktrctrl_read(clkdm);
- if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
+ if (((cpu_is_omap34xx() | cpu_is_omap44xx()) \
+ && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
(cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
_clkdm_del_autodeps(clkdm);
else
diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index fe319ae4ca0a..b4c11843a18c 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -1,10 +1,12 @@
/*
- * OMAP2/3 clockdomains
+ * OMAP2/3/4 clockdomains
*
* Copyright (C) 2008 Texas Instruments, Inc.
* Copyright (C) 2008 Nokia Corporation
*
* Written by Paul Walmsley
+ *
+ * Updated with the OMAP4 specific Clock Domains by Abhijit Pagare
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
@@ -12,8 +14,19 @@
#include <mach/clockdomain.h>
+#include "prcm-common.h"
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "cm.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+#include "cm1-regbits-44xx.h"
+#include "cm2-regbits-44xx.h"
+
/*
- * OMAP2/3-common clockdomains
+ * OMAP2/3/4-common clockdomains
*
* Even though the 2420 has a single PRCM module from the
* interconnect's perspective, internally it does appear to have
@@ -25,19 +38,15 @@
static struct clockdomain wkup_clkdm = {
.name = "wkup_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430 \
+ | CHIP_IS_OMAP4430),
};
static struct clockdomain prm_clkdm = {
.name = "prm_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cm_clkdm = {
- .name = "cm_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430 \
+ | CHIP_IS_OMAP4430),
};
/*
@@ -96,6 +105,12 @@ static struct clockdomain mdm_clkdm = {
#if defined(CONFIG_ARCH_OMAP24XX)
+static struct clockdomain cm_clkdm = {
+ .name = "cm_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
static struct clockdomain dsp_clkdm = {
.name = "dsp_clkdm",
.pwrdm = { .name = "dsp_pwrdm" },
@@ -145,6 +160,12 @@ static struct clockdomain dss_24xx_clkdm = {
#if defined(CONFIG_ARCH_OMAP34XX)
+static struct clockdomain cm_clkdm = {
+ .name = "cm_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
static struct clockdomain mpu_34xx_clkdm = {
.name = "mpu_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
@@ -293,10 +314,192 @@ static struct clockdomain dpll5_clkdm = {
#endif /* CONFIG_ARCH_OMAP34XX */
/*
+ * 44xx clockdomains
+ */
+
+/* The Flags will be populated later */
+
+#if defined(CONFIG_ARCH_OMAP4)
+
+static struct clockdomain cm1_clkdm = {
+ .name = "cm1_clkdm",
+ .pwrdm = { .name = "pd_alwon_core_pwrdm" },
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cm2_clkdm = {
+ .name = "cm2_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_dsp_clkdm = {
+ .name = "cd_dsp_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_std_efuse_clkdm = {
+ .name = "cd_std_efuse_clkdm",
+ .pwrdm = { .name = "std_effuse_pwrdm" },
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_cortexa9_clkdm = {
+ .name = "cd_cortexa9_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l4_per_clkdm = {
+ .name = "cd_l4_per_clkdm",
+ .pwrdm = { .name = "pd_l4_per_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l3_init_clkdm = {
+ .name = "cd_l3_init_clkdm",
+ .pwrdm = { .name = "pd_l3_init_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_ivahd_clkdm = {
+ .name = "cd_ivahd_clkdm",
+ .pwrdm = { .name = "ivahd_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_sgx_clkdm = {
+ .name = "cd_sgx_clkdm",
+ .pwrdm = { .name = "pd_sgx_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_emu_clkdm = {
+ .name = "cd_emu_clkdm",
+ .pwrdm = { .name = "pd_emu_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_dss_clkdm = {
+ .name = "cd_dss_clkdm",
+ .pwrdm = { .name = "pd_dss_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l4_cfg_clkdm = {
+ .name = "cd_l4_cfg_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l3_instr_clkdm = {
+ .name = "cd_l3_instr_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l3_2_clkdm = {
+ .name = "cd_l3_2_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l3_1_clkdm = {
+ .name = "cd_l3_1_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_emif_clkdm = {
+ .name = "cd_emif_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_cortexm3_clkdm = {
+ .name = "cd_cortexm3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_dma_clkdm = {
+ .name = "cd_dma_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_d2d_clkdm = {
+ .name = "cd_d2d_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_cam_clkdm = {
+ .name = "cd_cam_clkdm",
+ .pwrdm = { .name = "pd_cam_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_abe_clkdm = {
+ .name = "cd_abe_clkdm",
+ .pwrdm = { .name = "pd_audio_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct clockdomain cd_l4_alwon_core_clkdm = {
+ .name = "cd_l4_alwon_core_clkdm",
+ .pwrdm = { .name = "pd_alwon_core_pwrdm" },
+ .clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
+ .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+#endif
+
+/*
* Clockdomain-powerdomain hwsup dependencies (34XX only)
*/
static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
+
+#ifdef CONFIG_ARCH_OMAP34xx
{
.pwrdm = { .name = "mpu_pwrdm" },
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
@@ -308,6 +511,9 @@ static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
{
.pwrdm = { .name = NULL },
}
+#endif
+
+/* The dependencies for OMAP4 will be populated later */
};
/*
@@ -317,7 +523,6 @@ static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
static struct clockdomain *clockdomains_omap[] = {
&wkup_clkdm,
- &cm_clkdm,
&prm_clkdm,
#ifdef CONFIG_ARCH_OMAP2420
@@ -331,6 +536,7 @@ static struct clockdomain *clockdomains_omap[] = {
#endif
#ifdef CONFIG_ARCH_OMAP24XX
+ &cm_clkdm,
&dsp_clkdm,
&gfx_24xx_clkdm,
&core_l3_24xx_clkdm,
@@ -339,6 +545,7 @@ static struct clockdomain *clockdomains_omap[] = {
#endif
#ifdef CONFIG_ARCH_OMAP34XX
+ &cm_clkdm,
&mpu_34xx_clkdm,
&neon_clkdm,
&iva2_clkdm,
@@ -359,6 +566,30 @@ static struct clockdomain *clockdomains_omap[] = {
&dpll5_clkdm,
#endif
+#ifdef CONFIG_ARCH_OMAP4
+ &cm1_clkdm,
+ &cm2_clkdm,
+ &cd_dsp_clkdm,
+ &cd_std_efuse_clkdm,
+ &cd_cortexa9_clkdm,
+ &cd_l4_per_clkdm,
+ &cd_l3_init_clkdm,
+ &cd_ivahd_clkdm,
+ &cd_sgx_clkdm,
+ &cd_emu_clkdm,
+ &cd_dss_clkdm,
+ &cd_l4_cfg_clkdm,
+ &cd_l3_instr_clkdm,
+ &cd_l3_2_clkdm,
+ &cd_l3_1_clkdm,
+ &cd_emif_clkdm,
+ &cd_cortexm3_clkdm,
+ &cd_dma_clkdm,
+ &cd_d2d_clkdm,
+ &cd_cam_clkdm,
+ &cd_abe_clkdm,
+ &cd_l4_alwon_core_clkdm,
+#endif
NULL,
};
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index f3c91a1ca391..24e7cf2652eb 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -4,10 +4,11 @@
/*
* OMAP2/3 Clock Management (CM) register definitions
*
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
* Copyright (C) 2007-2008 Nokia Corporation
*
* Written by Paul Walmsley
+ * Updated for OMAP4 by Rajendra Nayak (rnayak@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
@@ -22,6 +23,10 @@
IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
#define OMAP34XX_CM_REGADDR(module, reg) \
IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
+#define OMAP44XX_CM1_REGADDR(module, reg) \
+ IO_ADDRESS(OMAP4430_CM1_BASE + (module) + (reg))
+#define OMAP44XX_CM2_REGADDR(module, reg) \
+ IO_ADDRESS(OMAP4430_CM2_BASE + (module) + (reg))
/*
* Architecture-specific global CM registers
@@ -61,7 +66,8 @@
#define CM_CLKSEL 0x0040
#define CM_CLKSEL1 CM_CLKSEL
#define CM_CLKSEL2 0x0044
-#define CM_CLKSTCTRL 0x0048
+#define OMAP2_CM_CLKSTCTRL 0x0048
+#define OMAP4_CM_CLKSTCTRL 0x0000
/* Architecture-specific registers */
@@ -82,13 +88,271 @@
#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
#define OMAP3430_CM_SLEEPDEP CM_CLKSEL2
-#define OMAP3430_CM_CLKSEL3 CM_CLKSTCTRL
+#define OMAP3430_CM_CLKSEL3 OMAP2_CM_CLKSTCTRL
#define OMAP3430_CM_CLKSTST 0x004c
#define OMAP3430ES2_CM_CLKSEL4 0x004c
#define OMAP3430ES2_CM_CLKSEL5 0x0050
#define OMAP3430_CM_CLKSEL2_EMU 0x0050
#define OMAP3430_CM_CLKSEL3_EMU 0x0054
+#define OMAP4430_CM_CLKSEL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x0)
+#define OMAP4430_CM_CLKSEL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x8)
+#define OMAP4430_CM_DLL_CTRL OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x10)
+#define OMAP4430_CM_CLKMODE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x20)
+#define OMAP4430_CM_IDLEST_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x24)
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x28)
+#define OMAP4430_CM_CLKSEL_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x2C)
+#define OMAP4430_CM_DIV_M2_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x30)
+#define OMAP4430_CM_DIV_M3_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x34)
+#define OMAP4430_CM_DIV_M4_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x38)
+#define OMAP4430_CM_DIV_M5_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x3C)
+#define OMAP4430_CM_DIV_M6_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x40)
+#define OMAP4430_CM_DIV_M7_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x44)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x48)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x4C)
+#define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x50)
+#define OMAP4430_CM_CLKMODE_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x60)
+#define OMAP4430_CM_IDLEST_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x64)
+#define OMAP4430_CM_AUTOIDLE_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x68)
+#define OMAP4430_CM_CLKSEL_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x6C)
+#define OMAP4430_CM_DIV_M2_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x70)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x88)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x8C)
+#define OMAP4430_CM_BYPCLK_DPLL_MPU OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x9C)
+#define OMAP4430_CM_CLKMODE_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xA0)
+#define OMAP4430_CM_IDLEST_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xA4)
+#define OMAP4430_CM_AUTOIDLE_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xA8)
+#define OMAP4430_CM_CLKSEL_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xAC)
+#define OMAP4430_CM_DIV_M4_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xB8)
+#define OMAP4430_CM_DIV_M5_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xBC)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xC8)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xCC)
+#define OMAP4430_CM_BYPCLK_DPLL_IVA OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xDC)
+#define OMAP4430_CM_CLKMODE_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xE0)
+#define OMAP4430_CM_IDLEST_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xE4)
+#define OMAP4430_CM_AUTOIDLE_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xE8)
+#define OMAP4430_CM_CLKSEL_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xEC)
+#define OMAP4430_CM_DIV_M2_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xF0)
+#define OMAP4430_CM_DIV_M3_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0xF4)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x108)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x10C)
+#define OMAP4430_CM_CLKMODE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x120)
+#define OMAP4430_CM_IDLEST_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x124)
+#define OMAP4430_CM_AUTOIDLE_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x128)
+#define OMAP4430_CM_CLKSEL_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x12C)
+#define OMAP4430_CM_DIV_M2_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x130)
+#define OMAP4430_CM_DIV_M4_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x138)
+#define OMAP4430_CM_DIV_M5_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x13C)
+#define OMAP4430_CM_DIV_M6_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x140)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x148)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x14C)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1 OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x160)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2 OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x164)
+#define OMAP4430_CM_DYN_DEP_PRESCAL OMAP44XX_CM1_REGADDR(OMAP4430_CKGEN_MOD, 0x170)
+#define OMAP4430_CM1_ABE_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x0)
+#define OMAP4430_CM1_ABE_L4ABE_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x20)
+#define OMAP4430_CM1_ABE_AESS_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x28)
+#define OMAP4430_CM1_ABE_PDM_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x30)
+#define OMAP4430_CM1_ABE_DMIC_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x38)
+#define OMAP4430_CM1_ABE_MCASP_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x40)
+#define OMAP4430_CM1_ABE_MCBSP1_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x48)
+#define OMAP4430_CM1_ABE_MCBSP2_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x50)
+#define OMAP4430_CM1_ABE_MCBSP3_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x58)
+#define OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x60)
+#define OMAP4430_CM1_ABE_TIMER5_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x68)
+#define OMAP4430_CM1_ABE_TIMER6_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x70)
+#define OMAP4430_CM1_ABE_TIMER7_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x78)
+#define OMAP4430_CM1_ABE_TIMER8_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x80)
+#define OMAP4430_CM1_ABE_WDT3_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_ABE_MOD, 0x88)
+#define OMAP4430_CM_MPU_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_MPU_MOD, 0x0)
+#define OMAP4430_CM_MPU_STATICDEP OMAP44XX_CM1_REGADDR(OMAP4430_MPU_MOD, 0x4)
+#define OMAP4430_CM_MPU_DYNAMICDEP OMAP44XX_CM1_REGADDR(OMAP4430_MPU_MOD, 0x8)
+#define OMAP4430_CM_MPU_MPU_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_MPU_MOD, 0x20)
+#define OMAP4430_CM_TESLA_CLKSTCTRL OMAP44XX_CM1_REGADDR(OMAP4430_DSP_MOD, 0x0)
+#define OMAP4430_CM_TESLA_STATICDEP OMAP44XX_CM1_REGADDR(OMAP4430_DSP_MOD, 0x4)
+#define OMAP4430_CM_TESLA_DYNAMICDEP OMAP44XX_CM1_REGADDR(OMAP4430_DSP_MOD, 0x8)
+#define OMAP4430_CM_TESLA_TESLA_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_DSP_MOD, 0x20)
+#define OMAP4430_REVISION_CM1 OMAP44XX_CM1_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x0)
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL OMAP44XX_CM1_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x40)
+
+#define OMAP4430_CM_CAM_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CAM_MOD, 0x0)
+#define OMAP4430_CM_CAM_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CAM_MOD, 0x4)
+#define OMAP4430_CM_CAM_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CAM_MOD, 0x8)
+#define OMAP4430_CM_CAM_ISS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CAM_MOD, 0x20)
+#define OMAP4430_CM_CAM_FDIF_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CAM_MOD, 0x28)
+#define OMAP4430_CM_L3INIT_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x0)
+#define OMAP4430_CM_L3INIT_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x4)
+#define OMAP4430_CM_L3INIT_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x8)
+#define OMAP4430_CM_L3INIT_MMC1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x28)
+#define OMAP4430_CM_L3INIT_MMC2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x30)
+#define OMAP4430_CM_L3INIT_HSI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x38)
+#define OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x40)
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x58)
+#define OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x60)
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x68)
+#define OMAP4430_CM_L3INIT_P1500_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x78)
+#define OMAP4430_CM_L3INIT_EMAC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x80)
+#define OMAP4430_CM_L3INIT_SATA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x88)
+#define OMAP4430_CM_L3INIT_TPPSS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x90)
+#define OMAP4430_CM_L3INIT_PCIESS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0x98)
+#define OMAP4430_CM_L3INIT_CCPTX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0xA8)
+#define OMAP4430_CM_L3INIT_XHPI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0xC0)
+#define OMAP4430_CM_L3INIT_MMC6_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0xC8)
+#define OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0xD0)
+#define OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L3INIT_MOD, 0xE0)
+#define OMAP4430_CM_IVAHD_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_IVAHD_MOD, 0x0)
+#define OMAP4430_CM_IVAHD_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_IVAHD_MOD, 0x4)
+#define OMAP4430_CM_IVAHD_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_IVAHD_MOD, 0x8)
+#define OMAP4430_CM_IVAHD_IVAHD_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_IVAHD_MOD, 0x20)
+#define OMAP4430_CM_IVAHD_SL2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_IVAHD_MOD, 0x28)
+#define OMAP4430_CM_DSS_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_DSS_MOD, 0x0)
+#define OMAP4430_CM_DSS_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_DSS_MOD, 0x4)
+#define OMAP4430_CM_DSS_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_DSS_MOD, 0x8)
+#define OMAP4430_CM_DSS_DSS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_DSS_MOD, 0x20)
+#define OMAP4430_CM_DSS_DEISS_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_DSS_MOD, 0x28)
+#define OMAP4430_CM_L4PER_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x0)
+#define OMAP4430_CM_L4PER_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x8)
+#define OMAP4430_CM_L4PER_ADC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x20)
+#define OMAP4430_CM_L4PER_GPTIMER10_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x28)
+#define OMAP4430_CM_L4PER_GPTIMER11_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x30)
+#define OMAP4430_CM_L4PER_GPTIMER2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x38)
+#define OMAP4430_CM_L4PER_GPTIMER3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x40)
+#define OMAP4430_CM_L4PER_GPTIMER4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x48)
+#define OMAP4430_CM_L4PER_GPTIMER9_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x50)
+#define OMAP4430_CM_L4PER_ELM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x58)
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x60)
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x68)
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x70)
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x78)
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x80)
+#define OMAP4430_CM_L4PER_HDQ1W_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x88)
+#define OMAP4430_CM_L4PER_HECC1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x90)
+#define OMAP4430_CM_L4PER_HECC2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x98)
+#define OMAP4430_CM_L4PER_I2C1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xA0)
+#define OMAP4430_CM_L4PER_I2C2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xA8)
+#define OMAP4430_CM_L4PER_I2C3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xB0)
+#define OMAP4430_CM_L4PER_I2C4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xB8)
+#define OMAP4430_CM_L4PER_L4PER_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xC0)
+#define OMAP4430_CM_L4PER_MCASP2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xD0)
+#define OMAP4430_CM_L4PER_MCASP3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xD8)
+#define OMAP4430_CM_L4PER_MCBSP4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xE0)
+#define OMAP4430_CM_L4PER_MGATE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xE8)
+#define OMAP4430_CM_L4PER_MCSPI1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xF0)
+#define OMAP4430_CM_L4PER_MCSPI2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0xF8)
+#define OMAP4430_CM_L4PER_MCSPI3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x100)
+#define OMAP4430_CM_L4PER_MCSPI4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x108)
+#define OMAP4430_CM_L4PER_MMCSD3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x120)
+#define OMAP4430_CM_L4PER_MMCSD4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x128)
+#define OMAP4430_CM_L4PER_MSPROHG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x130)
+#define OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x138)
+#define OMAP4430_CM_L4PER_UART1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x140)
+#define OMAP4430_CM_L4PER_UART2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x148)
+#define OMAP4430_CM_L4PER_UART3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x150)
+#define OMAP4430_CM_L4PER_UART4_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x158)
+#define OMAP4430_CM_L4PER_MMCSD5_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x160)
+#define OMAP4430_CM_L4SEC_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x180)
+#define OMAP4430_CM_L4SEC_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x184)
+#define OMAP4430_CM_L4SEC_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x188)
+#define OMAP4430_CM_L4SEC_AES1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1A0)
+#define OMAP4430_CM_L4SEC_AES2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1A8)
+#define OMAP4430_CM_L4SEC_DES3DES_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1B0)
+#define OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1B8)
+#define OMAP4430_CM_L4SEC_RNG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1C0)
+#define OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1C8)
+#define OMAP4430_CM_L4SEC_CRYPTODMA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_L4PER_MOD, 0x1D8)
+#define OMAP4430_CM_GFX_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_GFX_MOD, 0x0)
+#define OMAP4430_CM_GFX_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_GFX_MOD, 0x4)
+#define OMAP4430_CM_GFX_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_GFX_MOD, 0x8)
+#define OMAP4430_CM_GFX_GFX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_GFX_MOD, 0x20)
+#define OMAP4430_CM_L3_1_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x0)
+#define OMAP4430_CM_L3_1_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x8)
+#define OMAP4430_CM_L3_1_L3_1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x20)
+#define OMAP4430_CM_L3_2_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x100)
+#define OMAP4430_CM_L3_2_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x108)
+#define OMAP4430_CM_L3_2_L3_2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x120)
+#define OMAP4430_CM_L3_2_GPMC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x128)
+#define OMAP4430_CM_L3_2_OCMC_RAM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x130)
+#define OMAP4430_CM_DUCATI_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x200)
+#define OMAP4430_CM_DUCATI_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x204)
+#define OMAP4430_CM_DUCATI_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x208)
+#define OMAP4430_CM_DUCATI_DUCATI_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x220)
+#define OMAP4430_CM_SDMA_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x300)
+#define OMAP4430_CM_SDMA_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x304)
+#define OMAP4430_CM_SDMA_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x308)
+#define OMAP4430_CM_SDMA_SDMA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x320)
+#define OMAP4430_CM_MEMIF_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x400)
+#define OMAP4430_CM_MEMIF_DMM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x420)
+#define OMAP4430_CM_MEMIF_EMIF_FW_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x428)
+#define OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x430)
+#define OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x438)
+#define OMAP4430_CM_MEMIF_DLL_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x440)
+#define OMAP4430_CM_MEMIF_EMIF_H1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x450)
+#define OMAP4430_CM_MEMIF_EMIF_H2_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x458)
+#define OMAP4430_CM_MEMIF_DLL_H_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x460)
+#define OMAP4430_CM_D2D_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x500)
+#define OMAP4430_CM_D2D_STATICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x504)
+#define OMAP4430_CM_D2D_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x508)
+#define OMAP4430_CM_D2D_SAD2D_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x520)
+#define OMAP4430_CM_D2D_MODEM_ICR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x528)
+#define OMAP4430_CM_L4CFG_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x600)
+#define OMAP4430_CM_L4CFG_DYNAMICDEP OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x608)
+#define OMAP4430_CM_L4CFG_L4_CFG_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x620)
+#define OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x628)
+#define OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x630)
+#define OMAP4430_CM_L4CFG_SAR_ROM_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x638)
+#define OMAP4430_CM_L3INSTR_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x700)
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x720)
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x728)
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CORE_MOD, 0x740)
+#define OMAP4430_CM_CEFUSE_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CEFUSE_MOD, 0x0)
+#define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_CEFUSE_MOD, 0x20)
+#define OMAP4430_REVISION_CM2 OMAP44XX_CM2_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x0)
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x40)
+#define OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x0)
+#define OMAP4430_CM_CLKSEL_USB_60MHZ OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x4)
+#define OMAP4430_CM_SCALE_FCLK OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x8)
+#define OMAP4430_CM_CORE_DVFS_PERF1 OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x10)
+#define OMAP4430_CM_CORE_DVFS_PERF2 OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x14)
+#define OMAP4430_CM_CORE_DVFS_PERF3 OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x18)
+#define OMAP4430_CM_CORE_DVFS_PERF4 OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x1C)
+#define OMAP4430_CM_CORE_DVFS_CURRENT OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x24)
+#define OMAP4430_CM_IVA_DVFS_PERF_TESLA OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x28)
+#define OMAP4430_CM_IVA_DVFS_PERF_IVAHD OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x2C)
+#define OMAP4430_CM_IVA_DVFS_PERF_ABE OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x30)
+#define OMAP4430_CM_IVA_DVFS_CURRENT OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x38)
+#define OMAP4430_CM_CLKMODE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x40)
+#define OMAP4430_CM_IDLEST_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x44)
+#define OMAP4430_CM_AUTOIDLE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x48)
+#define OMAP4430_CM_CLKSEL_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x4C)
+#define OMAP4430_CM_DIV_M2_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x50)
+#define OMAP4430_CM_DIV_M3_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x54)
+#define OMAP4430_CM_DIV_M4_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x58)
+#define OMAP4430_CM_DIV_M5_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x5C)
+#define OMAP4430_CM_DIV_M6_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x60)
+#define OMAP4430_CM_DIV_M7_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x64)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x68)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x6C)
+#define OMAP4430_CM_EMU_OVERRIDE_DPLL_PER OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x70)
+#define OMAP4430_CM_CLKMODE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x80)
+#define OMAP4430_CM_IDLEST_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x84)
+#define OMAP4430_CM_AUTOIDLE_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x88)
+#define OMAP4430_CM_CLKSEL_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x8C)
+#define OMAP4430_CM_DIV_M2_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0x90)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xA8)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xAC)
+#define OMAP4430_CM_CLKDCOLDO_DPLL_USB OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xB4)
+#define OMAP4430_CM_CLKMODE_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xC0)
+#define OMAP4430_CM_IDLEST_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xC4)
+#define OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xC8)
+#define OMAP4430_CM_CLKSEL_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xCC)
+#define OMAP4430_CM_DIV_M2_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xD0)
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xE8)
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO OMAP44XX_CM2_REGADDR(OMAP4430_CKGEN_MOD, 0xEC)
+#define OMAP4430_CM_ALWON_CLKSTCTRL OMAP44XX_CM2_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x0)
+#define OMAP4430_CM_ALWON_MDMINTC_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x20)
+#define OMAP4430_CM_ALWON_SR_MPU_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x28)
+#define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x30)
+#define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL OMAP44XX_CM2_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x38)
/* Clock management domain register get/set */
diff --git a/arch/arm/mach-omap2/cm1-regbits-44xx.h b/arch/arm/mach-omap2/cm1-regbits-44xx.h
new file mode 100644
index 000000000000..c2081851dd13
--- /dev/null
+++ b/arch/arm/mach-omap2/cm1-regbits-44xx.h
@@ -0,0 +1,325 @@
+#ifndef __ARCH_ARM_MACH_OMAP2_CM1_REGBITS_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM1_REGBITS_44XX_H
+
+/*
+ * OMAP4430 Clock Management Module1 register bits
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Written by Rajendra Nayak (rnayak@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 "cm.h"
+
+#define OMAP4430_CLKSEL_L4 (1 << 8)
+#define OMAP4430_CM_CLKSEL_CORE_CLKSEL_L3 (1 << 4)
+#define OMAP4430_CLKSEL_CORE (1 << 0)
+#define OMAP4430_SLIMBUS_CLK_GATE (1 << 10)
+#define OMAP4430_PAD_CLKS_GATE (1 << 8)
+#define OMAP4430_CLKSEL_OPP (1 << 0)
+#define OMAP4430_CM_DLL_CTRL_DLL_OVERRIDE (1 << 0)
+#define OMAP4430_DPLL_SSC_TYPE (1 << 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD (1 << 14)
+#define OMAP4430_DPLL_SSC_ACK (1 << 13)
+#define OMAP4430_DPLL_SSC_EN (1 << 12)
+#define OMAP4430_DPLL_REGM4XEN (1 << 11)
+#define OMAP4430_DPLL_LPMODE_EN (1 << 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN (1 << 9)
+#define OMAP4430_DPLL_RAMP_RATE (1 << 6)
+#define OMAP4430_DPLL_RAMP_LEVEL (1 << 4)
+#define OMAP4430_DPLL_DRIFTGUARD_EN (1 << 3)
+#define OMAP4430_DPLL_EN (1 << 0)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN (1 << 4)
+#define OMAP4430_AUTO_DPLL_MODE (1 << 0)
+#define OMAP4430_DPLL_BYP_CLKSEL (1 << 23)
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL (1 << 20)
+#define OMAP4430_DPLL_MULT (1 << 8)
+#define OMAP4430_DPLL_DIV (1 << 0)
+#define OMAP4430_DPLL_M2_PWDN (1 << 12)
+#define OMAP4430_ST_DPLL_CLKOUT (1 << 9)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK (1 << 5)
+#define OMAP4430_DPLL_CLKOUT_DIV (1 << 0)
+#define OMAP4430_DPLL_M3_PWDN (1 << 12)
+#define OMAP4430_ST_DPLL_CLKOUTHIF (1 << 9)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK (1 << 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV (1 << 0)
+#define OMAP4430_DELTAMSTEP (1 << 0)
+#define OMAP4430_MODFREQDIV_EXPONENT (1 << 8)
+#define OMAP4430_MODFREQDIV_MANTISSA (1 << 0)
+#define OMAP4430_OVERRIDE_ENABLE (1 << 19)
+#define OMAP4430_CORE_DPLL_EMU_MULT (1 << 8)
+#define OMAP4430_RESERVED (1 << 7)
+#define OMAP4430_CORE_DPLL_EMU_DIV (1 << 0)
+#define OMAP4430_ST_DPLL_CLK (1 << 0)
+#define OMAP4430_BYPCLK_DPLL_CLKSEL (1 << 0)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN (1 << 4)
+#define OMAP4430_ST_DPLL_CLKOUTX2 (1 << 11)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL (1 << 10)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN (1 << 4)
+#define OMAP4430_DPLL_DDRPHY_M6_DIV (1 << 24)
+#define OMAP4430_DPLL_DDRPHY_M5_DIV (1 << 19)
+#define OMAP4430_DPLL_DDRPHY_DPLL_EN (1 << 16)
+#define OMAP4430_DPLL_CORE_M2_DIV (1 << 11)
+#define OMAP4430_DPLL_CORE_DPLL_EN (1 << 8)
+#define OMAP4430_DLL_RESET (1 << 3)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_DLL_OVERRIDE (1 << 2)
+#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL (1 << 1)
+#define OMAP4430_FREQ_UPDATE (1 << 0)
+#define OMAP4430_DPLL_CORE_M5_DIV (1 << 3)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_CLKSEL_L3 (1 << 2)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_CLKSEL_CORE (1 << 1)
+#define OMAP4430_GPMC_FREQ_UPDATE (1 << 0)
+#define OMAP4430_PRESCAL (1 << 0)
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK (1 << 13)
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK (1 << 12)
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK (1 << 8)
+#define OMAP4430_CLKTRCTRL (1 << 0)
+#define OMAP4430_IDLEST (1 << 16)
+#define OMAP4430_MODULEMODE (1 << 0)
+#define OMAP4430_CLKSEL_AESS_FCLK (1 << 24)
+#define OMAP4430_STBYST (1 << 18)
+#define OMAP4430_ABE_CLKSEL_INTERNAL_SOURCE (1 << 26)
+#define OMAP4430_CLKSEL_SOURCE (1 << 24)
+#define OMAP4430_ABE_OPTFCLKEN_SLIMBUS_CLK (1 << 11)
+#define OMAP4430_OPTFCLKEN_FCLK2 (1 << 10)
+#define OMAP4430_OPTFCLKEN_FCLK1 (1 << 9)
+#define OMAP4430_OPTFCLKEN_FCLK0 (1 << 8)
+#define OMAP4430_ABE_GPTIMER_CLKCTRL_CLKSEL (1 << 24)
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK (1 << 8)
+#define OMAP4430_D2D_STATDEP (1 << 18)
+#define OMAP4430_CEFUSE_STATDEP (1 << 17)
+#define OMAP4430_ALWONCORE_STATDEP (1 << 16)
+#define OMAP4430_L4WKUP_STATDEP (1 << 15)
+#define OMAP4430_L4SEC_STATDEP (1 << 14)
+#define OMAP4430_L4PER_STATDEP (1 << 13)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_SDMA_STATDEP (1 << 11)
+#define OMAP4430_GFX_STATDEP (1 << 10)
+#define OMAP4430_ISS_STATDEP (1 << 9)
+#define OMAP4430_DSS_STATDEP (1 << 8)
+#define OMAP4430_L3INIT_STATDEP (1 << 7)
+#define OMAP4430_L3_2_STATDEP (1 << 6)
+#define OMAP4430_L3_1_STATDEP (1 << 5)
+#define OMAP4430_MEMIF_STATDEP (1 << 4)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_TESLA_STATDEP (1 << 1)
+#define OMAP4430_DUCATI_STATDEP (1 << 0)
+#define OMAP4430_WINDOWSIZE (1 << 24)
+#define OMAP4430_L3_1_DYNDEP (1 << 5)
+#define OMAP4430_MEMIF_DYNDEP (1 << 4)
+#define OMAP4430_ABE_DYNDEP (1 << 3)
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK (1 << 8)
+#define OMAP4430_CEFUSE_STATDEP (1 << 17)
+#define OMAP4430_ALWONCORE_STATDEP (1 << 16)
+#define OMAP4430_L4WKUP_STATDEP (1 << 15)
+#define OMAP4430_L4PER_STATDEP (1 << 13)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_ISS_STATDEP (1 << 9)
+#define OMAP4430_L3INIT_STATDEP (1 << 7)
+#define OMAP4430_L3_2_STATDEP (1 << 6)
+#define OMAP4430_L3_1_STATDEP (1 << 5)
+#define OMAP4430_MEMIF_STATDEP (1 << 4)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_WINDOWSIZE (1 << 24)
+#define OMAP4430_L3_1_DYNDEP (1 << 5)
+#define OMAP4430_ABE_DYNDEP (1 << 3)
+#define OMAP4430_IVAHD_DYNDEP (1 << 2)
+#define OMAP4430_CLKACTIVITY_BGAP_32K_GFCLK (1 << 12)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_BGAP_32K (1 << 8)
+#define OMAP4430_REV (1 << 0)
+
+
+#define OMAP4430_CLKSEL_L4_MASK BITFIELD(8, 8)
+#define OMAP4430_CM_CLKSEL_CORE_RESTORE_CLKSEL_L3_MASK BITFIELD(4, 4)
+#define OMAP4430_CLKSEL_CORE_MASK BITFIELD(0, 0)
+#define OMAP4430_SLIMBUS_CLK_GATE_MASK BITFIELD(10, 10)
+#define OMAP4430_PAD_CLKS_GATE_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKSEL_OPP_MASK BITFIELD(1, 0)
+#define OMAP4430_CM_DLL_CTRL_DLL_OVERRIDE_MASK BITFIELD(0, 0)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_REGM4XEN_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_LPMODE_EN_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_RAMP_RATE_MASK BITFIELD(8, 6)
+#define OMAP4430_DPLL_RAMP_LEVEL_MASK BITFIELD(5, 4)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_EN_MASK BITFIELD(2, 0)
+#define OMAP4430_ST_DPLL_CLK_MASK BITFIELD(0, 0)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN_MASK BITFIELD(4, 4)
+#define OMAP4430_AUTO_DPLL_MODE_MASK BITFIELD(2, 0)
+#define OMAP4430_DPLL_BYP_CLKSEL_MASK BITFIELD(23, 23)
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK BITFIELD(20, 20)
+#define OMAP4430_CM1_DPLL_MULT_MASK BITFIELD(18, 8)
+#define OMAP4430_CM1_DPLL_DIV_MASK BITFIELD(6, 0)
+#define OMAP4430_DPLL_M2_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUT_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_DPLL_M3_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_DELTAMSTEP_MASK BITFIELD(19, 0)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK BITFIELD(10, 8)
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK BITFIELD(6, 0)
+#define OMAP4430_OVERRIDE_ENABLE_MASK BITFIELD(19, 19)
+#define OMAP4430_CORE_DPLL_EMU_MULT_MASK BITFIELD(18, 8)
+#define OMAP4430_RESERVED_MASK BITFIELD(7, 7)
+#define OMAP4430_CORE_DPLL_EMU_DIV_MASK BITFIELD(6, 0)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_CLKSEL_MASK BITFIELD(1, 0)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_DDRPHY_M6_DIV_MASK BITFIELD(28, 24)
+#define OMAP4430_DPLL_DDRPHY_M5_DIV_MASK BITFIELD(23, 19)
+#define OMAP4430_DPLL_DDRPHY_DPLL_EN_MASK BITFIELD(18, 16)
+#define OMAP4430_DPLL_CORE_M2_DIV_MASK BITFIELD(15, 11)
+#define OMAP4430_DPLL_CORE_DPLL_EN_MASK BITFIELD(10, 8)
+#define OMAP4430_DLL_RESET_MASK BITFIELD(3, 3)
+#define OMAP4430_SHADOW_FREQ_DLL_OVERRIDE_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_MASK BITFIELD(1, 1)
+#define OMAP4430_FREQ_UPDATE_MASK BITFIELD(0, 0)
+#define OMAP4430_DPLL_CORE_M5_DIV_MASK BITFIELD(7, 3)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_CLKSEL_L3_MASK BITFIELD(2, 2)
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_CLKSEL_CORE_MASK BITFIELD(1, 1)
+#define OMAP4430_GPMC_FREQ_UPDATE_MASK BITFIELD(0, 0)
+#define OMAP4430_PRESCAL_MASK BITFIELD(5, 0)
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKTRCTRL_MASK BITFIELD(1, 0)
+#define OMAP4430_IDLEST_MASK BITFIELD(17, 16)
+#define OMAP4430_MODULEMODE_MASK BITFIELD(1, 0)
+#define OMAP4430_CLKSEL_AESS_FCLK_MASK BITFIELD(24, 24)
+#define OMAP4430_STBYST_MASK BITFIELD(18, 18)
+#define OMAP4430_CM1_CLKSEL_INTERNAL_SOURCE_MASK BITFIELD(27, 26)
+#define OMAP4430_CM1_CLKSEL_SOURCE_MASK BITFIELD(25, 24)
+#define OMAP4430_CM1_OPTFCLKEN_SLIMBUS_CLK_MASK BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_FCLK2_MASK BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_FCLK1_MASK BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_FCLK0_MASK BITFIELD(8, 8)
+#define OMAP4430_GPTIMER_CLKSEL_MASK BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_D2D_STATDEP_MASK BITFIELD(18, 18)
+#define OMAP4430_CEFUSE_STATDEP_MASK BITFIELD(17, 17)
+#define OMAP4430_ALWONCORE_STATDEP_MASK BITFIELD(16, 16)
+#define OMAP4430_L4WKUP_STATDEP_MASK BITFIELD(15, 15)
+#define OMAP4430_L4SEC_STATDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_SDMA_STATDEP_MASK BITFIELD(11, 11)
+#define OMAP4430_GFX_STATDEP_MASK BITFIELD(10, 10)
+#define OMAP4430_ISS_STATDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_DSS_STATDEP_MASK BITFIELD(8, 8)
+#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_L3_2_STATDEP_MASK BITFIELD(6, 6)
+#define OMAP4430_L3_1_STATDEP_MASK BITFIELD(5, 5)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_TESLA_STATDEP_MASK BITFIELD(1, 1)
+#define OMAP4430_DUCATI_STATDEP_MASK BITFIELD(0, 0)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_L3_1_DYNDEP_MASK BITFIELD(5, 5)
+#define OMAP4430_MEMIF_DYNDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_DYNDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CEFUSE_STATDEP_MASK BITFIELD(17, 17)
+#define OMAP4430_ALWONCORE_STATDEP_MASK BITFIELD(16, 16)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_ISS_STATDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_L3_1_STATDEP_MASK BITFIELD(5, 5)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_ABE_DYNDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_DYNDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_CLKACTIVITY_BGAP_32K_GFCLK_MASK BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK BITFIELD(8, 8)
+#define OMAP4430_REV_MASK BITFIELD(7, 0)
+#endif /* __ARCH_ARM_MACH_OMAP2_CM1_REGBITS_44XX_H */
diff --git a/arch/arm/mach-omap2/cm2-regbits-44xx.h b/arch/arm/mach-omap2/cm2-regbits-44xx.h
new file mode 100644
index 000000000000..ac8b151f456f
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2-regbits-44xx.h
@@ -0,0 +1,584 @@
+#ifndef __ARCH_ARM_MACH_OMAP2_CM2_REGBITS_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM2_REGBITS_44XX_H
+
+/*
+ * OMAP4430 Clock Management Module2 register bits
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Written by Rajendra Nayak (rnayak@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 "cm.h"
+
+#define OMAP4430_EN_GPT_SHIFT 1
+
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_ISS_GCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK (1 << 8)
+#define OMAP4430_CLKTRCTRL (1 << 0)
+#define OMAP4430_L3_2_STATDEP (1 << 6)
+#define OMAP4430_L3_1_STATDEP (1 << 5)
+#define OMAP4430_MEMIF_STATDEP (1 << 4)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_L3_2_DYNDEP (1 << 6)
+#define OMAP4430_STBYST (1 << 18)
+#define OMAP4430_IDLEST (1 << 16)
+#define OMAP4430_OPTFCLKEN_CTRLCLK (1 << 8)
+#define OMAP4430_MODULEMODE (1 << 0)
+#define OMAP4430_CLKSEL_FCLK (1 << 24)
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK (1 << 30)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK (1 << 29)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK (1 << 28)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK (1 << 27)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK (1 << 26)
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK (1 << 25)
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK (1 << 24)
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK (1 << 23)
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK (1 << 22)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK (1 << 21)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK (1 << 20)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK (1 << 19)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK (1 << 18)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK (1 << 17)
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK (1 << 16)
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK (1 << 15)
+#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK (1 << 14)
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK (1 << 13)
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK (1 << 12)
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK (1 << 8)
+#define OMAP4430_L4WKUP_STATDEP (1 << 15)
+#define OMAP4430_L4SEC_STATDEP (1 << 14)
+#define OMAP4430_L4PER_STATDEP (1 << 13)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_L3_1_DYNDEP (1 << 5)
+#define OMAP4430_HSMMC1_CLKSEL (1 << 24)
+#define OMAP4430_HSMMC2_CLKSEL (1 << 24)
+#define OMAP4430_HSI_CLKSEL (1 << 24)
+#define OMAP4430_OPTFCLKEN_TXPHYCLK (1 << 8)
+#define OMAP4430_CLKSEL_UTMI_P2 (1 << 25)
+#define OMAP4430_CLKSEL_UTMI_P1 (1 << 24)
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK (1 << 15)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK (1 << 14)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK (1 << 13)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK (1 << 12)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK (1 << 11)
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK (1 << 10)
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK (1 << 9)
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK (1 << 8)
+#define OMAP4430_SAR_MODE (1 << 4)
+#define OMAP4430_CLKSEL_60M (1 << 24)
+#define OMAP4430_OPTFCLKEN_XCLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK (1 << 10)
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK (1 << 9)
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK (1 << 8)
+#define OMAP4430_GPTIMER10_CLKSEL (1 << 24)
+#define OMAP4430_OPTFCLKEN_PHY_48M (1 << 8)
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_DSS_FCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK (1 << 8)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_OPTFCLKEN_TV_CLK (1 << 11)
+#define OMAP4430_OPTFCLKEN_SYS_CLK (1 << 10)
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK (1 << 9)
+#define OMAP4430_OPTFCLKEN_DSSCLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK (1 << 25)
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK (1 << 24)
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK (1 << 22)
+#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK (1 << 21)
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK (1 << 20)
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK (1 << 19)
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK (1 << 18)
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK (1 << 17)
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK (1 << 16)
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK (1 << 15)
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK (1 << 14)
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK (1 << 13)
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK (1 << 12)
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK (1 << 8)
+#define OMAP4430_WINDOWSIZE (1 << 24)
+#define OMAP4430_L4SEC_DYNDEP (1 << 14)
+#define OMAP4430_DSS_DYNDEP (1 << 8)
+#define OMAP4430_L3INIT_DYNDEP (1 << 7)
+#define OMAP4430_GPTIMER11_CLKSEL (1 << 24)
+#define OMAP4430_GPTIMER2_CLKSEL (1 << 24)
+#define OMAP4430_GPTIMER3_CLKSEL (1 << 24)
+#define OMAP4430_GPTIMER4_CLKSEL (1 << 24)
+#define OMAP4430_GPTIMER9_CLKSEL (1 << 24)
+#define OMAP4430_OPTFCLKEN_DBCLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DBCLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DBCLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DBCLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DBCLK (1 << 8)
+#define OMAP4430_L4PER_CLKSEL_INTERNAL_SOURCE (1 << 25)
+#define OMAP4430_CLKSEL_SOURCE (1 << 24)
+#define OMAP4430_L4PER_OPTFCLKEN_SLIMBUS_CLK (1 << 10)
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK (1 << 9)
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK (1 << 8)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_CLKSEL_PER_192M (1 << 25)
+#define OMAP4430_CLKSEL_SGX_FCLK (1 << 24)
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK (1 << 8)
+#define OMAP4430_L4CFG_DYNDEP (1 << 12)
+#define OMAP4430_MEMIF_DYNDEP (1 << 4)
+#define OMAP4430_ABE_DYNDEP (1 << 3)
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK (1 << 8)
+#define OMAP4430_L4PER_DYNDEP (1 << 13)
+#define OMAP4430_GFX_DYNDEP (1 << 10)
+#define OMAP4430_ISS_DYNDEP (1 << 9)
+#define OMAP4430_IVAHD_DYNDEP (1 << 2)
+#define OMAP4430_DUCATI_DYNDEP (1 << 0)
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK (1 << 8)
+#define OMAP4430_CEFUSE_STATDEP (1 << 17)
+#define OMAP4430_ALWONCORE_STATDEP (1 << 16)
+#define OMAP4430_L4SEC_STATDEP (1 << 14)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_SDMA_STATDEP (1 << 11)
+#define OMAP4430_GFX_STATDEP (1 << 10)
+#define OMAP4430_ISS_STATDEP (1 << 9)
+#define OMAP4430_DSS_STATDEP (1 << 8)
+#define OMAP4430_L3INIT_STATDEP (1 << 7)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_IVAHD_STATDEP (1 << 2)
+#define OMAP4430_TESLA_STATDEP (1 << 1)
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK (1 << 8)
+#define OMAP4430_L4SEC_STATDEP (1 << 14)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_ISS_STATDEP (1 << 9)
+#define OMAP4430_L3INIT_STATDEP (1 << 7)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_DUCATI_STATDEP (1 << 0)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK (1 << 13)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK (1 << 12)
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_DLL_CLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK (1 << 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK (1 << 8)
+#define OMAP4430_L4CFG_STATDEP (1 << 12)
+#define OMAP4430_L3INIT_STATDEP (1 << 7)
+#define OMAP4430_ABE_STATDEP (1 << 3)
+#define OMAP4430_MEMIF_DYNDEP (1 << 4)
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK (1 << 8)
+#define OMAP4430_D2D_DYNDEP (1 << 18)
+#define OMAP4430_CEFUSE_DYNDEP (1 << 17)
+#define OMAP4430_ALWONCORE_DYNDEP (1 << 16)
+#define OMAP4430_L4WKUP_DYNDEP (1 << 15)
+#define OMAP4430_SDMA_DYNDEP (1 << 11)
+#define OMAP4430_MEMIF_DYNDEP (1 << 4)
+#define OMAP4430_TESLA_DYNDEP (1 << 1)
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK (1 << 8)
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK (1 << 8)
+#define OMAP4430_REV (1 << 0)
+#define OMAP4430_CLKSEL_MPU (1 << 0)
+#define OMAP4430_CLKSEL_USB (1 << 0)
+#define OMAP4430_SCALE_FCLK (1 << 0)
+#define OMAP4430_PERF_REQ (1 << 0)
+#define OMAP4430_PERF_CURRENT (1 << 0)
+#define OMAP4430_DPLL_SSC_TYPE (1 << 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD (1 << 14)
+#define OMAP4430_DPLL_SSC_ACK (1 << 13)
+#define OMAP4430_DPLL_SSC_EN (1 << 12)
+#define OMAP4430_DPLL_REGM4XEN (1 << 11)
+#define OMAP4430_DPLL_LPMODE_EN (1 << 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN (1 << 9)
+#define OMAP4430_DPLL_RAMP_RATE (1 << 6)
+#define OMAP4430_DPLL_RAMP_LEVEL (1 << 4)
+#define OMAP4430_DPLL_DRIFTGUARD_EN (1 << 3)
+#define OMAP4430_DPLL_EN (1 << 0)
+#define OMAP4430_ST_DPLL_CLK (1 << 0)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN (1 << 4)
+#define OMAP4430_AUTO_DPLL_MODE (1 << 0)
+#define OMAP4430_DPLL_BYP_CLKSEL (1 << 23)
+#define OMAP4430_DPLL_MULT (1 << 8)
+#define OMAP4430_DPLL_DIV (1 << 0)
+#define OMAP4430_DPLL_M2_PWDN (1 << 12)
+#define OMAP4430_ST_DPLL_CLKOUTX2 (1 << 11)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL (1 << 10)
+#define OMAP4430_ST_DPLL_CLKOUT (1 << 9)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_PER_CLKOUT_DIVCHACK (1 << 5)
+#define OMAP4430_DPLL_CLKOUT_DIV (1 << 0)
+#define OMAP4430_DPLL_M3_PWDN (1 << 12)
+#define OMAP4430_ST_DPLL_CLKOUTHIF (1 << 9)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK (1 << 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV (1 << 0)
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN (1 << 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4 (1 << 9)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL (1 << 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK (1 << 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV (1 << 0)
+#define OMAP4430_DELTAMSTEP (1 << 0)
+#define OMAP4430_MODFREQDIV_EXPONENT (1 << 8)
+#define OMAP4430_MODFREQDIV_MANTISSA (1 << 0)
+#define OMAP4430_OVERRIDE_ENABLE (1 << 19)
+#define OMAP4430_PER_DPLL_EMU_MULT (1 << 8)
+#define OMAP4430_RESERVED (1 << 7)
+#define OMAP4430_PER_DPLL_EMU_DIV (1 << 0)
+#define OMAP4430_DPLL_SSC_TYPE (1 << 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD (1 << 14)
+#define OMAP4430_DPLL_SSC_ACK (1 << 13)
+#define OMAP4430_DPLL_SSC_EN (1 << 12)
+#define OMAP4430_DPLL_DRIFTGUARD_EN (1 << 3)
+#define OMAP4430_AUTO_DPLL_MODE (1 << 0)
+#define OMAP4430_DPLL_SD_DIV (1 << 24)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_USB_CLKOUT_DIVCHACK (1 << 7)
+#define OMAP4430_DPLL_CLKOUT_DIV (1 << 0)
+#define OMAP4430_DELTAMSTEP (1 << 0)
+#define OMAP4430_MODFREQDIV_EXPONENT (1 << 8)
+#define OMAP4430_MODFREQDIV_MANTISSA (1 << 0)
+#define OMAP4430_DPLL_CLKDCOLDO_PWDN (1 << 12)
+#define OMAP4430_ST_DPLL_CLKDCOLDO (1 << 9)
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL (1 << 8)
+#define OMAP4430_DPLL_SSC_TYPE (1 << 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD (1 << 14)
+#define OMAP4430_DPLL_SSC_ACK (1 << 13)
+#define OMAP4430_DPLL_SSC_EN (1 << 12)
+#define OMAP4430_DPLL_REGM4XEN (1 << 11)
+#define OMAP4430_DPLL_LPMODE_EN (1 << 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN (1 << 9)
+#define OMAP4430_DPLL_RAMP_RATE (1 << 6)
+#define OMAP4430_DPLL_RAMP_LEVEL (1 << 4)
+#define OMAP4430_DPLL_DRIFTGUARD_EN (1 << 3)
+#define OMAP4430_AUTO_DPLL_MODE (1 << 0)
+#define OMAP4430_DPLL_UNIPRO_CLKOUT_DIVCHACK (1 << 5)
+#define OMAP4430_DPLL_CLKOUT_DIV (1 << 0)
+#define OMAP4430_DELTAMSTEP (1 << 0)
+#define OMAP4430_MODFREQDIV_EXPONENT (1 << 8)
+#define OMAP4430_MODFREQDIV_MANTISSA (1 << 0)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK (1 << 11)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK (1 << 10)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK (1 << 9)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK (1 << 8)
+
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKTRCTRL_MASK BITFIELD(1, 0)
+#define OMAP4430_L3_2_STATDEP_MASK BITFIELD(6, 6)
+#define OMAP4430_L3_1_STATDEP_MASK BITFIELD(5, 5)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_L3_2_DYNDEP_MASK BITFIELD(6, 6)
+#define OMAP4430_STBYST_MASK BITFIELD(18, 18)
+#define OMAP4430_IDLEST_MASK BITFIELD(17, 16)
+#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_MODULEMODE_MASK BITFIELD(1, 0)
+#define OMAP4430_CLKSEL_FCLK_MASK BITFIELD(25, 24)
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK BITFIELD(30, 30)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK BITFIELD(29, 29)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK BITFIELD(28, 28)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK BITFIELD(27, 27)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK BITFIELD(26, 26)
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK BITFIELD(25, 25)
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK BITFIELD(23, 23)
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_MASK BITFIELD(14, 14)
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_L4WKUP_STATDEP_MASK BITFIELD(15, 15)
+#define OMAP4430_L4SEC_STATDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_L3_1_DYNDEP_MASK BITFIELD(5, 5)
+#define OMAP4430_CLKSEL_MASK BITFIELD(24, 24)
+#define OMAP4430_HSI_CLKSEL_MASK BITFIELD(25, 24)
+#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKSEL_UTMI_P2_MASK BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_UTMI_P1_MASK BITFIELD(24, 24)
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK BITFIELD(15, 15)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK BITFIELD(14, 14)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK BITFIELD(13, 13)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK BITFIELD(12, 12)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_SAR_MODE_MASK BITFIELD(4, 4)
+#define OMAP4430_CLKSEL_60M_MASK BITFIELD(24, 24)
+#define OMAP4430_OPTFCLKEN_XCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_SAR_MODE_MASK BITFIELD(4, 4)
+#define OMAP4430_OPTFCLKEN_PHY_48M_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_OPTFCLKEN_TV_CLK_MASK BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_DSSCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK BITFIELD(25, 25)
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK BITFIELD(14, 14)
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_L4SEC_DYNDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_DSS_DYNDEP_MASK BITFIELD(8, 8)
+#define OMAP4430_L3INIT_DYNDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CM2_CLKSEL_INTERNAL_SOURCE_MASK BITFIELD(25, 25)
+#define OMAP4430_CM2_CLKSEL_SOURCE_MASK BITFIELD(24, 24)
+#define OMAP4430_CM2_OPTFCLKEN_SLIMBUS_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_CLKSEL_PER_192M_MASK BITFIELD(26, 25)
+#define OMAP4430_CLKSEL_SGX_FCLK_MASK BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_L4CFG_DYNDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_MEMIF_DYNDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_DYNDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_L4SEC_DYNDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_L4PER_DYNDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_GFX_DYNDEP_MASK BITFIELD(10, 10)
+#define OMAP4430_ISS_DYNDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_L3INIT_DYNDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_IVAHD_DYNDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_DUCATI_DYNDEP_MASK BITFIELD(0, 0)
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CEFUSE_STATDEP_MASK BITFIELD(17, 17)
+#define OMAP4430_ALWONCORE_STATDEP_MASK BITFIELD(16, 16)
+#define OMAP4430_L4WKUP_STATDEP_MASK BITFIELD(15, 15)
+#define OMAP4430_L4SEC_STATDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_SDMA_STATDEP_MASK BITFIELD(11, 11)
+#define OMAP4430_GFX_STATDEP_MASK BITFIELD(10, 10)
+#define OMAP4430_ISS_STATDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_DSS_STATDEP_MASK BITFIELD(8, 8)
+#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_TESLA_STATDEP_MASK BITFIELD(1, 1)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_ISS_DYNDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_L4WKUP_STATDEP_MASK BITFIELD(15, 15)
+#define OMAP4430_L4SEC_STATDEP_MASK BITFIELD(14, 14)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_ISS_STATDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_DSS_STATDEP_MASK BITFIELD(8, 8)
+#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_DUCATI_STATDEP_MASK BITFIELD(0, 0)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_L4PER_STATDEP_MASK BITFIELD(13, 13)
+#define OMAP4430_L4CFG_STATDEP_MASK BITFIELD(12, 12)
+#define OMAP4430_L3INIT_STATDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_MEMIF_STATDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_ABE_STATDEP_MASK BITFIELD(3, 3)
+#define OMAP4430_IVAHD_STATDEP_MASK BITFIELD(2, 2)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_MEMIF_DYNDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_WINDOWSIZE_MASK BITFIELD(27, 24)
+#define OMAP4430_D2D_DYNDEP_MASK BITFIELD(18, 18)
+#define OMAP4430_CEFUSE_DYNDEP_MASK BITFIELD(17, 17)
+#define OMAP4430_ALWONCORE_DYNDEP_MASK BITFIELD(16, 16)
+#define OMAP4430_L4WKUP_DYNDEP_MASK BITFIELD(15, 15)
+#define OMAP4430_SDMA_DYNDEP_MASK BITFIELD(11, 11)
+#define OMAP4430_ISS_DYNDEP_MASK BITFIELD(9, 9)
+#define OMAP4430_L3INIT_DYNDEP_MASK BITFIELD(7, 7)
+#define OMAP4430_MEMIF_DYNDEP_MASK BITFIELD(4, 4)
+#define OMAP4430_TESLA_DYNDEP_MASK BITFIELD(1, 1)
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK BITFIELD(8, 8)
+#define OMAP4430_REV_MASK BITFIELD(7, 0)
+#define OMAP4430_MPU_M3_ISS_ROOT_CLKSEL_MASK BITFIELD(0, 0)
+#define OMAP4430_USB_60MHZ_CLKSEL_MASK BITFIELD(0, 0)
+#define OMAP4430_SCALE_FCLK_MASK BITFIELD(0, 0)
+#define OMAP4430_PERF_REQ_MASK BITFIELD(7, 0)
+#define OMAP4430_PERF_CURRENT_MASK BITFIELD(7, 0)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_REGM4XEN_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_LPMODE_EN_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_RAMP_RATE_MASK BITFIELD(8, 6)
+#define OMAP4430_DPLL_RAMP_LEVEL_MASK BITFIELD(5, 4)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_EN_MASK BITFIELD(2, 0)
+#define OMAP4430_ST_DPLL_CLK_MASK BITFIELD(0, 0)
+#define OMAP4430_DPLL_DCOCLKLDO_PWDN_MASK BITFIELD(4, 4)
+#define OMAP4430_AUTO_DPLL_MODE_MASK BITFIELD(2, 0)
+#define OMAP4430_DPLL_BYP_CLKSEL_MASK BITFIELD(23, 23)
+#define OMAP4430_CM2_DPLL_MULT_MASK BITFIELD(18, 8)
+#define OMAP4430_CM2_DPLL_DIV_MASK BITFIELD(6, 0)
+#define OMAP4430_DPLL_M2_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK BITFIELD(10, 10)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUT_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_DPLL_M3_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK BITFIELD(9, 9)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK BITFIELD(4, 0)
+#define OMAP4430_DELTAMSTEP_MASK BITFIELD(19, 0)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK BITFIELD(10, 8)
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK BITFIELD(6, 0)
+#define OMAP4430_OVERRIDE_ENABLE_MASK BITFIELD(19, 19)
+#define OMAP4430_PER_DPLL_EMU_MULT_MASK BITFIELD(18, 8)
+#define OMAP4430_RESERVED_MASK BITFIELD(7, 7)
+#define OMAP4430_PER_DPLL_EMU_DIV_MASK BITFIELD(6, 0)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_SD_DIV_MASK BITFIELD(31, 24)
+#define OMAP4430_CM2_USB_DPLL_MULT_MASK BITFIELD(19, 8)
+#define OMAP4430_CM2_USB_DPLL_DIV_MASK BITFIELD(7, 0)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_USB_DPLL_CLKOUT_DIVCHACK_MASK BITFIELD(7, 7)
+#define OMAP4430_USB_DPLL_CLKOUT_DIV_MASK BITFIELD(6, 0)
+#define OMAP4430_DELTAMSTEP_MASK BITFIELD(19, 0)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK BITFIELD(10, 8)
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK BITFIELD(6, 0)
+#define OMAP4430_DPLL_CLKDCOLDO_PWDN_MASK BITFIELD(12, 12)
+#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_SSC_TYPE_MASK BITFIELD(15, 15)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_ACK_MASK BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_DPLL_REGM4XEN_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_LPMODE_EN_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_RELOCK_RAMP_EN_MASK BITFIELD(9, 9)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK BITFIELD(11, 11)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK BITFIELD(10, 10)
+#define OMAP4430_DELTAMSTEP_MASK BITFIELD(19, 0)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK BITFIELD(10, 8)
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK BITFIELD(6, 0)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK BITFIELD(8, 8)
+#endif /* __ARCH_ARM_MACH_OMAP2_CM2_REGBITS_44XX_H */
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 5f3aad977842..b93ab8ddc797 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -19,17 +19,19 @@
#include <mach/control.h>
static void __iomem *omap2_ctrl_base;
+static void __iomem *omap2_ctrl_base1;
-#define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base + (reg))
+#define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base1 + (reg))
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
{
omap2_ctrl_base = omap2_globals->ctrl;
+ omap2_ctrl_base1 = omap2_globals->ctrl;
}
void __iomem *omap_ctrl_base_get(void)
{
- return omap2_ctrl_base;
+ return omap2_ctrl_base1;
}
u8 omap_ctrl_readb(u16 offset)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 894cc355818a..c9a83c09bdd8 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -136,8 +136,11 @@ static inline void omap_init_camera(void)
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+#ifdef CONFIG_ARCH_OMAP4
+#define MBOX_REG_SIZE 0x130
+#else
#define MBOX_REG_SIZE 0x120
-
+#endif
static struct resource omap2_mbox_resources[] = {
{
.start = OMAP24XX_MAILBOX_BASE,
@@ -166,6 +169,18 @@ static struct resource omap3_mbox_resources[] = {
},
};
+static struct resource omap4_mbox_resources[] = {
+ {
+ .start = OMAP44xx_MAILBOX_BASE,
+ .end = OMAP44xx_MAILBOX_BASE + MBOX_REG_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_44XX_MAIL_U0_MPU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct platform_device mbox_device = {
.name = "omap2-mailbox",
.id = -1,
@@ -179,6 +194,9 @@ static inline void omap_init_mbox(void)
} else if (cpu_is_omap3430()) {
mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
mbox_device.resource = omap3_mbox_resources;
+ } else if (cpu_is_omap44xx()) {
+ mbox_device.num_resources = ARRAY_SIZE(omap4_mbox_resources);
+ mbox_device.resource = omap4_mbox_resources;
} else {
pr_err("%s: platform not supported\n", __func__);
return;
@@ -259,6 +277,7 @@ static inline void omap_init_sti(void) {}
static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
.num_cs = 4,
+ .force_cs_mode = 1,
};
static struct resource omap2_mcspi1_resources[] = {
@@ -281,6 +300,10 @@ static struct platform_device omap2_mcspi1 = {
static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
.num_cs = 2,
+ .mode = OMAP2_MCSPI_MASTER,
+ .dma_mode = 1,
+ .force_cs_mode = 0,
+ .fifo_depth = 0,
};
static struct resource omap2_mcspi2_resources[] = {
@@ -301,7 +324,8 @@ static struct platform_device omap2_mcspi2 = {
},
};
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+defined(CONFIG_ARCH_OMAP4)
static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
.num_cs = 2,
};
@@ -325,7 +349,7 @@ static struct platform_device omap2_mcspi3 = {
};
#endif
-#ifdef CONFIG_ARCH_OMAP3
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
.num_cs = 1,
};
@@ -353,12 +377,13 @@ static void omap_init_mcspi(void)
{
platform_device_register(&omap2_mcspi1);
platform_device_register(&omap2_mcspi2);
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
- if (cpu_is_omap2430() || cpu_is_omap343x())
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+defined(CONFIG_ARCH_OMAP4)
+ if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx())
platform_device_register(&omap2_mcspi3);
#endif
-#ifdef CONFIG_ARCH_OMAP3
- if (cpu_is_omap343x())
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
+ if (cpu_is_omap343x() || cpu_is_omap44xx())
platform_device_register(&omap2_mcspi4);
#endif
}
@@ -397,7 +422,7 @@ static inline void omap_init_sha1_md5(void) { }
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_ARCH_OMAP3
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
#define MMCHS_SYSCONFIG 0x0010
#define MMCHS_SYSCONFIG_SWRESET (1 << 1)
@@ -424,8 +449,8 @@ static struct platform_device dummy_pdev = {
**/
static void __init omap_hsmmc_reset(void)
{
- u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC :
- OMAP24XX_NR_MMC;
+ u32 i, nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC :
+ (cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC);
for (i = 0; i < nr_controllers; i++) {
u32 v, base = 0;
@@ -442,8 +467,22 @@ static void __init omap_hsmmc_reset(void)
case 2:
base = OMAP3_MMC3_BASE;
break;
+ case 3:
+ if (!cpu_is_omap44xx())
+ return;
+ else
+ base = OMAP4_MMC4_BASE;
+ break;
+ case 4:
+ if (!cpu_is_omap44xx())
+ return;
+ else
+ base = OMAP4_MMC5_BASE;
+ break;
}
+ if (cpu_is_omap44xx())
+ base += OMAP4_MMC_REG_OFFSET;
dummy_pdev.id = i;
dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
iclk = clk_get(dev, "ick");
@@ -513,6 +552,63 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
}
}
+ if (cpu_is_omap44xx()) {
+ switch (controller_nr) {
+ case 0:
+ /* MMCC1 MUX configure */
+ omap_cfg_reg(A1_4430_MMC1_CLK);
+ omap_cfg_reg(C1_4430_MMC1_CMD);
+ omap_cfg_reg(D0_4430_MMC1_DAT0);
+ omap_cfg_reg(D1_4430_MMC1_DAT1);
+ omap_cfg_reg(D2_4430_MMC1_DAT2);
+ omap_cfg_reg(D3_4430_MMC1_DAT3);
+ omap_cfg_reg(D4_4430_MMC1_DAT4);
+ omap_cfg_reg(D5_4430_MMC1_DAT5);
+ omap_cfg_reg(D6_4430_MMC1_DAT6);
+ omap_cfg_reg(D7_4430_MMC1_DAT7);
+ break;
+ case 1:
+ /*MMC2 MUX configure */
+ omap_cfg_reg(A1_4430_MMC2_CLK);
+ omap_cfg_reg(C1_4430_MMC2_CMD);
+ omap_cfg_reg(D0_4430_MMC2_DAT0);
+ omap_cfg_reg(D1_4430_MMC2_DAT1);
+ omap_cfg_reg(D2_4430_MMC2_DAT2);
+ omap_cfg_reg(D3_4430_MMC2_DAT3);
+ omap_cfg_reg(D4_4430_MMC2_DAT4);
+ omap_cfg_reg(D5_4430_MMC2_DAT5);
+ omap_cfg_reg(D6_4430_MMC2_DAT6);
+ omap_cfg_reg(D7_4430_MMC2_DAT7);
+ break;
+ case 2:
+ /*MMC3 MUX configure */
+ omap_cfg_reg(A1_4430_MMC3_CLK);
+ omap_cfg_reg(C1_4430_MMC3_CMD);
+ omap_cfg_reg(D0_4430_MMC3_DAT0);
+ omap_cfg_reg(D1_4430_MMC3_DAT1);
+ omap_cfg_reg(D2_4430_MMC3_DAT2);
+ omap_cfg_reg(D3_4430_MMC3_DAT3);
+ break;
+ case 3:
+ /*MMC4 MUX configure */
+ omap_cfg_reg(A1_4430_MMC4_CLK);
+ omap_cfg_reg(C1_4430_MMC4_CMD);
+ omap_cfg_reg(D0_4430_MMC4_DAT0);
+ omap_cfg_reg(D1_4430_MMC4_DAT1);
+ omap_cfg_reg(D2_4430_MMC4_DAT2);
+ omap_cfg_reg(D3_4430_MMC4_DAT3);
+ break;
+ case 4:
+ /*MMC5 MUX configure */
+ omap_cfg_reg(A1_4430_MMC5_CLK);
+ omap_cfg_reg(C1_4430_MMC5_CMD);
+ omap_cfg_reg(D0_4430_MMC5_DAT0);
+ omap_cfg_reg(D1_4430_MMC5_DAT1);
+ omap_cfg_reg(D2_4430_MMC5_DAT2);
+ omap_cfg_reg(D3_4430_MMC2_DAT3);
+ break;
+ }
+ }
}
void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
@@ -540,11 +636,23 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
irq = INT_24XX_MMC2_IRQ;
break;
case 2:
- if (!cpu_is_omap34xx())
+ if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
return;
base = OMAP3_MMC3_BASE;
irq = INT_34XX_MMC3_IRQ;
break;
+ case 3:
+ if (!cpu_is_omap44xx())
+ return;
+ base = OMAP4_MMC4_BASE + OMAP4_MMC_REG_OFFSET;
+ irq = INT_44XX_MMC4_IRQ;
+ break;
+ case 4:
+ if (!cpu_is_omap44xx())
+ return;
+ base = OMAP4_MMC5_BASE + OMAP4_MMC_REG_OFFSET;
+ irq = INT_44XX_MMC5_IRQ;
+ break;
default:
continue;
}
@@ -552,8 +660,15 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
if (cpu_is_omap2420()) {
size = OMAP2420_MMC_SIZE;
name = "mmci-omap";
+ } else if (cpu_is_omap44xx()) {
+ if (i < 3) {
+ base += OMAP4_MMC_REG_OFFSET;
+ irq += IRQ_GIC_START;
+ }
+ size = OMAP4_HSMMC_SIZE;
+ name = "mmci-omap-hs";
} else {
- size = HSMMC_SIZE;
+ size = OMAP3_HSMMC_SIZE;
name = "mmci-omap-hs";
}
omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
new file mode 100644
index 000000000000..f00d0c963c7b
--- /dev/null
+++ b/arch/arm/mach-omap2/dspbridge.c
@@ -0,0 +1,76 @@
+/*
+ * TI's dspbridge platform device registration
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Written by 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/platform_device.h>
+
+#ifdef CONFIG_PM
+#include <mach/omap-pm.h>
+#endif
+#include <dspbridge/host_os.h>
+
+static struct platform_device *dspbridge_pdev;
+
+static struct dspbridge_platform_data dspbridge_pdata __initdata = {
+
+#ifdef CONFIG_BRIDGE_DVFS
+ .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
+ .dsp_get_opp = omap_pm_dsp_get_opp,
+ .cpu_set_freq = omap_pm_cpu_set_freq,
+ .cpu_get_freq = omap_pm_cpu_get_freq,
+#endif
+};
+
+static int __init dspbridge_init(void)
+{
+ struct platform_device *pdev;
+ int err = -ENOMEM;
+ struct dspbridge_platform_data *pdata = &dspbridge_pdata;
+
+ pdata->phys_mempool_base = dspbridge_get_mempool_base();
+
+ if (pdata->phys_mempool_base) {
+ pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
+ pr_info("%s: %x bytes @ %x\n", __func__,
+ pdata->phys_mempool_size, pdata->phys_mempool_base);
+ }
+
+ pdev = platform_device_alloc("C6410", -1);
+ if (!pdev)
+ goto err_out;
+
+ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (err)
+ goto err_out;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_out;
+
+ dspbridge_pdev = pdev;
+ return 0;
+
+err_out:
+ platform_device_put(pdev);
+ return err;
+}
+module_init(dspbridge_init);
+
+static void __exit dspbridge_exit(void)
+{
+ platform_device_unregister(dspbridge_pdev);
+}
+module_exit(dspbridge_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_DESCRIPTION("TI's dspbridge platform device registration");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index a98201cc265c..12e8b4a347b8 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -226,8 +226,11 @@ void __init omap2_check_revision(void)
else if (cpu_is_omap34xx())
omap34xx_check_revision();
else if (cpu_is_omap44xx()) {
+ /* omap44xx_check_revision() should
+ * be defined above and then called
+ * from here.
+ */
printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n");
- return;
} else
pr_err("OMAP revision unknown, please fix!\n");
@@ -252,6 +255,8 @@ void __init omap2_check_revision(void)
omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
else if (omap_rev() == OMAP3430_REV_ES3_1)
omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+ } else if (cpu_is_omap44xx()) {
+ omap_chip.oc |= CHIP_IS_OMAP4430;
} else {
pr_err("Uninitialized omap_chip, please fix!\n");
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 0a9f412dad58..a809efafb978 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <linux/clk.h>
#include <asm/tlb.h>
@@ -28,12 +29,10 @@
#include <asm/mach/map.h>
#include <mach/mux.h>
-#include <mach/omapfb.h>
#include <mach/sram.h>
#include <mach/sdrc.h>
#include <mach/gpmc.h>
-#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */
#include "clock.h"
#include <mach/powerdomain.h>
@@ -42,7 +41,8 @@
#include <mach/clockdomain.h>
#include "clockdomains.h"
-#endif
+#include <dspbridge/host_os.h>
+
/*
* The machine specific code may provide the extra mapping besides the
* default mapping provided here.
@@ -246,6 +246,7 @@ void __init omap2_map_common_io(void)
omap2_check_revision();
omap_sram_init();
omapfb_reserve_sdram();
+ dspbridge_reserve_sdram();
}
/*
@@ -286,12 +287,12 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1)
{
omap2_mux_init();
-#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
- omap2_clk_init();
+#ifndef CONFIG_ARCH_OMAP4
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
_omap2_init_reprogram_sdrc();
#endif
+ omap2_clk_init();
gpmc_init();
}
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 015f22a53ead..01cb15d9df3c 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -80,12 +80,16 @@ static int omap2_iommu_enable(struct iommu *obj)
if (l & MMU_SYS_RESETDONE)
break;
} while (time_after(jiffies, timeout));
-
+/* FIXME: Hack till the reading the MMU status register
+ * is resolved in Simulator. Simulator doesn't update
+ * the STATUS register.
+ */
+#ifndef CONFIG_ARCH_OMAP4
if (!(l & MMU_SYS_RESETDONE)) {
dev_err(obj->dev, "can't take mmu out of reset\n");
return -ENODEV;
}
-
+#endif
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 6f71f3730c97..6fc859079410 100644..100755
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -18,21 +18,36 @@
#include <mach/mailbox.h>
#include <mach/irqs.h>
+#define DRV_NAME "omap2-mailbox"
+
#define MAILBOX_REVISION 0x000
#define MAILBOX_SYSCONFIG 0x010
#define MAILBOX_SYSSTATUS 0x014
#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
+
+#ifdef CONFIG_ARCH_OMAP4
+#define MAILBOX_IRQSTATUS(u) (0x104 + 10 * (u))
+#define MAILBOX_IRQENABLE(u) (0x108 + 10 * (u))
+#define MAILBOX_IRQENABLE_CLR(u) (0x10c + 10 * (u))
+#else
#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
+#endif
-#define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u)))
-#define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1))
+#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
+#ifdef CONFIG_ARCH_OMAP4
+#define MBOX_REG_SIZE 0x130
+#else
#define MBOX_REG_SIZE 0x120
+#endif
+
#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
+
static void __iomem *mbox_base;
struct omap_mbox2_fifo {
@@ -49,9 +64,13 @@ struct omap_mbox2_priv {
u32 newmsg_bit;
u32 notfull_bit;
u32 ctx[MBOX_NR_REGS];
+#ifdef CONFIG_ARCH_OMAP4
+ unsigned long irqdisable;
+#endif
};
static struct clk *mbox_ick_handle;
+static int mbox_configured;
static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq);
@@ -70,31 +89,45 @@ static inline void mbox_write_reg(u32 val, size_t ofs)
static int omap2_mbox_startup(struct omap_mbox *mbox)
{
unsigned int l;
+ if (!mbox_configured) {
+ if (!cpu_is_omap44xx()) {
+ mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
+ if (IS_ERR(mbox_ick_handle)) {
+ printk(KERN_ERR "Could not get"
+ "mailboxes_ick\n");
+ return -ENODEV;
+ }
+ clk_enable(mbox_ick_handle);
+ }
- mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
- if (IS_ERR(mbox_ick_handle)) {
- printk("Could not get mailboxes_ick\n");
- return -ENODEV;
- }
- clk_enable(mbox_ick_handle);
-
- l = mbox_read_reg(MAILBOX_REVISION);
- pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
- /* set smart-idle & autoidle */
- l = mbox_read_reg(MAILBOX_SYSCONFIG);
- l |= 0x00000011;
- mbox_write_reg(l, MAILBOX_SYSCONFIG);
+ l = mbox_read_reg(MAILBOX_REVISION);
+ pr_info("omap mailbox rev %d.%d\n",
+ (l & 0xf0) >> 4, (l & 0x0f));
+ /* set smart-idle & autoidle */
+ l = mbox_read_reg(MAILBOX_SYSCONFIG);
+ l |= 0x00000011;
+ mbox_write_reg(l, MAILBOX_SYSCONFIG);
+ }
+ mbox_configured++;
omap2_mbox_enable_irq(mbox, IRQ_RX);
return 0;
}
static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
- clk_disable(mbox_ick_handle);
- clk_put(mbox_ick_handle);
+{ if (mbox_configured > 0)
+ mbox_configured--;
+ if (!cpu_is_omap44xx()) {
+ if (!mbox_configured) {
+ clk_disable(mbox_ick_handle);
+ clk_put(mbox_ick_handle);
+ mbox_ick_handle = NULL;
+ }
+ } else {
+ printk(KERN_ERR "OMAP4 clocks are not modeled");
+ }
+
}
/* Mailbox FIFO handle functions */
@@ -123,7 +156,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
- return (mbox_read_reg(fifo->fifo_stat));
+ return mbox_read_reg(fifo->fifo_stat);
}
/* Mailbox IRQ handle functions */
@@ -143,10 +176,9 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
- l = mbox_read_reg(p->irqenable);
+ l = mbox_read_reg(p->irqdisable);
l &= ~bit;
- mbox_write_reg(l, p->irqenable);
+ mbox_write_reg(l, p->irqdisable);
}
static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
@@ -156,6 +188,8 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_write_reg(bit, p->irqstatus);
+ /* Flush post writing */
+ mbox_read_reg(p->irqstatus);
}
static int omap2_mbox_is_irq(struct omap_mbox *mbox,
@@ -166,7 +200,7 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox,
u32 enable = mbox_read_reg(p->irqenable);
u32 status = mbox_read_reg(p->irqstatus);
- return (enable & status & bit);
+ return (int)(enable & status & bit);
}
static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
@@ -219,9 +253,12 @@ static struct omap_mbox_ops omap2_mbox_ops = {
*/
/* FIXME: the following structs should be filled automatically by the user id */
-
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_mbox2_priv omap2_mbox_1_priv = {
+#else
/* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
+#endif
.tx_fifo = {
.msg = MAILBOX_MESSAGE(0),
.fifo_stat = MAILBOX_FIFOSTATUS(0),
@@ -234,7 +271,19 @@ static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
.irqstatus = MAILBOX_IRQSTATUS(0),
.notfull_bit = MAILBOX_IRQ_NOTFULL(0),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
+#ifdef CONFIG_ARCH_OMAP4
+ .irqdisable = MAILBOX_IRQENABLE_CLR(0),
+#endif
+};
+
+#ifdef CONFIG_ARCH_OMAP4
+struct omap_mbox mbox_1_info = {
+ .name = "mailbox-1",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_1_priv,
};
+EXPORT_SYMBOL(mbox_1_info);
+#else
struct omap_mbox mbox_dsp_info = {
.name = "dsp",
@@ -242,6 +291,33 @@ struct omap_mbox mbox_dsp_info = {
.priv = &omap2_mbox_dsp_priv,
};
EXPORT_SYMBOL(mbox_dsp_info);
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_mbox2_priv omap2_mbox_2_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE(3),
+ .fifo_stat = MAILBOX_FIFOSTATUS(3),
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE(2),
+ .msg_stat = MAILBOX_MSGSTATUS(2),
+ },
+ .irqenable = MAILBOX_IRQENABLE(0),
+ .irqstatus = MAILBOX_IRQSTATUS(0),
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(3),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(2),
+ .irqdisable = MAILBOX_IRQENABLE_CLR(0),
+};
+
+struct omap_mbox mbox_2_info = {
+ .name = "mailbox-2",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_2_priv,
+};
+EXPORT_SYMBOL(mbox_2_info);
+#endif
+
#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
static struct omap_mbox2_priv omap2_mbox_iva_priv = {
@@ -282,17 +358,31 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
return -ENOMEM;
/* DSP or IVA2 IRQ */
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n");
+ ret = -ENODEV;
goto err_dsp;
}
- mbox_dsp_info.irq = ret;
-
+#ifdef CONFIG_ARCH_OMAP4
+ mbox_1_info.irq = res->start;
+ ret = omap_mbox_register(&pdev->dev, &mbox_1_info);
+#else
+ mbox_dsp_info.irq = res->start;
ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
+#endif
if (ret)
goto err_dsp;
+#ifdef CONFIG_ARCH_OMAP4
+
+ mbox_2_info.irq = res->start;
+ ret = omap_mbox_register(&pdev->dev, &mbox_2_info);
+ if (ret)
+ goto err_mbox_2;
+#endif
+
#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
if (cpu_is_omap2420()) {
/* IVA IRQ */
@@ -310,8 +400,14 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
#endif
return 0;
+#ifdef CONFIG_ARCH_OMAP4
+err_mbox_2:
+ omap_mbox_unregister(&mbox_1_info);
+#else
err_iva1:
omap_mbox_unregister(&mbox_dsp_info);
+#endif
+
err_dsp:
iounmap(mbox_base);
return ret;
@@ -322,7 +418,13 @@ static int __devexit omap2_mbox_remove(struct platform_device *pdev)
#if defined(CONFIG_ARCH_OMAP2420)
omap_mbox_unregister(&mbox_iva_info);
#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+ omap_mbox_unregister(&mbox_2_info);
+ omap_mbox_unregister(&mbox_1_info);
+#else
omap_mbox_unregister(&mbox_dsp_info);
+#endif
iounmap(mbox_base);
return 0;
}
@@ -331,7 +433,7 @@ static struct platform_driver omap2_mbox_driver = {
.probe = omap2_mbox_probe,
.remove = __devexit_p(omap2_mbox_remove),
.driver = {
- .name = "omap2-mailbox",
+ .name = DRV_NAME,
},
};
@@ -351,4 +453,4 @@ module_exit(omap2_mbox_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");
+MODULE_ALIAS("platform:"DRV_NAME);
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 99b6e1546311..5819872e12f8 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -168,6 +168,47 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
#define OMAP34XX_MCBSP_PDATA_SZ 0
#endif
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
+ {
+ .phys_base = OMAP44XX_MCBSP1_BASE,
+ .dma_rx_sync = OMAP44XX_DMA_MCBSP1_RX,
+ .dma_tx_sync = OMAP44XX_DMA_MCBSP1_TX,
+ .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+ .ops = &omap2_mcbsp_ops,
+ },
+ {
+ .phys_base = OMAP44XX_MCBSP2_BASE,
+ .dma_rx_sync = OMAP44XX_DMA_MCBSP2_RX,
+ .dma_tx_sync = OMAP44XX_DMA_MCBSP2_TX,
+ .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+ .ops = &omap2_mcbsp_ops,
+ },
+ {
+ .phys_base = OMAP44XX_MCBSP3_BASE,
+ .dma_rx_sync = OMAP44XX_DMA_MCBSP3_RX,
+ .dma_tx_sync = OMAP44XX_DMA_MCBSP3_TX,
+ .rx_irq = INT_24XX_MCBSP3_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP3_IRQ_TX,
+ .ops = &omap2_mcbsp_ops,
+ },
+ {
+ .phys_base = OMAP44XX_MCBSP4_BASE,
+ .dma_rx_sync = OMAP44XX_DMA_MCBSP4_RX,
+ .dma_tx_sync = OMAP44XX_DMA_MCBSP4_TX,
+ .rx_irq = INT_24XX_MCBSP4_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP4_IRQ_TX,
+ .ops = &omap2_mcbsp_ops,
+ },
+};
+#define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata)
+#else
+#define omap44xx_mcbsp_pdata NULL
+#define OMAP44XX_MCBSP_PDATA_SZ 0
+#endif
+
static int __init omap2_mcbsp_init(void)
{
if (cpu_is_omap2420())
@@ -176,6 +217,8 @@ static int __init omap2_mcbsp_init(void)
omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
if (cpu_is_omap34xx())
omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
+ if (cpu_is_omap44xx())
+ omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ;
mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
GFP_KERNEL);
@@ -191,6 +234,9 @@ static int __init omap2_mcbsp_init(void)
if (cpu_is_omap34xx())
omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
OMAP34XX_MCBSP_PDATA_SZ);
+ if (cpu_is_omap44xx())
+ omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata,
+ OMAP44XX_MCBSP_PDATA_SZ);
return omap_mcbsp_init();
}
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c
index 3c04c2f1b23f..b2a5086f1827 100644
--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -25,7 +25,7 @@
#include <mach/board.h>
#include "mmc-twl4030.h"
-
+#include <linux/i2c/twl.h>
#if defined(CONFIG_REGULATOR) && \
(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
@@ -34,6 +34,7 @@ static u16 control_pbias_offset;
static u16 control_devconf1_offset;
#define HSMMC_NAME_LEN 9
+#define REG_SIMCTRL 0x0C
static struct twl_mmc_controller {
struct omap_mmc_platform_data *mmc;
@@ -46,23 +47,41 @@ static struct twl_mmc_controller {
struct regulator *vcc;
struct regulator *vcc_aux;
char name[HSMMC_NAME_LEN + 1];
-} hsmmc[OMAP34XX_NR_MMC];
+} hsmmc[OMAP44XX_NR_MMC];
static int twl_mmc_card_detect(int irq)
{
- unsigned i;
-
- for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
- struct omap_mmc_platform_data *mmc;
-
- mmc = hsmmc[i].mmc;
- if (!mmc)
- continue;
- if (irq != mmc->slots[0].card_detect_irq)
- continue;
-
- /* NOTE: assumes card detect signal is active-low */
- return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+ if (!cpu_is_omap44xx()) {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
+ struct omap_mmc_platform_data *mmc;
+
+ mmc = hsmmc[i].mmc;
+ if (!mmc)
+ continue;
+ if (irq != mmc->slots[0].card_detect_irq)
+ continue;
+
+ /* NOTE: assumes card detect signal is active-low */
+ return !gpio_get_value_cansleep
+ (mmc->slots[0].switch_pin);
+ }
+ } else {
+ /* BIT0 of REG_SIMCTRL
+ * 0 - Card not present
+ * 1 - Card present
+ */
+ u8 read_reg;
+ unsigned res;
+ res = twl_i2c_read_u8(TWL6030_MODULE_PM_MISC,
+ &read_reg, REG_SIMCTRL);
+ if (res < 0) {
+ printk(KERN_ERR"%s: i2c_read fail at %x \n",
+ __func__, REG_SIMCTRL);
+ return -1;
+ } else {
+ return read_reg & 0x1;
+ }
}
return -ENOSYS;
}
@@ -328,7 +347,7 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v
return ret;
}
-static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
+static struct omap_mmc_platform_data *hsmmc_data[OMAP44XX_NR_MMC] __initdata;
void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
{
@@ -375,31 +394,54 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
mmc->dma_mask = 0xffffffff;
mmc->init = twl_mmc_late_init;
- /* note: twl4030 card detect GPIOs can disable VMMCx ... */
- if (gpio_is_valid(c->gpio_cd)) {
+ if (!cpu_is_omap44xx()) {
+ /* note: twl4030 card detect GPIOs can disable
+ * VMMCx ...
+ */
+ if (gpio_is_valid(c->gpio_cd)) {
+ mmc->cleanup = twl_mmc_cleanup;
+ mmc->suspend = twl_mmc_suspend;
+ mmc->resume = twl_mmc_resume;
+
+ mmc->slots[0].switch_pin = c->gpio_cd;
+ mmc->slots[0].card_detect_irq =
+ gpio_to_irq(c->gpio_cd);
+ if (c->cover_only)
+ mmc->slots[0].get_cover_state =
+ twl_mmc_get_cover_state;
+ else
+ mmc->slots[0].card_detect =
+ twl_mmc_card_detect;
+ } else
+ mmc->slots[0].switch_pin = -EINVAL;
+
+ /* write protect normally uses an OMAP gpio */
+ if (gpio_is_valid(c->gpio_wp)) {
+ gpio_request(c->gpio_wp, "mmc_wp");
+ gpio_direction_input(c->gpio_wp);
+
+ mmc->slots[0].gpio_wp = c->gpio_wp;
+ mmc->slots[0].get_ro = twl_mmc_get_ro;
+ } else
+ mmc->slots[0].gpio_wp = -EINVAL;
+ } else {
+ /* Dummy Initialization for OMAP4 */
+ mmc->init = twl_mmc_late_init;
mmc->cleanup = twl_mmc_cleanup;
mmc->suspend = twl_mmc_suspend;
mmc->resume = twl_mmc_resume;
-
+ mmc->slots[0].switch_pin = NULL;
+ mmc->slots[0].get_cover_state = NULL;
mmc->slots[0].switch_pin = c->gpio_cd;
- mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd);
- if (c->cover_only)
- mmc->slots[0].get_cover_state = twl_mmc_get_cover_state;
+ /* HardCoding Phoenix number for only MMC1 */
+ if (c->mmc == 1)
+ mmc->slots[0].card_detect_irq = 373;
else
- mmc->slots[0].card_detect = twl_mmc_card_detect;
- } else
- mmc->slots[0].switch_pin = -EINVAL;
-
- /* write protect normally uses an OMAP gpio */
- if (gpio_is_valid(c->gpio_wp)) {
- gpio_request(c->gpio_wp, "mmc_wp");
- gpio_direction_input(c->gpio_wp);
-
- mmc->slots[0].gpio_wp = c->gpio_wp;
- mmc->slots[0].get_ro = twl_mmc_get_ro;
- } else
- mmc->slots[0].gpio_wp = -EINVAL;
-
+ mmc->slots[0].card_detect_irq = 0;
+ mmc->slots[0].card_detect = twl_mmc_card_detect;
+ mmc->slots[0].gpio_wp = NULL;
+ mmc->slots[0].get_ro = NULL;
+ }
/* NOTE: MMC slots should have a Vcc regulator set up.
* This may be from a TWL4030-family chip, another
* controllable regulator, or a fixed supply.
@@ -423,6 +465,14 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
/* off-chip level shifting, or none */
mmc->slots[0].set_power = twl_mmc23_set_power;
break;
+ case 4:
+ /* off-chip level shifting, or none */
+ mmc->slots[0].set_power = twl_mmc23_set_power;
+ break;
+ case 5:
+ /* off-chip level shifting, or none */
+ mmc->slots[0].set_power = twl_mmc23_set_power;
+ break;
default:
pr_err("MMC%d configuration not supported!\n", c->mmc);
kfree(mmc);
@@ -431,7 +481,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
hsmmc_data[c->mmc - 1] = mmc;
}
- omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
+ omap2_init_mmc(hsmmc_data, OMAP44XX_NR_MMC);
/* pass the device nodes back to board setup code */
for (c = controllers; c->mmc; c++) {
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 43d6b92b65f2..1f434a35132a 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -501,6 +501,213 @@ MUX_CFG_34XX("H17_34XX_SDRC_CKE1", 0x264,
#define OMAP34XX_PINS_SZ 0
#endif /* CONFIG_ARCH_OMAP34XX */
+#ifdef CONFIG_ARCH_OMAP4
+static struct pin_config __initdata_or_module omap44xx_pins[] = {
+/*
+ * Name, reg-offset,
+ * mux-mode | [active-mode | off-mode]
+ */
+/* 34xx I2C */
+MUX_CFG_34XX("AA3_4430_McSPI1_CLK", 0x130,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y2_4430_McSPI1_SIMO", 0x136,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y3_4430_McSPI1_SOMI", 0x134,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y4_4430_McSPI1_CS0", 0x138,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y4_4430_McSPI1_CS1", 0x13a,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y4_4430_McSPI1_CS2", 0x13c,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y4_4430_McSPI1_CS3", 0x13e,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+
+MUX_CFG_34XX("AA3_4430_McBSP1_CLK", 0x00fe,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("Y3_4430_McBSP1_DR", 0x100,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("Y2_4430_McBSP1_DX", 0x102,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y4_4430_McBSP1_FSX", 0x104,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+
+MUX_CFG_34XX("PAD0_4430_UNIPRO_TX0", 0x17c,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_TY0", 0x17e,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD0_4430_UNIPRO_TX1", 0x180,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_TY1", 0x182,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD0_4430_UNIPRO_TX2", 0x184,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_TY2", 0x186,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD0_4430_UNIPRO_RX0", 0x188,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD0_4430_UNIPRO_RX1", 0x18c,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_RY1", 0x18e,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_RY0", 0x18a,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD0_4430_UNIPRO_RX2", 0x190,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("PAD1_4430_UNIPRO_RY2", 0x192,
+ OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT)
+
+
+/* MMC1 MUX Config */
+MUX_CFG_34XX("A1_4430_MMC1_CLK", 0x00e2, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_OFF_EN)
+MUX_CFG_34XX("C1_4430_MMC1_CMD", 0x00e4, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ |OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D0_4430_MMC1_DAT0", 0x00e6, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D1_4430_MMC1_DAT1", 0x00e8, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D2_4430_MMC1_DAT2", 0x00ea, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D3_4430_MMC1_DAT3", 0x00ec, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D4_4430_MMC1_DAT4", 0x00ee, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D5_4430_MMC1_DAT5", 0x00f0, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D6_4430_MMC1_DAT6", 0x00f2, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D7_4430_MMC1_DAT7", 0x00f4, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+
+/* MMC2 MUX Config */
+MUX_CFG_34XX("A1_4430_MMC2_CLK", 0x0082, OMAP34XX_MUX_MODE1
+ |OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("C1_4430_MMC2_CMD", 0x0080, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D0_4430_MMC2_DAT0", 0x0040, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D1_4430_MMC2_DAT1", 0x0042, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D2_4430_MMC2_DAT2", 0x0044, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D3_4430_MMC2_DAT3", 0x0046, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D4_4430_MMC2_DAT4", 0x0048, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D5_4430_MMC2_DAT5", 0x004a, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D6_4430_MMC2_DAT6", 0x004c, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D7_4430_MMC2_DAT7", 0x004e, OMAP34XX_MUX_MODE1 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+
+/* MMC3 MUX Config*/
+MUX_CFG_34XX("A1_4430_MMC3_CLK", 0x0176, OMAP34XX_MUX_MODE2
+ | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("C1_4430_MMC3_CMD", 0x0174, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D0_4430_MMC3_DAT0", 0x0170, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D1_4430_MMC3_DAT1", 0x016e, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D2_4430_MMC3_DAT2", 0x016c, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D3_4430_MMC3_DAT3", 0x0172, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+
+/* MMC4 MUX Config*/
+MUX_CFG_34XX("A1_4430_MMC4_CLK", 0x0162, OMAP34XX_MUX_MODE2
+ | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("C1_4430_MMC4_CMD", 0x0160, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D0_4430_MMC4_DAT0", 0x0164, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D1_4430_MMC4_DAT1", 0x0166, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D2_4430_MMC4_DAT2", 0x0168, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D3_4430_MMC4_DAT3", 0x016a, OMAP34XX_MUX_MODE2 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+
+/* MMC5 MUX Config*/
+MUX_CFG_34XX("A1_4430_MMC5_CLK", 0x0148, OMAP34XX_MUX_MODE0
+ | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("C1_4430_MMC5_CMD", 0x014a, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D0_4430_MMC5_DAT0", 0x014c, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D1_4430_MMC5_DAT1", 0x014e, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D2_4430_MMC5_DAT2", 0x0150, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+MUX_CFG_34XX("D3_4430_MMC5_DAT3", 0x0152, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN | OMAP3_OFF_EN
+ | OMAP3_OFFOUT_EN | OMAP3_OFF_PULL_EN)
+
+/* SYS_nIRQ MUX Config */
+MUX_CFG_34XX("PAD1_4430_SYS_NIRQ1", 0x019E, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN)
+MUX_CFG_34XX("PAD0_4430_SYS_NIRQ2", 0x01A0, OMAP34XX_MUX_MODE0 | OMAP2_PULL_ENA
+ | OMAP2_PULL_UP | OMAP3_INPUT_EN)
+/* Audio */
+MUX_CFG_34XX("AG25_4430_ABE_PDM_UL_DATA", 0x0106,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AF25_4430_ABE_PDM_DL_DATA", 0x0108,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AE25_4430_ABE_PDM_FRAME", 0x010a,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AF26_4430_ABE_PDM_LB_CLK", 0x010c,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AH26_4430_ABE_PDM_CLKS", 0x010e,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT)
+
+MUX_CFG_34XX("AA27_4430_GPIO_127", 0x0120,
+ OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT)
+};
+#define OMAP44XX_PINS_SZ ARRAY_SIZE(omap44xx_pins)
+
+#else
+#define omap44xx_pins NULL
+#define OMAP44XX_PINS_SZ 0
+#endif /* CONFIG_ARCH_OMAP34XX */
+
#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 reg)
{
@@ -549,7 +756,7 @@ static int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg)
#define omap24xx_cfg_reg NULL
#endif
-#ifdef CONFIG_ARCH_OMAP34XX
+#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
static int __init_or_module omap34xx_cfg_reg(const struct pin_config *cfg)
{
static DEFINE_SPINLOCK(mux_spin_lock);
@@ -579,7 +786,11 @@ int __init omap2_mux_init(void)
arch_mux_cfg.size = OMAP34XX_PINS_SZ;
arch_mux_cfg.cfg_reg = omap34xx_cfg_reg;
}
-
+ if (cpu_is_omap44xx()) {
+ arch_mux_cfg.pins = omap44xx_pins;
+ arch_mux_cfg.size = OMAP44XX_PINS_SZ;
+ arch_mux_cfg.cfg_reg = omap34xx_cfg_reg;
+ }
return omap_mux_register(&arch_mux_cfg);
}
diff --git a/arch/arm/mach-omap2/omap4-iommu.c b/arch/arm/mach-omap2/omap4-iommu.c
new file mode 100644
index 000000000000..5a782df0dcd2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-iommu.c
@@ -0,0 +1,112 @@
+/*
+ * omap iommu: omap4 device registration
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Written by Hari Kanigeri <h-kanigeri2@ti.com>
+ *
+ * Added support for OMAP4. This is based on original file
+ * omap3-iommu.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/platform_device.h>
+
+#include <mach/iommu.h>
+#include <mach/irqs.h>
+
+#define OMAP4_MMU1_BASE 0x55082000
+#define OMAP4_MMU2_BASE 0x4A066000
+
+#define OMAP4_MMU1_IRQ INT_44XX_DUCATI_MMU_IRQ
+#define OMAP4_MMU2_IRQ INT_44XX_DSP_MMU
+
+
+
+static unsigned long iommu_base[] __initdata = {
+ OMAP4_MMU1_BASE,
+ OMAP4_MMU2_BASE,
+};
+
+static int iommu_irq[] __initdata = {
+ OMAP4_MMU1_IRQ,
+ OMAP4_MMU2_IRQ,
+};
+
+static const struct iommu_platform_data omap4_iommu_pdata[] __initconst = {
+ {
+ .name = "ducati",
+ .nr_tlb_entries = 32,
+ .clk_name = "ducati_ick",
+ },
+#if defined(CONFIG_MPU_TESLA_IOMMU)
+ {
+ .name = "tesla",
+ .nr_tlb_entries = 32,
+ .clk_name = "tesla_ick",
+ },
+#endif
+};
+#define NR_IOMMU_DEVICES ARRAY_SIZE(omap4_iommu_pdata)
+
+static struct platform_device *omap4_iommu_pdev[NR_IOMMU_DEVICES];
+
+static int __init omap4_iommu_init(void)
+{
+ int i, err;
+
+ for (i = 0; i < NR_IOMMU_DEVICES; i++) {
+ struct platform_device *pdev;
+ struct resource res[2];
+
+ pdev = platform_device_alloc("omap-iommu", i);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(res, 0, sizeof(res));
+ res[0].start = iommu_base[i];
+ res[0].end = iommu_base[i] + MMU_REG_SIZE - 1;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = res[1].end = iommu_irq[i];
+ res[1].flags = IORESOURCE_IRQ;
+
+ err = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (err)
+ goto err_out;
+ err = platform_device_add_data(pdev, &omap4_iommu_pdata[i],
+ sizeof(omap4_iommu_pdata[0]));
+ if (err)
+ goto err_out;
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_out;
+ omap4_iommu_pdev[i] = pdev;
+ }
+ return 0;
+
+err_out:
+ while (i--)
+ platform_device_put(omap4_iommu_pdev[i]);
+ return err;
+}
+module_init(omap4_iommu_init);
+
+static void __exit omap4_iommu_exit(void)
+{
+ int i;
+
+ for (i = 0; i < NR_IOMMU_DEVICES; i++)
+ platform_device_unregister(omap4_iommu_pdev[i]);
+}
+module_exit(omap4_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU, Hari Kanigeri");
+MODULE_DESCRIPTION("omap iommu: omap4 device registration");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 6cc375a275be..bed01b3daa1a 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -63,9 +63,9 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
#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_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
+ DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
+ DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
#endif
#if 0
@@ -89,7 +89,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
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);
+ DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
#endif
#if 0
/* DSP */
@@ -99,11 +99,11 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
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);
+ DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
+ DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
+ DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
+ DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
+ DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
}
#endif
} else {
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 528dbdc26e23..92b070bb2c15 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -219,11 +219,12 @@ static void omap2_enter_mpu_retention(void)
/* Try to enter MPU retention */
prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
OMAP_LOGICRETSTATE,
- MPU_MOD, PM_PWSTCTRL);
+ MPU_MOD, OMAP2_PM_PWSTCTRL);
} else {
/* Block MPU retention */
- prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
+ prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD,
+ OMAP2_PM_PWSTCTRL);
only_idle = 1;
}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 488d595d8e4b..aac0bff37ca3 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -415,7 +415,7 @@ static void __init omap3_iva_idle(void)
prm_write_mod_reg(OMAP3430_RST1_IVA2 |
OMAP3430_RST2_IVA2 |
OMAP3430_RST3_IVA2,
- OMAP3430_IVA2_MOD, RM_RSTCTRL);
+ OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
/* Enable IVA2 clock */
cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
@@ -426,7 +426,7 @@ static void __init omap3_iva_idle(void)
OMAP343X_CONTROL_IVA2_BOOTMOD);
/* Un-reset IVA2 */
- prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
+ prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
/* Disable IVA2 clock */
cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
@@ -435,7 +435,7 @@ static void __init omap3_iva_idle(void)
prm_write_mod_reg(OMAP3430_RST1_IVA2 |
OMAP3430_RST2_IVA2 |
OMAP3430_RST3_IVA2,
- OMAP3430_IVA2_MOD, RM_RSTCTRL);
+ OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
}
static void __init omap3_d2d_idle(void)
@@ -458,8 +458,8 @@ static void __init omap3_d2d_idle(void)
/* reset modem */
prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
- CORE_MOD, RM_RSTCTRL);
- prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
+ CORE_MOD, OMAP2_RM_RSTCTRL);
+ prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
}
static void __init prcm_setup_regs(void)
@@ -625,13 +625,13 @@ static void __init prcm_setup_regs(void)
prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
/* Clear any pending 'reset' flags */
- prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+ prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
/* Clear any pending PRCM interrupts */
prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
@@ -643,13 +643,13 @@ static void __init prcm_setup_regs(void)
prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
/* Clear any pending 'reset' flags */
- prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
- prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+ prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+ prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
/* Clear any pending PRCM interrupts */
prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 983f1cb676be..6fcb1c592edd 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -6,6 +6,8 @@
*
* Written by Paul Walmsley
*
+ * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@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.
@@ -28,13 +30,42 @@
#include "cm.h"
#include "cm-regbits-34xx.h"
+#include "cm1-regbits-44xx.h"
+#include "cm2-regbits-44xx.h"
#include "prm.h"
#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
#include <mach/cpu.h>
#include <mach/powerdomain.h>
#include <mach/clockdomain.h>
+/* OMAP3 and OMAP4 specific register bit initialisations
+ * Notice that the names here are not according to each power
+ * domain but the bit mapping used applies to all of them
+ */
+
+/* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
+#define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
+#define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
+#define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
+#define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
+#define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
+
+/* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
+#define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE
+#define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE
+#define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE
+#define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE
+#define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
+
+/* OMAP3 and OMAP4 Memory Status bits */
+#define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
+#define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
+#define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
+#define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
+#define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
+
/* pwrdm_list contains all registered struct powerdomains */
static LIST_HEAD(pwrdm_list);
@@ -625,9 +656,14 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
pwrdm->name, pwrst);
- prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+ (pwrst << OMAP_POWERSTATE_SHIFT),
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
(pwrst << OMAP_POWERSTATE_SHIFT),
- pwrdm->prcm_offs, PM_PWSTCTRL);
+ pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -645,8 +681,12 @@ 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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP2_PM_PWSTCTRL, OMAP_POWERSTATE_MASK);
+ if (cpu_is_omap44xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP4_PM_PWSTCTRL, OMAP_POWERSTATE_MASK);
}
/**
@@ -662,8 +702,12 @@ 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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP2_PM_PWSTST, OMAP_POWERSTATEST_MASK);
+ if (cpu_is_omap44xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP4_PM_PWSTST, OMAP_POWERSTATEST_MASK);
}
/**
@@ -711,9 +755,14 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
* but the type of value returned is the same for each
* powerdomain.
*/
- prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
+ (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
(pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
- pwrdm->prcm_offs, PM_PWSTCTRL);
+ pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -756,24 +805,31 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
*/
switch (bank) {
case 0:
- m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
+ m = OMAP_MEM0_ONSTATE_MASK;
break;
case 1:
- m = OMAP3430_L1FLATMEMONSTATE_MASK;
+ m = OMAP_MEM1_ONSTATE_MASK;
break;
case 2:
- m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
+ m = OMAP_MEM2_ONSTATE_MASK;
break;
case 3:
- m = OMAP3430_L2FLATMEMONSTATE_MASK;
+ m = OMAP_MEM3_ONSTATE_MASK;
+ break;
+ case 4:
+ m = OMAP_MEM4_ONSTATE_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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
+ pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -817,24 +873,31 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
*/
switch (bank) {
case 0:
- m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
+ m = OMAP_MEM0_RETSTATE_MASK;
break;
case 1:
- m = OMAP3430_L1FLATMEMRETSTATE;
+ m = OMAP_MEM1_RETSTATE_MASK;
break;
case 2:
- m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
+ m = OMAP_MEM2_RETSTATE_MASK;
break;
case 3:
- m = OMAP3430_L2FLATMEMRETSTATE;
+ m = OMAP_MEM3_RETSTATE_MASK;
+ break;
+ case 4:
+ m = OMAP_MEM4_RETSTATE_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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+ OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+ OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -853,8 +916,12 @@ 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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP2_PM_PWSTST, OMAP3430_LOGICSTATEST);
+ if (cpu_is_omap44xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP4_PM_PWSTST, OMAP3430_LOGICSTATEST);
}
/**
@@ -908,23 +975,31 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
*/
switch (bank) {
case 0:
- m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
+ m = OMAP_MEM0_STATEST_MASK;
break;
case 1:
- m = OMAP3430_L1FLATMEMSTATEST_MASK;
+ m = OMAP_MEM1_STATEST_MASK;
break;
case 2:
- m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
+ m = OMAP_MEM2_STATEST_MASK;
break;
case 3:
- m = OMAP3430_L2FLATMEMSTATEST_MASK;
+ m = OMAP_MEM3_STATEST_MASK;
+ break;
+ case 4:
+ m = OMAP_MEM4_STATEST_MASK;
break;
default:
WARN_ON(1); /* should never happen */
return -EEXIST;
}
- return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP2_PM_PWSTST, m);
+ if (cpu_is_omap44xx())
+ return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+ OMAP4_PM_PWSTST, m);
}
/**
@@ -1024,8 +1099,12 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+ pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -1052,8 +1131,12 @@ int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
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);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
+ pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
+ pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
return 0;
}
@@ -1094,10 +1177,16 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
*/
/* XXX Is this udelay() value meaningful? */
- while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ while ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
+ OMAP_INTRANSITION) &&
+ (c++ < PWRDM_TRANSITION_BAILOUT))
+ udelay(1);
+ if (cpu_is_omap44xx())
+ while ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP4_PM_PWSTST) &
OMAP_INTRANSITION) &&
(c++ < PWRDM_TRANSITION_BAILOUT))
- udelay(1);
+ udelay(1);
if (c > PWRDM_TRANSITION_BAILOUT) {
printk(KERN_ERR "powerdomain: waited too long for "
diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
index 691470ea4c6a..7f1f270a1d81 100644
--- a/arch/arm/mach-omap2/powerdomains.h
+++ b/arch/arm/mach-omap2/powerdomains.h
@@ -76,6 +76,7 @@
* 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
* 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
*/
+#ifndef CONFIG_ARCH_OMAP4
static struct pwrdm_dep gfx_sgx_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
@@ -110,42 +111,22 @@ static struct pwrdm_dep cam_gfx_sleepdeps[] = {
},
{ NULL },
};
-
+#endif
#include "powerdomains24xx.h"
#include "powerdomains34xx.h"
+#include "powerdomains44xx.h"
/*
- * OMAP2/3 common powerdomains
+ * OMAP2/3/4 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),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430 | \
+ CHIP_IS_OMAP4430),
.dep_bit = OMAP_EN_WKUP_SHIFT,
};
@@ -153,21 +134,22 @@ static struct powerdomain wkup_pwrdm = {
/* 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
+ &gfx_pwrdm,
&dsp_pwrdm,
&mpu_24xx_pwrdm,
&core_24xx_pwrdm,
#endif
#ifdef CONFIG_ARCH_OMAP2430
+ &gfx_pwrdm,
&mdm_pwrdm,
#endif
#ifdef CONFIG_ARCH_OMAP34XX
+ &gfx_pwrdm,
&iva2_pwrdm,
&mpu_34xx_pwrdm,
&neon_pwrdm,
@@ -186,6 +168,23 @@ static struct powerdomain *powerdomains_omap[] __initdata = {
&dpll5_pwrdm,
#endif
+#ifdef CONFIG_ARCH_OMAP4
+ &dsp_44xx_pwrdm,
+ &std_efuse_44xx_pwrdm,
+ &mpu_44xx_pwrdm,
+ &pd_l4_per_44xx_pwrdm,
+ &pd_l3_init_44xx_pwrdm,
+ &ivahd_44xx_pwrdm,
+ &pd_sgx_44xx_pwrdm,
+ &pd_emu_44xx_pwrdm,
+ &pd_dss_44xx_pwrdm,
+ &pd_core_44xx_pwrdm,
+ &pd_cam_44xx_pwrdm,
+ &pd_audio_44xx_pwrdm,
+ &pd_alwon_mpu_44xx_pwrdm,
+ &pd_alwon_dsp_44xx_pwrdm,
+ &pd_alwon_core_44xx_pwrdm,
+#endif
NULL
};
diff --git a/arch/arm/mach-omap2/powerdomains24xx.h b/arch/arm/mach-omap2/powerdomains24xx.h
index 9f08dc3f7fd2..bc0ec5195744 100644
--- a/arch/arm/mach-omap2/powerdomains24xx.h
+++ b/arch/arm/mach-omap2/powerdomains24xx.h
@@ -110,6 +110,24 @@ static struct pwrdm_dep core_24xx_wkdeps[] = {
/* Powerdomains */
+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 dsp_pwrdm = {
.name = "dsp_pwrdm",
.prcm_offs = OMAP24XX_DSP_MOD,
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
index 4dcf94b800ab..abc2bb44d819 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -159,6 +159,24 @@ static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = {
* Powerdomains
*/
+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 iva2_pwrdm = {
.name = "iva2_pwrdm",
.prcm_offs = OMAP3430_IVA2_MOD,
diff --git a/arch/arm/mach-omap2/powerdomains44xx.h b/arch/arm/mach-omap2/powerdomains44xx.h
new file mode 100644
index 000000000000..109082d19fd7
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains44xx.h
@@ -0,0 +1,258 @@
+/*
+ * OMAP44XX powerdomain definitions
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ *
+ * Written by Abhijit Pagare(abhijitpagare@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.
+ */
+
+#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS44XX
+#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS44XX
+
+/*
+ * 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-44xx.h"
+#include "cm.h"
+#include "cm1-regbits-44xx.h"
+#include "cm2-regbits-44xx.h"
+
+/*
+ * 44XX-specific powerdomains, dependencies
+ */
+
+#ifdef CONFIG_ARCH_OMAP4
+
+/* Wakeup dependency for 44xx-specific pwrdm modules (to be populated later) */
+
+/* Sleep dependency for 44xx-specific pwrdm modules (to be populated later) */
+
+
+/*
+ * Powerdomains (without the dpendency parameter definitions)
+ */
+
+static struct powerdomain dsp_44xx_pwrdm = {
+ .name = "dsp_pwrdm",
+ .prcm_offs = OMAP4430_DSP_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 3,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_RET,
+ [1] = PWRSTS_OFF_RET,
+ [2] = PWRSTS_OFF_RET,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRDM_POWER_ON,
+ [2] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain std_efuse_44xx_pwrdm = {
+ .name = "std_effuse_pwrdm",
+ .prcm_offs = OMAP4430_CEFUSE_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct powerdomain mpu_44xx_pwrdm = {
+ .name = "mpu_pwrdm",
+ .prcm_offs = OMAP4430_MPU_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 3,
+ .pwrsts_mem_ret = {
+ [0] = PWRSTS_OFF_RET,
+ [1] = PWRSTS_OFF_RET,
+ [2] = PWRDM_POWER_RET,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRDM_POWER_ON,
+ [2] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_l4_per_44xx_pwrdm = {
+ .name = "pd_l4_per_pwrdm",
+ .prcm_offs = OMAP4430_L4PER_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 2,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ [1] = PWRDM_POWER_RET,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_l3_init_44xx_pwrdm = {
+ .name = "pd_l3_init_pwrdm",
+ .prcm_offs = OMAP4430_L3INIT_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 1,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain ivahd_44xx_pwrdm = {
+ .name = "ivahd_pwrdm",
+ .prcm_offs = OMAP4430_IVAHD_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_ON,
+ .banks = 4,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ [1] = PWRSTS_OFF_RET,
+ [2] = PWRSTS_OFF_RET,
+ [3] = PWRSTS_OFF_RET,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRDM_POWER_ON,
+ [2] = PWRDM_POWER_ON,
+ [3] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_sgx_44xx_pwrdm = {
+ .name = "pd_sgx_pwrdm",
+ .prcm_offs = OMAP4430_GFX_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_ON,
+ .banks = 1,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_emu_44xx_pwrdm = {
+ .name = "pd_emu_pwrdm",
+ .prcm_offs = OMAP4430_EMU_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_ON,
+ .banks = 1,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_dss_44xx_pwrdm = {
+ .name = "pd_dss_pwrdm",
+ .prcm_offs = OMAP4430_DSS_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 1,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_core_44xx_pwrdm = {
+ .name = "core_pwrdm",
+ .prcm_offs = OMAP4430_CORE_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .banks = 5,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ [1] = PWRSTS_OFF_RET,
+ [2] = PWRDM_POWER_RET,
+ [3] = PWRSTS_OFF_RET,
+ [4] = PWRSTS_OFF_RET,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRSTS_OFF_RET_ON,
+ [2] = PWRDM_POWER_ON,
+ [3] = PWRDM_POWER_ON,
+ [4] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_cam_44xx_pwrdm = {
+ .name = "pd_cam_pwrdm",
+ .prcm_offs = OMAP4430_CAM_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_ON,
+ .banks = 1,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_OFF,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_audio_44xx_pwrdm = {
+ .name = "pd_audio_pwrdm",
+ .prcm_offs = OMAP4430_ABE_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+ .pwrsts = PWRSTS_OFF_ON,
+ .banks = 2,
+ .pwrsts_mem_ret = {
+ [0] = PWRDM_POWER_RET,
+ [1] = PWRDM_POWER_ON,
+ },
+ .pwrsts_mem_on = {
+ [0] = PWRDM_POWER_ON,
+ [1] = PWRDM_POWER_ON,
+ },
+};
+
+static struct powerdomain pd_alwon_mpu_44xx_pwrdm = {
+ .name = "pd_alwon_mpu_pwrdm",
+ .prcm_offs = OMAP4430_ALWAYS_ON_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct powerdomain pd_alwon_dsp_44xx_pwrdm = {
+ .name = "pd_alwon_dsp_pwrdm",
+ .prcm_offs = OMAP4430_ALWAYS_ON_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct powerdomain pd_alwon_core_44xx_pwrdm = {
+ .name = "pd_alwon_core_pwrdm",
+ .prcm_offs = OMAP4430_ALWAYS_ON_MOD,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+#endif /* CONFIG_ARCH_OMAP4 */
+
+#endif
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index cb1ae84e0925..a3bcdd2d021d 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -49,6 +49,34 @@
#define OMAP3430_NEON_MOD 0xb00
#define OMAP3430ES2_USBHOST_MOD 0xc00
+#define BITS(n_bit) \
+ (((1 << n_bit) - 1) | (1 << n_bit))
+
+#define BITFIELD(u_bit, l_bit) \
+ (BITS(u_bit) & ~((BITS(l_bit)) >> 1))
+
+/* OMAP44XX specific module offsets */
+#define OMAP4430_OCP_SOCKET_MOD 0x0000
+#define OMAP4430_CKGEN_MOD 0x0100
+#define OMAP4430_MPU_MOD 0x0300
+#define OMAP4430_DSP_MOD 0x0400
+#define OMAP4430_ABE_MOD 0x0500
+#define OMAP4430_ALWAYS_ON_MOD 0x0600
+#define OMAP4430_CORE_MOD 0x0700
+#define OMAP4430_IVAHD_MOD 0x0F00
+#define OMAP4430_CAM_MOD 0x1000
+#define OMAP4430_DSS_MOD 0x1100
+#define OMAP4430_GFX_MOD 0x1200
+#define OMAP4430_L3INIT_MOD 0x1300
+#define OMAP4430_L4PER_MOD 0x1400
+#define OMAP4430_CEFUSE_MOD 0x1600
+#define OMAP4430_WKUP_MOD 0x1700
+#define OMAP4430_WKUP_CM_MOD 0x1800
+#define OMAP4430_EMU_MOD 0x1900
+#define OMAP4430_EMU_CM_MOD 0x1A00
+#define OMAP4430_DEVICE_MOD 0x1B00
+#define OMAP4430_RESTORE_MOD 0x1E00
+#define OMAP4430_INSTR_MOD 0x1F00
/* 24XX register bits shared between CM & PRM registers */
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index ced555a4cd1a..2173cf1930a4 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -8,6 +8,7 @@
* Written by Tony Lindgren <tony.lindgren@nokia.com>
*
* Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
+ * Upgraded with OMAP4 support by Abhijit Pagare <abhijitpagare@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
@@ -28,13 +29,17 @@
static void __iomem *prm_base;
static void __iomem *cm_base;
+static void __iomem *cm2_base;
#define MAX_MODULE_ENABLE_WAIT 100000
u32 omap_prcm_get_reset_sources(void)
{
/* XXX This presumably needs modification for 34XX */
- return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ return prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
+ if (cpu_is_omap44xx())
+ return prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
}
EXPORT_SYMBOL(omap_prcm_get_reset_sources);
@@ -48,10 +53,17 @@ void omap_prcm_arch_reset(char mode)
prcm_offs = WKUP_MOD;
else if (cpu_is_omap34xx())
prcm_offs = OMAP3430_GR_MOD;
+ else if (cpu_is_omap44xx())
+ prcm_offs = OMAP4430_DEVICE_MOD;
else
WARN_ON(1);
- prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL);
+ if (cpu_is_omap24xx() | cpu_is_omap34xx())
+ prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs,
+ OMAP2_RM_RSTCTRL);
+ if (cpu_is_omap44xx())
+ prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs,
+ OMAP4_RM_RSTCTRL);
}
static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@@ -167,4 +179,5 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
{
prm_base = omap2_globals->prm;
cm_base = omap2_globals->cm;
+ cm2_base = omap2_globals->cm2;
}
diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
new file mode 100644
index 000000000000..13c1dcbfbe0a
--- /dev/null
+++ b/arch/arm/mach-omap2/prm-regbits-44xx.h
@@ -0,0 +1,1141 @@
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_44XX_H
+
+/*
+ * OMAP4430 Power/Reset Management register bits
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Written by Rajendra Nayak (rnayak@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 "prm.h"
+
+#define OMAP4430_CLKSEL (1 << 0)
+#define OMAP4430_SYS_CLKSEL (1 << 0)
+#define OMAP4430_PERIPHMEM_ONSTATE (1 << 20)
+#define OMAP4430_AESSMEM_ONSTATE (1 << 16)
+#define OMAP4430_PERIPHMEM_RETSTATE (1 << 10)
+#define OMAP4430_AESSMEM_RETSTATE (1 << 8)
+#define OMAP4430_LOWPOWERSTATECHANGE (1 << 4)
+#define OMAP4430_LOGICRETSTATE (1 << 2)
+#define OMAP4430_POWERSTATE (1 << 0)
+#define OMAP4430_INTRANSITION (1 << 20)
+#define OMAP4430_PERIPHMEM_STATEST (1 << 8)
+#define OMAP4430_AESSMEM_STATEST (1 << 4)
+#define OMAP4430_LOGICSTATEST (1 << 2)
+#define OMAP4430_POWERSTATEST (1 << 0)
+#define OMAP4430_LOSTMEM_AESSMEM (1 << 8)
+#define OMAP4430_LOSTCONTEXT_DFF (1 << 0)
+#define OMAP4430_WKUPDEP_PDM_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_PDM_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_PDM_IRQ_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_PERIHPMEM (1 << 8)
+#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCBSP1_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCBSP1_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCBSP1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCBSP2_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCBSP2_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCBSP2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCBSP3_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCBSP3_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCBSP3_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER5_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_TIMER5_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER6_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_TIMER6_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER7_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_TIMER7_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER8_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_TIMER8_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_WDT3_MPU (1 << 0)
+#define OMAP4430_DSS_MEM_ONSTATE (1 << 16)
+#define OMAP4430_DSS_MEM_RETSTATE (1 << 8)
+#define OMAP4430_DSS_MEM_STATEST (1 << 4)
+#define OMAP4430_WKUPDEP_HDMIDMA_SDMA (1 << 19)
+#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA (1 << 14)
+#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI (1 << 13)
+#define OMAP4430_WKUPDEP_HDMIIRQ_MPU (1 << 12)
+#define OMAP4430_WKUPDEP_DSI2_SDMA (1 << 11)
+#define OMAP4430_WKUPDEP_DSI2_TESLA (1 << 10)
+#define OMAP4430_WKUPDEP_DSI2_DUCATI (1 << 9)
+#define OMAP4430_WKUPDEP_DSI2_MPU (1 << 8)
+#define OMAP4430_WKUPDEP_DSI1_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_DSI1_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_DSI1_DUCATI (1 << 5)
+#define OMAP4430_WKUPDEP_DSI1_MPU (1 << 4)
+#define OMAP4430_WKUPDEP_DISPC_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_DISPC_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_DISPC_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_DISPC_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_DSS_MEM (1 << 8)
+#define OMAP4430_LOSTCONTEXT_RFF (1 << 1)
+#define OMAP4430_L3INIT_BANK1_ONSTATE (1 << 16)
+#define OMAP4430_L3INIT_BANK1_RETSTATE (1 << 8)
+#define OMAP4430_L3INIT_BANK1_STATEST (1 << 4)
+#define OMAP4430_WKUPDEP_MMC1_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MMC1_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MMC1_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMC1_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_MMC2_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MMC2_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MMC2_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMC2_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU (1 << 8)
+#define OMAP4430_WKUPDEP_HSI_DSP_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_HSI_MCU_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_UNIPRO1_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_USB_HOST_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_USB_HOST_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_USB_OTG_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_USB_OTG_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_USB_TLL_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_USB_TLL_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_SATA_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_SATA_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_PCIESS_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_PCIESS_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_XHPI_DUCATI (1 << 1)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_MMC6_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MMC6_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMC6_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1 (1 << 8)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU (1 << 0)
+#define OMAP4430_NONRETAINED_BANK_ONSTATE (1 << 18)
+#define OMAP4430_RETAINED_BANK_ONSTATE (1 << 16)
+#define OMAP4430_NONRETAINED_BANK_RETSTATE (1 << 9)
+#define OMAP4430_RETAINED_BANK_RETSTATE (1 << 8)
+#define OMAP4430_NONRETAINED_BANK_STATEST (1 << 6)
+#define OMAP4430_RETAINED_BANK_STATEST (1 << 4)
+#define OMAP4430_WKUPDEP_DMTIMER10_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_DMTIMER11_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_DMTIMER2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_DMTIMER3_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_DMTIMER4_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_DMTIMER9_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_HECC1_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_NONRETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_HECC2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCBSP4_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCBSP4_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCBSP4_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCSPI1_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCSPI1_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_MCSPI1_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MCSPI1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCSPI2_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCSPI2_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MCSPI2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCSPI3_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCSPI3_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MCSPI4_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MCSPI4_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MMCSD3_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MMCSD3_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMCSD3_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MMCSD4_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MMCSD4_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMCSD4_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA (1 << 7)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_UART1_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_UART1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_UART2_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_UART2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_UART3_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_UART3_TESLA (1 << 2)
+#define OMAP4430_WKUPDEP_UART3_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_UART3_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_UART4_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_UART4_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_MMCSD5_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_MMCSD5_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_MMCSD5_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_WDT2_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_WDT2_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA (1 << 6)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER1_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_TIMER12_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_USIM_SDMA (1 << 3)
+#define OMAP4430_WKUPDEP_USIM_MPU (1 << 0)
+#define OMAP4430_LOSTMEM_WKUP_BANK (1 << 8)
+#define OMAP4430_WKUPDEP_KEYBOARD_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_RTC_MPU (1 << 0)
+#define OMAP4430_MPU_RAM_ONSTATE (1 << 20)
+#define OMAP4430_MPU_L2_ONSTATE (1 << 18)
+#define OMAP4430_MPU_L1_ONSTATE (1 << 16)
+#define OMAP4430_MPU_RAM_RETSTATE (1 << 10)
+#define OMAP4430_MPU_L2_RETSTATE (1 << 9)
+#define OMAP4430_MPU_L1_RETSTATE (1 << 8)
+#define OMAP4430_MPU_RAM_STATEST (1 << 8)
+#define OMAP4430_MPU_L2_STATEST (1 << 6)
+#define OMAP4430_MPU_L1_STATEST (1 << 4)
+#define OMAP4430_ICECRUSHER_MPU_RST (1 << 1)
+#define OMAP4430_EMULATION_RST (1 << 0)
+#define OMAP4430_LOSTMEM_MPU_RAM (1 << 10)
+#define OMAP4430_LOSTMEM_MPU_L2 (1 << 9)
+#define OMAP4430_LOSTMEM_MPU_L1 (1 << 8)
+#define OMAP4430_TESLA_EDMA_ONSTATE (1 << 20)
+#define OMAP4430_TESLA_L2_ONSTATE (1 << 18)
+#define OMAP4430_TESLA_L1_ONSTATE (1 << 16)
+#define OMAP4430_TESLA_EDMA_RETSTATE (1 << 10)
+#define OMAP4430_TESLA_L2_RETSTATE (1 << 9)
+#define OMAP4430_TESLA_L1_RETSTATE (1 << 8)
+#define OMAP4430_TESLA_EDMA_STATEST (1 << 8)
+#define OMAP4430_TESLA_L2_STATEST (1 << 6)
+#define OMAP4430_TESLA_L1_STATEST (1 << 4)
+#define OMAP4430_RST2 (1 << 1)
+#define OMAP4430_RST1 (1 << 0)
+#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST (1 << 3)
+#define OMAP4430_TESLASS_EMU_RSTST (1 << 2)
+#define OMAP4430_RST2ST (1 << 1)
+#define OMAP4430_RST1ST (1 << 0)
+#define OMAP4430_LOSTMEM_TESLA_EDMA (1 << 10)
+#define OMAP4430_LOSTMEM_TESLA_L2 (1 << 9)
+#define OMAP4430_LOSTMEM_TESLA_L1 (1 << 8)
+#define OMAP4430_TCM2_MEM_ONSTATE (1 << 22)
+#define OMAP4430_TCM1_MEM_ONSTATE (1 << 20)
+#define OMAP4430_SL2_MEM_ONSTATE (1 << 18)
+#define OMAP4430_HWA_MEM_ONSTATE (1 << 16)
+#define OMAP4430_TCM2_MEM_RETSTATE (1 << 11)
+#define OMAP4430_TCM1_MEM_RETSTATE (1 << 10)
+#define OMAP4430_SL2_MEM_RETSTATE (1 << 9)
+#define OMAP4430_HWA_MEM_RETSTATE (1 << 8)
+#define OMAP4430_TCM2_MEM_STATEST (1 << 10)
+#define OMAP4430_TCM1_MEM_STATEST (1 << 8)
+#define OMAP4430_SL2_MEM_STATEST (1 << 6)
+#define OMAP4430_HWA_MEM_STATEST (1 << 4)
+#define OMAP4430_RST3 (1 << 2)
+#define OMAP4430_ICECRUSHER_SEQ2_RST2ST (1 << 6)
+#define OMAP4430_ICECRUSHER_SEQ1_RST1ST (1 << 5)
+#define OMAP4430_EMULATION_SEQ2_RST2ST (1 << 4)
+#define OMAP4430_EMULATION_SEQ1_RST1ST (1 << 3)
+#define OMAP4430_RST3ST (1 << 2)
+#define OMAP4430_LOSTMEM_HWA_MEM (1 << 10)
+#define OMAP4430_LOSTMEM_TCM2_MEM (1 << 9)
+#define OMAP4430_LOSTMEM_TCM1_MEM (1 << 8)
+#define OMAP4430_LOSTMEM_SL2_MEM (1 << 8)
+#define OMAP4430_OCP_NRET_BANK_ONSTATE (1 << 24)
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE (1 << 22)
+#define OMAP4430_DUCATI_L2RAM_ONSTATE (1 << 20)
+#define OMAP4430_CORE_OCMRAM_ONSTATE (1 << 18)
+#define OMAP4430_CORE_OTHER_BANK_ONSTATE (1 << 16)
+#define OMAP4430_OCP_NRET_BANK_RETSTATE (1 << 12)
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE (1 << 11)
+#define OMAP4430_DUCATI_L2RAM_RETSTATE (1 << 10)
+#define OMAP4430_CORE_OCMRAM_RETSTATE (1 << 9)
+#define OMAP4430_CORE_OTHER_BANK_RETSTATE (1 << 8)
+#define OMAP4430_MEMORYCHANGE (1 << 3)
+#define OMAP4430_OCP_NRET_BANK_STATEST (1 << 12)
+#define OMAP4430_DUCATI_UNICACHE_STATEST (1 << 10)
+#define OMAP4430_DUCATI_L2RAM_STATEST (1 << 8)
+#define OMAP4430_CORE_OCMRAM_STATEST (1 << 6)
+#define OMAP4430_CORE_OTHER_BANK_STATEST (1 << 4)
+#define OMAP4430_LOSTMEM_CORE_OCMRAM (1 << 8)
+#define OMAP4430_ICECRUSHER_RST2ST (1 << 6)
+#define OMAP4430_ICECRUSHER_RST1ST (1 << 5)
+#define OMAP4430_EMULATION_RST2ST (1 << 4)
+#define OMAP4430_EMULATION_RST1ST (1 << 3)
+#define OMAP4430_LOSTMEM_DUCATI_L2RAM (1 << 9)
+#define OMAP4430_LOSTMEM_DUCATI_UNICACHE (1 << 8)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK (1 << 8)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK (1 << 9)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK (1 << 8)
+#define OMAP4430_OCP_SOCKET_REVISION_REV (1 << 0)
+#define OMAP4430_VC_TOERR_ST (1 << 31)
+#define OMAP4430_VC_RAERR_ST (1 << 30)
+#define OMAP4430_VC_SAERR_ST (1 << 29)
+#define OMAP4430_VP_CORE_TRANXDONE_ST (1 << 28)
+#define OMAP4430_VP_CORE_EQVALUE_ST (1 << 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST (1 << 26)
+#define OMAP4430_VP_CORE_MAXVDD_ST (1 << 25)
+#define OMAP4430_VP_CORE_MINVDD_ST (1 << 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST (1 << 23)
+#define OMAP4430_VP_IVA_TRANXDONE_ST (1 << 22)
+#define OMAP4430_VP_IVA_EQVALUE_ST (1 << 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST (1 << 20)
+#define OMAP4430_VP_IVA_MAXVDD_ST (1 << 19)
+#define OMAP4430_VP_IVA_MINVDD_ST (1 << 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST (1 << 17)
+#define OMAP4430_VP_MPU_TRANXDONE_ST (1 << 16)
+#define OMAP4430_VP_MPU_EQVALUE_ST (1 << 15)
+#define OMAP4430_VP_MPU_NOSMPSACK_ST (1 << 14)
+#define OMAP4430_VP_MPU_MAXVDD_ST (1 << 13)
+#define OMAP4430_VP_MPU_MINVDD_ST (1 << 12)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST (1 << 11)
+#define OMAP4430_IO_ST (1 << 9)
+#define OMAP4430_TRANSITION_ST (1 << 8)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST (1 << 7)
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST (1 << 6)
+#define OMAP4430_DPLL_USB_RECAL_ST (1 << 5)
+#define OMAP4430_DPLL_ABE_RECAL_ST (1 << 4)
+#define OMAP4430_DPLL_PER_RECAL_ST (1 << 3)
+#define OMAP4430_DPLL_IVA_RECAL_ST (1 << 2)
+#define OMAP4430_DPLL_MPU_RECAL_ST (1 << 1)
+#define OMAP4430_DPLL_CORE_RECAL_ST (1 << 0)
+#define OMAP4430_VC_TOERR_EN (1 << 31)
+#define OMAP4430_VC_RAERR_EN (1 << 30)
+#define OMAP4430_VC_SAERR_EN (1 << 29)
+#define OMAP4430_VP_CORE_TRANXDONE_EN (1 << 28)
+#define OMAP4430_VP_CORE_EQVALUE_EN (1 << 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN (1 << 26)
+#define OMAP4430_VP_CORE_MAXVDD_EN (1 << 25)
+#define OMAP4430_VP_CORE_MINVDD_EN (1 << 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN (1 << 23)
+#define OMAP4430_VP_IVA_TRANXDONE_EN (1 << 22)
+#define OMAP4430_VP_IVA_EQVALUE_EN (1 << 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN (1 << 20)
+#define OMAP4430_VP_IVA_MAXVDD_EN (1 << 19)
+#define OMAP4430_VP_IVA_MINVDD_EN (1 << 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN (1 << 17)
+#define OMAP4430_VP_MPU_TRANXDONE_EN (1 << 16)
+#define OMAP4430_VP_MPU_EQVALUE_EN (1 << 15)
+#define OMAP4430_VP_MPU_NOSMPSACK_EN (1 << 14)
+#define OMAP4430_VP_MPU_MAXVDD_EN (1 << 13)
+#define OMAP4430_VP_MPU_MINVDD_EN (1 << 12)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN (1 << 11)
+#define OMAP4430_IO_EN (1 << 9)
+#define OMAP4430_TRANSITION_EN (1 << 8)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN (1 << 7)
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN (1 << 6)
+#define OMAP4430_DPLL_USB_RECAL_EN (1 << 5)
+#define OMAP4430_DPLL_ABE_RECAL_EN (1 << 4)
+#define OMAP4430_DPLL_PER_RECAL_EN (1 << 3)
+#define OMAP4430_DPLL_IVA_RECAL_EN (1 << 2)
+#define OMAP4430_DPLL_MPU_RECAL_EN (1 << 1)
+#define OMAP4430_DPLL_CORE_RECAL_EN (1 << 0)
+#define OMAP4430_VC_TOERR_ST (1 << 31)
+#define OMAP4430_VC_RAERR_ST (1 << 30)
+#define OMAP4430_VC_SAERR_ST (1 << 29)
+#define OMAP4430_VP_CORE_TRANXDONE_ST (1 << 28)
+#define OMAP4430_VP_CORE_EQVALUE_ST (1 << 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST (1 << 26)
+#define OMAP4430_VP_CORE_MAXVDD_ST (1 << 25)
+#define OMAP4430_VP_CORE_MINVDD_ST (1 << 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST (1 << 23)
+#define OMAP4430_VP_IVA_TRANXDONE_ST (1 << 22)
+#define OMAP4430_VP_IVA_EQVALUE_ST (1 << 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST (1 << 20)
+#define OMAP4430_VP_IVA_MAXVDD_ST (1 << 19)
+#define OMAP4430_VP_IVA_MINVDD_ST (1 << 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST (1 << 17)
+#define OMAP4430_FORCEWKUP_ST (1 << 10)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST (1 << 7)
+#define OMAP4430_DPLL_PER_RECAL_ST (1 << 3)
+#define OMAP4430_DPLL_IVA_RECAL_ST (1 << 2)
+#define OMAP4430_DPLL_CORE_RECAL_ST (1 << 0)
+#define OMAP4430_VC_TOERR_EN (1 << 31)
+#define OMAP4430_VC_RAERR_EN (1 << 30)
+#define OMAP4430_VC_SAERR_EN (1 << 29)
+#define OMAP4430_VP_CORE_TRANXDONE_EN (1 << 28)
+#define OMAP4430_VP_CORE_EQVALUE_EN (1 << 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN (1 << 26)
+#define OMAP4430_VP_CORE_MAXVDD_EN (1 << 25)
+#define OMAP4430_VP_CORE_MINVDD_EN (1 << 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN (1 << 23)
+#define OMAP4430_VP_IVA_TRANXDONE_EN (1 << 22)
+#define OMAP4430_VP_IVA_EQVALUE_EN (1 << 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN (1 << 20)
+#define OMAP4430_VP_IVA_MAXVDD_EN (1 << 19)
+#define OMAP4430_VP_IVA_MINVDD_EN (1 << 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN (1 << 17)
+#define OMAP4430_FORCEWKUP_EN (1 << 10)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN (1 << 7)
+#define OMAP4430_DPLL_PER_RECAL_EN (1 << 3)
+#define OMAP4430_DPLL_IVA_RECAL_EN (1 << 2)
+#define OMAP4430_DPLL_CORE_RECAL_EN (1 << 0)
+#define OMAP4430_DPLL_ABE_RECAL_ST (1 << 4)
+#define OMAP4430_DPLL_IVA_RECAL_ST (1 << 2)
+#define OMAP4430_DPLL_ABE_RECAL_EN (1 << 4)
+#define OMAP4430_DPLL_IVA_RECAL_EN (1 << 2)
+#define OMAP4430_MODULEMODE (1 << 0)
+#define OMAP4430_WKUPDEP_SR_MPU_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_SR_IVA_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_SR_IVA_MPU (1 << 0)
+#define OMAP4430_WKUPDEP_SR_CORE_DUCATI (1 << 1)
+#define OMAP4430_WKUPDEP_SR_CORE_MPU (1 << 0)
+#define OMAP4430_CAM_MEM_ONSTATE (1 << 16)
+#define OMAP4430_CAM_MEM_STATEST (1 << 4)
+#define OMAP4430_LOSTMEM_CAM_MEM (1 << 8)
+#define OMAP4430_LOSTMEM_CAM_MEM (1 << 8)
+#define OMAP4430_GFX_MEM_ONSTATE (1 << 16)
+#define OMAP4430_GFX_MEM_STATEST (1 << 4)
+#define OMAP4430_LOSTMEM_GFX_MEM (1 << 8)
+#define OMAP4430_EMU_BANK_ONSTATE (1 << 16)
+#define OMAP4430_EMU_BANK_STATEST (1 << 4)
+#define OMAP4430_LOSTMEM_EMU_BANK (1 << 8)
+#define OMAP4430_RST_GLOBAL_COLD_SW (1 << 1)
+#define OMAP4430_RST_GLOBAL_WARM_SW (1 << 0)
+#define OMAP4430_ICEPICK_RST (1 << 9)
+#define OMAP4430_VDD_CORE_VOLT_MGR_RST (1 << 8)
+#define OMAP4430_VDD_IVA_VOLT_MGR_RST (1 << 7)
+#define OMAP4430_VDD_MPU_VOLT_MGR_RST (1 << 6)
+#define OMAP4430_EXTERNAL_WARM_RST (1 << 5)
+#define OMAP4430_SECURE_WDT_RST (1 << 4)
+#define OMAP4430_MPU_WDT_RST (1 << 3)
+#define OMAP4430_MPU_SECURITY_VIOL_RST (1 << 2)
+#define OMAP4430_GLOBAL_WARM_SW_RST (1 << 1)
+#define OMAP4430_GLOBAL_COLD_RST (1 << 0)
+#define OMAP4430_RSTTIME2 (1 << 8)
+#define OMAP4430_RSTTIME1 (1 << 0)
+#define OMAP4430_CLKREQ_COND (1 << 0)
+#define OMAP4430_VDD_IVA_PRESENCE (1 << 9)
+#define OMAP4430_VDD_MPU_PRESENCE (1 << 8)
+#define OMAP4430_AUTO_CTRL_VDD_IVA_L (1 << 4)
+#define OMAP4430_AUTO_CTRL_VDD_MPU_L (1 << 2)
+#define OMAP4430_AUTO_CTRL_VDD_CORE_L (1 << 0)
+#define OMAP4430_PWRREQ_COND (1 << 0)
+#define OMAP4430_PONOUT_2_PGOODIN_TIME (1 << 8)
+#define OMAP4430_PCHARGE_TIME (1 << 0)
+#define OMAP4430_ISO_2_ON_TIME (1 << 0)
+#define OMAP4430_GLOBAL_WUEN (1 << 16)
+#define OMAP4430_WUCLK_STATUS (1 << 9)
+#define OMAP4430_WUCLK_CTRL (1 << 8)
+#define OMAP4430_ISOCLK_STATUS (1 << 1)
+#define OMAP4430_ISOCLK_OVERRIDE (1 << 0)
+#define OMAP4430_RAMP_DOWN_PRESCAL (1 << 24)
+#define OMAP4430_RAMP_DOWN_COUNT (1 << 16)
+#define OMAP4430_RAMP_UP_PRESCAL (1 << 8)
+#define OMAP4430_RAMP_UP_COUNT (1 << 0)
+#define OMAP4430_ERROROFFSET (1 << 24)
+#define OMAP4430_ERRORGAIN (1 << 16)
+#define OMAP4430_INITVOLTAGE (1 << 8)
+#define OMAP4430_TIMEOUTEN (1 << 3)
+#define OMAP4430_INITVDD (1 << 2)
+#define OMAP4430_FORCEUPDATE (1 << 1)
+#define OMAP4430_VPENABLE (1 << 0)
+#define OMAP4430_VPINIDLE (1 << 0)
+#define OMAP4430_VDDMAX (1 << 24)
+#define OMAP4430_VDDMIN (1 << 16)
+#define OMAP4430_TIMEOUT (1 << 0)
+#define OMAP4430_VPVOLTAGE (1 << 0)
+#define OMAP4430_SMPSWAITTIMEMAX (1 << 8)
+#define OMAP4430_VSTEPMAX (1 << 0)
+#define OMAP4430_SMPSWAITTIMEMIN (1 << 8)
+#define OMAP4430_VSTEPMIN (1 << 0)
+#define OMAP4430_SA_VDD_MPU_L (1 << 16)
+#define OMAP4430_SA_VDD_IVA_L (1 << 8)
+#define OMAP4430_SA_VDD_CORE_L (1 << 0)
+#define OMAP4430_VOLRA_VDD_MPU_L (1 << 16)
+#define OMAP4430_VOLRA_VDD_IVA_L (1 << 8)
+#define OMAP4430_VOLRA_VDD_CORE_L (1 << 0)
+#define OMAP4430_CMDRA_VDD_MPU_L (1 << 16)
+#define OMAP4430_CMDRA_VDD_IVA_L (1 << 8)
+#define OMAP4430_CMDRA_VDD_CORE_L (1 << 0)
+#define OMAP4430_ON (1 << 24)
+#define OMAP4430_ONLP (1 << 16)
+#define OMAP4430_RET (1 << 8)
+#define OMAP4430_OFF (1 << 0)
+#define OMAP4430_VALID (1 << 24)
+#define OMAP4430_DATA (1 << 16)
+#define OMAP4430_REGADDR (1 << 8)
+#define OMAP4430_SLAVEADDR (1 << 0)
+#define OMAP4430_RACEN_VDD_MPU_L (1 << 20)
+#define OMAP4430_RAC_VDD_MPU_L (1 << 19)
+#define OMAP4430_RAV_VDD_MPU_L (1 << 18)
+#define OMAP4430_CMD_VDD_MPU_L (1 << 17)
+#define OMAP4430_CMD_VDD_IVA_L (1 << 12)
+#define OMAP4430_RACEN_VDD_IVA_L (1 << 11)
+#define OMAP4430_RAC_VDD_IVA_L (1 << 10)
+#define OMAP4430_RAV_VDD_IVA_L (1 << 9)
+#define OMAP4430_CMD_VDD_CORE_L (1 << 4)
+#define OMAP4430_RACEN_VDD_CORE_L (1 << 3)
+#define OMAP4430_RAC_VDD_CORE_L (1 << 2)
+#define OMAP4430_RAV_VDD_CORE_L (1 << 1)
+#define OMAP4430_DFILTEREN (1 << 6)
+#define OMAP4430_HSMASTER (1 << 5)
+#define OMAP4430_SRMODEEN (1 << 4)
+#define OMAP4430_HSMODEEN (1 << 3)
+#define OMAP4430_HSMCODE (1 << 0)
+#define OMAP4430_HSSCLL (1 << 24)
+#define OMAP4430_HSSCLH (1 << 16)
+#define OMAP4430_SCLL (1 << 8)
+#define OMAP4430_SCLH (1 << 0)
+#define OMAP4430_SLPCNT_VALUE (1 << 16)
+#define OMAP4430_VSETUPCNT_VALUE (1 << 8)
+#define OMAP4430_PCHARGECNT_VALUE (1 << 0)
+#define OMAP4430_ENABLE_RTA_EXPORT (1 << 0)
+#define OMAP4430_AIPOFF (1 << 8)
+#define OMAP4430_ENFUNC5 (1 << 7)
+#define OMAP4430_ENFUNC4 (1 << 6)
+#define OMAP4430_ENFUNC3 (1 << 5)
+#define OMAP4430_ENFUNC2_EXPORT (1 << 4)
+#define OMAP4430_ENFUNC1 (1 << 3)
+#define OMAP4430_ABBOFF_SLEEP_EXPORT (1 << 2)
+#define OMAP4430_ABBOFF_ACT_EXPORT (1 << 1)
+#define OMAP4430_SRAM_IN_TRANSITION (1 << 9)
+#define OMAP4430_SRAMLDO_STATUS (1 << 8)
+#define OMAP4430_RETMODE_ENABLE (1 << 0)
+#define OMAP4430_SRAM_IN_TRANSITION (1 << 9)
+#define OMAP4430_SRAMLDO_STATUS (1 << 8)
+#define OMAP4430_SRAM_IN_TRANSITION (1 << 9)
+#define OMAP4430_SRAMLDO_STATUS (1 << 8)
+#define OMAP4430_SR2_WTCNT_VALUE (1 << 8)
+#define OMAP4430_NOCAP_EXPORT (1 << 4)
+#define OMAP4430_SLEEP_RBB_SEL (1 << 3)
+#define OMAP4430_ACTIVE_FBB_SEL (1 << 2)
+#define OMAP4430_ACTIVE_RBB_SEL (1 << 1)
+#define OMAP4430_SR2EN (1 << 0)
+#define OMAP4430_SR2_IN_TRANSITION (1 << 6)
+#define OMAP4430_SR2_STATUS (1 << 3)
+#define OMAP4430_OPP_CHANGE (1 << 2)
+#define OMAP4430_OPP_SEL (1 << 0)
+#define OMAP4430_NOCAP_EXPORT (1 << 4)
+#define OMAP4430_SLEEP_RBB_SEL (1 << 3)
+#define OMAP4430_ACTIVE_FBB_SEL (1 << 2)
+#define OMAP4430_ACTIVE_RBB_SEL (1 << 1)
+#define OMAP4430_CBIASSEL (1 << 0)
+#define OMAP4430_DEVICE_OFF_ENABLE (1 << 0)
+#define OMAP4430_PHASE2B_COMPLETED (1 << 2)
+#define OMAP4430_PHASE2A_COMPLETED (1 << 1)
+#define OMAP4430_PHASE1_COMPLETED (1 << 0)
+#define OMAP4430_PHASE1_CNDP (1 << 0)
+#define OMAP4430_PHASE2A_CNDP (1 << 0)
+#define OMAP4430_PHASE2B_CNDP (1 << 0)
+#define OMAP4430_MODEM_SLEEP_ST (1 << 16)
+#define OMAP4430_MODEM_SHUTDOWN_IRQ (1 << 9)
+#define OMAP4430_MODEM_WAKE_IRQ (1 << 8)
+#define OMAP4430_MODEM_READY (1 << 1)
+#define OMAP4430_WAKE_MODEM (1 << 0)
+#define OMAP4430_INITVDD_EDGE (1 << 1)
+#define OMAP4430_FORCEUPDATE_EDGE (1 << 1)
+
+
+#define OMAP4430_PRM_CLKSEL_MASK BITFIELD(0, 0)
+#define OMAP4430_SYS_CLKSEL_MASK BITFIELD(2, 0)
+#define OMAP4430_PERIPHMEM_ONSTATE_MASK BITFIELD(21, 20)
+#define OMAP4430_AESSMEM_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_PERIPHMEM_RETSTATE_MASK BITFIELD(10, 10)
+#define OMAP4430_AESSMEM_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_LOWPOWERSTATECHANGE_MASK BITFIELD(4, 4)
+#define OMAP4430_LOGICRETSTATE_MASK BITFIELD(2, 2)
+#define OMAP4430_POWERSTATE_MASK BITFIELD(1, 0)
+#define OMAP4430_INTRANSITION_MASK BITFIELD(20, 20)
+#define OMAP4430_PERIPHMEM_STATEST_MASK BITFIELD(9, 8)
+#define OMAP4430_AESSMEM_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_LOGICSTATEST_MASK BITFIELD(2, 2)
+#define OMAP4430_POWERSTATEST_MASK BITFIELD(1, 0)
+#define OMAP4430_LOSTMEM_AESSMEM_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTCONTEXT_DFF_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_PERIHPMEM_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_DSS_MEM_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_DSS_MEM_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_DSS_MEM_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK BITFIELD(19, 19)
+#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK BITFIELD(14, 14)
+#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK BITFIELD(13, 13)
+#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK BITFIELD(12, 12)
+#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK BITFIELD(11, 11)
+#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK BITFIELD(10, 10)
+#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK BITFIELD(9, 9)
+#define OMAP4430_WKUPDEP_DSI2_MPU_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK BITFIELD(5, 5)
+#define OMAP4430_WKUPDEP_DSI1_MPU_MASK BITFIELD(4, 4)
+#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DISPC_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_DSS_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTCONTEXT_RFF_MASK BITFIELD(1, 1)
+#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_L3INIT_BANK1_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_SATA_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SATA_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC6_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK BITFIELD(19, 18)
+#define OMAP4430_RETAINED_BANK_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK BITFIELD(9, 9)
+#define OMAP4430_RETAINED_BANK_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_NONRETAINED_BANK_STATEST_MASK BITFIELD(7, 6)
+#define OMAP4430_RETAINED_BANK_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_HECC2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART1_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART2_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART3_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART3_TESLA_MASK BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UART3_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART4_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART4_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_WDT2_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USIM_SDMA_MASK BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_USIM_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_WKUP_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_RTC_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_MPU_RAM_ONSTATE_MASK BITFIELD(21, 20)
+#define OMAP4430_MPU_L2_ONSTATE_MASK BITFIELD(19, 18)
+#define OMAP4430_MPU_L1_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_MPU_RAM_RETSTATE_MASK BITFIELD(10, 10)
+#define OMAP4430_MPU_L2_RETSTATE_MASK BITFIELD(9, 9)
+#define OMAP4430_MPU_L1_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_MPU_RAM_STATEST_MASK BITFIELD(9, 8)
+#define OMAP4430_MPU_L2_STATEST_MASK BITFIELD(7, 6)
+#define OMAP4430_MPU_L1_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_ICECRUSHER_MPU_RST_MASK BITFIELD(1, 1)
+#define OMAP4430_EMULATION_RST_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_MPU_RAM_MASK BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_MPU_L2_MASK BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_MPU_L1_MASK BITFIELD(8, 8)
+#define OMAP4430_TESLA_EDMA_ONSTATE_MASK BITFIELD(21, 20)
+#define OMAP4430_TESLA_L2_ONSTATE_MASK BITFIELD(19, 18)
+#define OMAP4430_TESLA_L1_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_TESLA_EDMA_RETSTATE_MASK BITFIELD(10, 10)
+#define OMAP4430_TESLA_L2_RETSTATE_MASK BITFIELD(9, 9)
+#define OMAP4430_TESLA_L1_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_TESLA_EDMA_STATEST_MASK BITFIELD(9, 8)
+#define OMAP4430_TESLA_L2_STATEST_MASK BITFIELD(7, 6)
+#define OMAP4430_TESLA_L1_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_RST2_MASK BITFIELD(1, 1)
+#define OMAP4430_RST1_MASK BITFIELD(0, 0)
+#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK BITFIELD(3, 3)
+#define OMAP4430_TESLASS_EMU_RSTST_MASK BITFIELD(2, 2)
+#define OMAP4430_RST2ST_MASK BITFIELD(1, 1)
+#define OMAP4430_RST1ST_MASK BITFIELD(0, 0)
+#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_TESLA_L2_MASK BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TESLA_L1_MASK BITFIELD(8, 8)
+#define OMAP4430_TCM2_MEM_ONSTATE_MASK BITFIELD(23, 22)
+#define OMAP4430_TCM1_MEM_ONSTATE_MASK BITFIELD(21, 20)
+#define OMAP4430_SL2_MEM_ONSTATE_MASK BITFIELD(19, 18)
+#define OMAP4430_HWA_MEM_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_TCM2_MEM_RETSTATE_MASK BITFIELD(11, 11)
+#define OMAP4430_TCM1_MEM_RETSTATE_MASK BITFIELD(10, 10)
+#define OMAP4430_SL2_MEM_RETSTATE_MASK BITFIELD(9, 9)
+#define OMAP4430_HWA_MEM_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_TCM2_MEM_STATEST_MASK BITFIELD(11, 10)
+#define OMAP4430_TCM1_MEM_STATEST_MASK BITFIELD(9, 8)
+#define OMAP4430_SL2_MEM_STATEST_MASK BITFIELD(7, 6)
+#define OMAP4430_HWA_MEM_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_RST3_MASK BITFIELD(2, 2)
+#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK BITFIELD(5, 5)
+#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK BITFIELD(4, 4)
+#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK BITFIELD(3, 3)
+#define OMAP4430_RST3ST_MASK BITFIELD(2, 2)
+#define OMAP4430_LOSTMEM_HWA_MEM_MASK BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_TCM2_MEM_MASK BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TCM1_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_SL2_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK BITFIELD(25, 24)
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK BITFIELD(23, 22)
+#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK BITFIELD(21, 20)
+#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK BITFIELD(19, 18)
+#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK BITFIELD(12, 12)
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK BITFIELD(11, 11)
+#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK BITFIELD(10, 10)
+#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK BITFIELD(9, 9)
+#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK BITFIELD(8, 8)
+#define OMAP4430_MEMORYCHANGE_MASK BITFIELD(3, 3)
+#define OMAP4430_OCP_NRET_BANK_STATEST_MASK BITFIELD(13, 12)
+#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK BITFIELD(11, 10)
+#define OMAP4430_DUCATI_L2RAM_STATEST_MASK BITFIELD(9, 8)
+#define OMAP4430_CORE_OCMRAM_STATEST_MASK BITFIELD(7, 6)
+#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK BITFIELD(8, 8)
+#define OMAP4430_ICECRUSHER_RST2ST_MASK BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_RST1ST_MASK BITFIELD(5, 5)
+#define OMAP4430_EMULATION_RST2ST_MASK BITFIELD(4, 4)
+#define OMAP4430_EMULATION_RST1ST_MASK BITFIELD(3, 3)
+#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_DMM_LOSTMEM_CORE_NRET_BANK_MASK BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_REV_MASK BITFIELD(7, 0)
+#define OMAP4430_VC_TOERR_ST_MASK BITFIELD(31, 31)
+#define OMAP4430_VC_RAERR_ST_MASK BITFIELD(30, 30)
+#define OMAP4430_VC_SAERR_ST_MASK BITFIELD(29, 29)
+#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK BITFIELD(28, 28)
+#define OMAP4430_VP_CORE_EQVALUE_ST_MASK BITFIELD(27, 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK BITFIELD(26, 26)
+#define OMAP4430_VP_CORE_MAXVDD_ST_MASK BITFIELD(25, 25)
+#define OMAP4430_VP_CORE_MINVDD_ST_MASK BITFIELD(24, 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK BITFIELD(23, 23)
+#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK BITFIELD(22, 22)
+#define OMAP4430_VP_IVA_EQVALUE_ST_MASK BITFIELD(21, 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK BITFIELD(20, 20)
+#define OMAP4430_VP_IVA_MAXVDD_ST_MASK BITFIELD(19, 19)
+#define OMAP4430_VP_IVA_MINVDD_ST_MASK BITFIELD(18, 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK BITFIELD(17, 17)
+#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK BITFIELD(16, 16)
+#define OMAP4430_VP_MPU_EQVALUE_ST_MASK BITFIELD(15, 15)
+#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK BITFIELD(14, 14)
+#define OMAP4430_VP_MPU_MAXVDD_ST_MASK BITFIELD(13, 13)
+#define OMAP4430_VP_MPU_MINVDD_ST_MASK BITFIELD(12, 12)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK BITFIELD(11, 11)
+#define OMAP4430_IO_ST_MASK BITFIELD(9, 9)
+#define OMAP4430_TRANSITION_ST_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK BITFIELD(7, 7)
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK BITFIELD(6, 6)
+#define OMAP4430_DPLL_USB_RECAL_ST_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_ABE_RECAL_ST_MASK BITFIELD(4, 4)
+#define OMAP4430_DPLL_PER_RECAL_ST_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_MPU_RECAL_ST_MASK BITFIELD(1, 1)
+#define OMAP4430_DPLL_CORE_RECAL_ST_MASK BITFIELD(0, 0)
+#define OMAP4430_VC_TOERR_EN_MASK BITFIELD(31, 31)
+#define OMAP4430_VC_RAERR_EN_MASK BITFIELD(30, 30)
+#define OMAP4430_VC_SAERR_EN_MASK BITFIELD(29, 29)
+#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK BITFIELD(28, 28)
+#define OMAP4430_VP_CORE_EQVALUE_EN_MASK BITFIELD(27, 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK BITFIELD(26, 26)
+#define OMAP4430_VP_CORE_MAXVDD_EN_MASK BITFIELD(25, 25)
+#define OMAP4430_VP_CORE_MINVDD_EN_MASK BITFIELD(24, 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK BITFIELD(23, 23)
+#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK BITFIELD(22, 22)
+#define OMAP4430_VP_IVA_EQVALUE_EN_MASK BITFIELD(21, 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK BITFIELD(20, 20)
+#define OMAP4430_VP_IVA_MAXVDD_EN_MASK BITFIELD(19, 19)
+#define OMAP4430_VP_IVA_MINVDD_EN_MASK BITFIELD(18, 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK BITFIELD(17, 17)
+#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK BITFIELD(16, 16)
+#define OMAP4430_VP_MPU_EQVALUE_EN_MASK BITFIELD(15, 15)
+#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK BITFIELD(14, 14)
+#define OMAP4430_VP_MPU_MAXVDD_EN_MASK BITFIELD(13, 13)
+#define OMAP4430_VP_MPU_MINVDD_EN_MASK BITFIELD(12, 12)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK BITFIELD(11, 11)
+#define OMAP4430_IO_EN_MASK BITFIELD(9, 9)
+#define OMAP4430_TRANSITION_EN_MASK BITFIELD(8, 8)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK BITFIELD(7, 7)
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK BITFIELD(6, 6)
+#define OMAP4430_DPLL_USB_RECAL_EN_MASK BITFIELD(5, 5)
+#define OMAP4430_DPLL_ABE_RECAL_EN_MASK BITFIELD(4, 4)
+#define OMAP4430_DPLL_PER_RECAL_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_MPU_RECAL_EN_MASK BITFIELD(1, 1)
+#define OMAP4430_DPLL_CORE_RECAL_EN_MASK BITFIELD(0, 0)
+#define OMAP4430_VC_TOERR_ST_MASK BITFIELD(31, 31)
+#define OMAP4430_VC_RAERR_ST_MASK BITFIELD(30, 30)
+#define OMAP4430_VC_SAERR_ST_MASK BITFIELD(29, 29)
+#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK BITFIELD(28, 28)
+#define OMAP4430_VP_CORE_EQVALUE_ST_MASK BITFIELD(27, 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK BITFIELD(26, 26)
+#define OMAP4430_VP_CORE_MAXVDD_ST_MASK BITFIELD(25, 25)
+#define OMAP4430_VP_CORE_MINVDD_ST_MASK BITFIELD(24, 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK BITFIELD(23, 23)
+#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK BITFIELD(22, 22)
+#define OMAP4430_VP_IVA_EQVALUE_ST_MASK BITFIELD(21, 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK BITFIELD(20, 20)
+#define OMAP4430_VP_IVA_MAXVDD_ST_MASK BITFIELD(19, 19)
+#define OMAP4430_VP_IVA_MINVDD_ST_MASK BITFIELD(18, 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK BITFIELD(17, 17)
+#define OMAP4430_FORCEWKUP_ST_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK BITFIELD(7, 7)
+#define OMAP4430_DPLL_PER_RECAL_ST_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_CORE_RECAL_ST_MASK BITFIELD(0, 0)
+#define OMAP4430_VC_TOERR_EN_MASK BITFIELD(31, 31)
+#define OMAP4430_VC_RAERR_EN_MASK BITFIELD(30, 30)
+#define OMAP4430_VC_SAERR_EN_MASK BITFIELD(29, 29)
+#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK BITFIELD(28, 28)
+#define OMAP4430_VP_CORE_EQVALUE_EN_MASK BITFIELD(27, 27)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK BITFIELD(26, 26)
+#define OMAP4430_VP_CORE_MAXVDD_EN_MASK BITFIELD(25, 25)
+#define OMAP4430_VP_CORE_MINVDD_EN_MASK BITFIELD(24, 24)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK BITFIELD(23, 23)
+#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK BITFIELD(22, 22)
+#define OMAP4430_VP_IVA_EQVALUE_EN_MASK BITFIELD(21, 21)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK BITFIELD(20, 20)
+#define OMAP4430_VP_IVA_MAXVDD_EN_MASK BITFIELD(19, 19)
+#define OMAP4430_VP_IVA_MINVDD_EN_MASK BITFIELD(18, 18)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK BITFIELD(17, 17)
+#define OMAP4430_FORCEWKUP_EN_MASK BITFIELD(10, 10)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK BITFIELD(7, 7)
+#define OMAP4430_DPLL_PER_RECAL_EN_MASK BITFIELD(3, 3)
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_CORE_RECAL_EN_MASK BITFIELD(0, 0)
+#define OMAP4430_DPLL_ABE_RECAL_ST_MASK BITFIELD(4, 4)
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK BITFIELD(2, 2)
+#define OMAP4430_DPLL_ABE_RECAL_EN_MASK BITFIELD(4, 4)
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK BITFIELD(2, 2)
+#define OMAP4430_MODULEMODE_MASK BITFIELD(1, 0)
+#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK BITFIELD(0, 0)
+#define OMAP4430_CAM_MEM_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_CAM_MEM_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_LOSTMEM_CAM_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CAM_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_GFX_MEM_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_GFX_MEM_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_LOSTMEM_GFX_MEM_MASK BITFIELD(8, 8)
+#define OMAP4430_EMU_BANK_ONSTATE_MASK BITFIELD(17, 16)
+#define OMAP4430_EMU_BANK_STATEST_MASK BITFIELD(5, 4)
+#define OMAP4430_LOSTMEM_EMU_BANK_MASK BITFIELD(8, 8)
+#define OMAP4430_RST_GLOBAL_COLD_SW_MASK BITFIELD(1, 1)
+#define OMAP4430_RST_GLOBAL_WARM_SW_MASK BITFIELD(0, 0)
+#define OMAP4430_ICEPICK_RST_MASK BITFIELD(9, 9)
+#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK BITFIELD(8, 8)
+#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK BITFIELD(7, 7)
+#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK BITFIELD(6, 6)
+#define OMAP4430_EXTERNAL_WARM_RST_MASK BITFIELD(5, 5)
+#define OMAP4430_SECURE_WDT_RST_MASK BITFIELD(4, 4)
+#define OMAP4430_MPU_WDT_RST_MASK BITFIELD(3, 3)
+#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK BITFIELD(2, 2)
+#define OMAP4430_GLOBAL_WARM_SW_RST_MASK BITFIELD(1, 1)
+#define OMAP4430_GLOBAL_COLD_RST_MASK BITFIELD(0, 0)
+#define OMAP4430_RSTTIME2_MASK BITFIELD(12, 8)
+#define OMAP4430_RSTTIME1_MASK BITFIELD(7, 0)
+#define OMAP4430_CLKREQ_COND_MASK BITFIELD(2, 0)
+#define OMAP4430_VDD_IVA_PRESENCE_MASK BITFIELD(9, 9)
+#define OMAP4430_VDD_MPU_PRESENCE_MASK BITFIELD(8, 8)
+#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK BITFIELD(5, 4)
+#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK BITFIELD(3, 2)
+#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK BITFIELD(1, 0)
+#define OMAP4430_PWRREQ_COND_MASK BITFIELD(1, 0)
+#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK BITFIELD(15, 8)
+#define OMAP4430_PCHARGE_TIME_MASK BITFIELD(7, 0)
+#define OMAP4430_ISO_2_ON_TIME_MASK BITFIELD(7, 0)
+#define OMAP4430_GLOBAL_WUEN_MASK BITFIELD(16, 16)
+#define OMAP4430_WUCLK_STATUS_MASK BITFIELD(9, 9)
+#define OMAP4430_WUCLK_CTRL_MASK BITFIELD(8, 8)
+#define OMAP4430_ISOCLK_STATUS_MASK BITFIELD(1, 1)
+#define OMAP4430_ISOCLK_OVERRIDE_MASK BITFIELD(0, 0)
+#define OMAP4430_RAMP_DOWN_PRESCAL_MASK BITFIELD(25, 24)
+#define OMAP4430_RAMP_DOWN_COUNT_MASK BITFIELD(21, 16)
+#define OMAP4430_RAMP_UP_PRESCAL_MASK BITFIELD(9, 8)
+#define OMAP4430_RAMP_UP_COUNT_MASK BITFIELD(5, 0)
+#define OMAP4430_ERROROFFSET_MASK BITFIELD(31, 24)
+#define OMAP4430_ERRORGAIN_MASK BITFIELD(23, 16)
+#define OMAP4430_INITVOLTAGE_MASK BITFIELD(15, 8)
+#define OMAP4430_TIMEOUTEN_MASK BITFIELD(3, 3)
+#define OMAP4430_INITVDD_MASK BITFIELD(2, 2)
+#define OMAP4430_FORCEUPDATE_MASK BITFIELD(1, 1)
+#define OMAP4430_VPENABLE_MASK BITFIELD(0, 0)
+#define OMAP4430_VPINIDLE_MASK BITFIELD(0, 0)
+#define OMAP4430_VDDMAX_MASK BITFIELD(31, 24)
+#define OMAP4430_VDDMIN_MASK BITFIELD(23, 16)
+#define OMAP4430_TIMEOUT_MASK BITFIELD(15, 0)
+#define OMAP4430_VPVOLTAGE_MASK BITFIELD(7, 0)
+#define OMAP4430_SMPSWAITTIMEMAX_MASK BITFIELD(23, 8)
+#define OMAP4430_VSTEPMAX_MASK BITFIELD(7, 0)
+#define OMAP4430_SMPSWAITTIMEMIN_MASK BITFIELD(23, 8)
+#define OMAP4430_VSTEPMIN_MASK BITFIELD(7, 0)
+#define OMAP4430_PRM_VC_SMPS_SA_VDD_MPU_L_MASK BITFIELD(22, 16)
+#define OMAP4430_PRM_VC_SMPS_SA_VDD_IVA_L_MASK BITFIELD(14, 8)
+#define OMAP4430_PRM_VC_SMPS_SA_VDD_CORE_L_MASK BITFIELD(6, 0)
+#define OMAP4430_VOLRA_VDD_MPU_L_MASK BITFIELD(23, 16)
+#define OMAP4430_VOLRA_VDD_IVA_L_MASK BITFIELD(15, 8)
+#define OMAP4430_VOLRA_VDD_CORE_L_MASK BITFIELD(7, 0)
+#define OMAP4430_CMDRA_VDD_MPU_L_MASK BITFIELD(23, 16)
+#define OMAP4430_CMDRA_VDD_IVA_L_MASK BITFIELD(15, 8)
+#define OMAP4430_CMDRA_VDD_CORE_L_MASK BITFIELD(7, 0)
+#define OMAP4430_ON_MASK BITFIELD(31, 24)
+#define OMAP4430_ONLP_MASK BITFIELD(23, 16)
+#define OMAP4430_RET_MASK BITFIELD(15, 8)
+#define OMAP4430_OFF_MASK BITFIELD(7, 0)
+#define OMAP4430_VALID_MASK BITFIELD(24, 24)
+#define OMAP4430_DATA_MASK BITFIELD(23, 16)
+#define OMAP4430_REGADDR_MASK BITFIELD(15, 8)
+#define OMAP4430_SLAVEADDR_MASK BITFIELD(6, 0)
+#define OMAP4430_RACEN_VDD_MPU_L_MASK BITFIELD(20, 20)
+#define OMAP4430_RAC_VDD_MPU_L_MASK BITFIELD(19, 19)
+#define OMAP4430_RAV_VDD_MPU_L_MASK BITFIELD(18, 18)
+#define OMAP4430_CMD_VDD_MPU_L_MASK BITFIELD(17, 17)
+#define OMAP4430_PRM_VC_CFG_CHANNEL_SA_VDD_MPU_L_MASK BITFIELD(16, 16)
+#define OMAP4430_CMD_VDD_IVA_L_MASK BITFIELD(12, 12)
+#define OMAP4430_RACEN_VDD_IVA_L_MASK BITFIELD(11, 11)
+#define OMAP4430_RAC_VDD_IVA_L_MASK BITFIELD(10, 10)
+#define OMAP4430_RAV_VDD_IVA_L_MASK BITFIELD(9, 9)
+#define OMAP4430_PRM_VC_CFG_CHANNEL_SA_VDD_IVA_L_MASK BITFIELD(8, 8)
+#define OMAP4430_CMD_VDD_CORE_L_MASK BITFIELD(4, 4)
+#define OMAP4430_RACEN_VDD_CORE_L_MASK BITFIELD(3, 3)
+#define OMAP4430_RAC_VDD_CORE_L_MASK BITFIELD(2, 2)
+#define OMAP4430_RAV_VDD_CORE_L_MASK BITFIELD(1, 1)
+#define OMAP4430_PRM_VC_CFG_CHANNEL_SA_VDD_CORE_L_MASK BITFIELD(0, 0)
+#define OMAP4430_DFILTEREN_MASK BITFIELD(6, 6)
+#define OMAP4430_HSMASTER_MASK BITFIELD(5, 5)
+#define OMAP4430_SRMODEEN_MASK BITFIELD(4, 4)
+#define OMAP4430_HSMODEEN_MASK BITFIELD(3, 3)
+#define OMAP4430_HSMCODE_MASK BITFIELD(2, 0)
+#define OMAP4430_HSSCLL_MASK BITFIELD(31, 24)
+#define OMAP4430_HSSCLH_MASK BITFIELD(23, 16)
+#define OMAP4430_SCLL_MASK BITFIELD(15, 8)
+#define OMAP4430_SCLH_MASK BITFIELD(7, 0)
+#define OMAP4430_SLPCNT_VALUE_MASK BITFIELD(23, 16)
+#define OMAP4430_VSETUPCNT_VALUE_MASK BITFIELD(15, 8)
+#define OMAP4430_PCHARGECNT_VALUE_MASK BITFIELD(5, 0)
+#define OMAP4430_ENABLE_RTA_EXPORT_MASK BITFIELD(0, 0)
+#define OMAP4430_AIPOFF_MASK BITFIELD(8, 8)
+#define OMAP4430_ENFUNC5_MASK BITFIELD(7, 7)
+#define OMAP4430_ENFUNC4_MASK BITFIELD(6, 6)
+#define OMAP4430_ENFUNC3_MASK BITFIELD(5, 5)
+#define OMAP4430_ENFUNC2_EXPORT_MASK BITFIELD(4, 4)
+#define OMAP4430_ENFUNC1_MASK BITFIELD(3, 3)
+#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK BITFIELD(2, 2)
+#define OMAP4430_ABBOFF_ACT_EXPORT_MASK BITFIELD(1, 1)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK BITFIELD(9, 9)
+#define OMAP4430_SRAMLDO_STATUS_MASK BITFIELD(8, 8)
+#define OMAP4430_RETMODE_ENABLE_MASK BITFIELD(0, 0)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK BITFIELD(9, 9)
+#define OMAP4430_SRAMLDO_STATUS_MASK BITFIELD(8, 8)
+#define OMAP4430_RETMODE_ENABLE_MASK BITFIELD(0, 0)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK BITFIELD(9, 9)
+#define OMAP4430_SRAMLDO_STATUS_MASK BITFIELD(8, 8)
+#define OMAP4430_RETMODE_ENABLE_MASK BITFIELD(0, 0)
+#define OMAP4430_SR2_WTCNT_VALUE_MASK BITFIELD(15, 8)
+#define OMAP4430_NOCAP_EXPORT_MASK BITFIELD(4, 4)
+#define OMAP4430_SLEEP_RBB_SEL_MASK BITFIELD(3, 3)
+#define OMAP4430_ACTIVE_FBB_SEL_MASK BITFIELD(2, 2)
+#define OMAP4430_ACTIVE_RBB_SEL_MASK BITFIELD(1, 1)
+#define OMAP4430_SR2EN_MASK BITFIELD(0, 0)
+#define OMAP4430_SR2_IN_TRANSITION_MASK BITFIELD(6, 6)
+#define OMAP4430_SR2_STATUS_MASK BITFIELD(4, 3)
+#define OMAP4430_OPP_CHANGE_MASK BITFIELD(2, 2)
+#define OMAP4430_OPP_SEL_MASK BITFIELD(1, 0)
+#define OMAP4430_NOCAP_EXPORT_MASK BITFIELD(4, 4)
+#define OMAP4430_SLEEP_RBB_SEL_MASK BITFIELD(3, 3)
+#define OMAP4430_ACTIVE_FBB_SEL_MASK BITFIELD(2, 2)
+#define OMAP4430_ACTIVE_RBB_SEL_MASK BITFIELD(1, 1)
+#define OMAP4430_CBIASSEL_MASK BITFIELD(0, 0)
+#define OMAP4430_DEVICE_OFF_ENABLE_MASK BITFIELD(0, 0)
+#define OMAP4430_PHASE2B_COMPLETED_MASK BITFIELD(2, 2)
+#define OMAP4430_PHASE2A_COMPLETED_MASK BITFIELD(1, 1)
+#define OMAP4430_PHASE1_COMPLETED_MASK BITFIELD(0, 0)
+#define OMAP4430_PHASE1_CNDP_MASK BITFIELD(31, 0)
+#define OMAP4430_PHASE2A_CNDP_MASK BITFIELD(31, 0)
+#define OMAP4430_PHASE2B_CNDP_MASK BITFIELD(31, 0)
+#define OMAP4430_MODEM_SLEEP_ST_MASK BITFIELD(16, 16)
+#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK BITFIELD(9, 9)
+#define OMAP4430_MODEM_WAKE_IRQ_MASK BITFIELD(8, 8)
+#define OMAP4430_MODEM_READY_MASK BITFIELD(1, 1)
+#define OMAP4430_WAKE_MODEM_MASK BITFIELD(0, 0)
+#endif /* __ARCH_ARM_MACH_OMAP2_PRM_REG BITS_44XX_H */
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 9937e2814696..1ae9b327b916 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -4,10 +4,11 @@
/*
* OMAP2/3 Power/Reset Management (PRM) register definitions
*
- * Copyright (C) 2007 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
* Copyright (C) 2007 Nokia Corporation
*
* Written by Paul Walmsley
+ * Updated for OMAP4 by Rajendra Nayak (rnayak@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
@@ -22,13 +23,15 @@
IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
#define OMAP34XX_PRM_REGADDR(module, reg) \
IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
+#define OMAP44XX_PRM_REGADDR(module, reg) \
+ IO_ADDRESS(OMAP4430_PRM_BASE + (module) + (reg))
/*
* Architecture-specific global PRM registers
* Use __raw_{read,write}l() with these registers.
*
* With a few exceptions, these are the register names beginning with
- * PRCM_* on 24xx, and PRM_* on 34xx. (The exceptions are the
+ * PRCM_* on 24xx, and PRM_* on 34xx and 44xx. (The exceptions are the
* IRQSTATUS and IRQENABLE bits.)
*
*/
@@ -160,6 +163,305 @@
#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070
#define OMAP3430_PRM_CLKOUT_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+#define OMAP4430_CM_ABE_DSS_SYS_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_CKGEN_MOD, 0x0)
+#define OMAP4430_CM_DPLL_SYS_REF_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_CKGEN_MOD, 0x4)
+#define OMAP4430_CM_L4_WKUP_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_CKGEN_MOD, 0x8)
+#define OMAP4430_CM_ABE_PLL_REF_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_CKGEN_MOD, 0xC)
+#define OMAP4430_CM_SYS_CLKSEL OMAP44XX_PRM_REGADDR(OMAP4430_CKGEN_MOD, 0x10)
+#define OMAP4430_PM_ABE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x0)
+#define OMAP4430_PM_ABE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x4)
+#define OMAP4430_RM_ABE_AESS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x2C)
+#define OMAP4430_PM_ABE_PDM_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x30)
+#define OMAP4430_RM_ABE_PDM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x34)
+#define OMAP4430_PM_ABE_DMIC_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x38)
+#define OMAP4430_RM_ABE_DMIC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x3C)
+#define OMAP4430_PM_ABE_MCASP_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x40)
+#define OMAP4430_RM_ABE_MCASP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x44)
+#define OMAP4430_PM_ABE_MCBSP1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x48)
+#define OMAP4430_RM_ABE_MCBSP1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x4C)
+#define OMAP4430_PM_ABE_MCBSP2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x50)
+#define OMAP4430_RM_ABE_MCBSP2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x54)
+#define OMAP4430_PM_ABE_MCBSP3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x58)
+#define OMAP4430_RM_ABE_MCBSP3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x5C)
+#define OMAP4430_PM_ABE_SLIMBUS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x60)
+#define OMAP4430_RM_ABE_SLIMBUS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x64)
+#define OMAP4430_PM_ABE_TIMER5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x68)
+#define OMAP4430_RM_ABE_TIMER5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x6C)
+#define OMAP4430_PM_ABE_TIMER6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x70)
+#define OMAP4430_RM_ABE_TIMER6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x74)
+#define OMAP4430_PM_ABE_TIMER7_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x78)
+#define OMAP4430_RM_ABE_TIMER7_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x7C)
+#define OMAP4430_PM_ABE_TIMER8_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x80)
+#define OMAP4430_RM_ABE_TIMER8_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x84)
+#define OMAP4430_PM_ABE_WDT3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x88)
+#define OMAP4430_RM_ABE_WDT3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ABE_MOD, 0x8C)
+#define OMAP4430_PM_DSS_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DSS_MOD, 0x0)
+#define OMAP4430_PM_DSS_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_DSS_MOD, 0x4)
+#define OMAP4430_PM_DSS_DSS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_DSS_MOD, 0x20)
+#define OMAP4430_RM_DSS_DSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_DSS_MOD, 0x24)
+#define OMAP4430_RM_DSS_DEISS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_DSS_MOD, 0x2C)
+#define OMAP4430_PM_L3INIT_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x0)
+#define OMAP4430_PM_L3INIT_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x4)
+#define OMAP4430_PM_L3INIT_MMC1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x28)
+#define OMAP4430_RM_L3INIT_MMC1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x2C)
+#define OMAP4430_PM_L3INIT_MMC2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x30)
+#define OMAP4430_RM_L3INIT_MMC2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x34)
+#define OMAP4430_PM_L3INIT_HSI_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x38)
+#define OMAP4430_RM_L3INIT_HSI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x3C)
+#define OMAP4430_PM_L3INIT_UNIPRO1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x40)
+#define OMAP4430_RM_L3INIT_UNIPRO1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x44)
+#define OMAP4430_PM_L3INIT_USB_HOST_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x58)
+#define OMAP4430_RM_L3INIT_USB_HOST_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x5C)
+#define OMAP4430_PM_L3INIT_USB_OTG_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x60)
+#define OMAP4430_RM_L3INIT_USB_OTG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x64)
+#define OMAP4430_PM_L3INIT_USB_TLL_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x68)
+#define OMAP4430_RM_L3INIT_USB_TLL_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x6C)
+#define OMAP4430_RM_L3INIT_P1500_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x7C)
+#define OMAP4430_RM_L3INIT_EMAC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x84)
+#define OMAP4430_PM_L3INIT_SATA_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x88)
+#define OMAP4430_RM_L3INIT_SATA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x8C)
+#define OMAP4430_RM_L3INIT_TPPSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x94)
+#define OMAP4430_PM_L3INIT_PCIESS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x98)
+#define OMAP4430_RM_L3INIT_PCIESS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0x9C)
+#define OMAP4430_RM_L3INIT_CCPTX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xAC)
+#define OMAP4430_PM_L3INIT_XHPI_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xC0)
+#define OMAP4430_RM_L3INIT_XHPI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xC4)
+#define OMAP4430_PM_L3INIT_MMC6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xC8)
+#define OMAP4430_RM_L3INIT_MMC6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xCC)
+#define OMAP4430_PM_L3INIT_USB_HOST_FS_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xD0)
+#define OMAP4430_RM_L3INIT_USB_HOST_FS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xD4)
+#define OMAP4430_RM_L3INIT_USBPHYOCP2SCP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L3INIT_MOD, 0xE4)
+#define OMAP4430_PM_L4PER_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x0)
+#define OMAP4430_PM_L4PER_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x4)
+#define OMAP4430_RM_L4PER_ADC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x24)
+#define OMAP4430_PM_L4PER_GPTIMER10_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x28)
+#define OMAP4430_RM_L4PER_GPTIMER10_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x2C)
+#define OMAP4430_PM_L4PER_GPTIMER11_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x30)
+#define OMAP4430_RM_L4PER_GPTIMER11_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x34)
+#define OMAP4430_PM_L4PER_GPTIMER2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x38)
+#define OMAP4430_RM_L4PER_GPTIMER2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x3C)
+#define OMAP4430_PM_L4PER_GPTIMER3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x40)
+#define OMAP4430_RM_L4PER_GPTIMER3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x44)
+#define OMAP4430_PM_L4PER_GPTIMER4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x48)
+#define OMAP4430_RM_L4PER_GPTIMER4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x4C)
+#define OMAP4430_PM_L4PER_GPTIMER9_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x50)
+#define OMAP4430_RM_L4PER_GPTIMER9_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x54)
+#define OMAP4430_RM_L4PER_ELM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x5C)
+#define OMAP4430_PM_L4PER_GPIO2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x60)
+#define OMAP4430_RM_L4PER_GPIO2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x64)
+#define OMAP4430_PM_L4PER_GPIO3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x68)
+#define OMAP4430_RM_L4PER_GPIO3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x6C)
+#define OMAP4430_PM_L4PER_GPIO4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x70)
+#define OMAP4430_RM_L4PER_GPIO4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x74)
+#define OMAP4430_PM_L4PER_GPIO5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x78)
+#define OMAP4430_RM_L4PER_GPIO5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x7C)
+#define OMAP4430_PM_L4PER_GPIO6_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x80)
+#define OMAP4430_RM_L4PER_GPIO6_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x84)
+#define OMAP4430_RM_L4PER_HDQ1W_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x8C)
+#define OMAP4430_PM_L4PER_HECC1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x90)
+#define OMAP4430_RM_L4PER_HECC1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x94)
+#define OMAP4430_PM_L4PER_HECC2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x98)
+#define OMAP4430_RM_L4PER_HECC2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x9C)
+#define OMAP4430_PM_L4PER_I2C1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xA0)
+#define OMAP4430_RM_L4PER_I2C1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xA4)
+#define OMAP4430_PM_L4PER_I2C2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xA8)
+#define OMAP4430_RM_L4PER_I2C2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xAC)
+#define OMAP4430_PM_L4PER_I2C3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xB0)
+#define OMAP4430_RM_L4PER_I2C3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xB4)
+#define OMAP4430_PM_L4PER_I2C4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xB8)
+#define OMAP4430_RM_L4PER_I2C4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xBC)
+#define OMAP4430_RM_L4PER_L4_PER_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xC0)
+#define OMAP4430_PM_L4PER_MCASP2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xD0)
+#define OMAP4430_RM_L4PER_MCASP2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xD4)
+#define OMAP4430_PM_L4PER_MCASP3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xD8)
+#define OMAP4430_RM_L4PER_MCASP3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xDC)
+#define OMAP4430_PM_L4PER_MCBSP4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xE0)
+#define OMAP4430_RM_L4PER_MCBSP4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xE4)
+#define OMAP4430_RM_L4PER_MGATE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xEC)
+#define OMAP4430_PM_L4PER_MCSPI1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xF0)
+#define OMAP4430_RM_L4PER_MCSPI1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xF4)
+#define OMAP4430_PM_L4PER_MCSPI2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xF8)
+#define OMAP4430_RM_L4PER_MCSPI2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0xFC)
+#define OMAP4430_PM_L4PER_MCSPI3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x100)
+#define OMAP4430_RM_L4PER_MCSPI3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x104)
+#define OMAP4430_PM_L4PER_MCSPI4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x108)
+#define OMAP4430_RM_L4PER_MCSPI4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x10C)
+#define OMAP4430_PM_L4PER_MMCSD3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x120)
+#define OMAP4430_RM_L4PER_MMCSD3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x124)
+#define OMAP4430_PM_L4PER_MMCSD4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x128)
+#define OMAP4430_RM_L4PER_MMCSD4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x12C)
+#define OMAP4430_RM_L4PER_MSPROHG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x134)
+#define OMAP4430_PM_L4PER_SLIMBUS2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x138)
+#define OMAP4430_RM_L4PER_SLIMBUS2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x13C)
+#define OMAP4430_PM_L4PER_UART1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x140)
+#define OMAP4430_RM_L4PER_UART1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x144)
+#define OMAP4430_PM_L4PER_UART2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x148)
+#define OMAP4430_RM_L4PER_UART2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x14C)
+#define OMAP4430_PM_L4PER_UART3_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x150)
+#define OMAP4430_RM_L4PER_UART3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x154)
+#define OMAP4430_PM_L4PER_UART4_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x158)
+#define OMAP4430_RM_L4PER_UART4_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x15C)
+#define OMAP4430_PM_L4PER_MMCSD5_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x160)
+#define OMAP4430_RM_L4PER_MMCSD5_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x164)
+#define OMAP4430_RM_L4SEC_AES1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1A4)
+#define OMAP4430_RM_L4SEC_AES2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1AC)
+#define OMAP4430_RM_L4SEC_DES3DES_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1B4)
+#define OMAP4430_RM_L4SEC_PKAEIP29_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1BC)
+#define OMAP4430_RM_L4SEC_RNG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1C4)
+#define OMAP4430_RM_L4SEC_SHA2MD51_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1CC)
+#define OMAP4430_RM_L4SEC_CRYPTODMA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_L4PER_MOD, 0x1DC)
+#define OMAP4430_RM_WKUP_L4WKUP_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x24)
+#define OMAP4430_RM_WKUP_WDT1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x2C)
+#define OMAP4430_PM_WKUP_WDT2_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x30)
+#define OMAP4430_RM_WKUP_WDT2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x34)
+#define OMAP4430_PM_WKUP_GPIO1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x38)
+#define OMAP4430_RM_WKUP_GPIO1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x3C)
+#define OMAP4430_PM_WKUP_TIMER1_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x40)
+#define OMAP4430_RM_WKUP_TIMER1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x44)
+#define OMAP4430_PM_WKUP_TIMER12_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x48)
+#define OMAP4430_RM_WKUP_TIMER12_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x4C)
+#define OMAP4430_RM_WKUP_SYNCTIMER_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x54)
+#define OMAP4430_PM_WKUP_USIM_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x58)
+#define OMAP4430_RM_WKUP_USIM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x5C)
+#define OMAP4430_RM_WKUP_SARRAM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x64)
+#define OMAP4430_PM_WKUP_KEYBOARD_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x78)
+#define OMAP4430_RM_WKUP_KEYBOARD_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x7C)
+#define OMAP4430_PM_WKUP_RTC_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x80)
+#define OMAP4430_RM_WKUP_RTC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_MOD, 0x84)
+#define OMAP4430_PM_MPU_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_MPU_MOD, 0x0)
+#define OMAP4430_PM_MPU_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_MPU_MOD, 0x4)
+#define OMAP4430_RM_MPU_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_MPU_MOD, 0x14)
+#define OMAP4430_RM_MPU_MPU_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_MPU_MOD, 0x24)
+#define OMAP4430_PM_TESLA_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DSP_MOD, 0x0)
+#define OMAP4430_PM_TESLA_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_DSP_MOD, 0x4)
+#define OMAP4430_RM_TESLA_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DSP_MOD, 0x10)
+#define OMAP4430_RM_TESLA_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_DSP_MOD, 0x14)
+#define OMAP4430_RM_TESLA_TESLA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_DSP_MOD, 0x24)
+#define OMAP4430_PM_IVAHD_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x0)
+#define OMAP4430_PM_IVAHD_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x4)
+#define OMAP4430_RM_IVAHD_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x10)
+#define OMAP4430_RM_IVAHD_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x14)
+#define OMAP4430_RM_IVAHD_IVAHD_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x24)
+#define OMAP4430_RM_IVAHD_SL2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x2C)
+#define OMAP4430_PM_CORE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CORE_MOD, 0x0)
+#define OMAP4430_PM_CORE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_CORE_MOD, 0x4)
+#define OMAP4430_RM_L3_1_L3_1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x24)
+#define OMAP4430_RM_L3_2_L3_2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x124)
+#define OMAP4430_RM_L3_2_GPMC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x12C)
+#define OMAP4430_RM_L3_2_OCMC_RAM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x134)
+#define OMAP4430_RM_DUCATI_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x210)
+#define OMAP4430_RM_DUCATI_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x214)
+#define OMAP4430_RM_DUCATI_DUCATI_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x224)
+#define OMAP4430_RM_SDMA_SDMA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x324)
+#define OMAP4430_RM_MEMIF_DMM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x424)
+#define OMAP4430_RM_MEMIF_EMIF_FW_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x42C)
+#define OMAP4430_RM_MEMIF_EMIF_1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x434)
+#define OMAP4430_RM_MEMIF_EMIF_2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x43C)
+#define OMAP4430_RM_MEMIF_DLL_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x444)
+#define OMAP4430_RM_MEMIF_EMIF_H1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x454)
+#define OMAP4430_RM_MEMIF_EMIF_H2_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x45C)
+#define OMAP4430_RM_MEMIF_DLL_H_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x464)
+#define OMAP4430_RM_D2D_SAD2D_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x524)
+#define OMAP4430_RM_D2D_MODEM_ICR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x52C)
+#define OMAP4430_RM_L4CFG_L4_CFG_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x624)
+#define OMAP4430_RM_L4CFG_HW_SEM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x62C)
+#define OMAP4430_RM_L4CFG_MAILBOX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x634)
+#define OMAP4430_RM_L4CFG_SAR_ROM_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x63C)
+#define OMAP4430_RM_L3INSTR_L3_3_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x724)
+#define OMAP4430_RM_L3INSTR_L3_INSTR_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x72C)
+#define OMAP4430_RM_L3INSTR_OCP_WP1_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_IVAHD_MOD, 0x744)
+#define OMAP4430_REVISION_PRM OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x0)
+#define OMAP4430_PRM_IRQSTATUS_MPU OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x10)
+#define OMAP4430_PRM_IRQENABLE_MPU OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x18)
+#define OMAP4430_PRM_IRQSTATUS_DUCATI OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x20)
+#define OMAP4430_PRM_IRQENABLE_DUCATI OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x28)
+#define OMAP4430_PRM_IRQSTATUS_TESLA OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x30)
+#define OMAP4430_PRM_IRQENABLE_TESLA OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x38)
+#define OMAP4430_PRM_PRM_PROFILING_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_OCP_SOCKET_MOD, 0x40)
+#define OMAP4430_RM_ALWON_MDMINTC_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x24)
+#define OMAP4430_PM_ALWON_SR_MPU_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x28)
+#define OMAP4430_RM_ALWON_SR_MPU_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x2C)
+#define OMAP4430_PM_ALWON_SR_IVA_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x30)
+#define OMAP4430_RM_ALWON_SR_IVA_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x34)
+#define OMAP4430_PM_ALWON_SR_CORE_WKDEP OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x38)
+#define OMAP4430_RM_ALWON_SR_CORE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_ALWAYS_ON_MOD, 0x3C)
+#define OMAP4430_PM_CAM_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CAM_MOD, 0x0)
+#define OMAP4430_PM_CAM_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_CAM_MOD, 0x4)
+#define OMAP4430_RM_CAM_ISS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_CAM_MOD, 0x24)
+#define OMAP4430_RM_CAM_FDIF_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_CAM_MOD, 0x2C)
+#define OMAP4430_PM_GFX_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_GFX_MOD, 0x0)
+#define OMAP4430_PM_GFX_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_GFX_MOD, 0x4)
+#define OMAP4430_RM_GFX_GFX_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_GFX_MOD, 0x24)
+#define OMAP4430_PM_EMU_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_EMU_MOD, 0x0)
+#define OMAP4430_PM_EMU_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_EMU_MOD, 0x4)
+#define OMAP4430_RM_EMU_DEBUGSS_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_EMU_MOD, 0x24)
+#define OMAP4430_PM_CEFUSE_PWRSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_CEFUSE_MOD, 0x0)
+#define OMAP4430_PM_CEFUSE_PWRSTST OMAP44XX_PRM_REGADDR(OMAP4430_CEFUSE_MOD, 0x4)
+#define OMAP4430_RM_CEFUSE_CEFUSE_CONTEXT OMAP44XX_PRM_REGADDR(OMAP4430_CEFUSE_MOD, 0x24)
+#define OMAP4430_PRM_RSTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x0)
+#define OMAP4430_PRM_RSTST OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x4)
+#define OMAP4430_PRM_RSTTIME OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x8)
+#define OMAP4430_PRM_CLKREQCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xC)
+#define OMAP4430_PRM_VOLTCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x10)
+#define OMAP4430_PRM_PWRREQCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x14)
+#define OMAP4430_PRM_PSCON_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x18)
+#define OMAP4430_PRM_IO_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x1C)
+#define OMAP4430_PRM_IO_PMCTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x20)
+#define OMAP4430_PRM_VOLTSETUP_CORE_OFF OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x24)
+#define OMAP4430_PRM_VOLTSETUP_MPU_OFF OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x28)
+#define OMAP4430_PRM_VOLTSETUP_IVA_OFF OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x2C)
+#define OMAP4430_PRM_VOLTSETUP_CORE_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x30)
+#define OMAP4430_PRM_VOLTSETUP_MPU_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x34)
+#define OMAP4430_PRM_VOLTSETUP_IVA_RET_SLEEP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x38)
+#define OMAP4430_PRM_VP_CORE_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x3C)
+#define OMAP4430_PRM_VP_CORE_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x40)
+#define OMAP4430_PRM_VP_CORE_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x44)
+#define OMAP4430_PRM_VP_CORE_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x48)
+#define OMAP4430_PRM_VP_CORE_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x4C)
+#define OMAP4430_PRM_VP_CORE_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x50)
+#define OMAP4430_PRM_VP_MPU_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x54)
+#define OMAP4430_PRM_VP_MPU_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x58)
+#define OMAP4430_PRM_VP_MPU_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x5C)
+#define OMAP4430_PRM_VP_MPU_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x60)
+#define OMAP4430_PRM_VP_MPU_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x64)
+#define OMAP4430_PRM_VP_MPU_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x68)
+#define OMAP4430_PRM_VP_IVA_CONFIG OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x6C)
+#define OMAP4430_PRM_VP_IVA_STATUS OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x70)
+#define OMAP4430_PRM_VP_IVA_VLIMITTO OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x74)
+#define OMAP4430_PRM_VP_IVA_VOLTAGE OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x78)
+#define OMAP4430_PRM_VP_IVA_VSTEPMAX OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x7C)
+#define OMAP4430_PRM_VP_IVA_VSTEPMIN OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x80)
+#define OMAP4430_PRM_VC_SMPS_SA OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x84)
+#define OMAP4430_PRM_VC_VAL_SMPS_RA_VOL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x88)
+#define OMAP4430_PRM_VC_VAL_SMPS_RA_CMD OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x8C)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_CORE_L OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x90)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_MPU_L OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x94)
+#define OMAP4430_PRM_VC_VAL_CMD_VDD_IVA_L OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x98)
+#define OMAP4430_PRM_VC_VAL_BYPASS OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0x9C)
+#define OMAP4430_PRM_VC_CFG_CHANNEL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xA0)
+#define OMAP4430_PRM_VC_CFG_I2C_MODE OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xA4)
+#define OMAP4430_PRM_VC_CFG_I2C_CLK OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xA8)
+#define OMAP4430_PRM_SRAM_COUNT OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xAC)
+#define OMAP4430_PRM_SRAM_WKUP_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xB0)
+#define OMAP4430_PRM_LDO_SRAM_CORE_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xB4)
+#define OMAP4430_PRM_LDO_SRAM_CORE_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xB8)
+#define OMAP4430_PRM_LDO_SRAM_MPU_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xBC)
+#define OMAP4430_PRM_LDO_SRAM_MPU_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xC0)
+#define OMAP4430_PRM_LDO_SRAM_IVA_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xC4)
+#define OMAP4430_PRM_LDO_SRAM_IVA_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xC8)
+#define OMAP4430_PRM_LDO_ABB_MPU_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xCC)
+#define OMAP4430_PRM_LDO_ABB_MPU_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xD0)
+#define OMAP4430_PRM_LDO_ABB_IVA_SETUP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xD4)
+#define OMAP4430_PRM_LDO_ABB_IVA_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xD8)
+#define OMAP4430_PRM_LDO_BANDGAP_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xDC)
+#define OMAP4430_PRM_DEVICE_OFF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xE0)
+#define OMAP4430_PRM_RESTORE_ST OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xE4)
+#define OMAP4430_PRM_PHASE1_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xE8)
+#define OMAP4430_PRM_PHASE2A_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xEC)
+#define OMAP4430_PRM_PHASE2B_CNDP OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xF0)
+#define OMAP4430_PRM_MODEM_IF_CTRL OMAP44XX_PRM_REGADDR(OMAP4430_DEVICE_MOD, 0xF4)
+#define OMAP4430_CM_WKUP_GPTIMER1_CLKCTRL OMAP44XX_PRM_REGADDR(OMAP4430_WKUP_CM_MOD, 0x40)
+
/*
* Module specific PRM registers from PRM_BASE + domain offset
*
@@ -173,9 +475,11 @@
/* Registers appearing on both 24xx and 34xx */
-#define RM_RSTCTRL 0x0050
-#define RM_RSTTIME 0x0054
-#define RM_RSTST 0x0058
+#define OMAP2_RM_RSTCTRL 0x0050
+#define OMAP2_RM_RSTTIME 0x0054
+#define OMAP2_RM_RSTST 0x0058
+#define OMAP2_PM_PWSTCTRL 0x00e0
+#define OMAP2_PM_PWSTST 0x00e4
#define PM_WKEN 0x00a0
#define PM_WKEN1 PM_WKEN
@@ -185,8 +489,6 @@
#define PM_EVGENCTRL 0x00d4
#define PM_EVGENONTIM 0x00d8
#define PM_EVGENOFFTIM 0x00dc
-#define PM_PWSTCTRL 0x00e0
-#define PM_PWSTST 0x00e4
/* Omap2 specific registers */
#define OMAP24XX_PM_WKEN2 0x00a4
@@ -214,6 +516,13 @@
#define OMAP3430_PRM_IRQSTATUS_IVA2 0x00f8
#define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc
+/* Omap4 specific registers */
+#define OMAP4_RM_RSTCTRL 0x0000
+#define OMAP4_RM_RSTTIME 0x0004
+#define OMAP4_RM_RSTST 0x0008
+#define OMAP4_PM_PWSTCTRL 0x0000
+#define OMAP4_PM_PWSTST 0x0004
+
#ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 436dd5083174..c3504259c8b8 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -29,6 +29,11 @@
#include <mach/clock.h>
#include <mach/control.h>
+#ifdef CONFIG_SERIAL_OMAP
+#include <mach/dma.h>
+#include <mach/omap-serial.h>
+#endif
+
#include "prm.h"
#include "pm.h"
#include "prm-regbits-34xx.h"
@@ -37,6 +42,7 @@
#define DEFAULT_TIMEOUT (5 * HZ)
+#ifdef CONFIG_SERIAL_8250
struct omap_uart_state {
int num;
int can_sleep;
@@ -109,6 +115,16 @@ static struct plat_serial8250_port serial_platform_data2[] = {
.regshift = 2,
.uartclk = OMAP24XX_BASE_BAUD * 16,
}, {
+#ifdef CONFIG_ARCH_OMAP4
+ .membase = IO_ADDRESS(OMAP_UART4_BASE),
+ .mapbase = OMAP_UART4_BASE,
+ .irq = 70,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = OMAP24XX_BASE_BAUD * 16,
+ }, {
+#endif
.flags = 0
}
};
@@ -606,20 +622,21 @@ void __init omap_serial_init(void)
continue;
}
- sprintf(name, "uart%d_ick", i+1);
- uart->ick = clk_get(NULL, name);
- if (IS_ERR(uart->ick)) {
- printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
- uart->ick = NULL;
- }
+ if (!cpu_is_omap44xx()) {
+ sprintf(name, "uart%d_ick", i+1);
+ uart->ick = clk_get(NULL, name);
+ if (IS_ERR(uart->ick)) {
+ printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
+ uart->ick = NULL;
+ }
- sprintf(name, "uart%d_fck", i+1);
- uart->fck = clk_get(NULL, name);
- if (IS_ERR(uart->fck)) {
- printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
- uart->fck = NULL;
+ sprintf(name, "uart%d_fck", i+1);
+ uart->fck = clk_get(NULL, name);
+ if (IS_ERR(uart->fck)) {
+ printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
+ uart->fck = NULL;
+ }
}
-
/* FIXME: Remove this once the clkdev is ready */
if (!cpu_is_omap44xx()) {
if (!uart->ick || !uart->fck)
@@ -647,3 +664,198 @@ void __init omap_serial_init(void)
}
}
}
+#endif
+
+#ifdef CONFIG_SERIAL_OMAP
+static struct uart_dma_info uart1_dma_state = {
+#ifdef CONFIG_SERIAL_OMAP_DMA_UART1
+ .dma_enabled = 1,
+ .rx_dma_bufsize =
+ CONFIG_SERIAL_OMAP_UART1_RXDMA_BUFSIZE,
+ .rx_timeout =
+ CONFIG_SERIAL_OMAP_UART1_RXDMA_TIMEOUT,
+#endif
+};
+
+static struct uart_dma_info uart2_dma_state = {
+#ifdef CONFIG_SERIAL_OMAP_DMA_UART2
+ .dma_enabled = 1,
+ .rx_dma_bufsize =
+ CONFIG_SERIAL_OMAP_UART2_RXDMA_BUFSIZE,
+ .rx_timeout =
+ CONFIG_SERIAL_OMAP_UART2_RXDMA_TIMEOUT,
+#endif
+};
+
+static struct uart_dma_info uart3_dma_state = {
+#ifdef CONFIG_SERIAL_OMAP_DMA_UART3
+ .dma_enabled = 1,
+ .rx_dma_bufsize =
+ CONFIG_SERIAL_OMAP_UART3_RXDMA_BUFSIZE,
+ .rx_timeout =
+ CONFIG_SERIAL_OMAP_UART3_RXDMA_TIMEOUT,
+#endif
+};
+
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct uart_dma_info uart4_dma_state = {
+#ifdef CONFIG_SERIAL_OMAP_DMA_UART4
+ .dma_enabled = 1,
+ .rx_dma_bufsize =
+ CONFIG_SERIAL_OMAP_UART4_RXDMA_BUFSIZE,
+ .rx_timeout =
+ CONFIG_SERIAL_OMAP_UART4_RXDMA_TIMEOUT,
+#endif
+};
+#endif
+
+static struct resource omap2_uart1_resources[] = {
+ {
+ .start = OMAP_UART1_BASE,
+ .end = OMAP_UART1_BASE + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ /* UART1 IRQ - 72*/
+ .start = INT_24XX_UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ /* UART1 TX DMA CHANNEL -S_DMA_48- */
+ .start = OMAP24XX_DMA_UART1_TX,
+ .flags = IORESOURCE_DMA,
+ }, {
+ /* UART1 RX DMA CHANNEL -S_DMA_49- */
+ .start = OMAP24XX_DMA_UART1_RX,
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static struct resource omap2_uart2_resources[] = {
+ {
+ .start = OMAP_UART2_BASE,
+ .end = OMAP_UART2_BASE + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ /* UART2 IRQ - 73*/
+ .start = INT_24XX_UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ /* UART2 TX DMA CHANNEL -S_DMA_50- */
+ .start = OMAP24XX_DMA_UART2_TX,
+ .flags = IORESOURCE_DMA,
+ }, {
+ /* UART2 RX DMA CHANNEL -S_DMA_51- */
+ .start = OMAP24XX_DMA_UART2_RX,
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static struct resource omap2_uart3_resources[] = {
+ {
+ .start = OMAP_UART3_BASE,
+ .end = OMAP_UART3_BASE + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ /* UART3 IRQ - 74*/
+ .start = INT_24XX_UART3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ /* UART3 TX DMA CHANNEL -S_DMA_52- */
+ .start = OMAP24XX_DMA_UART3_TX,
+ .flags = IORESOURCE_DMA,
+ }, {
+ /* UART3 RX DMA CHANNEL -S_DMA_53- */
+ .start = OMAP24XX_DMA_UART3_RX,
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct resource omap2_uart4_resources[] = {
+ {
+ .start = OMAP_UART4_BASE,
+ .end = OMAP_UART4_BASE + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ /* UART4 IRQ */
+ .start = 70,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ /* UART4 TX DMA CHANNEL -S_DMA_54- */
+ .start = OMAP44XX_DMA_UART4_DMA_TX,
+ .flags = IORESOURCE_DMA,
+ }, {
+ /* UART4 RX DMA CHANNEL -S_DMA_55- */
+ .start = OMAP44XX_DMA_UART4_DMA_RX,
+ .flags = IORESOURCE_DMA,
+ }
+};
+#endif
+
+/* OMAP UART platform structure */
+static struct platform_device uart1_device = {
+ .name = "omap-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(omap2_uart1_resources),
+ .resource = omap2_uart1_resources,
+ .dev = {
+ .platform_data = &uart1_dma_state,
+ },
+};
+static struct platform_device uart2_device = {
+ .name = "omap-uart",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(omap2_uart2_resources),
+ .resource = omap2_uart2_resources,
+ .dev = {
+ .platform_data = &uart2_dma_state,
+ },
+};
+static struct platform_device uart3_device = {
+ .name = "omap-uart",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(omap2_uart3_resources),
+ .resource = omap2_uart3_resources,
+ .dev = {
+ .platform_data = &uart3_dma_state,
+ },
+};
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct platform_device uart4_device = {
+ .name = "omap-uart",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(omap2_uart4_resources),
+ .resource = omap2_uart4_resources,
+ .dev = {
+ .platform_data = &uart4_dma_state,
+ },
+};
+#endif
+
+static struct platform_device *uart_devices[] = {
+ &uart1_device,
+ &uart2_device,
+ &uart3_device,
+#ifdef CONFIG_ARCH_OMAP4
+ &uart4_device,
+#endif
+};
+
+void __init omap_serial_init(void)
+{
+ int ret = 0, i;
+
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx())
+ omap_serial_early_init();
+
+ for (i = 0; i < OMAP_MAX_NR_PORTS; i++)
+ omap_uart_idle_init(i);
+
+ ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
+}
+#endif
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index e5e2553e79a6..4c223b2dfebd 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -36,7 +36,7 @@
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 PM_PWSTCTRL_MPU_P OMAP34XX_PRM_REGADDR(MPU_MOD, OMAP2_PM_PWSTCTRL)
#define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is
* available */
#define SCRATCHPAD_BASE_P OMAP343X_CTRL_REGADDR(\
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index efe85d095190..e7ac4f7b9688 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -27,6 +27,7 @@ config ARCH_OMAP4
bool "TI OMAP4"
select CPU_V7
select ARM_GIC
+ select COMMON_CLKDEV
endchoice
@@ -118,8 +119,9 @@ config OMAP_MBOX_FWK
DSP, IVA1.0 and IVA2 in OMAP1/2/3.
config OMAP_IOMMU
- tristate
-
+ tristate "iommu"
+ depends on ARCH_OMAP
+ default y
choice
prompt "System timer"
default OMAP_MPU_TIMER
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index a83279523958..cfc0967df153 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -4,7 +4,7 @@
# Common support
obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
- usb.o fb.o io.o
+ usb.o fb.o vram.o vrfb.o io.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index e8c327a45a55..972694b217fe 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -40,36 +40,10 @@ static struct clk_functions *arch_clock;
* clock framework is not up , it is defined here to avoid rework in
* every driver. Also dummy prcm reset function is added */
-/* Dummy hooks only for OMAP4.For rest OMAPs, common clkdev is used */
-#if defined(CONFIG_ARCH_OMAP4)
-struct clk *clk_get(struct device *dev, const char *id)
-{
- return NULL;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-void omap2_clk_prepare_for_reboot(void)
-{
-}
-EXPORT_SYMBOL(omap2_clk_prepare_for_reboot);
-
-void omap_prcm_arch_reset(char mode)
-{
-}
-EXPORT_SYMBOL(omap_prcm_arch_reset);
-#endif
int clk_enable(struct clk *clk)
{
unsigned long flags;
int ret = 0;
- if (cpu_is_omap44xx())
- /* OMAP4 clk framework not supported yet */
- return 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index ebcf006406f9..e848a12ce616 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -372,12 +372,14 @@ static struct omap_globals omap4_globals = {
.ctrl = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE),
.prm = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE),
.cm = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE),
+ .cm2 = OMAP2_IO_ADDRESS(OMAP4430_CM2_BASE),
};
void __init omap2_set_globals_443x(void)
{
omap2_set_globals_tap(&omap4_globals);
omap2_set_globals_control(&omap4_globals);
+ omap2_set_globals_prcm(&omap4_globals);
}
#endif
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index a64b692a1bfe..2ab6077dd4f8 100644..100755
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/bootmem.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -90,6 +91,32 @@ EXPORT_SYMBOL(dsp_kfunc_device_register);
static inline void omap_init_dsp(void) { }
#endif /* CONFIG_OMAP_DSP */
+#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
+static unsigned long dspbridge_phys_mempool_base;
+void dspbridge_reserve_sdram(void)
+{
+ void *va;
+ unsigned long size = CONFIG_BRIDGE_MEMPOOL_SIZE;
+
+ if (!size)
+ return;
+
+ va = __alloc_bootmem_nopanic(size, SZ_1M, 0);
+ if (!va) {
+ pr_err("%s: Failed to bootmem allocation(%lu bytes)\n",
+ __func__, size);
+ return;
+ }
+ dspbridge_phys_mempool_base = virt_to_phys(va);
+}
+
+unsigned long dspbridge_get_mempool_base(void)
+{
+ return dspbridge_phys_mempool_base;
+}
+EXPORT_SYMBOL(dspbridge_get_mempool_base);
+#endif
+
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
@@ -357,6 +384,42 @@ static void omap_init_rng(void)
static inline void omap_init_rng(void) {}
#endif
+#ifdef CONFIG_ARCH_OMAP4
+#define NUM_VOUT_RESOURCES 4
+#else
+#define NUM_VOUT_RESOURCES 3
+#endif
+
+#if defined(CONFIG_VIDEO_OMAP_VIDEOOUT) || \
+ defined(CONFIG_VIDEO_OMAP_VIDEOOUT_MODULE)
+
+#ifdef CONFIG_FB_OMAP2
+static struct resource
+ sdp4430_vout_resource[NUM_VOUT_RESOURCES - CONFIG_FB_OMAP2_NUM_FBS]
+ = {
+ };
+#else
+static struct resource sdp4430_vout_resource[NUM_VOUT_RESOURCES - 1] = {
+};
+#endif
+
+#undef NUM_VOUT_RESOURCES
+
+static struct platform_device sdp4430_vout_device = {
+ .name = "omap_vout",
+ .num_resources = ARRAY_SIZE(sdp4430_vout_resource),
+ .resource = &sdp4430_vout_resource[0],
+ .id = -1,
+};
+
+static void omap_init_vout(void)
+{
+ (void) platform_device_register(&sdp4430_vout_device);
+}
+#else
+static inline void omap_init_vout(void) {}
+#endif
+
/*
* This gets called after board-specific INIT_MACHINE, and initializes most
* on-chip peripherals accessible on this board (except for few like USB):
@@ -387,6 +450,7 @@ static int __init omap_init_devices(void)
omap_init_uwire();
omap_init_wdt();
omap_init_rng();
+ omap_init_vout();
return 0;
}
arch_initcall(omap_init_devices);
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index e3ac94f09006..d5760c777164 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/dma-mapping.h>
#include <asm/system.h>
#include <mach/hardware.h>
@@ -46,13 +47,42 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
#endif
+/* CDP Register bitmaps */
+#define DMA_LIST_CDP_DST_VALID (BIT(0))
+#define DMA_LIST_CDP_SRC_VALID (BIT(2))
+#define DMA_LIST_CDP_TYPE1 (BIT(4))
+#define DMA_LIST_CDP_TYPE2 (BIT(5))
+#define DMA_LIST_CDP_TYPE3 (BIT(4) | BIT(5))
+#define DMA_LIST_CDP_PAUSEMODE (BIT(7))
+#define DMA_LIST_CDP_LISTMODE (BIT(8))
+#define DMA_LIST_CDP_FASTMODE (BIT(10))
+/* CAPS register bitmaps */
+#define DMA_CAPS_SGLIST_SUPPORT (BIT(20))
+
+#define DMA_LIST_DESC_PAUSE (BIT(0))
+#define DMA_LIST_DESC_SRC_VALID (BIT(24))
+#define DMA_LIST_DESC_DST_VALID (BIT(26))
+#define DMA_LIST_DESC_BLK_END (BIT(28))
+
#define OMAP_DMA_ACTIVE 0x01
#define OMAP_DMA_CCR_EN (1 << 7)
#define OMAP2_DMA_CSR_CLEAR_MASK 0xffe
#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
+#define OMAP_DMA_INVALID_FRAME_COUNT (0xffff)
+#define OMAP_DMA_INVALID_ELEM_COUNT (0xffffff)
+#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER (0xfffffffc)
static int enable_1510_mode;
+static int dma_caps0_status;
+
+struct omap_dma_list_config_params {
+ int chid;
+ int num_elem;
+ struct omap_dma_sglist_node *sghead;
+ int sgheadphy;
+ int pausenode;
+};
struct omap_dma_lch {
int next_lch;
@@ -72,6 +102,8 @@ struct omap_dma_lch {
int status;
#endif
+
+ void *list_config;
long flags;
};
@@ -209,6 +241,12 @@ static void clear_lch_regs(int lch)
__raw_writew(0, lch_base + i);
}
+static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
+ int value)
+{
+ node->num_of_elem |= ((value) << 29);
+}
+
void omap_set_dma_priority(int lch, int dst_port, int priority)
{
unsigned long reg;
@@ -1789,6 +1827,269 @@ EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
#endif /* ifndef CONFIG_ARCH_OMAP1 */
/*----------------------------------------------------------------------------*/
+int omap_request_dma_sglist(int dev_id, const char *dev_name,
+ void (*callback) (int channel_id, u16 ch_status, void *data),
+ int *listid, int nelem, struct omap_dma_sglist_node **elems)
+{
+ struct omap_dma_list_config_params *lcfg;
+ struct omap_dma_sglist_node *desc;
+ int dma_lch;
+ int rc, i;
+
+ if (unlikely((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0)) {
+ printk(KERN_ERR "omap DMA: sglist feature not supported\n");
+ return -EPERM;
+ }
+ if (unlikely(nelem <= 2)) {
+ printk(KERN_ERR "omap DMA: Need >2 elements in the list\n");
+ return -EINVAL;
+ }
+ rc = omap_request_dma(dev_id, dev_name,
+ callback, NULL, &dma_lch);
+ if (rc < 0) {
+ printk(KERN_ERR "omap_dma_list: Request failed %d\n", rc);
+ return rc;
+ }
+ *listid = dma_lch;
+ dma_chan[dma_lch].state = DMA_CH_NOTSTARTED;
+ lcfg = kmalloc(sizeof(*lcfg), GFP_KERNEL);
+ if (NULL == lcfg)
+ goto error1;
+ dma_chan[dma_lch].list_config = lcfg;
+
+ lcfg->num_elem = nelem;
+
+ *elems = desc = lcfg->sghead = dma_alloc_coherent(NULL,
+ sizeof(*desc), &(lcfg->sgheadphy), 0);
+ if (NULL == desc)
+ goto error1;
+
+ for (i = 1; i < nelem; i++) {
+ desc->next = dma_alloc_coherent(NULL,
+ sizeof(*(desc->next)), &(desc->next_desc_add_ptr), 0);
+ if (NULL == desc->next)
+ goto error1;
+ desc = desc->next;
+ desc->next = NULL;
+ }
+ desc->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
+
+ dma_write(0, CCDN(dma_lch)); /* Reset List index numbering */
+ /* Initialize frame and element counters to invalid values */
+ dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN(dma_lch));
+ dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN(dma_lch));
+ return 0;
+
+error1:
+ omap_release_dma_sglist(dma_lch);
+ return -ENOMEM;
+
+}
+EXPORT_SYMBOL(omap_request_dma_sglist);
+
+/* The client can choose to not preconfigure the DMA registers
+ * In fast mode,the DMA controller uses the first element in the list to
+ * program the registers first, and then starts the transfer
+ */
+
+int omap_set_dma_sglist_params(const int listid,
+ struct omap_dma_sglist_node *sghead,
+ struct omap_dma_channel_params *chparams)
+{
+ struct omap_dma_list_config_params *lcfg;
+ struct omap_dma_sglist_node *sgitcurr, *sgitprev;
+ int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */
+
+ lcfg = dma_chan[listid].list_config;
+ if (lcfg->sghead != sghead) {
+ printk(KERN_ERR "Unknown config pointer passed\n");
+ return -EPERM;
+ }
+
+ if (NULL == chparams)
+ l |= DMA_LIST_CDP_FASTMODE;
+ else
+ omap_set_dma_params(listid, chparams);
+ /* The client can set the dma params and still use fast mode
+ * by using the set fast mode api
+ */
+ dma_write(l, CDP(listid));
+
+ sgitprev = sghead;
+ sgitcurr = sgitprev->next;
+
+ while (sgitcurr != NULL) {
+ switch (sgitcurr->desc_type) {
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+ omap_dma_list_set_ntype(sgitprev, 1);
+ break;
+
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+ /* intentional no break */
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+ omap_dma_list_set_ntype(sgitprev, 2);
+ break;
+
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+ /* intentional no break */
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+ omap_dma_list_set_ntype(sgitprev, 3);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (sgitcurr->flags & OMAP_DMA_LIST_SRC_VALID)
+ sgitprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
+ if (sgitcurr->flags & OMAP_DMA_LIST_DST_VALID)
+ sgitprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
+ if (sgitcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
+ sgitprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
+
+ sgitprev = sgitcurr;
+ sgitcurr = sgitcurr->next;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_set_dma_sglist_params);
+
+int omap_start_dma_sglist_transfers(const int listid, const int pauseafter)
+{
+ struct omap_dma_list_config_params *lcfg;
+ struct omap_dma_sglist_node *sgn;
+ unsigned int l, type_id;
+
+ lcfg = dma_chan[listid].list_config;
+ lcfg->pausenode = 0;
+ sgn = lcfg->sghead;
+ if (pauseafter > 0 && pauseafter <= lcfg->num_elem) {
+ for (l = 0; l < pauseafter; l++)
+ sgn = sgn->next;
+ sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
+ lcfg->pausenode = pauseafter;
+ }
+
+ /* Program the head descriptor's properties into CDP */
+ switch (lcfg->sghead->desc_type) {
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+ type_id = DMA_LIST_CDP_TYPE1;
+ break;
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+ type_id = DMA_LIST_CDP_TYPE2;
+ break;
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+ type_id = DMA_LIST_CDP_TYPE3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ l = dma_read(CDP(listid));
+ l |= type_id;
+ if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID)
+ l |= DMA_LIST_CDP_SRC_VALID;
+ if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID)
+ l |= DMA_LIST_CDP_DST_VALID;
+
+ dma_write(l, CDP(listid));
+
+ dma_write((lcfg->sgheadphy), CNDP(listid));
+ printk(KERN_DEBUG "Start list transfer for list %x\n",
+ lcfg->sgheadphy);
+ omap_start_dma(listid);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_sglist_transfers);
+
+int omap_resume_dma_sglist_transfers(const int listid, const int pauseafter)
+{
+ struct omap_dma_list_config_params *lcfg;
+ struct omap_dma_sglist_node *sgn;
+ int l;
+
+ lcfg = dma_chan[listid].list_config;
+ sgn = lcfg->sghead;
+ /* Clear the previous pause, if any */
+ lcfg->pausenode = 0;
+
+ if (pauseafter > 0 && pauseafter <= lcfg->num_elem) {
+ for (l = 0; l < pauseafter; l++)
+ sgn = sgn->next;
+ sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
+ lcfg->pausenode = pauseafter;
+ }
+
+ /* Clear pause bit in CDP */
+ l = dma_read(CDP(listid));
+ printk(KERN_DEBUG "Resuming after pause: CDP=%x\n", l);
+ l &= ~(DMA_LIST_CDP_PAUSEMODE);
+ dma_write(l, CDP(listid));
+ omap_start_dma(listid);
+ return 0;
+}
+EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
+
+int omap_release_dma_sglist(const int listid)
+{
+ struct omap_dma_list_config_params *lcfg;
+ struct omap_dma_sglist_node *sgn, *sgn2;
+
+ lcfg = dma_chan[listid].list_config;
+ sgn = lcfg->sghead;
+
+ if (NULL != sgn) {
+ sgn = sgn->next;
+ do {
+ sgn2 = sgn->next;
+ dma_free_coherent(NULL, sizeof(*sgn), sgn,
+ sgn->next_desc_add_ptr);
+ sgn = sgn2;
+ } while (sgn2 != NULL);
+
+ dma_free_coherent(NULL, sizeof(*(lcfg->sghead)),
+ lcfg->sghead, lcfg->sgheadphy);
+ }
+ if (NULL != dma_chan[listid].list_config)
+ kfree(dma_chan[listid].list_config);
+ dma_chan[listid].list_config = NULL;
+ omap_free_dma(listid);
+ return 0;
+}
+EXPORT_SYMBOL(omap_release_dma_sglist);
+
+int omap_get_completed_sglist_nodes(const int listid)
+{
+ int list_count;
+
+ list_count = dma_read(CCDN(listid));
+ return list_count & 0xffff; /* only 16 LSB bits are valid */
+}
+EXPORT_SYMBOL(omap_get_completed_sglist_nodes);
+
+int omap_dma_sglist_is_paused(const int listid)
+{
+ int list_state;
+
+ list_state = dma_read(CDP(listid));
+ return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0;
+}
+EXPORT_SYMBOL(omap_dma_sglist_is_paused);
+
+void omap_dma_set_sglist_fastmode(const int listid, const int fastmode)
+{
+ int l = dma_read(CDP(listid));
+
+ if (fastmode)
+ l |= DMA_LIST_CDP_FASTMODE;
+ else
+ l &= ~(DMA_LIST_CDP_FASTMODE);
+ dma_write(l, CDP(listid));
+}
+EXPORT_SYMBOL(omap_dma_set_sglist_fastmode);
+
#ifdef CONFIG_ARCH_OMAP1
@@ -2369,6 +2670,7 @@ static int __init omap_init_dma(void)
kfree(dma_chan);
return -ENOMEM;
}
+ dma_caps0_status = dma_read(CAPS_0);
}
if (cpu_is_omap15xx()) {
@@ -2420,6 +2722,7 @@ static int __init omap_init_dma(void)
omap_clear_dma(ch);
dma_chan[ch].dev_id = -1;
dma_chan[ch].next_lch = -1;
+ dma_chan[ch].list_config = NULL;
if (ch >= 6 && enable_1510_mode)
continue;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 3746222bed10..1dc34154d794 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -28,13 +28,13 @@
#include <linux/platform_device.h>
#include <linux/bootmem.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/hardware.h>
#include <asm/mach/map.h>
#include <mach/board.h>
#include <mach/sram.h>
-#include <mach/omapfb.h>
#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
@@ -327,6 +327,34 @@ static inline int omap_init_fb(void)
arch_initcall(omap_init_fb);
+#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+static struct omapfb_platform_data omapfb_config;
+
+static struct platform_device omap_fb_device = {
+ .name = "omapfb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &omap_fb_dma_mask,
+ .coherent_dma_mask = ~(u32)0,
+ .platform_data = &omapfb_config,
+ },
+ .num_resources = 0,
+};
+
+void omapfb_set_platform_data(struct omapfb_platform_data *data)
+{
+ omapfb_config = *data;
+}
+
+static inline int omap_init_fb(void)
+{
+ return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
#else
void omapfb_reserve_sdram(void) {}
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 9298bc0ab171..30f219fdb1b1 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -115,28 +115,65 @@
#define OMAP24XX_GPIO_REVISION 0x0000
#define OMAP24XX_GPIO_SYSCONFIG 0x0010
-#define OMAP24XX_GPIO_SYSSTATUS 0x0014
-#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
-#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
-#define OMAP24XX_GPIO_IRQENABLE2 0x002c
-#define OMAP24XX_GPIO_IRQENABLE1 0x001c
-#define OMAP24XX_GPIO_WAKE_EN 0x0020
-#define OMAP24XX_GPIO_CTRL 0x0030
-#define OMAP24XX_GPIO_OE 0x0034
-#define OMAP24XX_GPIO_DATAIN 0x0038
-#define OMAP24XX_GPIO_DATAOUT 0x003c
-#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
-#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
-#define OMAP24XX_GPIO_RISINGDETECT 0x0048
-#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
-#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050
-#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054
-#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
-#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
-#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
-#define OMAP24XX_GPIO_SETWKUENA 0x0084
-#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
-#define OMAP24XX_GPIO_SETDATAOUT 0x0094
+
+#ifdef CONFIG_ARCH_OMAP4
+#define OMAP24XX_GPIO_SYSSTATUS 0x0114
+#define OMAP24XX_GPIO_IRQSTATUS1 0x0118
+#define OMAP24XX_GPIO_IRQSTATUS2 0x0128
+#define OMAP24XX_GPIO_IRQENABLE2 0x012c
+#define OMAP24XX_GPIO_IRQENABLE1 0x011c
+#define OMAP24XX_GPIO_WAKE_EN 0x0120
+#define OMAP24XX_GPIO_CTRL 0x0130
+#define OMAP24XX_GPIO_OE 0x0134
+#define OMAP24XX_GPIO_DATAIN 0x0138
+#define OMAP24XX_GPIO_DATAOUT 0x013c
+#define OMAP24XX_GPIO_LEVELDETECT0 0x0140
+#define OMAP24XX_GPIO_LEVELDETECT1 0x0144
+#define OMAP24XX_GPIO_RISINGDETECT 0x0148
+#define OMAP24XX_GPIO_FALLINGDETECT 0x014c
+#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0150
+#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0154
+#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0160
+#define OMAP24XX_GPIO_SETIRQENABLE1 0x0164
+#define OMAP24XX_GPIO_CLEARWKUENA 0x0180
+#define OMAP24XX_GPIO_SETWKUENA 0x0184
+#define OMAP24XX_GPIO_CLEARDATAOUT 0x0190
+#define OMAP24XX_GPIO_SETDATAOUT 0x0194
+#define OMAP24XX_GPIO_STATUS_RAW_0 0x0024
+#define OMAP24XX_GPIO_STATUS_RAW_1 0x0028
+#define OMAP24XX_GPIO_IRQ_STATUS_0 0x002C
+#define OMAP24XX_GPIO_IRQ_STATUS_1 0x0030
+#define OMAP24XX_GPIO_IRQ_STATUS_SET_0 0x0034
+#define OMAP24XX_GPIO_IRQ_STATUS_SET_1 0x0038
+#define OMAP24XX_GPIO_IRQ_STATUS_CLR_0 0x003C
+#define OMAP24XX_GPIO_IRQ_STATUS_CLR_1 0x0040
+#define OMAP24XX_GPIO_IRQ_WAKE_ENABLE_0 0x0044
+#define OMAP24XX_GPIO_IRQ_WAKE_ENABLE_1 0x0048
+
+#else
+#define OMAP24XX_GPIO_SYSSTATUS 0x0014
+#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
+#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
+#define OMAP24XX_GPIO_IRQENABLE2 0x002c
+#define OMAP24XX_GPIO_IRQENABLE1 0x001c
+#define OMAP24XX_GPIO_WAKE_EN 0x0020
+#define OMAP24XX_GPIO_CTRL 0x0030
+#define OMAP24XX_GPIO_OE 0x0034
+#define OMAP24XX_GPIO_DATAIN 0x0038
+#define OMAP24XX_GPIO_DATAOUT 0x003c
+#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
+#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
+#define OMAP24XX_GPIO_RISINGDETECT 0x0048
+#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
+#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050
+#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054
+#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
+#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
+#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
+#define OMAP24XX_GPIO_SETWKUENA 0x0084
+#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
+#define OMAP24XX_GPIO_SETDATAOUT 0x0094
+#endif
/*
* omap34xx specific GPIO registers
@@ -829,11 +866,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
break;
#endif
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
- defined(CONFIG_ARCH_OMAP4)
+defined(CONFIG_ARCH_OMAP4)
case METHOD_GPIO_24XX:
+ #ifdef CONFIG_ARCH_OMAP4
+ reg += OMAP24XX_GPIO_IRQ_STATUS_0;
+ #else
reg += OMAP24XX_GPIO_IRQSTATUS1;
+ #endif
break;
#endif
+
default:
WARN_ON(1);
return;
@@ -841,14 +883,20 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
__raw_writel(gpio_mask, reg);
/* Workaround for clearing DSP GPIO interrupts to allow retention */
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+defined(CONFIG_ARCH_OMAP4)
+#ifdef CONFIG_ARCH_OMAP4
+ reg = bank->base + OMAP24XX_GPIO_IRQ_STATUS_1;
+#else
reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
+#endif
+ if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx())
__raw_writel(gpio_mask, reg);
/* Flush posted write for the irq status to avoid spurious interrupts */
__raw_readl(reg);
#endif
+
}
static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
@@ -901,7 +949,11 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
defined(CONFIG_ARCH_OMAP4)
case METHOD_GPIO_24XX:
+#ifdef CONFIG_ARCH_OMAP4
+ reg += OMAP24XX_GPIO_IRQ_STATUS_SET_0;
+#else
reg += OMAP24XX_GPIO_IRQENABLE1;
+#endif
mask = 0xffffffff;
break;
#endif
@@ -1160,7 +1212,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
defined(CONFIG_ARCH_OMAP4)
if (bank->method == METHOD_GPIO_24XX)
+ #ifdef CONFIG_ARCH_OMAP4
+ isr_reg = bank->base + OMAP24XX_GPIO_IRQ_STATUS_0;
+ #else
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
+ #endif
#endif
while(1) {
u32 isr_saved, level_mask = 0;
@@ -1555,14 +1611,21 @@ static int __init _omap_gpio_init(void)
#endif
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- for (i = 0; i < OMAP34XX_NR_GPIOS; i++) {
- sprintf(clk_name, "gpio%d_ick", i + 1);
- gpio_iclks[i] = clk_get(NULL, clk_name);
- if (IS_ERR(gpio_iclks[i]))
- printk(KERN_ERR "Could not get %s\n", clk_name);
- else
- clk_enable(gpio_iclks[i]);
+ if (!cpu_is_omap44xx()) {
+ for (i = 0; i < OMAP34XX_NR_GPIOS; i++) {
+ sprintf(clk_name, "gpio%d_ick", i + 1);
+ gpio_iclks[i] = clk_get(NULL, clk_name);
+ if (IS_ERR(gpio_iclks[i]))
+ printk(KERN_ERR "Could not get %s\n",
+ clk_name);
+ else
+ clk_enable(gpio_iclks[i]);
+ }
}
}
#endif
@@ -1672,9 +1735,17 @@ static int __init _omap_gpio_init(void)
static const u32 non_wakeup_gpios[] = {
0xe203ffc0, 0x08700040
};
-
- __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
- __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
+#ifdef CONFIG_ARCH_OMAP4
+ __raw_writel(0x00000000, bank->base +
+ OMAP24XX_GPIO_IRQ_STATUS_CLR_0);
+ __raw_writel(0xffffffff, bank->base +
+ OMAP24XX_GPIO_IRQ_STATUS_0);
+#else
+ __raw_writel(0x00000000, bank->base +
+ OMAP24XX_GPIO_IRQENABLE1);
+ __raw_writel(0xffffffff, bank->base +
+ OMAP24XX_GPIO_IRQSTATUS1);
+#endif
__raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG);
__raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_DEBOUNCE_EN);
@@ -1724,12 +1795,18 @@ static int __init _omap_gpio_init(void)
}
set_irq_chained_handler(bank->irq, gpio_irq_handler);
set_irq_data(bank->irq, bank);
-
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- sprintf(clk_name, "gpio%d_dbck", i + 1);
- bank->dbck = clk_get(NULL, clk_name);
- if (IS_ERR(bank->dbck))
- printk(KERN_ERR "Could not get %s\n", clk_name);
+ if (!cpu_is_omap44xx()) {
+ sprintf(clk_name, "gpio%d_dbck", i + 1);
+ bank->dbck = clk_get(NULL, clk_name);
+ if (IS_ERR(bank->dbck))
+ printk(KERN_ERR "Could not get %s\n",
+ clk_name);
+ }
}
}
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 8b848391f0c8..778e591f6112 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -53,9 +53,15 @@ static struct resource i2c_resources[][2] = {
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
{ I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) },
#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_44XX_I2C2_IRQ) },
+#endif
#if defined(CONFIG_ARCH_OMAP34XX)
{ I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) },
#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_44XX_I2C3_IRQ) },
+#endif
};
#define I2C_DEV_BUILDER(bus_id, res, data) \
@@ -72,10 +78,11 @@ static struct resource i2c_resources[][2] = {
static u32 i2c_rate[ARRAY_SIZE(i2c_resources)];
static struct platform_device omap_i2c_devices[] = {
I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]),
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+defined(CONFIG_ARCH_OMAP4)
I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]),
#endif
-#if defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]),
#endif
};
@@ -88,7 +95,7 @@ static const int omap24xx_pins[][2] = {
#else
static const int omap24xx_pins[][2] = {};
#endif
-#if defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
static const int omap34xx_pins[][2] = {
{ K21_34XX_I2C1_SCL, J21_34XX_I2C1_SDA},
{ AF15_34XX_I2C2_SCL, AE15_34XX_I2C2_SDA},
@@ -110,7 +117,7 @@ static void __init omap_i2c_mux_pins(int bus)
} else if (cpu_is_omap24xx()) {
scl = omap24xx_pins[bus][0];
sda = omap24xx_pins[bus][1];
- } else if (cpu_is_omap34xx()) {
+ } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
scl = omap34xx_pins[bus][0];
sda = omap34xx_pins[bus][1];
} else {
@@ -129,7 +136,7 @@ static int __init omap_i2c_nr_ports(void)
ports = 1;
else if (cpu_is_omap24xx())
ports = 2;
- else if (cpu_is_omap34xx())
+ else if (cpu_is_omap34xx() || cpu_is_omap44xx())
ports = 3;
return ports;
@@ -151,6 +158,10 @@ static int __init omap_i2c_add_bus(int bus_id)
base = OMAP2_I2C_BASE1;
irq = INT_24XX_I2C1_IRQ;
}
+ if (cpu_is_omap44xx()) {
+ base = OMAP2_I2C_BASE1;
+ irq = INT_44XX_I2C1_IRQ;
+ }
res[0].start = base;
res[0].end = base + OMAP_I2C_SIZE;
res[1].start = irq;
diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
new file mode 100755
index 000000000000..8948f6fdd2cf
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
@@ -0,0 +1,218 @@
+/*
+ * _chnl_sm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _chnl_sm.h ========
+ * Description:
+ * Private header file defining channel manager and channel objects for
+ * a shared memory channel driver.
+ *
+ * Public Functions:
+ * None.
+ *
+ * Notes:
+ * Shared between the modules implementing the shared memory channel class
+ * library.
+ *
+ *! Revision History:
+ *! ================
+ *! 15-Oct-2002 kc Removed legacy PERF code.
+ *! 12-Jan-2002 ag Removed unused gppReqIO & ddmaChnlId DDMA fields.
+ *! Added zero-copy chnl descriptor array: zchnldesc.
+ *! 21-Dec-2001 ag Moved descPaGpp to private chnl obj from chnl descriptor.
+ *! 20-May-2001 ag/jeh Removed fShmSyms field from CHNL_MGR.
+ *! 04-Feb-2001 ag DSP-DMA support added.
+ *! 26-Oct-2000 jeh Added arg and resvd to SHM control structure. Added dwArg
+ *! to CHNL_IRP.
+ *! 16-Oct-2000 jeh Removed #ifdef DEBUG from around channel object's cIOCs
+ *! field, added cIOReqs.
+ *! 20-Jan-2000 ag: Incorporated code review comments.
+ *! 05-Jan-2000 ag: Text format cleanup.
+ *! 03-Nov-1999 ag: Added szEventName[] to CHNL object for name event support.
+ *! 02-Nov-1999 ag: _SHM_BEG & _END Syms from COFF now used for IO and SM CLASS.
+ *! 27-Oct-1999 jeh Define SHM structure to work for 16-bit targets.
+ *! 25-May-1999 jg: Added target side symbol names for share memory buffer
+ *! 03-Jan-1997 gp: Added fSharedIRQ field.
+ *! 22-Oct-1996 gp: Made dwProcessID a handle.
+ *! 09-Sep-1996 gp: Added dwProcessID field to CHNL_OBJECT.
+ *! 13-Aug-1996 gp: Created.
+ */
+
+#ifndef _CHNL_SM_
+#define _CHNL_SM_
+
+#include <dspbridge/wcd.h>
+#include <dspbridge/wmd.h>
+#include <dspbridge/dpc.h>
+
+#include <dspbridge/list.h>
+#include <dspbridge/ntfy.h>
+
+/*
+ * These target side symbols define the beginning and ending addresses
+ * of shared memory buffer. They are defined in the *cfg.cmd file by
+ * cdb code.
+ */
+#define CHNL_SHARED_BUFFER_BASE_SYM "_SHM_BEG"
+#define CHNL_SHARED_BUFFER_LIMIT_SYM "_SHM_END"
+#define BRIDGEINIT_BIOSGPTIMER "_BRIDGEINIT_BIOSGPTIMER"
+#define BRIDGEINIT_LOADMON_GPTIMER "_BRIDGEINIT_LOADMON_GPTIMER"
+
+#ifndef _CHNL_WORDSIZE
+#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
+#endif
+#ifdef OMAP_3430
+
+#define MAXOPPS 16
+
+struct oppTableEntry {
+ u32 voltage;
+ u32 frequency;
+ u32 minFreq;
+ u32 maxFreq;
+} ;
+
+struct oppStruct {
+ u32 currOppPt;
+ u32 numOppPts;
+ struct oppTableEntry oppPoint[MAXOPPS];
+} ;
+
+/* Request to MPU */
+struct oppRqstStruct {
+ u32 rqstDspFreq;
+ u32 rqstOppPt;
+};
+
+/* Info to MPU */
+struct loadMonStruct {
+ u32 currDspLoad;
+ u32 currDspFreq;
+ u32 predDspLoad;
+ u32 predDspFreq;
+};
+
+#endif
+ enum SHM_DESCTYPE {
+ SHM_CURROPP = 0,
+ SHM_OPPINFO = 1,
+ SHM_GETOPP = 2, /* Get DSP requested OPP info */
+ } ;
+
+/* Structure in shared between DSP and PC for communication.*/
+ struct SHM {
+ u32 dspFreeMask; /* Written by DSP, read by PC. */
+ u32 hostFreeMask; /* Written by PC, read by DSP */
+
+ u32 inputFull; /* Input channel has unread data. */
+ u32 inputId; /* Channel for which input is available. */
+ u32 inputSize; /* Size of data block (in DSP words). */
+
+ u32 outputFull; /* Output channel has unread data. */
+ u32 outputId; /* Channel for which output is available. */
+ u32 outputSize; /* Size of data block (in DSP words). */
+
+ u32 arg; /* Arg for Issue/Reclaim (23 bits for 55x). */
+ u32 resvd; /* Keep structure size even for 32-bit DSPs */
+
+#ifdef OMAP_3430
+#ifndef DISABLE_BRIDGE_PM
+ /* Operating Point structure */
+ struct oppStruct oppTableStruct;
+ /* Operating Point Request structure */
+ struct oppRqstStruct oppRequest;
+ /* load monitor information structure*/
+ struct loadMonStruct loadMonInfo;
+ char dummy[184]; /* padding to 256 byte boundary */
+ u32 shm_dbg_var[64]; /* shared memory debug variables */
+#endif
+#endif
+ } ;
+
+ /* Channel Manager: only one created per board: */
+ struct CHNL_MGR {
+ u32 dwSignature; /* Used for object validation */
+ /* Function interface to WMD */
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct IO_MGR *hIOMgr; /* IO manager */
+ /* Device this board represents */
+ struct DEV_OBJECT *hDevObject;
+
+ /* These fields initialized in WMD_CHNL_Create(): */
+ u32 dwOutputMask; /* Host output channels w/ full buffers */
+ u32 dwLastOutput; /* Last output channel fired from DPC */
+ /* Critical section object handle */
+ struct SYNC_CSOBJECT *hCSObj;
+ u32 uWordSize; /* Size in bytes of DSP word */
+ u32 cChannels; /* Total number of channels */
+ u32 cOpenChannels; /* Total number of open channels */
+ struct CHNL_OBJECT **apChannel; /* Array of channels */
+ u32 dwType; /* Type of channel class library */
+ /* If no SHM syms, return for CHNL_Open */
+ DSP_STATUS chnlOpenStatus;
+ } ;
+
+/*
+ * Channel: up to CHNL_MAXCHANNELS per board or if DSP-DMA supported then
+ * up to CHNL_MAXCHANNELS + CHNL_MAXDDMACHNLS per board.
+ */
+ struct CHNL_OBJECT {
+ u32 dwSignature; /* Used for object validation */
+ /* Pointer back to channel manager */
+ struct CHNL_MGR *pChnlMgr;
+ u32 uId; /* Channel id */
+ u32 dwState; /* Current channel state */
+ u32 uMode; /* Chnl mode and attributes */
+ /* Chnl I/O completion event (user mode) */
+ HANDLE hUserEvent;
+ /* Abstract syncronization object */
+ struct SYNC_OBJECT *hSyncEvent;
+ /* Name of Sync event */
+ char szEventName[SYNC_MAXNAMELENGTH + 1];
+ u32 hProcess; /* Process which created this channel */
+ u32 pCBArg; /* Argument to use with callback */
+ struct LST_LIST *pIORequests; /* List of IOR's to driver */
+ s32 cIOCs; /* Number of IOC's in queue */
+ s32 cIOReqs; /* Number of IORequests in queue */
+ s32 cChirps; /* Initial number of free Irps */
+ /* List of IOC's from driver */
+ struct LST_LIST *pIOCompletions;
+ struct LST_LIST *pFreeList; /* List of free Irps */
+ struct NTFY_OBJECT *hNtfy;
+ u32 cBytesMoved; /* Total number of bytes transfered */
+
+ /* For DSP-DMA */
+
+ /* Type of chnl transport:CHNL_[PCPY][DDMA] */
+ u32 uChnlType;
+ } ;
+
+/* I/O Request/completion packet: */
+ struct CHNL_IRP {
+ struct LST_ELEM link; /* Link to next CHIRP in queue. */
+ /* Buffer to be filled/emptied. (User) */
+ u8 *pHostUserBuf;
+ /* Buffer to be filled/emptied. (System) */
+ u8 *pHostSysBuf;
+ u32 dwArg; /* Issue/Reclaim argument. */
+ u32 uDspAddr; /* Transfer address on DSP side. */
+ u32 cBytes; /* Bytes transferred. */
+ u32 cBufSize; /* Actual buffer size when allocated. */
+ u32 status; /* Status of IO completion. */
+ } ;
+
+#endif /* _CHNL_SM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/_dcd.h b/arch/arm/plat-omap/include/dspbridge/_dcd.h
new file mode 100644
index 000000000000..b6a8d9ec9c67
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/_dcd.h
@@ -0,0 +1,187 @@
+/*
+ * _dcd.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _dcd.h ========
+ * Description:
+ * Includes the wrapper functions called directly by the
+ * DeviceIOControl interface.
+ *
+ * Public Functions:
+ * WCD_CallDevIOCtl
+ * WCD_Init
+ * WCD_InitComplete2
+ * WCD_Exit
+ * <MOD>WRAP_*
+ *
+ * Notes:
+ * Compiled with CDECL calling convention.
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
+ *! 30-Jan-2002 ag Renamed CMMWRAP_AllocBuf to CMMWRAP_CallocBuf.
+ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data to acquire PERF stats.
+ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
+ *! NODEWRAP_GetMessageStream.
+ *! 10-Oct-2000 ag: Added user CMM wrappers.
+ *! 04-Aug-2000 rr: MEMWRAP and UTIL_Wrap added.
+ *! 27-Jul-2000 rr: NODEWRAP, STRMWRAP added.
+ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
+ *! 03-Dec-1999 rr: WCD_InitComplete2 enabled for BRD_AutoStart.
+ *! 09-Nov-1999 kc: Added MEMRY.
+ *! 02-Nov-1999 ag: Added CHNL.
+ *! 08-Oct-1999 rr: Utilwrap_Testdll fxn added
+ *! 24-Sep-1999 rr: header changed from _wcd.h to _dcd.h
+ *! 09-Sep-1997 gp: Created.
+ */
+
+#ifndef _WCD_
+#define _WCD_
+
+#include <dspbridge/wcdioctl.h>
+
+/*
+ * ======== WCD_CallDevIOCtl ========
+ * Purpose:
+ * Call the (wrapper) function for the corresponding WCD IOCTL.
+ * Parameters:
+ * cmd: IOCTL id, base 0.
+ * args: Argument structure.
+ * pResult:
+ * Returns:
+ * DSP_SOK if command called; DSP_EINVALIDARG if command not in IOCTL
+ * table.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS WCD_CallDevIOCtl(unsigned int cmd,
+ union Trapped_Args *args,
+ u32 *pResult);
+
+/*
+ * ======== WCD_Init ========
+ * Purpose:
+ * Initialize WCD modules, and export WCD services to WMD's.
+ * This procedure is called when the class driver is loaded.
+ * Parameters:
+ * Returns:
+ * TRUE if success; FALSE otherwise.
+ * Requires:
+ * Ensures:
+ */
+ extern bool WCD_Init(void);
+
+/*
+ * ======== WCD_InitComplete2 ========
+ * Purpose:
+ * Perform any required WCD, and WMD initialization which
+ * cannot not be performed in WCD_Init(void) or DEV_StartDevice() due
+ * to the fact that some services are not yet
+ * completely initialized.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Allow this device to load
+ * DSP_EFAIL: Failure.
+ * Requires:
+ * WCD initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS WCD_InitComplete2(void);
+
+/*
+ * ======== WCD_Exit ========
+ * Purpose:
+ * Exit all modules initialized in WCD_Init(void).
+ * This procedure is called when the class driver is unloaded.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * WCD_Init(void) was previously called.
+ * Ensures:
+ * Resources acquired in WCD_Init(void) are freed.
+ */
+ extern void WCD_Exit(void);
+
+/* MGR wrapper functions */
+ extern u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args);
+ extern u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args);
+ extern u32 MGRWRAP_RegisterObject(union Trapped_Args *args);
+ extern u32 MGRWRAP_UnregisterObject(union Trapped_Args *args);
+ extern u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args);
+
+#ifndef RES_CLEANUP_DISABLE
+ extern u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args);
+#endif
+
+
+/* CPRC (Processor) wrapper Functions */
+ extern u32 PROCWRAP_Attach(union Trapped_Args *args);
+ extern u32 PROCWRAP_Ctrl(union Trapped_Args *args);
+ extern u32 PROCWRAP_Detach(union Trapped_Args *args);
+ extern u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args);
+ extern u32 PROCWRAP_EnumResources(union Trapped_Args *args);
+ extern u32 PROCWRAP_GetState(union Trapped_Args *args);
+ extern u32 PROCWRAP_GetTrace(union Trapped_Args *args);
+ extern u32 PROCWRAP_Load(union Trapped_Args *args);
+ extern u32 PROCWRAP_RegisterNotify(union Trapped_Args *args);
+ extern u32 PROCWRAP_Start(union Trapped_Args *args);
+ extern u32 PROCWRAP_ReserveMemory(union Trapped_Args *args);
+ extern u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args);
+ extern u32 PROCWRAP_Map(union Trapped_Args *args);
+ extern u32 PROCWRAP_UnMap(union Trapped_Args *args);
+ extern u32 PROCWRAP_FlushMemory(union Trapped_Args *args);
+ extern u32 PROCWRAP_Stop(union Trapped_Args *args);
+ extern u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args);
+
+/* NODE wrapper functions */
+ extern u32 NODEWRAP_Allocate(union Trapped_Args *args);
+ extern u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args);
+ extern u32 NODEWRAP_ChangePriority(union Trapped_Args *args);
+ extern u32 NODEWRAP_Connect(union Trapped_Args *args);
+ extern u32 NODEWRAP_Create(union Trapped_Args *args);
+ extern u32 NODEWRAP_Delete(union Trapped_Args *args);
+ extern u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args);
+ extern u32 NODEWRAP_GetAttr(union Trapped_Args *args);
+ extern u32 NODEWRAP_GetMessage(union Trapped_Args *args);
+ extern u32 NODEWRAP_Pause(union Trapped_Args *args);
+ extern u32 NODEWRAP_PutMessage(union Trapped_Args *args);
+ extern u32 NODEWRAP_RegisterNotify(union Trapped_Args *args);
+ extern u32 NODEWRAP_Run(union Trapped_Args *args);
+ extern u32 NODEWRAP_Terminate(union Trapped_Args *args);
+ extern u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args);
+
+/* STRM wrapper functions */
+ extern u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args);
+ extern u32 STRMWRAP_Close(union Trapped_Args *args);
+ extern u32 STRMWRAP_FreeBuffer(union Trapped_Args *args);
+ extern u32 STRMWRAP_GetEventHandle(union Trapped_Args *args);
+ extern u32 STRMWRAP_GetInfo(union Trapped_Args *args);
+ extern u32 STRMWRAP_Idle(union Trapped_Args *args);
+ extern u32 STRMWRAP_Issue(union Trapped_Args *args);
+ extern u32 STRMWRAP_Open(union Trapped_Args *args);
+ extern u32 STRMWRAP_Reclaim(union Trapped_Args *args);
+ extern u32 STRMWRAP_RegisterNotify(union Trapped_Args *args);
+ extern u32 STRMWRAP_Select(union Trapped_Args *args);
+
+ extern u32 CMMWRAP_CallocBuf(union Trapped_Args *args);
+ extern u32 CMMWRAP_FreeBuf(union Trapped_Args *args);
+ extern u32 CMMWRAP_GetHandle(union Trapped_Args *args);
+ extern u32 CMMWRAP_GetInfo(union Trapped_Args *args);
+
+#endif /* _WCD_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/brddefs.h b/arch/arm/plat-omap/include/dspbridge/brddefs.h
new file mode 100644
index 000000000000..c62388c1f87a
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/brddefs.h
@@ -0,0 +1,54 @@
+/*
+ * brddefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== brddefs.h ========
+ * Description:
+ * Global BRD constants and types, shared between WSX, WCD, and WMD.
+ *
+ *! Revision History:
+ *! ================
+ *! 31-Jan-2000 rr: Comment Exec changed to Monitor
+ *! 22-Jul-1999 jeh Added BRD_LOADED state.
+ *! 26-Mar-1997 gp: Added BRD_SYNCINIT state.
+ *! 11-Dec-1996 cr: Added BRD_LASTSTATE definition.
+ *! 11-Jul-1996 gp: Added missing u32 callback argument to BRD_CALLBACK.
+ *! 10-Jun-1996 gp: Created from board.h and brd.h.
+ */
+
+#ifndef BRDDEFS_
+#define BRDDEFS_
+
+/* platform status values */
+#define BRD_STOPPED 0x0 /* No Monitor Loaded, Not running. */
+#define BRD_IDLE 0x1 /* Monitor Loaded, but suspended. */
+#define BRD_RUNNING 0x2 /* Monitor loaded, and executing. */
+#define BRD_UNKNOWN 0x3 /* Board state is indeterminate. */
+#define BRD_SYNCINIT 0x4
+#define BRD_LOADED 0x5
+#define BRD_LASTSTATE BRD_LOADED /* Set to highest legal board state. */
+#define BRD_SLEEP_TRANSITION 0x6 /* Sleep transition in progress */
+#define BRD_HIBERNATION 0x7 /* MPU initiated hibernation */
+#define BRD_RETENTION 0x8 /* Retention mode */
+#define BRD_DSP_HIBERNATION 0x9 /* DSP initiated hibernation */
+#define BRD_ERROR 0xA /* Board state is Error */
+ typedef u32 BRD_STATUS;
+
+/* BRD Object */
+ struct BRD_OBJECT;
+
+#endif /* BRDDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/cfg.h b/arch/arm/plat-omap/include/dspbridge/cfg.h
new file mode 100644
index 000000000000..68db842db9b9
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/cfg.h
@@ -0,0 +1,339 @@
+/*
+ * cfg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cfg.h ========
+ * Purpose:
+ * PM Configuration module.
+ *
+ * Private Functions:
+ * CFG_Exit
+ * CFG_GetAutoStart
+ * CFG_GetCDVersion
+ * CFG_GetDevObject
+ * CFG_GetDSPResources
+ * CFG_GetExecFile
+ * CFG_GetHostResources
+ * CFG_GetObject
+ * CFG_GetPerfValue
+ * CFG_GetWMDFileName
+ * CFG_GetZLFile
+ * CFG_Init
+ * CFG_SetDevObject
+ * CFG_SetObject
+ *
+ *! Revision History:
+ *! =================
+ *! 26-Feb-2003 kc Removed unused CFG fxns.
+ *! 28-Aug-2001 jeh Added CFG_GetLoaderName.
+ *! 26-Jul-2000 rr: Added CFG_GetDCDName to retrieve the DCD Dll name.
+ *! 13-Jul-2000 rr: Added CFG_GetObject & CFG_SetObject.
+ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
+ *! CFG_GetWinBRIDGEDir/Directory,CFG_GetSearchPath removed.
+ *! 15-Jan-1998 cr: Code review cleanup.
+ *! 16-Aug-1997 cr: Added explicit cdecl identifiers.
+ *! 12-Dec-1996 gp: Moved CFG_FindInSearchPath to CSP module.
+ *! 13-Sep-1996 gp: Added CFG_GetBoardName().
+ *! 22-Jul-1996 gp: Added CFG_GetTraceStr, to retrieve an initial GT trace.
+ *! 26-Jun-1996 cr: Added CFG_FindInSearchPath.
+ *! 25-Jun-1996 cr: Added CFG_GetWinSPOXDir.
+ *! 17-Jun-1996 cr: Added CFG_GetDevNode.
+ *! 11-Jun-1996 cr: Cleaned up for code review.
+ *! 07-Jun-1996 cr: Added CFG_GetExecFile and CFG_GetZLFileName functions.
+ *! 04-Jun-1996 gp: Added AutoStart regkey and accessor function. Placed
+ *! OUT parameters in accessor function param. lists at end.
+ *! 29-May-1996 gp: Moved DEV_HDEVNODE to here and renamed CFG_HDEVNODE.
+ *! 22-May-1996 cr: Added GetHostResources, GetDSPResources, and
+ *! GetWMDFileName services.
+ *! 18-May-1996 gp: Created.
+ */
+
+#ifndef CFG_
+#define CFG_
+#include <dspbridge/host_os.h>
+#include <dspbridge/cfgdefs.h>
+
+/*
+ * ======== CFG_Exit ========
+ * Purpose:
+ * Discontinue usage of the CFG module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * CFG_Init(void) was previously called.
+ * Ensures:
+ * Resources acquired in CFG_Init(void) are freed.
+ */
+ extern void CFG_Exit(void);
+
+/*
+ * ======== CFG_GetAutoStart ========
+ * Purpose:
+ * Retreive the autostart mask, if any, for this board.
+ * Parameters:
+ * hDevNode: Handle to the DevNode who's WMD we are querying.
+ * pdwAutoStart: Ptr to location for 32 bit autostart mask.
+ * Returns:
+ * DSP_SOK: Success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_RESOURCENOTAVAIL: Unable to retreive resource.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: *pdwAutoStart contains autostart mask for this devnode.
+ */
+ extern DSP_STATUS CFG_GetAutoStart(IN struct CFG_DEVNODE *hDevNode,
+ OUT u32 *pdwAutoStart);
+
+/*
+ * ======== CFG_GetCDVersion ========
+ * Purpose:
+ * Retrieves the version of the PM Class Driver.
+ * Parameters:
+ * pdwVersion: Ptr to u32 to contain version number upon return.
+ * Returns:
+ * DSP_SOK: Success. pdwVersion contains Class Driver version in
+ * the form: 0xAABBCCDD where AABB is Major version and
+ * CCDD is Minor.
+ * DSP_EFAIL: Failure.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: Success.
+ * else: *pdwVersion is NULL.
+ */
+ extern DSP_STATUS CFG_GetCDVersion(OUT u32 *pdwVersion);
+
+/*
+ * ======== CFG_GetDevObject ========
+ * Purpose:
+ * Retrieve the Device Object handle for a given devnode.
+ * Parameters:
+ * hDevNode: Platform's DevNode handle from which to retrieve value.
+ * pdwValue: Ptr to location to store the value.
+ * Returns:
+ * DSP_SOK: Success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_INVALIDPOINTER: phDevObject is invalid.
+ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: *pdwValue is set to the retrieved u32.
+ * else: *pdwValue is set to 0L.
+ */
+ extern DSP_STATUS CFG_GetDevObject(IN struct CFG_DEVNODE *hDevNode,
+ OUT u32 *pdwValue);
+
+/*
+ * ======== CFG_GetDSPResources ========
+ * Purpose:
+ * Get the DSP resources available to a given device.
+ * Parameters:
+ * hDevNode: Handle to the DEVNODE who's resources we are querying.
+ * pDSPResTable: Ptr to a location to store the DSP resource table.
+ * Returns:
+ * DSP_SOK: On success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_RESOURCENOTAVAIL: The DSP Resource information is not
+ * available
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: pDSPResTable points to a filled table of resources allocated
+ * for the specified WMD.
+ */
+ extern DSP_STATUS CFG_GetDSPResources(IN struct CFG_DEVNODE *hDevNode,
+ OUT struct CFG_DSPRES *pDSPResTable);
+
+
+/*
+ * ======== CFG_GetExecFile ========
+ * Purpose:
+ * Retreive the default executable, if any, for this board.
+ * Parameters:
+ * hDevNode: Handle to the DevNode who's WMD we are querying.
+ * cBufSize: Size of buffer.
+ * pstrExecFile: Ptr to character buf to hold ExecFile.
+ * Returns:
+ * DSP_SOK: Success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_INVALIDPOINTER: pstrExecFile is invalid.
+ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: Not more than cBufSize bytes were copied into pstrExecFile,
+ * and *pstrExecFile contains default executable for this
+ * devnode.
+ */
+ extern DSP_STATUS CFG_GetExecFile(IN struct CFG_DEVNODE *hDevNode,
+ IN u32 cBufSize,
+ OUT char *pstrExecFile);
+
+/*
+ * ======== CFG_GetHostResources ========
+ * Purpose:
+ * Get the Host PC allocated resources assigned to a given device.
+ * Parameters:
+ * hDevNode: Handle to the DEVNODE who's resources we are querying.
+ * pHostResTable: Ptr to a location to store the host resource table.
+ * Returns:
+ * DSP_SOK: On success.
+ * CFG_E_INVALIDPOINTER: pHostResTable is invalid.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: pHostResTable points to a filled table of resources
+ * allocated for the specified WMD.
+ *
+ */
+ extern DSP_STATUS CFG_GetHostResources(IN struct CFG_DEVNODE *hDevNode,
+ OUT struct CFG_HOSTRES *pHostResTable);
+
+/*
+ * ======== CFG_GetObject ========
+ * Purpose:
+ * Retrieve the Driver Object handle From the Registry
+ * Parameters:
+ * pdwValue: Ptr to location to store the value.
+ * dwType Type of Object to Get
+ * Returns:
+ * DSP_SOK: Success.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: *pdwValue is set to the retrieved u32(non-Zero).
+ * else: *pdwValue is set to 0L.
+ */
+ extern DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType);
+
+/*
+ * ======== CFG_GetPerfValue ========
+ * Purpose:
+ * Retrieve a flag indicating whether PERF should log statistics for the
+ * PM class driver.
+ * Parameters:
+ * pfEnablePerf: Location to store flag. 0 indicates the key was
+ * not found, or had a zero value. A nonzero value
+ * means the key was found and had a nonzero value.
+ * Returns:
+ * Requires:
+ * pfEnablePerf != NULL;
+ * Ensures:
+ */
+ extern void CFG_GetPerfValue(OUT bool *pfEnablePerf);
+
+/*
+ * ======== CFG_GetWMDFileName ========
+ * Purpose:
+ * Get the mini-driver file name for a given device.
+ * Parameters:
+ * hDevNode: Handle to the DevNode who's WMD we are querying.
+ * cBufSize: Size of buffer.
+ * pWMDFileName: Ptr to a character buffer to hold the WMD filename.
+ * Returns:
+ * DSP_SOK: On success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_RESOURCENOTAVAIL: The filename is not available.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: Not more than cBufSize bytes were copied
+ * into pWMDFileName.
+ *
+ */
+ extern DSP_STATUS CFG_GetWMDFileName(IN struct CFG_DEVNODE *hDevNode,
+ IN u32 cBufSize,
+ OUT char *pWMDFileName);
+
+/*
+ * ======== CFG_GetZLFile ========
+ * Purpose:
+ * Retreive the ZLFile, if any, for this board.
+ * Parameters:
+ * hDevNode: Handle to the DevNode who's WMD we are querying.
+ * cBufSize: Size of buffer.
+ * pstrZLFileName: Ptr to character buf to hold ZLFileName.
+ * Returns:
+ * DSP_SOK: Success.
+ * CFG_E_INVALIDPOINTER: pstrZLFileName is invalid.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * CFG_E_RESOURCENOTAVAIL: couldn't find the ZLFileName.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: Not more than cBufSize bytes were copied into
+ * pstrZLFileName, and *pstrZLFileName contains ZLFileName
+ * for this devnode.
+ */
+ extern DSP_STATUS CFG_GetZLFile(IN struct CFG_DEVNODE *hDevNode,
+ IN u32 cBufSize,
+ OUT char *pstrZLFileName);
+
+/*
+ * ======== CFG_Init ========
+ * Purpose:
+ * Initialize the CFG module's private state.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public CFG functions.
+ */
+ extern bool CFG_Init(void);
+
+/*
+ * ======== CFG_SetDevObject ========
+ * Purpose:
+ * Store the Device Object handle for a given devnode.
+ * Parameters:
+ * hDevNode: Platform's DevNode handle we are storing value with.
+ * dwValue: Arbitrary value to store.
+ * Returns:
+ * DSP_SOK: Success.
+ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
+ * DSP_EFAIL: Internal Error.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: The Private u32 was successfully set.
+ */
+ extern DSP_STATUS CFG_SetDevObject(IN struct CFG_DEVNODE *hDevNode,
+ IN u32 dwValue);
+
+/*
+ * ======== CFG_SetDrvObject ========
+ * Purpose:
+ * Store the Driver Object handle.
+ * Parameters:
+ * dwValue: Arbitrary value to store.
+ * dwType Type of Object to Store
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Internal Error.
+ * Requires:
+ * CFG initialized.
+ * Ensures:
+ * DSP_SOK: The Private u32 was successfully set.
+ */
+ extern DSP_STATUS CFG_SetObject(IN u32 dwValue, IN u32 dwType);
+
+#endif /* CFG_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
new file mode 100644
index 000000000000..75214bca84d8
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
@@ -0,0 +1,120 @@
+/*
+ * cfgdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== cfgdefs.h ========
+ * Purpose:
+ * Global CFG constants and types, shared between class and mini driver.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 kc Removed wIOPort* in CFG_HOSTRES.
+ *! 06-Sep-2000 jeh Added channel info to CFG_HOSTRES.
+ *! 09-May-2000 rr: CFG_HOSTRES now support multiple windows for PCI support.
+ *! 31-Jan-2000 rr: Comments changed after code review.
+ *! 06-Jan-2000 rr: Bus Type included in CFG_HOSTRES.
+ *! 12-Nov-1999 rr: CFG_HOSTRES member names changed.
+ *! 25-Oct-1999 rr: Modified the CFG_HOSTRES Structure
+ *! PCMCIA ISR Register/Unregister fxn removed..
+ *! New flag PCCARD introduced during compile time.
+ *! 10-Sep-1999 ww: Added PCMCIA ISR Register/Unregister fxn.
+ *! 01-Sep-1999 ag: Removed NT/95 specific fields in CFG_HOSTRES
+ *! 27-Oct-1997 cr: Updated CFG_HOSTRES struct to support 1+ IRQs per board.
+ *! 17-Sep-1997 gp: Tacked some NT config info to end of CFG_HOSTRES structure.
+ *! 12-Dec-1996 cr: Cleaned up after code review.
+ *! 14-Nov-1996 gp: Renamed from wsxcfg.h
+ *! 19-Jun-1996 cr: Created.
+ */
+
+#ifndef CFGDEFS_
+#define CFGDEFS_
+
+/* Maximum length of module search path. */
+#define CFG_MAXSEARCHPATHLEN 255
+
+/* Maximum length of general paths. */
+#define CFG_MAXPATH 255
+
+/* Host Resources: */
+#define CFG_MAXMEMREGISTERS 9
+#define CFG_MAXIOPORTS 20
+#define CFG_MAXIRQS 7
+#define CFG_MAXDMACHANNELS 7
+
+/* IRQ flag */
+#define CFG_IRQSHARED 0x01 /* IRQ can be shared */
+
+/* DSP Resources: */
+#define CFG_DSPMAXMEMTYPES 10
+#define CFG_DEFAULT_NUM_WINDOWS 1 /* We support only one window. */
+
+/* A platform-related device handle: */
+ struct CFG_DEVNODE;
+
+/*
+ * Host resource structure.
+ */
+ struct CFG_HOSTRES {
+ u32 wNumMemWindows; /* Set to default */
+ /* This is the base.memory */
+ u32 dwMemBase[CFG_MAXMEMREGISTERS]; /* SHM virtual address */
+ u32 dwMemLength[CFG_MAXMEMREGISTERS]; /* Length of the Base */
+ u32 dwMemPhys[CFG_MAXMEMREGISTERS]; /* SHM Physical address */
+ u8 bIRQRegisters; /* IRQ Number */
+ u8 bIRQAttrib; /* IRQ Attribute */
+ u32 dwOffsetForMonitor; /* The Shared memory starts from
+ * dwMemBase + this offset */
+ /*
+ * Info needed by NODE for allocating channels to communicate with RMS:
+ * dwChnlOffset: Offset of RMS channels. Lower channels are
+ * reserved.
+ * dwChnlBufSize: Size of channel buffer to send to RMS
+ * dwNumChnls: Total number of channels (including reserved).
+ */
+ u32 dwChnlOffset;
+ u32 dwChnlBufSize;
+ u32 dwNumChnls;
+ void __iomem *dwPrmBase;
+ void __iomem *dwCmBase;
+#ifdef OMAP44XX
+ u32 dwCm1Base;
+ u32 dwCm2Base;
+#endif
+ void __iomem *dwPerBase;
+ u32 dwPerPmBase;
+ u32 dwCorePmBase;
+ void __iomem *dwWdTimerDspBase;
+ void __iomem *dwMboxBase;
+ void __iomem *dwDmmuBase;
+ void __iomem *dwSysCtrlBase;
+ } ;
+
+ struct CFG_DSPMEMDESC {
+ u32 uMemType; /* Type of memory. */
+ u32 ulMin; /* Minimum amount of memory of this type. */
+ u32 ulMax; /* Maximum amount of memory of this type. */
+ } ;
+
+ struct CFG_DSPRES {
+ u32 uChipType; /* DSP chip type. */
+ u32 uWordSize; /* Number of bytes in a word */
+ u32 cChips; /* Number of chips. */
+ u32 cMemTypes; /* Types of memory. */
+ struct CFG_DSPMEMDESC aMemDesc[CFG_DSPMAXMEMTYPES];
+ /* DSP Memory types */
+ } ;
+
+#endif /* CFGDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/chnl.h b/arch/arm/plat-omap/include/dspbridge/chnl.h
new file mode 100644
index 000000000000..f39e3f4bca48
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/chnl.h
@@ -0,0 +1,170 @@
+/*
+ * chnl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnl.h ========
+ * Description:
+ * WCD channel interface: multiplexes data streams through the single
+ * physical link managed by a mini-driver.
+ *
+ * Public Functions:
+ * CHNL_AddIOReq
+ * CHNL_AllocBuffer
+ * CHNL_CancelIO
+ * CHNL_Close
+ * CHNL_CloseOrphans
+ * CHNL_Create
+ * CHNL_Destroy
+ * CHNL_Exit
+ * CHNL_FlushIO
+ * CHNL_FreeBuffer
+ * CHNL_GetEventHandle
+ * CHNL_GetHandle
+ * CHNL_GetIOCompletion
+ * CHNL_GetId
+ * CHNL_GetMgr
+ * CHNL_GetMode
+ * CHNL_GetPosition
+ * CHNL_GetProcessHandle
+ * CHNL_Init
+ * CHNL_Open
+ *
+ * Notes:
+ * See DSP API chnl.h for more details.
+ *
+ *! Revision History:
+ *! ================
+ *! 14-Jan-1997 gp: Updated based on code review feedback.
+ *! 24-Oct-1996 gp: Move CloseOrphans into here from dspsys.
+ *! 09-Sep-1996 gp: Added CHNL_GetProcessID() and CHNL_GetHandle().
+ *! 10-Jul-1996 gp: Created.
+ */
+
+#ifndef CHNL_
+#define CHNL_
+
+#include <dspbridge/chnlpriv.h>
+
+/*
+ * ======== CHNL_Close ========
+ * Purpose:
+ * Ensures all pending I/O on this channel is cancelled, discards all
+ * queued I/O completion notifications, then frees the resources allocated
+ * for this channel, and makes the corresponding logical channel id
+ * available for subsequent use.
+ * Parameters:
+ * hChnl: Channel object handle.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * Requires:
+ * CHNL_Init(void) called.
+ * No thread must be blocked on this channel's I/O completion event.
+ * Ensures:
+ * DSP_SOK: The I/O completion event for this channel is freed.
+ * hChnl is no longer valid.
+ */
+ extern DSP_STATUS CHNL_Close(struct CHNL_OBJECT *hChnl);
+
+
+/*
+ * ======== CHNL_Create ========
+ * Purpose:
+ * Create a channel manager object, responsible for opening new channels
+ * and closing old ones for a given board.
+ * Parameters:
+ * phChnlMgr: Location to store a channel manager object on output.
+ * hDevObject: Handle to a device object.
+ * pMgrAttrs: Channel manager attributes.
+ * pMgrAttrs->cChannels: Max channels
+ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
+ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
+ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: hDevObject is invalid.
+ * DSP_EINVALIDARG: cChannels is 0.
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
+ * CHNL_E_MAXCHANNELS: This manager cannot handle this many channels.
+ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
+ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
+ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
+ * CHNL_E_MGREXISTS: Channel manager already exists for this device.
+ * Requires:
+ * CHNL_Init(void) called.
+ * phChnlMgr != NULL.
+ * pMgrAttrs != NULL.
+ * Ensures:
+ * DSP_SOK: Subsequent calls to CHNL_Create() for the same
+ * board without an intervening call to
+ * CHNL_Destroy() will fail.
+ */
+ extern DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CHNL_MGRATTRS *pMgrAttrs);
+
+/*
+ * ======== CHNL_Destroy ========
+ * Purpose:
+ * Close all open channels, and destroy the channel manager.
+ * Parameters:
+ * hChnlMgr: Channel manager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: hChnlMgr was invalid.
+ * Requires:
+ * CHNL_Init(void) called.
+ * Ensures:
+ * DSP_SOK: Cancels I/O on each open channel.
+ * Closes each open channel.
+ * CHNL_Create may subsequently be called for the
+ * same board.
+ */
+ extern DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
+
+/*
+ * ======== CHNL_Exit ========
+ * Purpose:
+ * Discontinue usage of the CHNL module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * CHNL_Init(void) previously called.
+ * Ensures:
+ * Resources, if any acquired in CHNL_Init(void), are freed when the last
+ * client of CHNL calls CHNL_Exit(void).
+ */
+ extern void CHNL_Exit(void);
+
+
+/*
+ * ======== CHNL_Init ========
+ * Purpose:
+ * Initialize the CHNL module's private state.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occurred.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public CHNL functions.
+ */
+ extern bool CHNL_Init(void);
+
+
+
+#endif /* CHNL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
new file mode 100644
index 000000000000..789b9bd185d2
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
@@ -0,0 +1,168 @@
+/*
+ * chnl_sm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnl_sm.h ========
+ * Description:
+ * Prototypes for channel lower edge functions for a WinBRIDGE mini driver
+ * implementing data transfer via shared memory.
+ *
+ * Public Functions:
+ * CHNLSM_DisableInterrupt;
+ * CHNLSM_EnableInterrupt;
+ * CHNLSM_ISR;
+ * CHNLSM_Read;
+ * CHNLSM_UpdateSHMLength;
+ * CHNLSM_Write;
+ *
+ * Notes:
+ * These lower edge functions must be implemented by the WMD writer.
+ * Currently, CHNLSM_Read() and CHNLSM_Write() are not called, but must
+ * be defined to link.
+ *
+ */
+
+#ifndef CHNLSM_
+#define CHNLSM_
+
+#include <dspbridge/wmd.h>
+
+/*
+ * ======== CHNLSM_DisableInterrupt ========
+ * Purpose:
+ * Disable interrupts from the DSP board to the PC.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * Returns:
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT*
+ hDevContext);
+
+/*
+ * ======== CHNLSM_EnableInterrupt ========
+ * Purpose:
+ * Enable interrupts from the DSP board to the PC.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * Returns:
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT*
+ hDevContext);
+
+/*
+ * ======== CHNLSM_InterruptDSP2 ========
+ * Purpose:
+ * Set interrupt value & send an interrupt to the DSP processor(s).
+ * This is typicaly used when mailbox interrupt mechanisms allow data
+ * to be associated with interrupt such as for OMAP's CMD/DATA regs.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * wMbVal: Value associated with interrupt(e.g. mailbox value).
+ * Returns:
+ * DSP_SOK: Interrupt sent;
+ * else: Unable to send interrupt.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT*
+ hDevContext, u16 wMbVal);
+
+/*
+ * ======== CHNLSM_ISR ========
+ * Purpose:
+ * Mini-driver's ISR, called by WCD when the board interrupts the host.
+ * Parameters:
+ * hDevContext: Handle to the mini-driver defined device info.
+ * pfSchedDPC: Set to TRUE to schedule a deferred procedure call
+ * to advance the channel protocol. The channel class
+ * library will call the WMD's CHNLSM_DPC routine during
+ * its own DPC, before dispatching I/O.
+ * The channel class library should ignore *pfSchedDPC when
+ * CHNLSM_ISR returns FALSE.
+ * pwMBRegVal: Value of mailbox register.
+ * Returns:
+ * TRUE if this interrupt is was generated by the DSP board.
+ * FALSE otherwise.
+ * Requires:
+ * Interrupts to the host processor are disabled on entry.
+ * Must only call functions which are in page locked memory.
+ * Must only call asynchronous OS services.
+ * The EOI for this interrupt has already been sent to the PIC.
+ * Ensures:
+ * If the interrupt is *not* shared, this routine must return TRUE.
+ */
+ extern bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext,
+ OUT bool *pfSchedDPC,
+ OUT u16 *pwIntrVal);
+
+/*
+ * ======== CHNLSM_Read ========
+ * Purpose:
+ * Read data from DSP board memory into a Host buffer.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * pHostBuf: Pointer to host buffer (Destination).
+ * dwDSPAddr: Address on DSP board (Source).
+ * ulNumBytes: Number of bytes to transfer.
+ * Returns:
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CHNLSM_Read(struct WMD_DEV_CONTEXT *hDevContext,
+ OUT u8 *pHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes);
+
+/*
+ * ======== CHNLSM_UpdateSHMLength ========
+ * Purpose:
+ * Allow the minidriver a chance to override the SHM length as reported
+ * to the mini driver (chnl_sm.lib) by Windows Plug and Play.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * pSHMLength: Pointer to size of SHM window (in DSP words).
+ * Returns:
+ * TRUE if pSHMLength updated; FALSE otherwise.
+ * Requires:
+ * pSHMLength != NULL.
+ * Ensures:
+ * No more than sizeof(u32) bytes written to *pSHMLength
+ */
+ extern bool CHNLSM_UpdateSHMLength(struct WMD_DEV_CONTEXT *hDevContext,
+ IN OUT u32 *pSHMLength);
+
+/*
+ * ======== CHNLSM_Write ========
+ * Purpose:
+ * Write data from a Host buffer to DSP board memory.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * pHostBuf: Pointer to host buffer (Source).
+ * dwDSPAddr: Address on DSP board (Destination).
+ * ulNumBytes: Number of bytes to transfer.
+ * Returns:
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CHNLSM_Write(struct WMD_DEV_CONTEXT *hDevContext,
+ IN u8 *pHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes);
+
+#endif /* CHNLSM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/chnldefs.h b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
new file mode 100644
index 000000000000..9f592297f6d5
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
@@ -0,0 +1,92 @@
+/*
+ * chnldefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnldefs.h ========
+ * Purpose:
+ * System-wide channel objects and constants.
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Jan-2002 ag Added cBufSize to IOC.
+ *! 05-Jan-2000 ag: Text format cleanup.
+ *! 02-Dec-1999 ag: Added new chnl attribute pstrEventName.
+ *! 12-Nov-1999 kc: Enabled hEvent attribute for tests.
+ *! 01-Nov-1999 ag: hEvent attribute not supported(yet).
+ *! 16-Jan-1997 gp: Moved private stuff into chnlpriv.h
+ *! 14-Jan-1997 gp: Updated based on code review feedback:
+ *! Removed CHNL_MODENOWAIT, CHNL_MODEDIRECT,
+ *! 03-Jan-1997 gp: Added channel class library types.
+ *! 14-Dec-1996 gp: Moved uChnlId field from CHNL_ATTRS to CHNL_Open().
+ *! 10-Dec-1996 gp: Added CHNL_IsTimedOut() macro.
+ *! 14-Nov-1996 gp: Renamed from wsxchnl.h.
+ *! 09-Sep-1996 gp: Added hReserved2 field to CHNL_ATTRS. Updated CHNL_INFO.
+ *! 10-Jul-1996 gp: Created from channel.h.
+ */
+
+#ifndef CHNLDEFS_
+#define CHNLDEFS_
+
+/* Channel id option. */
+#define CHNL_PICKFREE (~0UL) /* Let manager pick a free channel. */
+
+/* Channel manager limits: */
+#define CHNL_INITIOREQS 4 /* Default # of I/O requests. */
+
+/* Channel modes */
+#define CHNL_MODETODSP 0x0000 /* Data streaming to the DSP. */
+#define CHNL_MODEFROMDSP 0x0001 /* Data streaming from the DSP. */
+
+/* GetIOCompletion flags */
+#define CHNL_IOCINFINITE 0xffffffff /* Wait forever for IO completion. */
+#define CHNL_IOCNOWAIT 0x0 /* Dequeue an IOC, if available. */
+
+/* IO Completion Record status: */
+#define CHNL_IOCSTATCOMPLETE 0x0000 /* IO Completed. */
+#define CHNL_IOCSTATCANCEL 0x0002 /* IO was cancelled */
+#define CHNL_IOCSTATTIMEOUT 0x0008 /* Wait for IOC timed out. */
+#define CHNL_IOCSTATEOS 0x8000 /* End Of Stream reached. */
+
+/* Macros for checking I/O Completion status: */
+#define CHNL_IsEOS(ioc) (ioc.status & CHNL_IOCSTATEOS)
+#define CHNL_IsIOComplete(ioc) (!(ioc.status & ~CHNL_IOCSTATEOS))
+#define CHNL_IsIOCancelled(ioc) (ioc.status & CHNL_IOCSTATCANCEL)
+#define CHNL_IsTimedOut(ioc) (ioc.status & CHNL_IOCSTATTIMEOUT)
+
+/* CHNL types: */
+ typedef u32 CHNL_MODE; /* Channel transfer mode. */
+
+/* Channel attributes: */
+ struct CHNL_ATTRS {
+ u32 uIOReqs; /* Max # of preallocated I/O requests. */
+ HANDLE hEvent; /* User supplied auto-reset event object. */
+ char *pstrEventName; /* Ptr to name of user event object. */
+ HANDLE hReserved1; /* Reserved for future use. */
+ u32 hReserved2; /* Reserved for future use. */
+
+ };
+
+/* I/O completion record: */
+ struct CHNL_IOC {
+ void *pBuf; /* Buffer to be filled/emptied. */
+ u32 cBytes; /* Bytes transferred. */
+ u32 cBufSize; /* Actual buffer size in bytes */
+ u32 status; /* Status of IO completion. */
+ u32 dwArg; /* User argument associated with pBuf. */
+ } ;
+
+#endif /* CHNLDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/chnlpriv.h b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
new file mode 100644
index 000000000000..fdcda241a20f
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
@@ -0,0 +1,136 @@
+/*
+ * chnlpriv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnlpriv.h ========
+ * Description:
+ * Private channel header shared between DSPSYS, WCD and WMD modules.
+ *
+ * Public Functions:
+ * None.
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 05-Jan-2002 ag Added cChannels(total # of chnls) to CHNL_MGRINFO struct.
+ *! Added private CHNL_[PCPY][ZCPY][DDMA].
+ *! 17-Nov-2000 jeh Removed IRQ, shared memory from CHNL_MGRATTRS, since these
+ *! now belong to IO_ATTRS.
+ *! 21-Jan-2000 ag: Code review comments added.
+ *! 05-Jan-2000 ag: Text format cleanup.
+ *! 11-Dec-1999 ag: Added CHNL_MAXLOCKPAGES for CHNL_PrepareBuffer().
+ *! 04-Dec-1999 ag: Added CHNL_MAXEVTNAMELEN for i/o compl named event support.
+ *! 01-Nov-1999 ag: CHNL_MAXCHANNELS set to 16 for 16-bit DSPs.
+ *! 27-Oct-1997 cr: Expanded CHNL_MAXIRQ from 0x0f to 0xff.
+ *! 16-Jan-1997 gp: Moved symbols into here from chnldefs.h.
+ *! 03-Jan-1997 gp: Added CHNL_MAXIRQ define.
+ *! 09-Dec-1996 gp: Removed CHNL_STATEIDLE.
+ *! 15-Jul-1996 gp: Created.
+ */
+
+#ifndef CHNLPRIV_
+#define CHNLPRIV_
+
+#include <dspbridge/chnldefs.h>
+#include <dspbridge/devdefs.h>
+#include <dspbridge/sync.h>
+
+/* CHNL Object validation signatures: */
+#define CHNL_MGRSIGNATURE 0x52474D43 /* "CMGR" (in reverse). */
+#define CHNL_SIGNATURE 0x4C4E4843 /* "CHNL" (in reverse). */
+
+/* Channel manager limits: */
+#define CHNL_MAXCHANNELS 32 /* Max channels available per transport */
+
+
+/*
+ * Trans port channel Id definitions:(must match dsp-side).
+ *
+ * For CHNL_MAXCHANNELS = 16:
+ *
+ * ChnlIds:
+ * 0-15 (PCPY) - transport 0)
+ * 16-31 (DDMA) - transport 1)
+ * 32-47 (ZCPY) - transport 2)
+ */
+#define CHNL_PCPY 0 /* Proc-copy transport 0 */
+
+#define CHNL_MAXIRQ 0xff /* Arbitrarily large number. */
+
+/* The following modes are private: */
+#define CHNL_MODEUSEREVENT 0x1000 /* User provided the channel event. */
+#define CHNL_MODEMASK 0x1001
+
+/* Higher level channel states: */
+#define CHNL_STATEREADY 0x0000 /* Channel ready for I/O. */
+#define CHNL_STATECANCEL 0x0001 /* I/O was cancelled. */
+#define CHNL_STATEEOS 0x0002 /* End Of Stream reached. */
+
+/* Determine if user supplied an event for this channel: */
+#define CHNL_IsUserEvent(mode) (mode & CHNL_MODEUSEREVENT)
+
+/* Macros for checking mode: */
+#define CHNL_IsInput(mode) (mode & CHNL_MODEFROMDSP)
+#define CHNL_IsOutput(mode) (!CHNL_IsInput(mode))
+
+/* Types of channel class libraries: */
+#define CHNL_TYPESM 1 /* Shared memory driver. */
+#define CHNL_TYPEBM 2 /* Bus Mastering driver. */
+
+/* Max string length of channel I/O completion event name - change if needed */
+#define CHNL_MAXEVTNAMELEN 32
+
+/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
+#define CHNL_MAXLOCKPAGES 64
+
+/* Channel info. */
+ struct CHNL_INFO {
+ struct CHNL_MGR *hChnlMgr; /* Owning channel manager. */
+ u32 dwID; /* Channel ID. */
+ HANDLE hEvent; /* Channel I/O completion event. */
+ /*Abstraction of I/O completion event.*/
+ struct SYNC_OBJECT *hSyncEvent;
+ u32 dwMode; /* Channel mode. */
+ u32 dwState; /* Current channel state. */
+ u32 cPosition; /* Total bytes transferred. */
+ u32 cIOCs; /* Number of IOCs in queue. */
+ u32 cIOReqs; /* Number of IO Requests in queue. */
+ u32 hProcess; /* Process owning this channel. */
+ /*
+ * Name of channel I/O completion event. Not required in Linux
+ */
+ char szEventName[CHNL_MAXEVTNAMELEN + 1];
+ } ;
+
+/* Channel manager info: */
+ struct CHNL_MGRINFO {
+ u32 dwType; /* Type of channel class library. */
+ /* Channel handle, given the channel id. */
+ struct CHNL_OBJECT *hChnl;
+ u32 cOpenChannels; /* Number of open channels. */
+ u32 cChannels; /* total # of chnls supported */
+ } ;
+
+/* Channel Manager Attrs: */
+ struct CHNL_MGRATTRS {
+ /* Max number of channels this manager can use. */
+ u32 cChannels;
+ u32 uWordSize; /* DSP Word size. */
+ } ;
+
+#endif /* CHNLPRIV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/clk.h b/arch/arm/plat-omap/include/dspbridge/clk.h
new file mode 100644
index 000000000000..4a23dab3c6be
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/clk.h
@@ -0,0 +1,155 @@
+/*
+ * clk.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== clk.h ========
+ * Purpose: Provides Clock functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 08-May-2007 rg: Moved all clock functions from sync module.
+ */
+
+#ifndef _CLK_H
+#define _CLK_H
+
+ /* Generic TIMER object: */
+ struct TIMER_OBJECT;
+ enum SERVICES_ClkId {
+ SERVICESCLK_iva2_ck = 0,
+ SERVICESCLK_mailbox_ick,
+ SERVICESCLK_gpt5_fck,
+ SERVICESCLK_gpt5_ick,
+ SERVICESCLK_gpt6_fck,
+ SERVICESCLK_gpt6_ick,
+ SERVICESCLK_gpt7_fck,
+ SERVICESCLK_gpt7_ick,
+ SERVICESCLK_gpt8_fck,
+ SERVICESCLK_gpt8_ick,
+ SERVICESCLK_wdt3_fck,
+ SERVICESCLK_wdt3_ick,
+ SERVICESCLK_mcbsp1_fck,
+ SERVICESCLK_mcbsp1_ick,
+ SERVICESCLK_mcbsp2_fck,
+ SERVICESCLK_mcbsp2_ick,
+ SERVICESCLK_mcbsp3_fck,
+ SERVICESCLK_mcbsp3_ick,
+ SERVICESCLK_mcbsp4_fck,
+ SERVICESCLK_mcbsp4_ick,
+ SERVICESCLK_mcbsp5_fck,
+ SERVICESCLK_mcbsp5_ick,
+ SERVICESCLK_ssi_fck,
+ SERVICESCLK_ssi_ick,
+ SERVICESCLK_sys_32k_ck,
+ SERVICESCLK_sys_ck,
+ SERVICESCLK_NOT_DEFINED
+ } ;
+
+/*
+ * ======== CLK_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * CLK initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void CLK_Exit(void);
+
+/*
+ * ======== CLK_Init ========
+ * Purpose:
+ * Initializes private state of CLK module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * CLK initialized.
+ */
+ extern bool CLK_Init(void);
+
+
+/*
+ * ======== CLK_Enable ========
+ * Purpose:
+ * Enables the clock requested.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Error occured while enabling the clock.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id);
+
+/*
+ * ======== CLK_Disable ========
+ * Purpose:
+ * Disables the clock requested.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Error occured while disabling the clock.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id);
+
+/*
+ * ======== CLK_GetRate ========
+ * Purpose:
+ * Get the clock rate of requested clock.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Error occured while Getting the clock rate.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id,
+ u32 *speedMhz);
+/*
+ * ======== CLK_Set_32KHz ========
+ * Purpose:
+ * Set the requested clock to 32KHz.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Error occured while setting the clock parent to 32KHz.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id);
+ extern void SSI_Clk_Prepare(bool FLAG);
+
+/*
+ * ======== CLK_Get_RefCnt ========
+ * Purpose:
+ * get the reference count for the clock.
+ * Parameters:
+ * Returns:
+ * s32: Reference Count for the clock.
+ * DSP_EFAIL: Error occured while getting the reference count of a clock.
+ * Requires:
+ * Ensures:
+ */
+ extern s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id);
+
+#endif /* _SYNC_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/cmm.h b/arch/arm/plat-omap/include/dspbridge/cmm.h
new file mode 100644
index 000000000000..0df8b832b3d6
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/cmm.h
@@ -0,0 +1,420 @@
+/*
+ * cmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== cmm.h ========
+ * Purpose:
+ * The Communication Memory Management(CMM) module provides shared memory
+ * management services for DSP/BIOS Bridge data streaming and messaging.
+ * Multiple shared memory segments can be registered with CMM. Memory is
+ * coelesced back to the appropriate pool when a buffer is freed.
+ *
+ * The CMM_Xlator[xxx] functions are used for node messaging and data
+ * streaming address translation to perform zero-copy inter-processor
+ * data transfer(GPP<->DSP). A "translator" object is created for a node or
+ * stream object that contains per thread virtual address information. This
+ * translator info is used at runtime to perform SM address translation
+ * to/from the DSP address space.
+ *
+ *
+ * Public Functions:
+ * CMM_CallocBuf
+ * CMM_Create
+ * CMM_Destroy
+ * CMM_Exit
+ * CMM_FreeBuf
+ * CMM_GetHandle
+ * CMM_GetInfo
+ * CMM_Init
+ * CMM_RegisterGPPSMSeg
+ * CMM_UnRegisterGPPSMSeg
+ * CMM_XlatorAllocBuf (Note #1 below)
+ * CMM_XlatorCreate "
+ * CMM_XlatorDelete "
+ * CMM_XlatorFreeBuf "
+ * CMM_XlatorTranslate "
+ *
+ *
+ * Notes:
+ * #1: Used by Node and Stream modules for SM address translation.
+ *
+ *! Revision History:
+ *! ================
+ *! 30-Jan-2002 ag Removed unused CMM_Alloc[Free]Desc & CMM_XlatorRegisterPa.
+ *! Renamed CMM_AllocBuf() to CMM_CallocBuf().
+ *! 29-Aug-2001 ag: Added dsp virt base and size to CMM_RegisterGPPSMSeg().
+ *! 12-Aug-2001 ag: Added CMM_UnRegisterGPP[DSP}SMSeg[s]().
+ *! 05-Dec-2000 ag: Added param to CMM_XlatorDelete() to force buf cleanup.
+ *! 30-Oct-2000 ag: Added conversion factor to CMM_RegisterDSP[GPP]SMSeg().
+ *! 12-Oct-2000 ag: Added CMM_Xlator[xxx] functions.
+ *! 10-Aug-2000 ag: Created.
+ *!
+ */
+
+#ifndef CMM_
+#define CMM_
+
+#include <dspbridge/devdefs.h>
+
+#include <dspbridge/cmmdefs.h>
+#include <dspbridge/host_os.h>
+
+/*
+ * ======== CMM_CallocBuf ========
+ * Purpose:
+ * Allocate memory buffers that can be used for data streaming or
+ * messaging.
+ * Parameters:
+ * hCmmMgr: Cmm Mgr handle.
+ * uSize: Number of bytes to allocate.
+ * pAttr: Attributes of memory to allocate.
+ * ppBufVA: Address of where to place VA.
+ * Returns:
+ * Pointer to a zero'd block of SM memory;
+ * NULL if memory couldn't be allocated,
+ * or if cBytes == 0,
+ * Requires:
+ * Valid hCmmMgr.
+ * CMM initialized.
+ * Ensures:
+ * The returned pointer, if not NULL, points to a valid memory block of
+ * the size requested.
+ *
+ */
+ extern void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr,
+ u32 uSize, struct CMM_ATTRS *pAttrs,
+ OUT void **ppBufVA);
+
+/*
+ * ======== CMM_Create ========
+ * Purpose:
+ * Create a communication memory manager object.
+ * Parameters:
+ * phCmmMgr: Location to store a communication manager handle on output.
+ * hDevObject: Handle to a device object.
+ * pMgrAttrs: Comm mem manager attributes.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * DSP_EFAIL: Failed to initialize critical sect sync object.
+ *
+ * Requires:
+ * CMM_Init(void) called.
+ * phCmmMgr != NULL.
+ * pMgrAttrs->ulMinBlockSize >= 4 bytes.
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CMM_MGRATTRS *pMgrAttrs);
+
+/*
+ * ======== CMM_Destroy ========
+ * Purpose:
+ * Destroy the communication memory manager object.
+ * Parameters:
+ * hCmmMgr: Cmm Mgr handle.
+ * bForce: Force deallocation of all cmm memory immediately if set TRUE.
+ * If FALSE, and outstanding allocations will return DSP_EFAIL
+ * status.
+ * Returns:
+ * DSP_SOK: CMM object & resources deleted.
+ * DSP_EFAIL: Unable to free CMM object due to outstanding allocation.
+ * DSP_EHANDLE: Unable to free CMM due to bad handle.
+ * Requires:
+ * CMM is initialized.
+ * hCmmMgr != NULL.
+ * Ensures:
+ * Memory resources used by Cmm Mgr are freed.
+ */
+ extern DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce);
+
+/*
+ * ======== CMM_Exit ========
+ * Purpose:
+ * Discontinue usage of module. Cleanup CMM module if CMM cRef reaches zero.
+ * Parameters:
+ * n/a
+ * Returns:
+ * n/a
+ * Requires:
+ * CMM is initialized.
+ * Ensures:
+ */
+ extern void CMM_Exit(void);
+
+/*
+ * ======== CMM_FreeBuf ========
+ * Purpose:
+ * Free the given buffer.
+ * Parameters:
+ * hCmmMgr: Cmm Mgr handle.
+ * pBuf: Pointer to memory allocated by CMM_CallocBuf().
+ * ulSegId: SM segment Id used in CMM_Calloc() attrs.
+ * Set to 0 to use default segment.
+ * Returns:
+ * DSP_SOK
+ * DSP_EFAIL
+ * Requires:
+ * CMM initialized.
+ * pBufPA != NULL
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr,
+ void *pBufPA, u32 ulSegId);
+
+/*
+ * ======== CMM_GetHandle ========
+ * Purpose:
+ * Return the handle to the cmm mgr for the given device obj.
+ * Parameters:
+ * hProcessor: Handle to a Processor.
+ * phCmmMgr: Location to store the shared memory mgr handle on output.
+ *
+ * Returns:
+ * DSP_SOK: Cmm Mgr opaque handle returned.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * phCmmMgr != NULL
+ * hDevObject != NULL
+ * Ensures:
+ */
+ extern DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
+ OUT struct CMM_OBJECT **phCmmMgr);
+
+/*
+ * ======== CMM_GetInfo ========
+ * Purpose:
+ * Return the current SM and VM utilization information.
+ * Parameters:
+ * hCmmMgr: Handle to a Cmm Mgr.
+ * pCmmInfo: Location to store the Cmm information on output.
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid handle.
+ * DSP_EINVALIDARG Invalid input argument.
+ * Requires:
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
+ OUT struct CMM_INFO *pCmmInfo);
+
+/*
+ * ======== CMM_Init ========
+ * Purpose:
+ * Initializes private state of CMM module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * CMM initialized.
+ */
+ extern bool CMM_Init(void);
+
+/*
+ * ======== CMM_RegisterGPPSMSeg ========
+ * Purpose:
+ * Register a block of SM with the CMM.
+ * Parameters:
+ * hCmmMgr: Handle to a Cmm Mgr.
+ * lpGPPBasePA: GPP Base Physical address.
+ * ulSize: Size in GPP bytes.
+ * dwDSPAddrOffset GPP PA to DSP PA Offset.
+ * cFactor: Add offset if CMM_ADDTODSPPA, sub if CMM_SUBFROMDSPPA.
+ * dwDSPBase: DSP virtual base byte address.
+ * ulDSPSize: Size of DSP segment in bytes.
+ * pulSegId: Address to store segment Id.
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hCmmMgr handle.
+ * DSP_EINVALIDARG: Invalid input argument.
+ * DSP_EFAIL: Unable to register.
+ * - On success *pulSegId is a valid SM segment ID.
+ * Requires:
+ * ulSize > 0
+ * pulSegId != NULL
+ * dwGPPBasePA != 0
+ * cFactor = CMM_ADDTODSPPA || cFactor = CMM_SUBFROMDSPPA
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
+ unsigned int dwGPPBasePA,
+ u32 ulSize,
+ u32 dwDSPAddrOffset,
+ enum CMM_CNVTTYPE cFactor,
+ unsigned int dwDSPBase,
+ u32 ulDSPSize,
+ u32 *pulSegId,
+ u32 dwGPPBaseBA);
+
+/*
+ * ======== CMM_UnRegisterGPPSMSeg ========
+ * Purpose:
+ * Unregister the given memory segment that was previously registered
+ * by CMM_RegisterGPPSMSeg.
+ * Parameters:
+ * hCmmMgr: Handle to a Cmm Mgr.
+ * ulSegId Segment identifier returned by CMM_RegisterGPPSMSeg.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid handle.
+ * DSP_EINVALIDARG: Invalid ulSegId.
+ * DSP_EFAIL: Unable to unregister for unknown reason.
+ * Requires:
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
+ u32 ulSegId);
+
+/*
+ * ======== CMM_XlatorAllocBuf ========
+ * Purpose:
+ * Allocate the specified SM buffer and create a local memory descriptor.
+ * Place on the descriptor on the translator's HaQ (Host Alloc'd Queue).
+ * Parameters:
+ * hXlator: Handle to a Xlator object.
+ * pVaBuf: Virtual address ptr(client context)
+ * uPaSize: Size of SM memory to allocate.
+ * Returns:
+ * Ptr to valid physical address(Pa) of uPaSize bytes, NULL if failed.
+ * Requires:
+ * pVaBuf != 0.
+ * uPaSize != 0.
+ * Ensures:
+ *
+ */
+ extern void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator,
+ void *pVaBuf, u32 uPaSize);
+
+/*
+ * ======== CMM_XlatorCreate ========
+ * Purpose:
+ * Create a translator(xlator) object used for process specific Va<->Pa
+ * address translation. Node messaging and streams use this to perform
+ * inter-processor(GPP<->DSP) zero-copy data transfer.
+ * Parameters:
+ * phXlator: Address to place handle to a new Xlator handle.
+ * hCmmMgr: Handle to Cmm Mgr associated with this translator.
+ * pXlatorAttrs: Translator attributes used for the client NODE or STREAM.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EINVALIDARG: Bad input Attrs.
+ * DSP_EMEMORY: Insufficient memory(local) for requested resources.
+ * Requires:
+ * phXlator != NULL
+ * hCmmMgr != NULL
+ * pXlatorAttrs != NULL
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
+ struct CMM_OBJECT *hCmmMgr,
+ struct CMM_XLATORATTRS *pXlatorAttrs);
+
+/*
+ * ======== CMM_XlatorDelete ========
+ * Purpose:
+ * Delete translator resources
+ * Parameters:
+ * hXlator: handle to translator.
+ * bForce: bForce = TRUE will free XLators SM buffers/dscriptrs.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Bad translator handle.
+ * DSP_EFAIL: Unable to free translator resources.
+ * Requires:
+ * cRefs > 0
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator,
+ bool bForce);
+
+/*
+ * ======== CMM_XlatorFreeBuf ========
+ * Purpose:
+ * Free SM buffer and descriptor.
+ * Does not free client process VM.
+ * Parameters:
+ * hXlator: handle to translator.
+ * pBufVa Virtual address of PA to free.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Bad translator handle.
+ * Requires:
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator,
+ void *pBufVa);
+
+/*
+ * ======== CMM_XlatorInfo ========
+ * Purpose:
+ * Set/Get process specific "translator" address info.
+ * This is used to perform fast virtaul address translation
+ * for shared memory buffers between the GPP and DSP.
+ * Parameters:
+ * hXlator: handle to translator.
+ * pAddr: Virtual base address of segment.
+ * ulSize: Size in bytes.
+ * uSegId: Segment identifier of SM segment(s)
+ * bSetInfo Set xlator fields if TRUE, else return base addr
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Bad translator handle.
+ * Requires:
+ * (cRefs > 0)
+ * (pAddr != NULL)
+ * (ulSize > 0)
+ * Ensures:
+ *
+ */
+ extern DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator,
+ IN OUT u8 **pAddr,
+ u32 ulSize, u32 uSegId,
+ bool bSetInfo);
+
+/*
+ * ======== CMM_XlatorTranslate ========
+ * Purpose:
+ * Perform address translation VA<->PA for the specified stream or
+ * message shared memory buffer.
+ * Parameters:
+ * hXlator: handle to translator.
+ * pAddr address of buffer to translate.
+ * xType Type of address xlation. CMM_PA2VA or CMM_VA2PA.
+ * Returns:
+ * Valid address on success, else NULL.
+ * Requires:
+ * cRefs > 0
+ * pAddr != NULL
+ * xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA)
+ * Ensures:
+ *
+ */
+ extern void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator,
+ void *pAddr, enum CMM_XLATETYPE xType);
+
+#endif /* CMM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/cmmdefs.h b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
new file mode 100644
index 000000000000..a77937782528
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
@@ -0,0 +1,135 @@
+/*
+ * cmmdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== cmmdefs.h ========
+ * Purpose:
+ * Global MEM constants and types.
+ *
+ *! Revision History:
+ *! ================
+ *! 12-Nov-2001 ag CMM_KERNMAPTYPE added for dsp<->device process addr map'n.
+ *! This allows addr conversion from drvr process <-> DSP addr.
+ *! 29-Aug-2001 ag Added CMM_ALLSEGMENTS.
+ *! 08-Dec-2000 ag Added bus address conversion type CMM_POMAPEMIF2DSPBUS.
+ *! 05-Dec-2000 ag Added default CMM_DEFLTCONVFACTOR & CMM_DEFLTDSPADDROFFSET.
+ *! 29-Oct-2000 ag Added converstion factor for GPP DSP Pa translation.
+ *! 15-Oct-2000 ag Added address translator attributes and defaults.
+ *! 12-Jul-2000 ag Created.
+ */
+
+#ifndef CMMDEFS_
+#define CMMDEFS_
+
+#include <dspbridge/list.h>
+
+/* Cmm attributes used in CMM_Create() */
+ struct CMM_MGRATTRS {
+ /* Minimum SM allocation; default 32 bytes. */
+ u32 ulMinBlockSize;
+ } ;
+
+/* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
+ struct CMM_ATTRS {
+ u32 ulSegId; /* 1,2... are SM segments. 0 is not. */
+ u32 ulAlignment; /* 0,1,2,4....ulMinBlockSize */
+ } ;
+
+/*
+ * DSPPa to GPPPa Conversion Factor.
+ *
+ * For typical platforms:
+ * converted Address = PaDSP + ( cFactor * addressToConvert).
+ */
+ enum CMM_CNVTTYPE {
+ CMM_SUBFROMDSPPA = -1,
+ /* PreOMAP is special case: not simple offset */
+ CMM_POMAPEMIF2DSPBUS = 0,
+ CMM_ADDTODSPPA = 1
+ } ;
+
+#define CMM_DEFLTDSPADDROFFSET 0
+#define CMM_DEFLTCONVFACTOR CMM_POMAPEMIF2DSPBUS /* PreOMAP DSPBUS<->EMIF */
+#define CMM_ALLSEGMENTS 0xFFFFFF /* All SegIds */
+#define CMM_MAXGPPSEGS 1 /* Maximum # of SM segs */
+
+/*
+ * SMSEGs are SM segments the DSP allocates from.
+ *
+ * This info is used by the GPP to xlate DSP allocated PAs.
+ */
+
+ struct CMM_SEGINFO {
+ u32 dwSegBasePa; /* Start Phys address of SM segment */
+ /* Total size in bytes of segment: DSP+GPP */
+ u32 ulTotalSegSize;
+ u32 dwGPPBasePA; /* Start Phys addr of Gpp SM seg */
+ u32 ulGPPSize; /* Size of Gpp SM seg in bytes */
+ u32 dwDSPBaseVA; /* DSP virt base byte address */
+ u32 ulDSPSize; /* DSP seg size in bytes */
+ /* # of current GPP allocations from this segment */
+ u32 ulInUseCnt;
+ u32 dwSegBaseVa; /* Start Virt address of SM seg */
+
+ } ;
+
+/* CMM useful information */
+ struct CMM_INFO {
+ /* # of SM segments registered with this Cmm. */
+ u32 ulNumGPPSMSegs;
+ /* Total # of allocations outstanding for CMM */
+ u32 ulTotalInUseCnt;
+ /* Min SM block size allocation from CMM_Create() */
+ u32 ulMinBlockSize;
+ /* Info per registered SM segment. */
+ struct CMM_SEGINFO segInfo[CMM_MAXGPPSEGS];
+ } ;
+
+/* XlatorCreate attributes */
+ struct CMM_XLATORATTRS {
+ u32 ulSegId; /* segment Id used for SM allocations */
+ u32 dwDSPBufs; /* # of DSP-side bufs */
+ u32 dwDSPBufSize; /* size of DSP-side bufs in GPP bytes */
+ /* Vm base address alloc'd in client process context */
+ void *pVmBase;
+ /* dwVmSize must be >= (dwMaxNumBufs * dwMaxSize) */
+ u32 dwVmSize;
+ } ;
+
+/*
+ * Cmm translation types. Use to map SM addresses to process context.
+ */
+ enum CMM_XLATETYPE {
+ CMM_VA2PA = 0, /* Virtual to GPP physical address xlation */
+ CMM_PA2VA = 1, /* GPP Physical to virtual */
+ CMM_VA2DSPPA = 2, /* Va to DSP Pa */
+ CMM_PA2DSPPA = 3, /* GPP Pa to DSP Pa */
+ CMM_DSPPA2PA = 4, /* DSP Pa to GPP Pa */
+ } ;
+
+/*
+ * Used to "map" between device process virt addr and dsp addr.
+ */
+ enum CMM_KERNMAPTYPE {
+ CMM_KERNVA2DSP = 0, /* Device process context to dsp address. */
+ CMM_DSP2KERNVA = 1, /* Dsp address to device process context. */
+ } ;
+
+ struct CMM_OBJECT;
+ struct CMM_XLATOROBJECT;
+
+#endif /* CMMDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/cod.h b/arch/arm/plat-omap/include/dspbridge/cod.h
new file mode 100644
index 000000000000..a8a12c638746
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/cod.h
@@ -0,0 +1,433 @@
+/*
+ * cod.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cod.h ========
+ * Description:
+ * Code management module for DSPs. This module provides an interface
+ * interface for loading both static and dynamic code objects onto DSP
+ * systems.
+ *
+ * Public Functions:
+ * COD_Close
+ * COD_Create
+ * COD_Delete
+ * COD_Exit
+ * COD_GetBaseLib
+ * COD_GetBaseName
+ * COD_GetLoader
+ * COD_GetSection
+ * COD_GetSymValue
+ * COD_Init
+ * COD_LoadBase
+ * COD_Open
+ * COD_OpenBase
+ * COD_ReadSection
+ * COD_UnloadSection
+ *
+ * Note:
+ * Currently, only static loading is supported.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Apr-2003 map: Changed DBL to DBLL
+ *! 07-Aug-2002 jeh: Added COD_GetBaseName().
+ *! 17-Jul-2002 jeh: Added COD_Open(), COD_Close().
+ *! 15-Mar-2002 jeh: Added DBL_Flags param to COD_OpenBase().
+ *! 19-Oct-2001 jeh: Added COD_GetBaseLib, COD_GetLoader, (left in
+ *! COD_LoadSection(), COD_UnloadSection(), since they
+ *! may be needed for BridgeLite).
+ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
+ *! 11-Jan-2001 jeh: Added COD_OpenBase.
+ *! 29-Sep-2000 kc: Added size param to COD_ReadSection for input buffer
+ *! validation.
+ *! 02-Aug-2000 kc: Added COD_ReadSection.
+ *! 04-Sep-1997 gp: Added CDECL identifier to COD_WRITEFXN (for NT)..
+ *! 18-Aug-1997 cr: Added explicit CDECL identifier.
+ *! 28-Oct-1996 gp: Added COD_GetSection.
+ *! 30-Jul-1996 gp: Added envp[] argument to COD_LoadBase().
+ *! 12-Jun-1996 gp: Moved OUT param first in _Create(). Updated _Create()
+ *! call to take a ZLFileName. Moved COD_ processor types
+ *! to CFG.
+ *! 29-May-1996 gp: Changed WCD_STATUS to DSP_STATUS. Removed include's.
+ *! 07-May-1996 mg: Created.
+ *
+ */
+
+#ifndef COD_
+#define COD_
+
+#include <dspbridge/dblldefs.h>
+
+#define COD_MAXPATHLENGTH 255
+#define COD_TRACEBEG "SYS_PUTCBEG"
+#define COD_TRACEEND "SYS_PUTCEND"
+#define COD_TRACESECT "trace"
+#define COD_TRACEBEGOLD "PUTCBEG"
+#define COD_TRACEENDOLD "PUTCEND"
+
+#define COD_NOLOAD DBLL_NOLOAD
+#define COD_SYMB DBLL_SYMB
+
+/* Flags passed to COD_Open */
+ typedef DBLL_Flags COD_FLAGS;
+
+/* COD code manager handle */
+ struct COD_MANAGER;
+
+/* COD library handle */
+ struct COD_LIBRARYOBJ;
+
+/* COD attributes */
+ struct COD_ATTRS {
+ u32 ulReserved;
+ } ;
+
+/*
+ * Function prototypes for writing memory to a DSP system, allocating
+ * and freeing DSP memory.
+ */
+ typedef u32(*COD_WRITEFXN) (void *pPrivRef, u32 ulDspAddr,
+ void *pBuf, u32 ulNumBytes,
+ u32 nMemSpace);
+
+
+/*
+ * ======== COD_Close ========
+ * Purpose:
+ * Close a library opened with COD_Open().
+ * Parameters:
+ * lib - Library handle returned by COD_Open().
+ * Returns:
+ * None.
+ * Requires:
+ * COD module initialized.
+ * valid lib.
+ * Ensures:
+ *
+ */
+ extern void COD_Close(struct COD_LIBRARYOBJ *lib);
+
+/*
+ * ======== COD_Create ========
+ * Purpose:
+ * Create an object to manage code on a DSP system. This object can be
+ * used to load an initial program image with arguments that can later
+ * be expanded with dynamically loaded object files.
+ * Symbol table information is managed by this object and can be retrieved
+ * using the COD_GetSymValue() function.
+ * Parameters:
+ * phManager: created manager object
+ * pstrZLFile: ZL DLL filename, of length < COD_MAXPATHLENGTH.
+ * attrs: attributes to be used by this object. A NULL value
+ * will cause default attrs to be used.
+ * Returns:
+ * DSP_SOK: Success.
+ * COD_E_NOZLFUNCTIONS: Could not initialize ZL functions.
+ * COD_E_ZLCREATEFAILED: ZL_Create failed.
+ * DSP_ENOTIMPL: attrs was not NULL. We don't yet support
+ * non default values of attrs.
+ * Requires:
+ * COD module initialized.
+ * pstrZLFile != NULL
+ * Ensures:
+ */
+ extern DSP_STATUS COD_Create(OUT struct COD_MANAGER **phManager,
+ char *pstrZLFile,
+ IN OPTIONAL CONST struct COD_ATTRS *attrs);
+
+/*
+ * ======== COD_Delete ========
+ * Purpose:
+ * Delete a code manager object.
+ * Parameters:
+ * hManager: handle of manager to be deleted
+ * Returns:
+ * None.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * Ensures:
+ */
+ extern void COD_Delete(struct COD_MANAGER *hManager);
+
+/*
+ * ======== COD_Exit ========
+ * Purpose:
+ * Discontinue usage of the COD module.
+ * Parameters:
+ * None.
+ * Returns:
+ * None.
+ * Requires:
+ * COD initialized.
+ * Ensures:
+ * Resources acquired in COD_Init(void) are freed.
+ */
+ extern void COD_Exit(void);
+
+/*
+ * ======== COD_GetBaseLib ========
+ * Purpose:
+ * Get handle to the base image DBL library.
+ * Parameters:
+ * hManager: handle of manager to be deleted
+ * plib: location to store library handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * plib != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
+ struct DBLL_LibraryObj **plib);
+
+/*
+ * ======== COD_GetBaseName ========
+ * Purpose:
+ * Get the name of the base image DBL library.
+ * Parameters:
+ * hManager: handle of manager to be deleted
+ * pszName: location to store library name on output.
+ * uSize: size of name buffer.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Buffer too small.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * pszName != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager,
+ char *pszName, u32 uSize);
+
+/*
+ * ======== COD_GetEntry ========
+ * Purpose:
+ * Retrieve the entry point of a loaded DSP program image
+ * Parameters:
+ * hManager: handle of manager to be deleted
+ * pulEntry: pointer to location for entry point
+ * Returns:
+ * DSP_SOK: Success.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * pulEntry != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager,
+ u32 *pulEntry);
+
+/*
+ * ======== COD_GetLoader ========
+ * Purpose:
+ * Get handle to the DBL loader.
+ * Parameters:
+ * hManager: handle of manager to be deleted
+ * phLoader: location to store loader handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * phLoader != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
+ struct DBLL_TarObj **phLoader);
+
+/*
+ * ======== COD_GetSection ========
+ * Purpose:
+ * Retrieve the starting address and length of a section in the COFF file
+ * given the section name.
+ * Parameters:
+ * lib Library handle returned from COD_Open().
+ * pstrSect: name of the section, with or without leading "."
+ * puAddr: Location to store address.
+ * puLen: Location to store length.
+ * Returns:
+ * DSP_SOK: Success
+ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
+ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * pstrSect != NULL;
+ * puAddr != NULL;
+ * puLen != NULL;
+ * Ensures:
+ * DSP_SOK: *puAddr and *puLen contain the address and length of the
+ * section.
+ * else: *puAddr == 0 and *puLen == 0;
+ *
+ */
+ extern DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib,
+ IN char *pstrSect,
+ OUT u32 *puAddr,
+ OUT u32 *puLen);
+
+/*
+ * ======== COD_GetSymValue ========
+ * Purpose:
+ * Retrieve the value for the specified symbol. The symbol is first
+ * searched for literally and then, if not found, searched for as a
+ * C symbol.
+ * Parameters:
+ * lib: library handle returned from COD_Open().
+ * pstrSymbol: name of the symbol
+ * value: value of the symbol
+ * Returns:
+ * DSP_SOK: Success.
+ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
+ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
+ * Requires:
+ * COD module initialized.
+ * Valid hManager.
+ * pstrSym != NULL.
+ * pulValue != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hManager,
+ IN char *pstrSym,
+ OUT u32 *pulValue);
+
+/*
+ * ======== COD_Init ========
+ * Purpose:
+ * Initialize the COD module's private state.
+ * Parameters:
+ * None.
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public COD functions.
+ */
+ extern bool COD_Init(void);
+
+/*
+ * ======== COD_LoadBase ========
+ * Purpose:
+ * Load the initial program image, optionally with command-line arguments,
+ * on the DSP system managed by the supplied handle. The program to be
+ * loaded must be the first element of the args array and must be a fully
+ * qualified pathname.
+ * Parameters:
+ * hMgr: manager to load the code with
+ * nArgc: number of arguments in the args array
+ * args: array of strings for arguments to DSP program
+ * writeFxn: board-specific function to write data to DSP system
+ * pArb: arbitrary pointer to be passed as first arg to writeFxn
+ * envp: array of environment strings for DSP exec.
+ * Returns:
+ * DSP_SOK: Success.
+ * COD_E_OPENFAILED: Failed to open target code.
+ * COD_E_LOADFAILED: Failed to load code onto target.
+ * Requires:
+ * COD module initialized.
+ * hMgr is valid.
+ * nArgc > 0.
+ * aArgs != NULL.
+ * aArgs[0] != NULL.
+ * pfnWrite != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_LoadBase(struct COD_MANAGER *hManager,
+ u32 nArgc, char *aArgs[],
+ COD_WRITEFXN pfnWrite, void *pArb,
+ char *envp[]);
+
+
+/*
+ * ======== COD_Open ========
+ * Purpose:
+ * Open a library for reading sections. Does not load or set the base.
+ * Parameters:
+ * hMgr: manager to load the code with
+ * pszCoffPath: Coff file to open.
+ * flags: COD_NOLOAD (don't load symbols) or COD_SYMB (load
+ * symbols).
+ * pLib: Handle returned that can be used in calls to COD_Close
+ * and COD_GetSection.
+ * Returns:
+ * S_OK: Success.
+ * COD_E_OPENFAILED: Failed to open target code.
+ * Requires:
+ * COD module initialized.
+ * hMgr is valid.
+ * flags == COD_NOLOAD || flags == COD_SYMB.
+ * pszCoffPath != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS COD_Open(struct COD_MANAGER *hMgr,
+ IN char *pszCoffPath,
+ COD_FLAGS flags,
+ OUT struct COD_LIBRARYOBJ **pLib);
+
+/*
+ * ======== COD_OpenBase ========
+ * Purpose:
+ * Open base image for reading sections. Does not load the base.
+ * Parameters:
+ * hMgr: manager to load the code with
+ * pszCoffPath: Coff file to open.
+ * flags: Specifies whether to load symbols.
+ * Returns:
+ * DSP_SOK: Success.
+ * COD_E_OPENFAILED: Failed to open target code.
+ * Requires:
+ * COD module initialized.
+ * hMgr is valid.
+ * pszCoffPath != NULL.
+ * Ensures:
+ */
+extern DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
+ DBLL_Flags flags);
+
+/*
+ * ======== COD_ReadSection ========
+ * Purpose:
+ * Retrieve the content of a code section given the section name.
+ * Parameters:
+ * hManager - manager in which to search for the symbol
+ * pstrSect - name of the section, with or without leading "."
+ * pstrContent - buffer to store content of the section.
+ * Returns:
+ * DSP_SOK: on success, error code on failure
+ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
+ * COD_E_READFAILED: Failed to read content of code section.
+ * Requires:
+ * COD module initialized.
+ * valid hManager.
+ * pstrSect != NULL;
+ * pstrContent != NULL;
+ * Ensures:
+ * DSP_SOK: *pstrContent stores the content of the named section.
+ */
+ extern DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib,
+ IN char *pstrSect,
+ OUT char *pstrContent,
+ IN u32 cContentSize);
+
+
+
+#endif /* COD_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/csl.h b/arch/arm/plat-omap/include/dspbridge/csl.h
new file mode 100644
index 000000000000..b90d6ff14346
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/csl.h
@@ -0,0 +1,135 @@
+/*
+ * csl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== csl.h ========
+ * Purpose:
+ * Platform independent C Standard library functions.
+ *
+ * Public Functions:
+ * CSL_AnsiToWchar
+ * CSL_ByteSwap
+ * CSL_Exit
+ * CSL_Init
+ * CSL_NumToAscii
+ * CSL_Strtok
+ * CSL_Strtokr
+ * CSL_WcharToAnsi
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
+ *! 21-Sep-2001 jeh: Added CSL_Strncmp.
+ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
+ *! 19-Nov-2000 kc: Added CSL_ByteSwap().
+ *! 09-Nov-2000 kc: Added CSL_Strncat.
+ *! 29-Oct-1999 kc: Added CSL_Wstrlen().
+ *! 20-Sep-1999 ag: Added CSL_Wchar2Ansi().
+ *! 19-Jan-1998 cr: Code review cleanup (mostly documentation fixes).
+ *! 29-Dec-1997 cr: Changed CSL_lowercase to CSL_Uppercase, added
+ *! CSL_AnsiToWchar.
+ *! 30-Sep-1997 cr: Added explicit cdecl descriptors to fxn definitions.
+ *! 25-Jun-1997 cr: Added CSL_strcmp.
+ *! 12-Jun-1996 gp: Created.
+ */
+
+#ifndef CSL_
+#define CSL_
+
+#include <dspbridge/host_os.h>
+
+/*
+ * ======== CSL_Exit ========
+ * Purpose:
+ * Discontinue usage of the CSL module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * CSL initialized.
+ * Ensures:
+ * Resources acquired in CSL_Init(void) are freed.
+ */
+ extern void CSL_Exit(void);
+
+/*
+ * ======== CSL_Init ========
+ * Purpose:
+ * Initialize the CSL module's private state.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public CSL functions.
+ */
+ extern bool CSL_Init(void);
+
+/*
+ * ======== CSL_NumToAscii ========
+ * Purpose:
+ * Convert a 1 or 2 digit number to a 2 digit string.
+ * Parameters:
+ * pstrNumber: Buffer to store converted string.
+ * dwNum: Number to convert.
+ * Returns:
+ * Requires:
+ * pstrNumber must be able to hold at least three characters.
+ * Ensures:
+ * pstrNumber will be null terminated.
+ */
+ extern void CSL_NumToAscii(OUT char *pstrNumber, IN u32 dwNum);
+
+
+/*
+ * ======== CSL_Strtok ========
+ * Purpose:
+ * Tokenize a NULL terminated string
+ * Parameters:
+ * ptstrSrc: pointer to string.
+ * szSeparators: pointer to a string of seperators
+ * Returns:
+ * char *
+ * Requires:
+ * CSL initialized.
+ * ptstrSrc is a valid string pointer.
+ * szSeparators is a valid string pointer.
+ * Ensures:
+ */
+ extern char *CSL_Strtok(IN char *ptstrSrc,
+ IN CONST char *szSeparators);
+
+/*
+ * ======== CSL_Strtokr ========
+ * Purpose:
+ * Re-entrant version of strtok.
+ * Parameters:
+ * pstrSrc: Pointer to string. May be NULL on subsequent calls.
+ * szSeparators: Pointer to a string of seperators
+ * ppstrCur: Location to store start of string for next call to
+ * to CSL_Strtokr.
+ * Returns:
+ * char * (the token)
+ * Requires:
+ * CSL initialized.
+ * szSeparators != NULL
+ * ppstrCur != NULL
+ * Ensures:
+ */
+ extern char *CSL_Strtokr(IN char *pstrSrc,
+ IN CONST char *szSeparators,
+ OUT char **ppstrCur);
+
+#endif /* CSL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbc.h b/arch/arm/plat-omap/include/dspbridge/dbc.h
new file mode 100644
index 000000000000..0e6a67d4f6d3
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbc.h
@@ -0,0 +1,66 @@
+/*
+ * dbc.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== dbc.h ========
+ * Purpose:
+ * "Design by Contract" programming macros.
+ *
+ * Public Functions:
+ * DBC_Assert
+ * DBC_Require
+ * DBC_Ensure
+ *
+ * Notes:
+ * Requires that the GT->ERROR function has been defaulted to a valid
+ * error handler for the given execution environment.
+ *
+ * Does not require that GT_init() be called.
+ *
+ *! Revision History:
+ *! ================
+ *! 11-Aug-2000 ag: Removed include <dspbridge/std.h>
+ *! 22-Apr-1996 gp: Created.
+ */
+
+#ifndef DBC_
+#define DBC_
+
+#ifndef GT_TRACE
+#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
+#endif
+
+/* Assertion Macros: */
+#if GT_TRACE
+
+#include <dspbridge/gt.h>
+
+#define DBC_Assert(exp) \
+ if (!(exp)) \
+ printk("%s, line %d: Assertion (" #exp ") failed.\n", \
+ __FILE__, __LINE__)
+#define DBC_Require DBC_Assert /* Function Precondition. */
+#define DBC_Ensure DBC_Assert /* Function Postcondition. */
+
+#else
+
+#define DBC_Assert(exp)
+#define DBC_Require(exp)
+#define DBC_Ensure(exp)
+
+#endif /* DEBUG */
+
+#endif /* DBC_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcd.h b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
new file mode 100644
index 000000000000..fbc3870455d4
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
@@ -0,0 +1,388 @@
+/*
+ * dbdcd.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== dbdcd.h ========
+ * Description:
+ * Defines the DSP/BIOS Bridge Configuration Database (DCD) API.
+ *
+ *! Revision History
+ *! ================
+ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
+ *! 24-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
+ *! DCD implementation.
+ *! 05-Aug-2002 jeh Added DCD_GetObjects().
+ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
+ *! 22-Apr-2002 jeh Added DCD_GetLibraryName().
+ *! 03-Apr-2001 sg Changed error names to have DCD_E* format.
+ *! 13-Feb-2001 kc Name changed from dcdbs.h to dbdcd.h.
+ *! 12-Dec-2000 kc Added DCD_AutoUnregister.
+ *! 09-Nov-2000 kc Updated usage of DCD_EnumerateObject.
+ *! 30-Oct-2000 kc Added DCD_AutoRegister. Updated error DCD error codes.
+ *! 29-Sep-2000 kc Incorporated code review comments. See
+ *! /src/reviews/dcd_review.txt.
+ *! 26-Jul-2000 kc Created.
+ *!
+ */
+
+#ifndef DBDCD_
+#define DBDCD_
+
+#include <dspbridge/dbdcddef.h>
+#include <dspbridge/host_os.h>
+#include <dspbridge/nldrdefs.h>
+
+/*
+ * ======== DCD_AutoRegister ========
+ * Purpose:
+ * This function automatically registers DCD objects specified in a
+ * special COFF section called ".dcd_register"
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pszCoffPath: Pointer to name of COFF file containing DCD
+ * objects to be registered.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
+ * DSP_EDCDREADSECT: Unable to read object code section.
+ * DSP_EDCDLOADBASE: Unable to load code base.
+ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
+ * Requires:
+ * DCD initialized.
+ * Ensures:
+ * Note:
+ * Due to the DCD database construction, it is essential for a DCD-enabled
+ * COFF file to contain the right COFF sections, especially
+ * ".dcd_register", which is used for auto registration.
+ */
+ extern DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
+ IN char *pszCoffPath);
+
+/*
+ * ======== DCD_AutoUnregister ========
+ * Purpose:
+ * This function automatically unregisters DCD objects specified in a
+ * special COFF section called ".dcd_register"
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pszCoffPath: Pointer to name of COFF file containing
+ * DCD objects to be unregistered.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
+ * DSP_EDCDREADSECT: Unable to read object code section.
+ * DSP_EDCDLOADBASE: Unable to load code base.
+ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
+ * Requires:
+ * DCD initialized.
+ * Ensures:
+ * Note:
+ * Due to the DCD database construction, it is essential for a DCD-enabled
+ * COFF file to contain the right COFF sections, especially
+ * ".dcd_register", which is used for auto unregistration.
+ */
+ extern DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
+ IN char *pszCoffPath);
+
+/*
+ * ======== DCD_CreateManager ========
+ * Purpose:
+ * This function creates a DCD module manager.
+ * Parameters:
+ * pszZlDllName: Pointer to a DLL name string.
+ * phDcdMgr: A pointer to a DCD manager handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Unable to allocate memory for DCD manager handle.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * DCD initialized.
+ * pszZlDllName is non-NULL.
+ * phDcdMgr is non-NULL.
+ * Ensures:
+ * A DCD manager handle is created.
+ */
+ extern DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
+ OUT struct DCD_MANAGER **phDcdMgr);
+
+/*
+ * ======== DCD_DestroyManager ========
+ * Purpose:
+ * This function destroys a DCD module manager.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid DCD manager handle.
+ * Requires:
+ * DCD initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr);
+
+/*
+ * ======== DCD_EnumerateObject ========
+ * Purpose:
+ * This function enumerates currently visible DSP/BIOS Bridge objects
+ * and returns the UUID and type of each enumerated object.
+ * Parameters:
+ * cIndex: The object enumeration index.
+ * objType: Type of object to enumerate.
+ * pUuid: Pointer to a DSP_UUID object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Unable to enumerate through the DCD database.
+ * DSP_SENUMCOMPLETE: Enumeration completed. This is not an error code.
+ * Requires:
+ * DCD initialized.
+ * pUuid is a valid pointer.
+ * Ensures:
+ * Details:
+ * This function can be used in conjunction with DCD_GetObjectDef to
+ * retrieve object properties.
+ */
+ extern DSP_STATUS DCD_EnumerateObject(IN s32 cIndex,
+ IN enum DSP_DCDOBJTYPE objType,
+ OUT struct DSP_UUID *pUuid);
+
+/*
+ * ======== DCD_Exit ========
+ * Purpose:
+ * This function cleans up the DCD module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * DCD initialized.
+ * Ensures:
+ */
+ extern void DCD_Exit(void);
+
+/*
+ * ======== DCD_GetDepLibs ========
+ * Purpose:
+ * Given the uuid of a library and size of array of uuids, this function
+ * fills the array with the uuids of all dependent libraries of the input
+ * library.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pUuid: Pointer to a DSP_UUID for a library.
+ * numLibs: Size of uuid array (number of library uuids).
+ * pDepLibUuids: Array of dependent library uuids to be filled in.
+ * pPersistentDepLibs: Array indicating if corresponding lib is persistent.
+ * phase: phase to obtain correct input library
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EDCDREADSECT: Failure to read section containing library info.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * DCD initialized.
+ * Valid hDcdMgr.
+ * pUuid != NULL
+ * pDepLibUuids != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ u16 numLibs,
+ OUT struct DSP_UUID *pDepLibUuids,
+ OUT bool *pPersistentDepLibs,
+ IN enum NLDR_PHASE phase);
+
+/*
+ * ======== DCD_GetNumDepLibs ========
+ * Purpose:
+ * Given the uuid of a library, determine its number of dependent
+ * libraries.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pUuid: Pointer to a DSP_UUID for a library.
+ * pNumLibs: Size of uuid array (number of library uuids).
+ * pNumPersLibs: number of persistent dependent library.
+ * phase: Phase to obtain correct input library
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EDCDREADSECT: Failure to read section containing library info.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * DCD initialized.
+ * Valid hDcdMgr.
+ * pUuid != NULL
+ * pNumLibs != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ OUT u16 *pNumLibs,
+ OUT u16 *pNumPersLibs,
+ IN enum NLDR_PHASE phase);
+
+/*
+ * ======== DCD_GetLibraryName ========
+ * Purpose:
+ * This function returns the name of a (dynamic) library for a given
+ * UUID.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pUuid: Pointer to a DSP_UUID that represents a unique DSP/BIOS
+ * Bridge object.
+ * pstrLibName: Buffer to hold library name.
+ * pdwSize: Contains buffer size. Set to string size on output.
+ * phase: Which phase to load
+ * fPhaseSplit: Are phases in multiple libraries
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * DCD initialized.
+ * Valid hDcdMgr.
+ * pstrLibName != NULL.
+ * pUuid != NULL
+ * pdwSize != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ IN OUT char *pstrLibName,
+ IN OUT u32 *pdwSize,
+ IN enum NLDR_PHASE phase,
+ OUT bool *fPhaseSplit);
+
+/*
+ * ======== DCD_GetObjectDef ========
+ * Purpose:
+ * This function returns the properties/attributes of a DSP/BIOS Bridge
+ * object.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pUuid: Pointer to a DSP_UUID that represents a unique
+ * DSP/BIOS Bridge object.
+ * objType: The type of DSP/BIOS Bridge object to be
+ * referenced (node, processor, etc).
+ * pObjDef: Pointer to an object definition structure. A
+ * union of various possible DCD object types.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EDCDPARSESECT: Unable to parse content of object code section.
+ * DSP_EDCDREADSECT: Unable to read object code section.
+ * DSP_EDCDGETSECT: Unable to access object code section.
+ * DSP_EDCDLOADBASE: Unable to load code base.
+ * DSP_EFAIL: General failure.
+ * DSP_EHANDLE: Invalid DCD_HMANAGER handle.
+ * Requires:
+ * DCD initialized.
+ * pObjUuid is non-NULL.
+ * pObjDef is non-NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pObjUuid,
+ IN enum DSP_DCDOBJTYPE objType,
+ OUT struct DCD_GENERICOBJ *pObjDef);
+
+/*
+ * ======== DCD_GetObjects ========
+ * Purpose:
+ * This function finds all DCD objects specified in a special
+ * COFF section called ".dcd_register", and for each object,
+ * call a "register" function. The "register" function may perform
+ * various actions, such as 1) register nodes in the node database, 2)
+ * unregister nodes from the node database, and 3) add overlay nodes.
+ * Parameters:
+ * hDcdMgr: A DCD manager handle.
+ * pszCoffPath: Pointer to name of COFF file containing DCD
+ * objects.
+ * registerFxn: Callback fxn to be applied on each located
+ * DCD object.
+ * handle: Handle to pass to callback.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EDCDNOAUTOREGISTER: Unable to find .dcd_register section.
+ * DSP_EDCDREADSECT: Unable to read object code section.
+ * DSP_EDCDLOADBASE: Unable to load code base.
+ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
+ * Requires:
+ * DCD initialized.
+ * Ensures:
+ * Note:
+ * Due to the DCD database construction, it is essential for a DCD-enabled
+ * COFF file to contain the right COFF sections, especially
+ * ".dcd_register", which is used for auto registration.
+ */
+ extern DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr,
+ IN char *pszCoffPath,
+ DCD_REGISTERFXN registerFxn,
+ void *handle);
+
+/*
+ * ======== DCD_Init ========
+ * Purpose:
+ * This function initializes DCD.
+ * Parameters:
+ * Returns:
+ * FALSE: Initialization failed.
+ * TRUE: Initialization succeeded.
+ * Requires:
+ * Ensures:
+ * DCD initialized.
+ */
+ extern bool DCD_Init(void);
+
+/*
+ * ======== DCD_RegisterObject ========
+ * Purpose:
+ * This function registers a DSP/BIOS Bridge object in the DCD database.
+ * Parameters:
+ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS
+ * Bridge object.
+ * objType: Type of object.
+ * pszPathName: Path to the object's COFF file.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Failed to register object.
+ * Requires:
+ * DCD initialized.
+ * pUuid and szPathName are non-NULL values.
+ * objType is a valid type value.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
+ IN enum DSP_DCDOBJTYPE objType,
+ IN char *pszPathName);
+
+/*
+ * ======== DCD_UnregisterObject ========
+ * Purpose:
+ * This function de-registers a valid DSP/BIOS Bridge object from the DCD
+ * database.
+ * Parameters:
+ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS Bridge
+ * object.
+ * objType: Type of object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Unable to de-register the specified object.
+ * Requires:
+ * DCD initialized.
+ * pUuid is a non-NULL value.
+ * objType is a valid type value.
+ * Ensures:
+ */
+ extern DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
+ IN enum DSP_DCDOBJTYPE objType);
+
+#endif /* _DBDCD_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcddef.h b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
new file mode 100644
index 000000000000..91b1c45c469a
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
@@ -0,0 +1,94 @@
+/*
+ * dbdcddef.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== dbdcddef.h ========
+ * Description:
+ * DCD (DSP/BIOS Bridge Configuration Database) constants and types.
+ *
+ *! Revision History:
+ *! ================
+ *! 03-Dec-2003 map Moved and renamed DCD_OBJTYPE to DSP_DCDOBJTYPE in dbdefs.h
+ *! 05-Dec-2002 map Added DCD_CREATELIBTYPE, DCD_EXECUTELIBTYPE,
+ * DCD_DELETELIBTYPE
+ *! 24-Feb-2003 kc Updated REG entry names to DspBridge.
+ *! 22-Nov-2002 gp Cleaned up comments, formatting.
+ *! 05-Aug-2002 jeh Added DCD_REGISTERFXN.
+ *! 19-Apr-2002 jeh Added DCD_LIBRARYTYPE to DCD_OBJTYPE, dynamic load
+ *! properties to DCD_NODEPROPS.
+ *! 29-Jul-2001 ag Added extended procObj.
+ *! 13-Feb-2001 kc: Named changed from dcdbsdef.h dbdcddef.h.
+ *! 12-Dec-2000 jeh Added DAIS iAlg name to DCD_NODEPROPS.
+ *! 30-Oct-2000 kc: Added #defines for DCD_AutoRegister function.
+ *! 05-Sep-2000 jeh Added DCD_NODEPROPS.
+ *! 12-Aug-2000 kc: Incoroporated the use of types defined in <dspdefs.h>.
+ *! 29-Jul-2000 kc: Created.
+ */
+
+#ifndef DBDCDDEF_
+#define DBDCDDEF_
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/mgrpriv.h> /* for MGR_PROCESSOREXTINFO */
+
+/*
+ * The following defines are critical elements for the DCD module:
+ *
+ * - DCD_REGKEY enables DCD functions to locate registered DCD objects.
+ * - DCD_REGISTER_SECTION identifies the COFF section where the UUID of
+ * registered DCD objects are stored.
+ */
+#define DCD_REGKEY "Software\\TexasInstruments\\DspBridge\\DCD"
+#define DCD_REGISTER_SECTION ".dcd_register"
+
+/* DCD Manager Object */
+ struct DCD_MANAGER;
+
+/* DCD Node Properties */
+ struct DCD_NODEPROPS {
+ struct DSP_NDBPROPS ndbProps;
+ u32 uMsgSegid;
+ u32 uMsgNotifyType;
+ char *pstrCreatePhaseFxn;
+ char *pstrDeletePhaseFxn;
+ char *pstrExecutePhaseFxn;
+ char *pstrIAlgName;
+
+ /* Dynamic load properties */
+ u16 usLoadType; /* Static, dynamic, overlay */
+ u32 ulDataMemSegMask; /* Data memory requirements */
+ u32 ulCodeMemSegMask; /* Code memory requirements */
+ } ;
+
+/* DCD Generic Object Type */
+ struct DCD_GENERICOBJ {
+ union dcdObjUnion {
+ struct DCD_NODEPROPS nodeObj; /* node object. */
+ /* processor object. */
+ struct DSP_PROCESSORINFO procObj;
+ /* extended proc object (private) */
+ struct MGR_PROCESSOREXTINFO extProcObj;
+ } objData;
+ } ;
+
+/* DCD Internal Callback Type */
+ typedef DSP_STATUS(*DCD_REGISTERFXN) (IN struct DSP_UUID *pUuid,
+ IN enum DSP_DCDOBJTYPE objType,
+ IN void *handle);
+
+#endif /* DBDCDDEF_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
new file mode 100644
index 000000000000..78be880687ef
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
@@ -0,0 +1,583 @@
+/*
+ * dbdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== dbdefs.h ========
+ * Description:
+ * Global definitions and constants for DSP/BIOS Bridge.
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added MAPATTR & ELEM_SIZE for Dynamic Memory Mapping feature
+ *! 09-Feb-2004 vp Added processor ID numbers for DSP and IVA
+ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE. Updated IsValid*Event macros.
+ *! 22-Nov-2002 gp Cleaned up comments, formatting.
+ *! Removed unused DSP_ENUMLASTNODE define.
+ *! 13-Feb-2002 jeh Added uSysStackSize to DSP_NDBPROPS.
+ *! 23-Jan-2002 ag Added #define DSP_SHMSEG0.
+ *! 12-Dec-2001 ag Added DSP_ESTRMMODE error code.
+ *! 04-Dec-2001 jeh Added DSP_ENOTCONNECTED error code.
+ *! 10-Dec-2001 kc: Modified macros and definitions to disable DSP_POSTMESSAGE.
+ *! 01-Nov-2001 jeh Added DSP_EOVERLAYMEMORY.
+ *! 18-Oct-2001 ag Added DSP_STRMMODE type.
+ *! Added DSP_ENOTSHAREDMEM.
+ *! 21-Sep-2001 ag Added additional error codes.
+ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
+ *! 11-May-2001 jeh Changed DSP_NODE_MIN_PRIORITY from 0 to 1. Removed hNode
+ *! from DSP_NODEINFO.
+ *! 02-Apr-2001 sg Added missing error codes, rearranged codes, switched to
+ *! hex offsets, renamed some codes to match API spec.
+ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 05-Dec-2000 ag: Added DSP_RMSxxx user available message command codes.
+ *! 09-Nov-2000 rr: Added DSP_PROCEESORRESTART define; Removed DSP_PBUFFER.
+ *! Added DSP_DCD_ENOAUTOREGISTER, DSP_EUSER1-16, DSP_ESTRMFUL
+ *! Removed DSP_EDONE. Macros's modified.
+ *! 23-Oct-2000 jeh Replaced DSP_STREAMSTATECHANGE with DSP_STREAMDONE.
+ *! 09-Oct-2000 jeh Updated to version 0.9 DSP Bridge API spec.
+ *! 29-Sep-2000 kc Added error codes for DCD and REG to simplify use of
+ *! these codes within the RM module.
+ *! 27-Sep-2000 jeh Added segid, alignment, uNumBufs to DSP_STREAMATTRIN.
+ *! 29-Aug-2000 jeh Added DSP_NODETYPE enum, changed DSP_EALREADYATTACHED to
+ *! DSP_EALREADYCONNECTED. Changed scStreamConnection[1]
+ *! to scStreamConnection[16] in DSP_NODEINFO structure.
+ *! Added DSP_NOTIFICATION, DSP_STRMATTR. PSTRING changed
+ *! back to TCHAR * and moved to dbtype.h.
+ *! 11-Aug-2000 rr: Macros to check valid events and notify masks added.
+ *! 09-Aug-2000 rr: Changed PSTRING to *s8
+ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
+ *! 20-Jul-2000 rr: Updated to version 0.8
+ *! 17-Jul-2000 rr: New PROC states added to the DSP_PROCSTATE.
+ *! 27-Jun-2000 rr: Created from dspapi.h
+ */
+
+#ifndef DBDEFS_
+#define DBDEFS_
+
+#include <linux/types.h>
+
+#include <dspbridge/dbtype.h> /* GPP side type definitions */
+#include <dspbridge/std.h> /* DSP/BIOS type definitions */
+#include <dspbridge/rms_sh.h> /* Types shared between GPP and DSP */
+
+#define PG_SIZE_4K 4096
+#define PG_MASK(pg_size) (~((pg_size)-1))
+#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
+#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
+
+/* API return value and calling convention */
+#define DBAPI DSP_STATUS
+
+/* Infinite time value for the uTimeout parameter to DSPStream_Select() */
+#define DSP_FOREVER (-1)
+
+/* Maximum length of node name, used in DSP_NDBPROPS */
+#define DSP_MAXNAMELEN 32
+
+/* uNotifyType values for the RegisterNotify() functions. */
+#define DSP_SIGNALEVENT 0x00000001
+
+/* Types of events for processors */
+#define DSP_PROCESSORSTATECHANGE 0x00000001
+#define DSP_PROCESSORATTACH 0x00000002
+#define DSP_PROCESSORDETACH 0x00000004
+#define DSP_PROCESSORRESTART 0x00000008
+
+/* DSP exception events (DSP/BIOS and DSP MMU fault) */
+#define DSP_MMUFAULT 0x00000010
+#define DSP_SYSERROR 0x00000020
+#define DSP_EXCEPTIONABORT 0x00000300
+#define DSP_PWRERROR 0x00000080
+
+/* IVA exception events (IVA MMU fault) */
+#define IVA_MMUFAULT 0x00000040
+/* Types of events for nodes */
+#define DSP_NODESTATECHANGE 0x00000100
+#define DSP_NODEMESSAGEREADY 0x00000200
+
+/* Types of events for streams */
+#define DSP_STREAMDONE 0x00001000
+#define DSP_STREAMIOCOMPLETION 0x00002000
+
+/* Handle definition representing the GPP node in DSPNode_Connect() calls */
+#define DSP_HGPPNODE 0xFFFFFFFF
+
+/* Node directions used in DSPNode_Connect() */
+#define DSP_TONODE 1
+#define DSP_FROMNODE 2
+
+/* Define Node Minimum and Maximum Priorities */
+#define DSP_NODE_MIN_PRIORITY 1
+#define DSP_NODE_MAX_PRIORITY 15
+
+/* Pre-Defined Message Command Codes available to user: */
+#define DSP_RMSUSERCODESTART RMS_USER /* Start of RMS user cmd codes */
+/* end of user codes */
+#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
+#define DSP_RMSBUFDESC RMS_BUFDESC /* MSG contains SM buffer description */
+
+/* Shared memory identifier for MEM segment named "SHMSEG0" */
+#define DSP_SHMSEG0 (u32)(-1)
+
+/* Processor ID numbers */
+#define DSP_UNIT 0
+#define IVA_UNIT 1
+
+#define DSPWORD unsigned char
+#define DSPWORDSIZE sizeof(DSPWORD)
+
+/* Success & Failure macros */
+#define DSP_SUCCEEDED(Status) likely((s32)(Status) >= 0)
+#define DSP_FAILED(Status) unlikely((s32)(Status) < 0)
+
+/* Power control enumerations */
+#define PROC_PWRCONTROL 0x8070
+
+#define PROC_PWRMGT_ENABLE (PROC_PWRCONTROL + 0x3)
+#define PROC_PWRMGT_DISABLE (PROC_PWRCONTROL + 0x4)
+
+/* Bridge Code Version */
+#define BRIDGE_VERSION_CODE 333
+
+#define MAX_PROFILES 16
+
+/* Types defined for 'Bridge API */
+ typedef u32 DSP_STATUS; /* API return code type */
+
+ typedef HANDLE DSP_HNODE; /* Handle to a DSP Node object */
+ typedef HANDLE DSP_HPROCESSOR; /* Handle to a Processor object */
+ typedef HANDLE DSP_HSTREAM; /* Handle to a Stream object */
+
+ typedef u32 DSP_PROCFAMILY; /* Processor family */
+ typedef u32 DSP_PROCTYPE; /* Processor type (w/in family) */
+ typedef u32 DSP_RTOSTYPE; /* Type of DSP RTOS */
+
+/* Handy Macros */
+#define IsValidProcEvent(x) (((x) == 0) || (((x) & (DSP_PROCESSORSTATECHANGE | \
+ DSP_PROCESSORATTACH | \
+ DSP_PROCESSORDETACH | \
+ DSP_PROCESSORRESTART | \
+ DSP_NODESTATECHANGE | \
+ DSP_STREAMDONE | \
+ DSP_STREAMIOCOMPLETION | \
+ DSP_MMUFAULT | \
+ DSP_SYSERROR | \
+ DSP_PWRERROR)) && \
+ !((x) & ~(DSP_PROCESSORSTATECHANGE | \
+ DSP_PROCESSORATTACH | \
+ DSP_PROCESSORDETACH | \
+ DSP_PROCESSORRESTART | \
+ DSP_NODESTATECHANGE | \
+ DSP_STREAMDONE | \
+ DSP_STREAMIOCOMPLETION | \
+ DSP_MMUFAULT | \
+ DSP_SYSERROR | \
+ DSP_PWRERROR))))
+
+#define IsValidNodeEvent(x) (((x) == 0) || (((x) & (DSP_NODESTATECHANGE | \
+ DSP_NODEMESSAGEREADY)) && \
+ !((x) & ~(DSP_NODESTATECHANGE | \
+ DSP_NODEMESSAGEREADY))))
+
+#define IsValidStrmEvent(x) (((x) == 0) || (((x) & (DSP_STREAMDONE | \
+ DSP_STREAMIOCOMPLETION)) && \
+ !((x) & ~(DSP_STREAMDONE | \
+ DSP_STREAMIOCOMPLETION))))
+
+#define IsValidNotifyMask(x) ((x) & DSP_SIGNALEVENT)
+
+/* The Node UUID structure */
+ struct DSP_UUID {
+ u32 ulData1;
+ u16 usData2;
+ u16 usData3;
+ u8 ucData4;
+ u8 ucData5;
+ u8 ucData6[6];
+ };
+
+/* DCD types */
+ enum DSP_DCDOBJTYPE {
+ DSP_DCDNODETYPE,
+ DSP_DCDPROCESSORTYPE,
+ DSP_DCDLIBRARYTYPE,
+ DSP_DCDCREATELIBTYPE,
+ DSP_DCDEXECUTELIBTYPE,
+ DSP_DCDDELETELIBTYPE
+ } ;
+
+/* Processor states */
+ enum DSP_PROCSTATE {
+ PROC_STOPPED,
+ PROC_LOADED,
+ PROC_RUNNING,
+ PROC_ERROR
+ } ;
+
+/*
+ * Node types: Message node, task node, xDAIS socket node, and
+ * device node. _NODE_GPP is used when defining a stream connection
+ * between a task or socket node and the GPP.
+ *
+ */
+ enum NODE_TYPE {
+ NODE_DEVICE,
+ NODE_TASK,
+ NODE_DAISSOCKET,
+ NODE_MESSAGE,
+ NODE_GPP
+ } ;
+
+/*
+ * ======== NODE_STATE ========
+ * Internal node states.
+ */
+ enum NODE_STATE {
+ NODE_ALLOCATED,
+ NODE_CREATED,
+ NODE_RUNNING,
+ NODE_PAUSED,
+ NODE_DONE,
+ NODE_CREATING,
+ NODE_STARTING,
+ NODE_PAUSING,
+ NODE_TERMINATING,
+ NODE_DELETING,
+ } ;
+
+/* Stream states */
+ enum DSP_STREAMSTATE {
+ STREAM_IDLE,
+ STREAM_READY,
+ STREAM_PENDING,
+ STREAM_DONE
+ } ;
+
+/* Stream connect types */
+ enum DSP_CONNECTTYPE {
+ CONNECTTYPE_NODEOUTPUT,
+ CONNECTTYPE_GPPOUTPUT,
+ CONNECTTYPE_NODEINPUT,
+ CONNECTTYPE_GPPINPUT
+ } ;
+
+/* Stream mode types */
+ enum DSP_STRMMODE {
+ STRMMODE_PROCCOPY, /* Processor(s) copy stream data payloads */
+ STRMMODE_ZEROCOPY, /* Strm buffer ptrs swapped no data copied */
+ STRMMODE_LDMA, /* Local DMA : OMAP's System-DMA device */
+ STRMMODE_RDMA /* Remote DMA: OMAP's DSP-DMA device */
+ } ;
+
+/* Resource Types */
+ enum DSP_RESOURCEINFOTYPE {
+ DSP_RESOURCE_DYNDARAM = 0,
+ DSP_RESOURCE_DYNSARAM,
+ DSP_RESOURCE_DYNEXTERNAL,
+ DSP_RESOURCE_DYNSRAM,
+ DSP_RESOURCE_PROCLOAD
+ } ;
+
+/* Memory Segment Types */
+ enum DSP_MEMTYPE {
+ DSP_DYNDARAM = 0,
+ DSP_DYNSARAM,
+ DSP_DYNEXTERNAL,
+ DSP_DYNSRAM
+ } ;
+
+/* Memory Flush Types */
+ enum DSP_FLUSHTYPE {
+ PROC_INVALIDATE_MEM = 0,
+ PROC_WRITEBACK_MEM,
+ PROC_WRITEBACK_INVALIDATE_MEM,
+ } ;
+
+/* Memory Segment Status Values */
+ struct DSP_MEMSTAT {
+ u32 ulSize;
+ u32 ulTotalFreeSize;
+ u32 ulLenMaxFreeBlock;
+ u32 ulNumFreeBlocks;
+ u32 ulNumAllocBlocks;
+ } ;
+
+/* Processor Load information Values */
+ struct DSP_PROCLOADSTAT {
+ u32 uCurrLoad;
+ u32 uPredictedLoad;
+ u32 uCurrDspFreq;
+ u32 uPredictedFreq;
+ } ;
+
+/* Attributes for STRM connections between nodes */
+ struct DSP_STRMATTR {
+ u32 uSegid; /* Memory segment on DSP to allocate buffers */
+ u32 uBufsize; /* Buffer size (DSP words) */
+ u32 uNumBufs; /* Number of buffers */
+ u32 uAlignment; /* Buffer alignment */
+ u32 uTimeout; /* Timeout for blocking STRM calls */
+ enum DSP_STRMMODE lMode; /* mode of stream when opened */
+ /* DMA chnl id if DSP_STRMMODE is LDMA or RDMA */
+ u32 uDMAChnlId;
+ u32 uDMAPriority; /* DMA channel priority 0=lowest, >0=high */
+ } ;
+
+/* The DSP_CBDATA structure */
+ struct DSP_CBDATA {
+ u32 cbData;
+ u8 cData[1];
+ } ;
+
+/* The DSP_MSG structure */
+ struct DSP_MSG {
+ u32 dwCmd;
+ u32 dwArg1;
+ u32 dwArg2;
+ } ;
+
+/* The DSP_RESOURCEREQMTS structure for node's resource requirements */
+ struct DSP_RESOURCEREQMTS {
+ u32 cbStruct;
+ u32 uStaticDataSize;
+ u32 uGlobalDataSize;
+ u32 uProgramMemSize;
+ u32 uWCExecutionTime;
+ u32 uWCPeriod;
+ u32 uWCDeadline;
+ u32 uAvgExectionTime;
+ u32 uMinimumPeriod;
+ } ;
+
+/*
+ * The DSP_STREAMCONNECT structure describes a stream connection
+ * between two nodes, or between a node and the GPP
+ */
+ struct DSP_STREAMCONNECT {
+ u32 cbStruct;
+ enum DSP_CONNECTTYPE lType;
+ u32 uThisNodeStreamIndex;
+ DSP_HNODE hConnectedNode;
+ struct DSP_UUID uiConnectedNodeID;
+ u32 uConnectedNodeStreamIndex;
+ } ;
+
+ struct DSP_NODEPROFS {
+ u32 ulHeapSize;
+ } ;
+
+/* The DSP_NDBPROPS structure reports the attributes of a node */
+ struct DSP_NDBPROPS {
+ u32 cbStruct;
+ struct DSP_UUID uiNodeID;
+ char acName[DSP_MAXNAMELEN];
+ enum NODE_TYPE uNodeType;
+ u32 bCacheOnGPP;
+ struct DSP_RESOURCEREQMTS dspResourceReqmts;
+ s32 iPriority;
+ u32 uStackSize;
+ u32 uSysStackSize;
+ u32 uStackSeg;
+ u32 uMessageDepth;
+ u32 uNumInputStreams;
+ u32 uNumOutputStreams;
+ u32 uTimeout;
+ u32 uCountProfiles; /* Number of supported profiles */
+ /* Array of profiles */
+ struct DSP_NODEPROFS aProfiles[MAX_PROFILES];
+ u32 uStackSegName; /* Stack Segment Name */
+ } ;
+
+ /* The DSP_NODEATTRIN structure describes the attributes of a
+ * node client */
+ struct DSP_NODEATTRIN {
+ u32 cbStruct;
+ s32 iPriority;
+ u32 uTimeout;
+ u32 uProfileID;
+ /* Reserved, for Bridge Internal use only */
+ u32 uHeapSize;
+ void *pGPPVirtAddr; /* Reserved, for Bridge Internal use only */
+ } ;
+
+ /* The DSP_NODEINFO structure is used to retrieve information
+ * about a node */
+ struct DSP_NODEINFO {
+ u32 cbStruct;
+ struct DSP_NDBPROPS nbNodeDatabaseProps;
+ u32 uExecutionPriority;
+ enum NODE_STATE nsExecutionState;
+ DSP_HNODE hDeviceOwner;
+ u32 uNumberStreams;
+ struct DSP_STREAMCONNECT scStreamConnection[16];
+ u32 uNodeEnv;
+ } ;
+
+ /* The DSP_NODEATTR structure describes the attributes of a node */
+ struct DSP_NODEATTR {
+ u32 cbStruct;
+ struct DSP_NODEATTRIN inNodeAttrIn;
+ u32 uInputs;
+ u32 uOutputs;
+ struct DSP_NODEINFO iNodeInfo;
+ } ;
+
+/*
+ * Notification type: either the name of an opened event, or an event or
+ * window handle.
+ */
+ struct DSP_NOTIFICATION {
+ char *psName;
+ HANDLE handle;
+ } ;
+
+/* The DSP_PROCESSORATTRIN structure describes the attributes of a processor */
+ struct DSP_PROCESSORATTRIN{
+ u32 cbStruct;
+ u32 uTimeout;
+ } ;
+
+ enum chipTypes {
+ DSPTYPE_55 = 6,
+ IVA_ARM7 = 0x97,
+ DSPTYPE_64 = 0x99
+ };
+
+/*
+ * The DSP_PROCESSORINFO structure describes basic capabilities of a
+ * DSP processor
+ */
+ struct DSP_PROCESSORINFO {
+ u32 cbStruct;
+ DSP_PROCFAMILY uProcessorFamily;
+ DSP_PROCTYPE uProcessorType;
+ u32 uClockRate;
+ u32 ulInternalMemSize;
+ u32 ulExternalMemSize;
+ u32 uProcessorID;
+ DSP_RTOSTYPE tyRunningRTOS;
+ s32 nNodeMinPriority;
+ s32 nNodeMaxPriority;
+ } ;
+
+/* Error information of last DSP exception signalled to the GPP */
+ struct DSP_ERRORINFO {
+ u32 dwErrMask;
+ u32 dwVal1;
+ u32 dwVal2;
+ u32 dwVal3;
+ } ;
+
+/* The DSP_PROCESSORSTATE structure describes the state of a DSP processor */
+ struct DSP_PROCESSORSTATE {
+ u32 cbStruct;
+ enum DSP_PROCSTATE iState;
+ struct DSP_ERRORINFO errInfo;
+ } ;
+
+/*
+ * The DSP_RESOURCEINFO structure is used to retrieve information about a
+ * processor's resources
+ */
+ struct DSP_RESOURCEINFO {
+ u32 cbStruct;
+ enum DSP_RESOURCEINFOTYPE uResourceType;
+ union {
+ u32 ulResource;
+ struct DSP_MEMSTAT memStat;
+ struct DSP_PROCLOADSTAT procLoadStat;
+ } result;
+ } ;
+
+/*
+ * The DSP_STREAMATTRIN structure describes the attributes of a stream,
+ * including segment and alignment of data buffers allocated with
+ * DSPStream_AllocateBuffers(), if applicable
+ */
+ struct DSP_STREAMATTRIN {
+ u32 cbStruct;
+ u32 uTimeout;
+ u32 uSegment;
+ u32 uAlignment;
+ u32 uNumBufs;
+ enum DSP_STRMMODE lMode;
+ u32 uDMAChnlId;
+ u32 uDMAPriority;
+ } ;
+
+/* The DSP_BUFFERATTR structure describes the attributes of a data buffer */
+ struct DSP_BUFFERATTR {
+ u32 cbStruct;
+ u32 uSegment;
+ u32 uAlignment;
+ } ;
+
+/*
+ * The DSP_STREAMINFO structure is used to retrieve information
+ * about a stream.
+ */
+ struct DSP_STREAMINFO {
+ u32 cbStruct;
+ u32 uNumberBufsAllowed;
+ u32 uNumberBufsInStream;
+ u32 ulNumberBytes;
+ HANDLE hSyncObjectHandle;
+ enum DSP_STREAMSTATE ssStreamState;
+ } ;
+
+/* DMM MAP attributes
+It is a bit mask with each bit value indicating a specific attribute
+bit 0 - GPP address type (user virtual=0, physical=1)
+bit 1 - MMU Endianism (Big Endian=1, Little Endian=0)
+bit 2 - MMU mixed page attribute (Mixed/ CPUES=1, TLBES =0)
+bit 3 - MMU element size = 8bit (valid only for non mixed page entries)
+bit 4 - MMU element size = 16bit (valid only for non mixed page entries)
+bit 5 - MMU element size = 32bit (valid only for non mixed page entries)
+bit 6 - MMU element size = 64bit (valid only for non mixed page entries)
+*/
+
+/* Types of mapping attributes */
+
+/* MPU address is virtual and needs to be translated to physical addr */
+#define DSP_MAPVIRTUALADDR 0x00000000
+#define DSP_MAPPHYSICALADDR 0x00000001
+
+/* Mapped data is big endian */
+#define DSP_MAPBIGENDIAN 0x00000002
+#define DSP_MAPLITTLEENDIAN 0x00000000
+
+/* Element size is based on DSP r/w access size */
+#define DSP_MAPMIXEDELEMSIZE 0x00000004
+
+/*
+ * Element size for MMU mapping (8, 16, 32, or 64 bit)
+ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
+ */
+#define DSP_MAPELEMSIZE8 0x00000008
+#define DSP_MAPELEMSIZE16 0x00000010
+#define DSP_MAPELEMSIZE32 0x00000020
+#define DSP_MAPELEMSIZE64 0x00000040
+
+#define DSP_MAPVMALLOCADDR 0x00000080
+
+#define DSP_MAPDONOTLOCK 0x00000100
+
+
+#define GEM_CACHE_LINE_SIZE 128
+#define GEM_L1P_PREFETCH_SIZE 128
+
+#endif /* DBDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbg.h b/arch/arm/plat-omap/include/dspbridge/dbg.h
new file mode 100644
index 000000000000..7f44ff988c15
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbg.h
@@ -0,0 +1,110 @@
+/*
+ * dbg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== dbg.h ========
+ * Purpose:
+ * Provide debugging services for 'Bridge Mini Drivers.
+ *
+ * Public Functions:
+ * DBG_Exit
+ * DBG_Init
+ * DBG_Printf
+ * DBG_Trace
+ *
+ * Notes:
+ * WMD's must not call DBG_Init or DBG_Exit.
+ *
+ *! Revision History:
+ *! ================
+ *! 03-Feb-2000 rr: DBG Levels redefined.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 10-Oct-1997 cr: Added DBG_Printf service.
+ *! 29-May-1996 gp: Removed WCD_ prefix.
+ *! 15-May-1996 gp: Created.
+ */
+
+#ifndef DBG_
+#define DBG_
+#include <dspbridge/host_os.h>
+#include <linux/types.h>
+
+/* Levels of trace debug messages: */
+#define DBG_ENTER (u8)(0x01) /* Function entry point. */
+#define DBG_LEVEL1 (u8)(0x02) /* Display debugging state/varibles */
+#define DBG_LEVEL2 (u8)(0x04) /* Display debugging state/varibles */
+#define DBG_LEVEL3 (u8)(0x08) /* Display debugging state/varibles */
+#define DBG_LEVEL4 (u8)(0x10) /* Display debugging state/varibles */
+#define DBG_LEVEL5 (u8)(0x20) /* Module Init, Exit */
+#define DBG_LEVEL6 (u8)(0x40) /* Warn SERVICES Failures */
+#define DBG_LEVEL7 (u8)(0x80) /* Warn Critical Errors */
+
+#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
+
+/*
+ * ======== DBG_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * DBG initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void DBG_Exit(void);
+
+/*
+ * ======== DBG_Init ========
+ * Purpose:
+ * Initializes private state of DBG module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ */
+ extern bool DBG_Init(void);
+
+/*
+ * ======== DBG_Trace ========
+ * Purpose:
+ * Output a trace message to the debugger, if the given trace level
+ * is unmasked.
+ * Parameters:
+ * bLevel: Trace level.
+ * pstrFormat: sprintf-style format string.
+ * ...: Arguments for format string.
+ * Returns:
+ * DSP_SOK: Success, or trace level masked.
+ * DSP_EFAIL: On Error.
+ * Requires:
+ * DBG initialized.
+ * Ensures:
+ * Debug message is printed to debugger output window, if trace level
+ * is unmasked.
+ */
+ extern DSP_STATUS DBG_Trace(IN u8 bLevel, IN char *pstrFormat, ...);
+#else
+
+#define DBG_Exit(void)
+#define DBG_Init(void) true
+#define DBG_Trace(bLevel, pstrFormat, args...)
+
+#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+
+#endif /* DBG_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbl.h b/arch/arm/plat-omap/include/dspbridge/dbl.h
new file mode 100644
index 000000000000..19847f9d29a3
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbl.h
@@ -0,0 +1,354 @@
+/*
+ * dbl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbl.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 19-Mar-2002 jeh Pass DBL_Symbol pointer to DBL_getAddr, DBL_getCAddr
+ *! to accomodate dynamic loader library.
+ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
+ *! 24-Sep-2001 jeh Code review changes.
+ *! 07-Sep-2001 jeh Added DBL_LoadSect(), DBL_UnloadSect().
+ *! 05-Jun-2001 jeh Created based on zl.h.
+ */
+
+#ifndef DBL_
+#define DBL_
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/dbldefs.h>
+
+/*
+ * ======== DBL_close ========
+ * Close library opened with DBL_open.
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * Ensures:
+ */
+ extern void DBL_close(struct DBL_LibraryObj *lib);
+
+/*
+ * ======== DBL_create ========
+ * Create a target object by specifying the alloc, free, and write
+ * functions for the target.
+ * Parameters:
+ * pTarget - Location to store target handle on output.
+ * pAttrs - Attributes.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failed.
+ * Requires:
+ * DBL initialized.
+ * pAttrs != NULL.
+ * pTarget != NULL;
+ * Ensures:
+ * Success: *pTarget != NULL.
+ * Failure: *pTarget == NULL.
+ */
+ extern DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget,
+ struct DBL_Attrs *pAttrs);
+
+/*
+ * ======== DBL_delete ========
+ * Delete target object and free resources for any loaded libraries.
+ * Parameters:
+ * target - Handle returned from DBL_Create().
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * Ensures:
+ */
+ extern void DBL_delete(struct DBL_TargetObj *target);
+
+/*
+ * ======== DBL_exit ========
+ * Discontinue use of DBL module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * cRefs > 0.
+ * Ensures:
+ * cRefs >= 0.
+ */
+ extern void DBL_exit(void);
+
+/*
+ * ======== DBL_getAddr ========
+ * Get address of name in the specified library.
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * name - Name of symbol
+ * ppSym - Location to store symbol address on output.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Symbol not found.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pAddr != NULL.
+ * Ensures:
+ */
+ extern bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
+ struct DBL_Symbol **ppSym);
+
+/*
+ * ======== DBL_getAttrs ========
+ * Retrieve the attributes of the target.
+ * Parameters:
+ * target - Handle returned from DBL_Create().
+ * pAttrs - Location to store attributes on output.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * pAttrs != NULL.
+ * Ensures:
+ */
+ extern void DBL_getAttrs(struct DBL_TargetObj *target,
+ struct DBL_Attrs *pAttrs);
+
+/*
+ * ======== DBL_getCAddr ========
+ * Get address of "C" name in the specified library.
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * name - Name of symbol
+ * ppSym - Location to store symbol address on output.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Symbol not found.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pAddr != NULL.
+ * Ensures:
+ */
+ extern bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
+ struct DBL_Symbol **ppSym);
+
+/*
+ * ======== DBL_getEntry ========
+ * Get program entry point.
+ *
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * pEntry - Location to store entry address on output.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Failure.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * pEntry != NULL.
+ * Ensures:
+ */
+ extern bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry);
+
+/*
+ * ======== DBL_getSect ========
+ * Get address and size of a named section.
+ * Parameters:
+ * lib - Library handle returned from DBL_open().
+ * name - Name of section.
+ * pAddr - Location to store section address on output.
+ * pSize - Location to store section size on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Section not found.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pAddr != NULL;
+ * pSize != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name,
+ u32 *pAddr, u32 *pSize);
+
+/*
+ * ======== DBL_init ========
+ * Initialize DBL module.
+ * Parameters:
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Failure.
+ * Requires:
+ * cRefs >= 0.
+ * Ensures:
+ * Success: cRefs > 0.
+ * Failure: cRefs >= 0.
+ */
+ extern bool DBL_init(void);
+
+/*
+ * ======== DBL_load ========
+ * Add symbols/code/data defined in file to that already present on
+ * the target.
+ *
+ * Parameters:
+ * lib - Library handle returned from DBL_open().
+ * flags - Specifies whether loading code, data, and/or symbols.
+ * attrs - May contain write, alloc, and free functions.
+ * pulEntry - Location to store program entry on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFREAD: File read failed.
+ * DSP_EFWRITE: Write to target failed.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * pEntry != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
+ struct DBL_Attrs *attrs, u32 *pEntry);
+
+/*
+ * ======== DBL_loadSect ========
+ * Load a named section from an library (for overlay support).
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * sectName - Name of section to load.
+ * attrs - Contains write function and handle to pass to it.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Section not found.
+ * DSP_EFWRITE: Write function failed.
+ * Requires:
+ * Valid lib.
+ * sectName != NULL.
+ * attrs != NULL.
+ * attrs->write != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib,
+ char *sectName,
+ struct DBL_Attrs *attrs);
+
+/*
+ * ======== DBL_open ========
+ * DBL_open() returns a library handle that can be used to load/unload
+ * the symbols/code/data via DBL_load()/DBL_unload().
+ * Parameters:
+ * target - Handle returned from DBL_create().
+ * file - Name of file to open.
+ * flags - Specifies whether to load symbols now.
+ * pLib - Location to store library handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EFOPEN: File open failure.
+ * DSP_EFREAD: File read failure.
+ * DSP_ECORRUPTFILE: Unable to determine target type.
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * file != NULL.
+ * pLib != NULL.
+ * struct DBL_Attrs fopen function non-NULL.
+ * Ensures:
+ * Success: Valid *pLib.
+ * Failure: *pLib == NULL.
+ */
+ extern DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file,
+ DBL_Flags flags,
+ struct DBL_LibraryObj **pLib);
+
+/*
+ * ======== DBL_readSect ========
+ * Read COFF section into a character buffer.
+ * Parameters:
+ * lib - Library handle returned from DBL_open().
+ * name - Name of section.
+ * pBuf - Buffer to write section contents into.
+ * size - Buffer size
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Named section does not exists.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pBuf != NULL.
+ * size != 0.
+ * Ensures:
+ */
+ extern DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name,
+ char *pBuf, u32 size);
+
+/*
+ * ======== DBL_setAttrs ========
+ * Set the attributes of the target.
+ * Parameters:
+ * target - Handle returned from DBL_create().
+ * pAttrs - New attributes.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * pAttrs != NULL.
+ * Ensures:
+ */
+ extern void DBL_setAttrs(struct DBL_TargetObj *target,
+ struct DBL_Attrs *pAttrs);
+
+/*
+ * ======== DBL_unload ========
+ * Remove the symbols/code/data corresponding to the library lib.
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * attrs - Contains free() function and handle to pass to it.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * Ensures:
+ */
+ extern void DBL_unload(struct DBL_LibraryObj *lib,
+ struct DBL_Attrs *attrs);
+
+/*
+ * ======== DBL_unloadSect ========
+ * Unload a named section from an library (for overlay support).
+ * Parameters:
+ * lib - Handle returned from DBL_open().
+ * sectName - Name of section to load.
+ * attrs - Contains free() function and handle to pass to it.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Named section not found.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * sectName != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib,
+ char *sectName,
+ struct DBL_Attrs *attrs);
+
+#endif /* DBL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbldefs.h b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
new file mode 100644
index 000000000000..79b9e54e3b3e
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
@@ -0,0 +1,155 @@
+/*
+ * dbldefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbldefs.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
+ *! between different loaders).
+ *! 28-Sep-2001 jeh Created from zl.h.
+ */
+#ifndef DBLDEFS_
+#define DBLDEFS_
+
+/*
+ * Bit masks for DBL_Flags.
+ */
+#define DBL_NOLOAD 0x0 /* Don't load symbols, code, or data */
+#define DBL_SYMB 0x1 /* load symbols */
+#define DBL_CODE 0x2 /* load code */
+#define DBL_DATA 0x4 /* load data */
+#define DBL_DYNAMIC 0x8 /* dynamic load */
+#define DBL_BSS 0x20 /* Unitialized section */
+
+#define DBL_MAXPATHLENGTH 255
+
+
+
+/*
+ * ======== DBL_Flags ========
+ * Specifies whether to load code, data, or symbols
+ */
+typedef s32 DBL_Flags;
+
+/*
+ * ======== DBL_SectInfo ========
+ * For collecting info on overlay sections
+ */
+struct DBL_SectInfo {
+ const char *name; /* name of section */
+ u32 runAddr; /* run address of section */
+ u32 loadAddr; /* load address of section */
+ u32 size; /* size of section (target MAUs) */
+ DBL_Flags type; /* Code, data, or BSS */
+} ;
+
+/*
+ * ======== DBL_Symbol ========
+ * (Needed for dynamic load library)
+ */
+struct DBL_Symbol {
+ u32 value;
+};
+
+/*
+ * ======== DBL_AllocFxn ========
+ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
+ * "size" bytes of memory from segment "space" and return the address in
+ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
+ * success, or an error code on failure.
+ */
+typedef s32(*DBL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
+ u32 *dspAddr, s32 segId, s32 req, bool reserved);
+
+
+
+/*
+ * ======== DBL_FreeFxn ========
+ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
+ * bytes of memory from segment "space"
+ */
+typedef bool(*DBL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
+ bool reserved);
+
+/*
+ * ======== DBL_LogWriteFxn ========
+ * Function to call when writing data from a section, to log the info.
+ * Can be NULL if no logging is required.
+ */
+typedef DSP_STATUS(*DBL_LogWriteFxn) (void *handle, struct DBL_SectInfo *sect,
+ u32 addr, u32 nBytes);
+
+
+/*
+ * ======== DBL_SymLookup ========
+ * Symbol lookup function - Find the symbol name and return its value.
+ *
+ * Parameters:
+ * handle - Opaque handle
+ * pArg - Opaque argument.
+ * name - Name of symbol to lookup.
+ * sym - Location to store address of symbol structure.
+ *
+ * Returns:
+ * TRUE: Success (symbol was found).
+ * FALSE: Failed to find symbol.
+ */
+typedef bool(*DBL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
+ const char *name, struct DBL_Symbol **sym);
+
+
+/*
+ * ======== DBL_WriteFxn ========
+ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
+ * starting at address "dspAddr" from the buffer "buf". The buffer is
+ * formatted as an array of words appropriate for the DSP.
+ */
+typedef s32(*DBL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
+ u32 n, s32 mtype);
+
+/*
+ * ======== DBL_Attrs ========
+ */
+struct DBL_Attrs {
+ DBL_AllocFxn alloc;
+ DBL_FreeFxn free;
+ void *rmmHandle; /* Handle to pass to alloc, free functions */
+ DBL_WriteFxn write;
+ void *wHandle; /* Handle to pass to write, cinit function */
+
+ DBL_LogWriteFxn logWrite;
+ void *logWriteHandle;
+
+ /* Symbol matching function and handle to pass to it */
+ DBL_SymLookup symLookup;
+ void *symHandle;
+ void *symArg;
+
+ /*
+ * These file manipulation functions should be compatible with the
+ * "C" run time library functions of the same name.
+ */
+ s32(*fread) (void *, size_t, size_t, void *);
+ s32(*fseek) (void *, long, int);
+ s32(*ftell) (void *);
+ s32(*fclose) (void *);
+ void *(*fopen) (const char *, const char *);
+} ;
+
+#endif /* DBLDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbll.h b/arch/arm/plat-omap/include/dspbridge/dbll.h
new file mode 100644
index 000000000000..c3aa212517a4
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbll.h
@@ -0,0 +1,70 @@
+/*
+ * dbll.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbll.h ========
+ * DSP/BIOS Bridge Dynamic load library module interface. Function header
+ * comments are in the file dblldefs.h.
+ *
+ *! Revision History
+ *! ================
+ *! 31-Jul-2002 jeh Removed function comments (now in dblldefs.h).
+ *! 17-Apr-2002 jeh Created based on zl.h.
+ */
+
+#ifndef DBLL_
+#define DBLL_
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/dblldefs.h>
+
+ extern void DBLL_close(struct DBLL_LibraryObj *lib);
+ extern DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget,
+ struct DBLL_Attrs *pAttrs);
+ extern void DBLL_delete(struct DBLL_TarObj *target);
+ extern void DBLL_exit(void);
+ extern bool DBLL_getAddr(struct DBLL_LibraryObj *lib, char *name,
+ struct DBLL_Symbol **ppSym);
+ extern void DBLL_getAttrs(struct DBLL_TarObj *target,
+ struct DBLL_Attrs *pAttrs);
+ extern bool DBLL_getCAddr(struct DBLL_LibraryObj *lib, char *name,
+ struct DBLL_Symbol **ppSym);
+ extern DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name,
+ u32 *pAddr, u32 *pSize);
+ extern bool DBLL_init(void);
+ extern DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib,
+ DBLL_Flags flags,
+ struct DBLL_Attrs *attrs, u32 *pEntry);
+ extern DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *lib,
+ char *sectName,
+ struct DBLL_Attrs *attrs);
+ extern DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file,
+ DBLL_Flags flags,
+ struct DBLL_LibraryObj **pLib);
+ extern DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib,
+ char *name,
+ char *pBuf, u32 size);
+ extern void DBLL_setAttrs(struct DBLL_TarObj *target,
+ struct DBLL_Attrs *pAttrs);
+ extern void DBLL_unload(struct DBLL_LibraryObj *lib,
+ struct DBLL_Attrs *attrs);
+ extern DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib,
+ char *sectName,
+ struct DBLL_Attrs *attrs);
+
+#endif /* DBLL_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/dblldefs.h b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
new file mode 100644
index 000000000000..2361ce885c3b
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
@@ -0,0 +1,509 @@
+/*
+ * dblldefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dblldefs.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 08-Apr-2003 map Consolidated DBL into DBLL name
+ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
+ *! between different loaders).
+ *! 28-Sep-2001 jeh Created from zl.h.
+ */
+#ifndef DBLLDEFS_
+#define DBLLDEFS_
+
+/*
+ * Bit masks for DBL_Flags.
+ */
+#define DBLL_NOLOAD 0x0 /* Don't load symbols, code, or data */
+#define DBLL_SYMB 0x1 /* load symbols */
+#define DBLL_CODE 0x2 /* load code */
+#define DBLL_DATA 0x4 /* load data */
+#define DBLL_DYNAMIC 0x8 /* dynamic load */
+#define DBLL_BSS 0x20 /* Unitialized section */
+
+#define DBLL_MAXPATHLENGTH 255
+
+
+/*
+ * ======== DBLL_Target ========
+ *
+ */
+struct DBLL_TarObj;
+
+/*
+ * ======== DBLL_Flags ========
+ * Specifies whether to load code, data, or symbols
+ */
+typedef s32 DBLL_Flags;
+
+/*
+ * ======== DBLL_Library ========
+ *
+ */
+struct DBLL_LibraryObj;
+
+/*
+ * ======== DBLL_SectInfo ========
+ * For collecting info on overlay sections
+ */
+struct DBLL_SectInfo {
+ const char *name; /* name of section */
+ u32 runAddr; /* run address of section */
+ u32 loadAddr; /* load address of section */
+ u32 size; /* size of section (target MAUs) */
+ DBLL_Flags type; /* Code, data, or BSS */
+} ;
+
+/*
+ * ======== DBLL_Symbol ========
+ * (Needed for dynamic load library)
+ */
+struct DBLL_Symbol {
+ u32 value;
+};
+
+/*
+ * ======== DBLL_AllocFxn ========
+ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
+ * "size" bytes of memory from segment "space" and return the address in
+ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
+ * success, or an error code on failure.
+ */
+typedef s32(*DBLL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
+ u32 *dspAddr, s32 segId, s32 req,
+ bool reserved);
+
+/*
+ * ======== DBLL_CloseFxn ========
+ */
+typedef s32(*DBLL_FCloseFxn) (void *);
+
+/*
+ * ======== DBLL_FreeFxn ========
+ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
+ * bytes of memory from segment "space"
+ */
+typedef bool(*DBLL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
+ bool reserved);
+
+/*
+ * ======== DBLL_FOpenFxn ========
+ */
+typedef void *(*DBLL_FOpenFxn) (const char *, const char *);
+
+/*
+ * ======== DBLL_LogWriteFxn ========
+ * Function to call when writing data from a section, to log the info.
+ * Can be NULL if no logging is required.
+ */
+typedef DSP_STATUS(*DBLL_LogWriteFxn)(void *handle, struct DBLL_SectInfo *sect,
+ u32 addr, u32 nBytes);
+
+/*
+ * ======== DBLL_ReadFxn ========
+ */
+typedef s32(*DBLL_ReadFxn) (void *, size_t, size_t, void *);
+
+/*
+ * ======== DBLL_SeekFxn ========
+ */
+typedef s32(*DBLL_SeekFxn) (void *, long, int);
+
+/*
+ * ======== DBLL_SymLookup ========
+ * Symbol lookup function - Find the symbol name and return its value.
+ *
+ * Parameters:
+ * handle - Opaque handle
+ * pArg - Opaque argument.
+ * name - Name of symbol to lookup.
+ * sym - Location to store address of symbol structure.
+ *
+ * Returns:
+ * TRUE: Success (symbol was found).
+ * FALSE: Failed to find symbol.
+ */
+typedef bool(*DBLL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
+ const char *name, struct DBLL_Symbol **sym);
+
+/*
+ * ======== DBLL_TellFxn ========
+ */
+typedef s32(*DBLL_TellFxn) (void *);
+
+/*
+ * ======== DBLL_WriteFxn ========
+ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
+ * starting at address "dspAddr" from the buffer "buf". The buffer is
+ * formatted as an array of words appropriate for the DSP.
+ */
+typedef s32(*DBLL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
+ u32 n, s32 mtype);
+
+/*
+ * ======== DBLL_Attrs ========
+ */
+struct DBLL_Attrs {
+ DBLL_AllocFxn alloc;
+ DBLL_FreeFxn free;
+ void *rmmHandle; /* Handle to pass to alloc, free functions */
+ DBLL_WriteFxn write;
+ void *wHandle; /* Handle to pass to write, cinit function */
+ bool baseImage;
+ DBLL_LogWriteFxn logWrite;
+ void *logWriteHandle;
+
+ /* Symbol matching function and handle to pass to it */
+ DBLL_SymLookup symLookup;
+ void *symHandle;
+ void *symArg;
+
+ /*
+ * These file manipulation functions should be compatible with the
+ * "C" run time library functions of the same name.
+ */
+ s32(*fread) (void *, size_t, size_t, void *);
+ s32(*fseek) (void *, long, int);
+ s32(*ftell) (void *);
+ s32(*fclose) (void *);
+ void *(*fopen) (const char *, const char *);
+} ;
+
+/*
+ * ======== DBLL_close ========
+ * Close library opened with DBLL_open.
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * Ensures:
+ */
+typedef void(*DBLL_CloseFxn) (struct DBLL_LibraryObj *library);
+
+/*
+ * ======== DBLL_create ========
+ * Create a target object, specifying the alloc, free, and write functions.
+ * Parameters:
+ * pTarget - Location to store target handle on output.
+ * pAttrs - Attributes.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failed.
+ * Requires:
+ * DBL initialized.
+ * pAttrs != NULL.
+ * pTarget != NULL;
+ * Ensures:
+ * Success: *pTarget != NULL.
+ * Failure: *pTarget == NULL.
+ */
+typedef DSP_STATUS(*DBLL_CreateFxn)(struct DBLL_TarObj **pTarget,
+ struct DBLL_Attrs *attrs);
+
+/*
+ * ======== DBLL_delete ========
+ * Delete target object and free resources for any loaded libraries.
+ * Parameters:
+ * target - Handle returned from DBLL_Create().
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * Ensures:
+ */
+typedef void(*DBLL_DeleteFxn) (struct DBLL_TarObj *target);
+
+/*
+ * ======== DBLL_exit ========
+ * Discontinue use of DBL module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * cRefs > 0.
+ * Ensures:
+ * cRefs >= 0.
+ */
+typedef void(*DBLL_ExitFxn) (void);
+
+/*
+ * ======== DBLL_getAddr ========
+ * Get address of name in the specified library.
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * name - Name of symbol
+ * ppSym - Location to store symbol address on output.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Symbol not found.
+ * Requires:
+ * DBL initialized.
+ * Valid library.
+ * name != NULL.
+ * ppSym != NULL.
+ * Ensures:
+ */
+typedef bool(*DBLL_GetAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
+ struct DBLL_Symbol **ppSym);
+
+/*
+ * ======== DBLL_getAttrs ========
+ * Retrieve the attributes of the target.
+ * Parameters:
+ * target - Handle returned from DBLL_Create().
+ * pAttrs - Location to store attributes on output.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * pAttrs != NULL.
+ * Ensures:
+ */
+typedef void(*DBLL_GetAttrsFxn) (struct DBLL_TarObj *target,
+ struct DBLL_Attrs *attrs);
+
+/*
+ * ======== DBLL_getCAddr ========
+ * Get address of "C" name on the specified library.
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * name - Name of symbol
+ * ppSym - Location to store symbol address on output.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Symbol not found.
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * name != NULL.
+ * ppSym != NULL.
+ * Ensures:
+ */
+typedef bool(*DBLL_GetCAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
+ struct DBLL_Symbol **ppSym);
+
+/*
+ * ======== DBLL_getSect ========
+ * Get address and size of a named section.
+ * Parameters:
+ * lib - Library handle returned from DBLL_open().
+ * name - Name of section.
+ * pAddr - Location to store section address on output.
+ * pSize - Location to store section size on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Section not found.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pAddr != NULL;
+ * pSize != NULL.
+ * Ensures:
+ */
+typedef DSP_STATUS(*DBLL_GetSectFxn) (struct DBLL_LibraryObj *lib, char *name,
+ u32 *addr, u32 *size);
+
+/*
+ * ======== DBLL_init ========
+ * Initialize DBL module.
+ * Parameters:
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Failure.
+ * Requires:
+ * cRefs >= 0.
+ * Ensures:
+ * Success: cRefs > 0.
+ * Failure: cRefs >= 0.
+ */
+typedef bool(*DBLL_InitFxn) (void);
+
+/*
+ * ======== DBLL_load ========
+ * Load library onto the target.
+ *
+ * Parameters:
+ * lib - Library handle returned from DBLL_open().
+ * flags - Load code, data and/or symbols.
+ * attrs - May contain alloc, free, and write function.
+ * pulEntry - Location to store program entry on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFREAD: File read failed.
+ * DSP_EFWRITE: Write to target failed.
+ * DSP_EDYNLOAD: Failure in dynamic loader library.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * pEntry != NULL.
+ * Ensures:
+ */
+typedef DSP_STATUS(*DBLL_LoadFxn) (struct DBLL_LibraryObj *lib,
+ DBLL_Flags flags,
+ struct DBLL_Attrs *attrs, u32 *entry);
+
+/*
+ * ======== DBLL_loadSect ========
+ * Load a named section from an library (for overlay support).
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * sectName - Name of section to load.
+ * attrs - Contains write function and handle to pass to it.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Section not found.
+ * DSP_EFWRITE: Write function failed.
+ * DSP_ENOTIMPL: Function not implemented.
+ * Requires:
+ * Valid lib.
+ * sectName != NULL.
+ * attrs != NULL.
+ * attrs->write != NULL.
+ * Ensures:
+ */
+typedef DSP_STATUS(*DBLL_LoadSectFxn) (struct DBLL_LibraryObj *lib,
+ char *pszSectName,
+ struct DBLL_Attrs *attrs);
+
+/*
+ * ======== DBLL_open ========
+ * DBLL_open() returns a library handle that can be used to load/unload
+ * the symbols/code/data via DBLL_load()/DBLL_unload().
+ * Parameters:
+ * target - Handle returned from DBLL_create().
+ * file - Name of file to open.
+ * flags - If flags & DBLL_SYMB, load symbols.
+ * pLib - Location to store library handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EFOPEN: File open failure.
+ * DSP_EFREAD: File read failure.
+ * DSP_ECORRUPTFILE: Unable to determine target type.
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * file != NULL.
+ * pLib != NULL.
+ * DBLL_Attrs fopen function non-NULL.
+ * Ensures:
+ * Success: Valid *pLib.
+ * Failure: *pLib == NULL.
+ */
+typedef DSP_STATUS(*DBLL_OpenFxn) (struct DBLL_TarObj *target, char *file,
+ DBLL_Flags flags,
+ struct DBLL_LibraryObj **pLib);
+
+/*
+ * ======== DBLL_readSect ========
+ * Read COFF section into a character buffer.
+ * Parameters:
+ * lib - Library handle returned from DBLL_open().
+ * name - Name of section.
+ * pBuf - Buffer to write section contents into.
+ * size - Buffer size
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Named section does not exists.
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * name != NULL.
+ * pBuf != NULL.
+ * size != 0.
+ * Ensures:
+ */
+typedef DSP_STATUS(*DBLL_ReadSectFxn) (struct DBLL_LibraryObj *lib, char *name,
+ char *content, u32 uContentSize);
+
+/*
+ * ======== DBLL_setAttrs ========
+ * Set the attributes of the target.
+ * Parameters:
+ * target - Handle returned from DBLL_create().
+ * pAttrs - New attributes.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid target.
+ * pAttrs != NULL.
+ * Ensures:
+ */
+typedef void(*DBLL_SetAttrsFxn)(struct DBLL_TarObj *target,
+ struct DBLL_Attrs *attrs);
+
+/*
+ * ======== DBLL_unload ========
+ * Unload library loaded with DBLL_load().
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * attrs - Contains free() function and handle to pass to it.
+ * Returns:
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * Ensures:
+ */
+typedef void(*DBLL_UnloadFxn) (struct DBLL_LibraryObj *library,
+ struct DBLL_Attrs *attrs);
+
+/*
+ * ======== DBLL_unloadSect ========
+ * Unload a named section from an library (for overlay support).
+ * Parameters:
+ * lib - Handle returned from DBLL_open().
+ * sectName - Name of section to load.
+ * attrs - Contains free() function and handle to pass to it.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ENOSECT: Named section not found.
+ * DSP_ENOTIMPL
+ * Requires:
+ * DBL initialized.
+ * Valid lib.
+ * sectName != NULL.
+ * Ensures:
+ */
+typedef DSP_STATUS(*DBLL_UnloadSectFxn) (struct DBLL_LibraryObj *lib,
+ char *pszSectName,
+ struct DBLL_Attrs *attrs);
+
+struct DBLL_Fxns {
+ DBLL_CloseFxn closeFxn;
+ DBLL_CreateFxn createFxn;
+ DBLL_DeleteFxn deleteFxn;
+ DBLL_ExitFxn exitFxn;
+ DBLL_GetAttrsFxn getAttrsFxn;
+ DBLL_GetAddrFxn getAddrFxn;
+ DBLL_GetCAddrFxn getCAddrFxn;
+ DBLL_GetSectFxn getSectFxn;
+ DBLL_InitFxn initFxn;
+ DBLL_LoadFxn loadFxn;
+ DBLL_LoadSectFxn loadSectFxn;
+ DBLL_OpenFxn openFxn;
+ DBLL_ReadSectFxn readSectFxn;
+ DBLL_SetAttrsFxn setAttrsFxn;
+ DBLL_UnloadFxn unloadFxn;
+ DBLL_UnloadSectFxn unloadSectFxn;
+} ;
+
+#endif /* DBLDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbof.h b/arch/arm/plat-omap/include/dspbridge/dbof.h
new file mode 100644
index 000000000000..54f425088754
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbof.h
@@ -0,0 +1,117 @@
+/*
+ * dbof.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbof.h ========
+ * Description:
+ * Defines and typedefs for DSP/BIOS Bridge Object File Format (DBOF).
+ *
+ *! Revision History
+ *! ================
+ *! 12-Jul-2002 jeh Added defines for DBOF_SectHdr page.
+ *! 12-Oct-2001 jeh Converted to std.h format.
+ *! 07-Sep-2001 jeh Added overlay support.
+ *! 06-Jul-2001 jeh Created.
+ */
+
+#ifndef DBOF_
+#define DBOF_
+
+/* Enough to hold DCD section names: 32 digit ID + underscores */
+#define DBOF_DCDSECTNAMELEN 40
+
+/* Values for DBOF_SectHdr page field. */
+#define DBOF_PROGRAM 0
+#define DBOF_DATA 1
+#define DBOF_CINIT 2
+
+/*
+ * ======== DBOF_FileHdr ========
+ */
+ struct DBOF_FileHdr {
+ u32 magic; /* COFF magic number */
+ u32 entry; /* Program entry point */
+ u16 numSymbols; /* Number of bridge symbols */
+ u16 numDCDSects; /* Number of DCD sections */
+ u16 numSects; /* Number of sections to load */
+ u16 numOvlySects; /* Number of overlay sections */
+ u32 symOffset; /* Offset in file to symbols */
+ u32 dcdSectOffset; /* Offset to DCD sections */
+ u32 loadSectOffset; /* Offset to loadable sections */
+ u32 ovlySectOffset; /* Offset to overlay data */
+ u16 version; /* DBOF version number */
+ u16 resvd; /* Reserved for future use */
+ } ;
+
+/*
+ * ======== DBOF_DCDSectHdr ========
+ */
+ struct DBOF_DCDSectHdr {
+ u32 size; /* Sect size (target MAUs) */
+ char name[DBOF_DCDSECTNAMELEN]; /* DCD section name */
+ } ;
+
+/*
+ * ======== DBOF_OvlySectHdr ========
+ */
+ struct DBOF_OvlySectHdr {
+ u16 nameLen; /* Length of section name */
+ u16 numCreateSects; /* # of sects loaded for create phase */
+ u16 numDeleteSects; /* # of sects loaded for delete phase */
+ u16 numExecuteSects; /* # of sects loaded for execute phase */
+
+ /*
+ * Number of sections where load/unload phase is not specified.
+ * These sections will be loaded when create phase sects are
+ * loaded, and unloaded when the delete phase is unloaded.
+ */
+ u16 numOtherSects;
+ u16 resvd; /* Reserved for future use */
+ };
+
+/*
+ * ======== DBOF_OvlySectData ========
+ */
+ struct DBOF_OvlySectData {
+ u32 loadAddr; /* Section load address */
+ u32 runAddr; /* Section run address */
+ u32 size; /* Section size (target MAUs) */
+ u16 page; /* Memory page number */
+ u16 resvd; /* Reserved */
+ } ;
+
+/*
+ * ======== DBOF_SectHdr ========
+ */
+ struct DBOF_SectHdr {
+ u32 addr; /* Section address */
+ u32 size; /* Section size (target MAUs) */
+ u16 page; /* Page number */
+ u16 resvd; /* Reserved for future use */
+ } ;
+
+/*
+ * ======== DBOF_SymbolHdr ========
+ */
+ struct DBOF_SymbolHdr {
+ u32 value; /* Symbol value */
+ u16 nameLen; /* Length of symbol name */
+ u16 resvd; /* Reserved for future use */
+ } ;
+
+#endif /* DBOF_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/dbreg.h b/arch/arm/plat-omap/include/dspbridge/dbreg.h
new file mode 100644
index 000000000000..d311b889f84c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbreg.h
@@ -0,0 +1,113 @@
+/*
+ * dbreg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbreg.h ========
+ * Purpose:
+ * Registry keys for use in Linux. This is the clearinghouse for
+ * registry definitions, hopefully eliminating overlapping between
+ * modules.
+ *
+ *! Revision History:
+ *! ================
+ *! 10-Apr-2003 vp: Added macro for subkey TCWORDSWAP.
+ *! 21-Mar-2003 sb: Added macro for subkey SHMSize
+ *! 27-Aug-2001 jeh Added WSXREG_LOADERFILENAME.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 29-Nov-2000 rr: Added WSXREG_DSPTYPE_55 as 6.
+ *! 06-Sep-2000 jeh: Added WSXREG_CHNLOFFSET, WSXREG_NUMCHNLS,
+ *! WSXREG_CHNLBUFSIZE.
+ *! 26-Aug-2000 rr: MEMBASE expanded to 9 entries.
+ *! 26-Jul-2000 rr: Added WSXREG_DCDNAME for the DCD Dll name. It will
+ *! live under WSXREG_WINSPOXCONFIG.
+ *! 17-Jul-2000 rr: REG_MGR_OBJECT and REG_DRV_OBJECT defined. They
+ *! are stored in the Registrty under WSXREG_WINSPOXCONFIG
+ *! when they are created in DSP_Init. WSXREG_DEVOBJECT
+ *! and WSXREG_MGROBJECT defined.
+ *! 11-Dec-1999 ag: Renamed Isa to IsaBus due to conflict with ceddk.h.
+ *! 12-Nov-1999 rr: New Registry Defnitions.
+ *! 15-Oct-1999 rr: New entry for DevObject created. WSXREG_DEVOBJECT
+ *! under WSXREG_DDSPDRIVERPATH
+ *! 10-Nov-1997 cr: Added WSXREG_INFPATH, WSXREG_WINDEVICEPATH,
+ *! WSXREG_WINCURVERSION
+ *! 21-Oct-1997 cr: Added WSXREG_BUSTYPE.
+ *! 08-Sep-1997 cr: Added WSXREG_SERVICES, WSXREG_SERVICENAME and
+ *! WSXREG_CLASSINDEX.
+ *! 30-Aug-1997 cr: Added WSXREG_SOFTWAREPATHNT & WSXREG_WBCLASSGUID.
+ *! 24-Mar-1997 gp: Added MAXCHIPINFOSUBKEY def.
+ *! 18-Feb-1997 cr: Changed Version1.1 -> Version1.0
+ *! 12-Feb-1997 cr: Changed WinSPOX -> WinBRIDGE.
+ *! 11-Dec-1996 gp: Added Perf key name in WinSPOX Config.
+ *! 22-Jul-1996 gp: Added Trace key name.
+ *! 30-May-1996 cr: Created.
+ */
+
+#ifndef DBREG_
+#define DBREG_ 1 /* Defined as "1" so InstallShield programs compile. */
+
+#define REG_MGR_OBJECT 1
+#define REG_DRV_OBJECT 2
+/* general registry definitions */
+#define MAXREGPATHLENGTH 255 /* Max registry path length. Also the
+ max registry value length. */
+#define DSPTYPE_55 6 /* This is the DSP Chip type for 55 */
+#define DSPTYPE_64 0x99
+#define IVA_ARM7 0x97 /* This is the DSP Chip type for IVA/ARM7 */
+
+#define DSPPROCTYPE_C55 5510
+#define DSPPROCTYPE_C64 6410
+#define IVAPROCTYPE_ARM7 470
+/* registry */
+#define DEVNODESTRING "DevNode" /* u32 devnode */
+#define CONFIG "Software\\TexasInstruments\\DirectDSP\\Config"
+#define DRVOBJECT "DrvObject"
+#define MGROBJECT "MgrObject"
+#define CLASS "Device" /* device class */
+#define TRACE "Trace" /* GT Trace settings. */
+#define PERFR "Perf" /* Enable perf bool. */
+#define ROOT "Root" /* root dir */
+
+/* MiniDriver related definitions */
+/* The following definitions are under "Drivers\\DirectDSP\\Device\\XXX "
+ * Where XXX is the device or board name */
+
+#define WMDFILENAME "MiniDriver" /* WMD entry name */
+#define CHIPTYPE "ChipType" /* Chip type */
+#define CHIPNUM "NumChips" /* Number of chips */
+#define NUMPROCS "NumOfProcessors" /* Number of processors */
+#define DEFEXEC "DefaultExecutable" /* Default executable */
+#define AUTOSTART "AutoStart" /* Statically load flag */
+#define IVAAUTOSTART "IvaAutoStart" /* Statically load flag */
+#define BOARDNAME "BoardName" /* Name of the Board */
+#define UNITNUMBER "UnitNumber" /* Unit # of the Board */
+#define BUSTYPE "BusType" /* Bus type board is on */
+#define BUSNUMBER "BusNumber" /* Bus number board is on */
+#define CURRENTCONFIG "CurrentConfig" /* Current resources */
+#define PCIVENDEVID "VendorDeviceId" /* The board's id */
+#define INFPATH "InfPath" /* wmd's inf filename */
+#define DEVOBJECT "DevObject"
+#define ZLFILENAME "ZLFileName" /* Name of ZL file */
+#define WORDSIZE "WordSize" /* NumBytes in DSP Word */
+#define SHMSIZE "SHMSize" /* Size of SHM reservd on MPU */
+#define IVAEXTMEMSIZE "IVAEXTMEMSize" /* IVA External Memeory size */
+#define TCWORDSWAP "TCWordSwap" /* Traffic Contoller Word Swap */
+#define DSPRESOURCES "DspTMSResources" /* C55 DSP resurces on OMAP */
+#define IVA1RESOURCES "ARM7IvaResources" /* ARM7 IVA resurces on OMAP */
+#define PHYSMEMPOOLBASE "PhysicalMemBase" /* Physical mem passed to driver */
+#define PHYSMEMPOOLSIZE "PhysicalMemSize" /* Physical mem passed to driver */
+
+#endif /* DBREG_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dbtype.h b/arch/arm/plat-omap/include/dspbridge/dbtype.h
new file mode 100644
index 000000000000..b4953a042c9c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dbtype.h
@@ -0,0 +1,103 @@
+/*
+ * dbtype.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== dbtype.h ========
+ * Description:
+ * This header defines data types for DSP/BIOS Bridge APIs and device
+ * driver modules. It also defines the Hungarian
+ * prefix to use for each base type.
+ *
+ *
+ *! Revision History:
+ *! =================
+ *! 23-Nov-2002 gp: Purpose -> Description in file header.
+ *! 13-Feb-2001 kc: Name changed from ddsptype.h dbtype.h.
+ *! 09-Oct-2000 jeh Added CHARACTER.
+ *! 11-Aug-2000 ag: Added 'typedef void void'.
+ *! 08-Apr-2000 ww: Cloned.
+ */
+
+#ifndef DBTYPE_
+#define DBTYPE_
+
+/*============================================================================*/
+/* Argument specification syntax */
+/*============================================================================*/
+
+#ifndef IN
+#define IN /* Following parameter is for input. */
+#endif
+
+#ifndef OUT
+#define OUT /* Following parameter is for output. */
+#endif
+
+#ifndef OPTIONAL
+#define OPTIONAL /* Function may optionally use previous parameter. */
+#endif
+
+#ifndef CONST
+#define CONST const
+#endif
+
+/*============================================================================*/
+/* Boolean constants */
+/*============================================================================*/
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/*============================================================================*/
+/* NULL (Definition is language specific) */
+/*============================================================================*/
+
+#ifndef NULL
+#define NULL ((void *)0) /* Null pointer. */
+#endif
+
+/*============================================================================*/
+/* NULL character (normally used for string termination) */
+/*============================================================================*/
+
+#ifndef NULL_CHAR
+#define NULL_CHAR '\0' /* Null character. */
+#endif
+
+/*============================================================================*/
+/* Basic Type definitions (with Prefixes for Hungarian notation) */
+/*============================================================================*/
+
+#ifndef OMAPBRIDGE_TYPES
+#define OMAPBRIDGE_TYPES
+typedef volatile unsigned short REG_UWORD16;
+#endif
+
+typedef void *HANDLE; /* h */
+
+#define TEXT(x) x
+
+#define DLLIMPORT
+#define DLLEXPORT
+
+/* Define DSPAPIDLL correctly in dspapi.h */
+#define _DSPSYSDLL32_
+
+#endif /* DBTYPE_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dehdefs.h b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
new file mode 100644
index 000000000000..06e55821a34d
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
@@ -0,0 +1,42 @@
+/*
+ * dehdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== dehdefs.h ========
+ * Purpose:
+ * Definition for mini-driver module DEH.
+ *
+ *! Revision History:
+ *! ================
+ *! 17-Dec-2001 ag: added #include <dspbridge/mbx_sh.h> for shared mailbox codes.
+ *! 10-Dec-2001 kc: added DEH error base value and error max value.
+ *! 11-Sep-2001 kc: created.
+ */
+
+#ifndef DEHDEFS_
+#define DEHDEFS_
+
+#include <dspbridge/mbx_sh.h> /* shared mailbox codes */
+
+/* DEH object manager */
+ struct DEH_MGR;
+
+/* Magic code used to determine if DSP signaled exception. */
+#define DEH_BASE MBX_DEH_BASE
+#define DEH_USERS_BASE MBX_DEH_USERS_BASE
+#define DEH_LIMIT MBX_DEH_LIMIT
+
+#endif /* _DEHDEFS_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/dev.h b/arch/arm/plat-omap/include/dspbridge/dev.h
new file mode 100644
index 000000000000..5f468c9164d3
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dev.h
@@ -0,0 +1,785 @@
+/*
+ * dev.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dev.h ========
+ * Description:
+ * 'Bridge Mini-driver device operations.
+ *
+ * Public Functions:
+ * DEV_BrdWriteFxn
+ * DEV_CreateDevice
+ * DEV_Create2
+ * DEV_Destroy2
+ * DEV_DestroyDevice
+ * DEV_GetChnlMgr
+ * DEV_GetCmmMgr
+ * DEV_GetCodMgr
+ * DEV_GetDehMgr
+ * DEV_GetDevNode
+ * DEV_GetDSPWordSize
+ * DEV_GetFirst
+ * DEV_GetIntfFxns
+ * DEV_GetIOMgr
+ * DEV_GetMsgMgr
+ * DEV_GetNext
+ * DEV_GetNodeManager
+ * DEV_GetSymbol
+ * DEV_GetWMDContext
+ * DEV_Exit
+ * DEV_Init
+ * DEV_InsertProcObject
+ * DEV_IsLocked
+ * DEV_NotifyClient
+ * DEV_RegisterNotify
+ * DEV_ReleaseCodMgr
+ * DEV_RemoveDevice
+ * DEV_RemoveProcObject
+ * DEV_SetChnlMgr
+ * DEV_SetMsgMgr
+ * DEV_SetLockOwner
+ * DEV_StartDevice
+ *
+ *! Revision History:
+ *! ================
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature - Dev_GetDmmMgr
+ *! 09-Feb-2004 vp Added functions required for IVA
+ *! 25-Feb-2003 swa PMGR Code Review changes incorporated
+ *! 05-Nov-2001 kc: Added DEV_GetDehMgr.
+ *! 05-Dec-2000 jeh Added DEV_SetMsgMgr.
+ *! 29-Nov-2000 rr: Incorporated code review changes.
+ *! 17-Nov-2000 jeh Added DEV_GetMsgMgr.
+ *! 05-Oct-2000 rr: DEV_Create2 & DEV_Destroy2 Added.
+ *! 02-Oct-2000 rr: Added DEV_GetNodeManager.
+ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr() for shared memory management.
+ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
+ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
+ *! 05-Nov-1999 kc: Updated function prototypes.
+ *! 08-Oct-1997 cr: Added explicit CDECL function identifiers.
+ *! 07-Nov-1996 gp: Updated for code review.
+ *! 22-Oct-1996 gp: Added DEV_CleanupProcessState().
+ *! 29-May-1996 gp: Changed DEV_HDEVNODE --> CFG_HDEVNODE.
+ *! 18-May-1996 gp: Created.
+ */
+
+#ifndef DEV_
+#define DEV_
+
+/* ----------------------------------- Module Dependent Headers */
+#include <dspbridge/chnldefs.h>
+#include <dspbridge/cmm.h>
+#include <dspbridge/cod.h>
+#include <dspbridge/dehdefs.h>
+#include <dspbridge/nodedefs.h>
+#include <dspbridge/dispdefs.h>
+#include <dspbridge/wmd.h>
+#include <dspbridge/dmm.h>
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/devdefs.h>
+
+
+/*
+ * ======== DEV_BrdWriteFxn ========
+ * Purpose:
+ * Exported function to be used as the COD write function. This function
+ * is passed a handle to a DEV_hObject by ZL in pArb, then calls the
+ * device's WMD_BRD_Write() function.
+ * Parameters:
+ * pArb: Handle to a Device Object.
+ * hDevContext: Handle to mini-driver defined device info.
+ * dwDSPAddr: Address on DSP board (Destination).
+ * pHostBuf: Pointer to host buffer (Source).
+ * ulNumBytes: Number of bytes to transfer.
+ * ulMemType: Memory space on DSP to which to transfer.
+ * Returns:
+ * Number of bytes written. Returns 0 if the DEV_hObject passed in via
+ * pArb is invalid.
+ * Requires:
+ * DEV Initialized.
+ * pHostBuf != NULL
+ * Ensures:
+ */
+ extern u32 DEV_BrdWriteFxn(void *pArb,
+ u32 ulDspAddr,
+ void *pHostBuf,
+ u32 ulNumBytes, u32 nMemSpace);
+
+/*
+ * ======== DEV_CreateDevice ========
+ * Purpose:
+ * Called by the operating system to load the 'Bridge Mini Driver for a
+ * 'Bridge device.
+ * Parameters:
+ * phDevObject: Ptr to location to receive the device object handle.
+ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
+ * path is not provided, the file is loaded through
+ * 'Bridge's module search path.
+ * pHostConfig: Host configuration information, to be passed down
+ * to the WMD when WMD_DEV_Create() is called.
+ * pDspConfig: DSP resources, to be passed down to the WMD when
+ * WMD_DEV_Create() is called.
+ * hDevNode: Platform (Windows) specific device node.
+ * Returns:
+ * DSP_SOK: Module is loaded, device object has been created
+ * DSP_EMEMORY: Insufficient memory to create needed resources.
+ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
+ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
+ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
+ * for this hDevNode.
+ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
+ * LDR_E_NOMEMORY: PELDR is out of resources.
+ * DSP_EFAIL: Unable to find WMD entry point function.
+ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
+ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
+ * Requires:
+ * DEV Initialized.
+ * phDevObject != NULL.
+ * pstrWMDFileName != NULL.
+ * pHostConfig != NULL.
+ * pDspConfig != NULL.
+ * Ensures:
+ * DSP_SOK: *phDevObject will contain handle to the new device object.
+ * Otherwise, does not create the device object, ensures the WMD module is
+ * unloaded, and sets *phDevObject to NULL.
+ */
+ extern DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT
+ **phDevObject,
+ IN CONST char *pstrWMDFileName,
+ IN CONST struct CFG_HOSTRES
+ *pHostConfig,
+ IN CONST struct CFG_DSPRES
+ *pDspConfig,
+ struct CFG_DEVNODE *hDevNode);
+
+/*
+ * ======== DEV_CreateIVADevice ========
+ * Purpose:
+ * Called by the operating system to load the 'Bridge Mini Driver for IVA.
+ * Parameters:
+ * phDevObject: Ptr to location to receive the device object handle.
+ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
+ * path is not provided, the file is loaded through
+ * 'Bridge's module search path.
+ * pHostConfig: Host configuration information, to be passed down
+ * to the WMD when WMD_DEV_Create() is called.
+ * pDspConfig: DSP resources, to be passed down to the WMD when
+ * WMD_DEV_Create() is called.
+ * hDevNode: Platform (Windows) specific device node.
+ * Returns:
+ * DSP_SOK: Module is loaded, device object has been created
+ * DSP_EMEMORY: Insufficient memory to create needed resources.
+ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
+ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
+ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
+ * for this hDevNode.
+ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
+ * LDR_E_NOMEMORY: PELDR is out of resources.
+ * DSP_EFAIL: Unable to find WMD entry point function.
+ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
+ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
+ * Requires:
+ * DEV Initialized.
+ * phDevObject != NULL.
+ * pstrWMDFileName != NULL.
+ * pHostConfig != NULL.
+ * pDspConfig != NULL.
+ * Ensures:
+ * DSP_SOK: *phDevObject will contain handle to the new device object.
+ * Otherwise, does not create the device object, ensures the WMD module is
+ * unloaded, and sets *phDevObject to NULL.
+ */
+ extern DSP_STATUS DEV_CreateIVADevice(OUT struct DEV_OBJECT
+ **phDevObject,
+ IN CONST char *pstrWMDFileName,
+ IN CONST struct CFG_HOSTRES *pHostConfig,
+ IN CONST struct CFG_DSPRES *pDspConfig,
+ struct CFG_DEVNODE *hDevNode);
+
+/*
+ * ======== DEV_Create2 ========
+ * Purpose:
+ * After successful loading of the image from WCD_InitComplete2
+ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
+ * the Node Manager and updates the DEV Object.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice().
+ * Returns:
+ * DSP_SOK: Successful Creation of Node Manager
+ * DSP_EFAIL: Some Error Occurred.
+ * Requires:
+ * DEV Initialized
+ * Valid hDevObject
+ * Ensures:
+ * DSP_SOK and hDevObject->hNodeMgr != NULL
+ * else hDevObject->hNodeMgr == NULL
+ */
+ extern DSP_STATUS DEV_Create2(IN struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== DEV_Destroy2 ========
+ * Purpose:
+ * Destroys the Node manager for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice().
+ * Returns:
+ * DSP_SOK: Successful Creation of Node Manager
+ * DSP_EFAIL: Some Error Occurred.
+ * Requires:
+ * DEV Initialized
+ * Valid hDevObject
+ * Ensures:
+ * DSP_SOK and hDevObject->hNodeMgr == NULL
+ * else DSP_EFAIL.
+ */
+ extern DSP_STATUS DEV_Destroy2(IN struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== DEV_DestroyDevice ========
+ * Purpose:
+ * Destroys the channel manager for this device, if any, calls
+ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * DSP_EFAIL: The WMD failed it's WMD_DEV_Destroy() function.
+ * Requires:
+ * DEV Initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT
+ *hDevObject);
+
+/*
+ * ======== DEV_GetChnlMgr ========
+ * Purpose:
+ * Retrieve the handle to the channel manager created for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *phMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phMgr != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phMgr contains a handle to a channel manager object,
+ * or NULL.
+ * else: *phMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct CHNL_MGR **phMgr);
+
+/*
+ * ======== DEV_GetCmmMgr ========
+ * Purpose:
+ * Retrieve the handle to the shared memory manager created for this
+ * device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *phMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phMgr != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phMgr contains a handle to a channel manager object,
+ * or NULL.
+ * else: *phMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct CMM_OBJECT **phMgr);
+
+/*
+ * ======== DEV_GetDmmMgr ========
+ * Purpose:
+ * Retrieve the handle to the dynamic memory manager created for this
+ * device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *phMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phMgr != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phMgr contains a handle to a channel manager object,
+ * or NULL.
+ * else: *phMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct DMM_OBJECT **phMgr);
+
+/*
+ * ======== DEV_GetCodMgr ========
+ * Purpose:
+ * Retrieve the COD manager create for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *phCodMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phCodMgr != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phCodMgr contains a handle to a COD manager object.
+ * else: *phCodMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct COD_MANAGER **phCodMgr);
+
+/*
+ * ======== DEV_GetDehMgr ========
+ * Purpose:
+ * Retrieve the DEH manager created for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice().
+ * *phDehMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phDehMgr != NULL.
+ * DEH Initialized.
+ * Ensures:
+ * DSP_SOK: *phDehMgr contains a handle to a DEH manager object.
+ * else: *phDehMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct DEH_MGR **phDehMgr);
+
+/*
+ * ======== DEV_GetDevNode ========
+ * Purpose:
+ * Retrieve the platform specific device ID for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * phDevNode: Ptr to location to get the device node handle.
+ * Returns:
+ * DSP_SOK: In Win95, returns a DEVNODE in *hDevNode; In NT, ???
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phDevNode != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phDevNode contains a platform specific device ID;
+ * else: *phDevNode is NULL.
+ */
+ extern DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
+ OUT struct CFG_DEVNODE **phDevNode);
+
+/*
+ * ======== DEV_GetDevType ========
+ * Purpose:
+ * Retrieve the platform specific device ID for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * phDevNode: Ptr to location to get the device node handle.
+ * Returns:
+ * DSP_SOK: Success
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phDevNode != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phDevNode contains a platform specific device ID;
+ * else: *phDevNode is NULL.
+ */
+ extern DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject,
+ u32 *devType);
+
+/*
+ * ======== DEV_GetFirst ========
+ * Purpose:
+ * Retrieve the first Device Object handle from an internal linked list of
+ * of DEV_OBJECTs maintained by DEV.
+ * Parameters:
+ * Returns:
+ * NULL if there are no device objects stored; else
+ * a valid DEV_HOBJECT.
+ * Requires:
+ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
+ * internal device object list) may occur between calls to DEV_GetFirst
+ * and DEV_GetNext.
+ * Ensures:
+ * The DEV_HOBJECT returned is valid.
+ * A subsequent call to DEV_GetNext will return the next device object in
+ * the list.
+ */
+ extern struct DEV_OBJECT *DEV_GetFirst(void);
+
+/*
+ * ======== DEV_GetIntfFxns ========
+ * Purpose:
+ * Retrieve the WMD interface function structure for the loaded WMD.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *ppIntfFxns: Ptr to location to store fxn interface.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * ppIntfFxns != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *ppIntfFxns contains a pointer to the WMD interface;
+ * else: *ppIntfFxns is NULL.
+ */
+ extern DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
+ OUT struct WMD_DRV_INTERFACE **ppIntfFxns);
+
+/*
+ * ======== DEV_GetIOMgr ========
+ * Purpose:
+ * Retrieve the handle to the IO manager created for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * *phMgr: Ptr to location to store handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phMgr != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phMgr contains a handle to an IO manager object.
+ * else: *phMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct IO_MGR **phMgr);
+
+/*
+ * ======== DEV_GetNext ========
+ * Purpose:
+ * Retrieve the next Device Object handle from an internal linked list of
+ * of DEV_OBJECTs maintained by DEV, after having previously called
+ * DEV_GetFirst() and zero or more DEV_GetNext
+ * Parameters:
+ * hDevObject: Handle to the device object returned from a previous
+ * call to DEV_GetFirst() or DEV_GetNext().
+ * Returns:
+ * NULL if there are no further device objects on the list or hDevObject
+ * was invalid;
+ * else the next valid DEV_HOBJECT in the list.
+ * Requires:
+ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
+ * internal device object list) may occur between calls to DEV_GetFirst
+ * and DEV_GetNext.
+ * Ensures:
+ * The DEV_HOBJECT returned is valid.
+ * A subsequent call to DEV_GetNext will return the next device object in
+ * the list.
+ */
+ extern struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT
+ *hDevObject);
+
+/*
+ * ========= DEV_GetMsgMgr ========
+ * Purpose:
+ * Retrieve the MSG Manager Handle from the DevObject.
+ * Parameters:
+ * hDevObject: Handle to the Dev Object
+ * phMsgMgr: Location where MSG Manager handle will be returned.
+ * Returns:
+ * Requires:
+ * DEV Initialized.
+ * Valid hDevObject.
+ * phNodeMgr != NULL.
+ * Ensures:
+ */
+ extern void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct MSG_MGR **phMsgMgr);
+
+/*
+ * ========= DEV_GetNodeManager ========
+ * Purpose:
+ * Retrieve the Node Manager Handle from the DevObject. It is an
+ * accessor function
+ * Parameters:
+ * hDevObject: Handle to the Dev Object
+ * phNodeMgr: Location where Handle to the Node Manager will be
+ * returned..
+ * Returns:
+ * DSP_SOK: Success
+ * DSP_EHANDLE: Invalid Dev Object handle.
+ * Requires:
+ * DEV Initialized.
+ * phNodeMgr is not null
+ * Ensures:
+ * DSP_SOK: *phNodeMgr contains a handle to a Node manager object.
+ * else: *phNodeMgr is NULL.
+ */
+ extern DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT
+ *hDevObject,
+ OUT struct NODE_MGR **phNodeMgr);
+
+/*
+ * ======== DEV_GetSymbol ========
+ * Purpose:
+ * Get the value of a symbol in the currently loaded program.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * pstrSym: Name of symbol to look up.
+ * pulValue: Ptr to symbol value.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
+ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
+ * Requires:
+ * pstrSym != NULL.
+ * pulValue != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *pulValue contains the symbol value;
+ */
+ extern DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
+ IN CONST char *pstrSym,
+ OUT u32 *pulValue);
+
+/*
+ * ======== DEV_GetWMDContext ========
+ * Purpose:
+ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice()
+ * *phWmdContext: Ptr to location to store context handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * phWmdContext != NULL.
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: *phWmdContext contains context handle;
+ * else: *phWmdContext is NULL;
+ */
+ extern DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
+ OUT struct WMD_DEV_CONTEXT **phWmdContext);
+
+/*
+ * ======== DEV_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * DEV is initialized.
+ * Ensures:
+ * When reference count == 0, DEV's private resources are freed.
+ */
+ extern void DEV_Exit(void);
+
+/*
+ * ======== DEV_Init ========
+ * Purpose:
+ * Initialize DEV's private state, keeping a reference count on each call.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * TRUE: A requirement for the other public DEV functions.
+ */
+ extern bool DEV_Init(void);
+
+/*
+ * ======== DEV_IsLocked ========
+ * Purpose:
+ * Predicate function to determine if the device has been
+ * locked by a client for exclusive access.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * Returns:
+ * DSP_SOK: TRUE: device has been locked.
+ * DSP_SFALSE: FALSE: device not locked.
+ * DSP_EHANDLE: hDevObject was invalid.
+ * Requires:
+ * DEV Initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS DEV_IsLocked(IN struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== DEV_InsertProcObject ========
+ * Purpose:
+ * Inserts the Processor Object into the List of PROC Objects
+ * kept in the DEV Object
+ * Parameters:
+ * hProcObject: Handle to the Proc Object
+ * hDevObject Handle to the Dev Object
+ * bAttachedNew Specifies if there are already processors attached
+ * Returns:
+ * DSP_SOK: Successfully inserted into the list
+ * Requires:
+ * hProcObject is not NULL
+ * hDevObject is a valid handle to the DEV.
+ * DEV Initialized.
+ * List(of Proc object in Dev) Exists.
+ * Ensures:
+ * DSP_SOK & the PROC Object is inserted and the list is not empty
+ * Details:
+ * If the List of Proc Object is empty bAttachedNew is TRUE, it indicated
+ * this is the first Processor attaching.
+ * If it is False, there are already processors attached.
+ */
+ extern DSP_STATUS DEV_InsertProcObject(IN struct DEV_OBJECT
+ *hDevObject,
+ IN u32 hProcObject,
+ OUT bool *
+ pbAlreadyAttached);
+
+/*
+ * ======== DEV_RemoveProcObject ========
+ * Purpose:
+ * Search for and remove a Proc object from the given list maintained
+ * by the DEV
+ * Parameters:
+ * pProcObject: Ptr to ProcObject to insert.
+ * pDevObject: Ptr to Dev Object where the list is.
+ * pbAlreadyAttached: Ptr to return the bool
+ * Returns:
+ * DSP_SOK: If successful.
+ * DSP_EFAIL Failure to Remove the PROC Object from the list
+ * Requires:
+ * DevObject is Valid
+ * hProcObject != 0
+ * pDevObject->procList != NULL
+ * !LST_IsEmpty(pDevObject->procList)
+ * pbAlreadyAttached !=NULL
+ * Ensures:
+ * Details:
+ * List will be deleted when the DEV is destroyed.
+ *
+ */
+ extern DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT
+ *hDevObject,
+ u32 hProcObject);
+
+/*
+ * ======== DEV_NotifyClients ========
+ * Purpose:
+ * Notify all clients of this device of a change in device status.
+ * Clients may include multiple users of BRD, as well as CHNL.
+ * This function is asychronous, and may be called by a timer event
+ * set up by a watchdog timer.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice().
+ * ulStatus: A status word, most likely a BRD_STATUS.
+ * Returns:
+ * DSP_SOK: All registered clients were asynchronously notified.
+ * DSP_EINVALIDARG: Invalid hDevObject.
+ * Requires:
+ * DEV Initialized.
+ * Ensures:
+ * DSP_SOK: Notifications are queued by the operating system to be
+ * delivered to clients. This function does not ensure that
+ * the notifications will ever be delivered.
+ */
+ extern DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject,
+ u32 ulStatus);
+
+
+
+/*
+ * ======== DEV_RemoveDevice ========
+ * Purpose:
+ * Destroys the Device Object created by DEV_StartDevice.
+ * Parameters:
+ * hDevNode: Device node as it is know to OS.
+ * Returns:
+ * DSP_SOK: If success;
+ * <error code> Otherwise.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode);
+
+/*
+ * ======== DEV_SetChnlMgr ========
+ * Purpose:
+ * Set the channel manager for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * hMgr: Handle to a channel manager, or NULL.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * DEV Initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject,
+ struct CHNL_MGR *hMgr);
+
+/*
+ * ======== DEV_SetMsgMgr ========
+ * Purpose:
+ * Set the Message manager for this device.
+ * Parameters:
+ * hDevObject: Handle to device object created with DEV_CreateDevice().
+ * hMgr: Handle to a message manager, or NULL.
+ * Returns:
+ * Requires:
+ * DEV Initialized.
+ * Ensures:
+ */
+ extern void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject,
+ struct MSG_MGR *hMgr);
+
+/*
+ * ======== DEV_StartDevice ========
+ * Purpose:
+ * Initializes the new device with the WinBRIDGE environment. This
+ * involves querying CM for allocated resources, querying the registry
+ * for necessary dsp resources (requested in the INF file), and using
+ * this information to create a WinBRIDGE device object.
+ * Parameters:
+ * hDevNode: Device node as it is know to OS.
+ * Returns:
+ * DSP_SOK: If success;
+ * <error code> Otherwise.
+ * Requires:
+ * DEV initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode);
+
+#endif /* DEV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/devdefs.h b/arch/arm/plat-omap/include/dspbridge/devdefs.h
new file mode 100644
index 000000000000..e9ff725cef77
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/devdefs.h
@@ -0,0 +1,35 @@
+/*
+ * devdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== devdefs.h ========
+ * Purpose:
+ * Definition of common include typedef between wmd.h and dev.h. Required
+ * to break circular dependency between WMD and DEV include files.
+ *
+ *! Revision History:
+ *! ================
+ *! 12-Nov-1996 gp: Renamed from dev1.h.
+ *! 30-May-1996 gp: Broke out from dev.h
+ */
+
+#ifndef DEVDEFS_
+#define DEVDEFS_
+
+/* WCD Device Object */
+ struct DEV_OBJECT;
+
+#endif /* DEVDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/disp.h b/arch/arm/plat-omap/include/dspbridge/disp.h
new file mode 100644
index 000000000000..e1167342ac0a
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/disp.h
@@ -0,0 +1,236 @@
+/*
+ * disp.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== disp.h ========
+ *
+ * Description:
+ * DSP/BIOS Bridge Node Dispatcher.
+ *
+ * Public Functions:
+ * DISP_Create
+ * DISP_Delete
+ * DISP_Exit
+ * DISP_Init
+ * DISP_NodeChangePriority
+ * DISP_NodeCreate
+ * DISP_NodeDelete
+ * DISP_NodeRun
+ *
+ *! Revision History:
+ *! =================
+ *! 28-Jan-2003 map Removed DISP_DoCinit().
+ *! 15-May-2002 jeh Added DISP_DoCinit().
+ *! 24-Apr-2002 jeh Added DISP_MemWrite().
+ *! 07-Sep-2001 jeh Added DISP_MemCopy().
+ *! 10-May-2001 jeh Code review cleanup.
+ *! 08-Aug-2000 jeh Removed DISP_NodeTerminate since it no longer uses RMS.
+ *! 17-Jul-2000 jeh Updates to function headers.
+ *! 19-Jun-2000 jeh Created.
+ */
+
+#ifndef DISP_
+#define DISP_
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/nodedefs.h>
+#include <dspbridge/nodepriv.h>
+#include <dspbridge/dispdefs.h>
+
+/*
+ * ======== DISP_Create ========
+ * Create a NODE Dispatcher object. This object handles the creation,
+ * deletion, and execution of nodes on the DSP target, through communication
+ * with the Resource Manager Server running on the target. Each NODE
+ * Manager object should have exactly one NODE Dispatcher.
+ *
+ * Parameters:
+ * phDispObject: Location to store node dispatcher object on output.
+ * hDevObject: Device for this processor.
+ * pDispAttrs: Node dispatcher attributes.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * DSP_EFAIL: Unable to create dispatcher.
+ * Requires:
+ * DISP_Init(void) called.
+ * pDispAttrs != NULL.
+ * hDevObject != NULL.
+ * phDispObject != NULL.
+ * Ensures:
+ * DSP_SOK: IsValid(*phDispObject).
+ * error: *phDispObject == NULL.
+ */
+ extern DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct DISP_ATTRS *pDispAttrs);
+
+/*
+ * ======== DISP_Delete ========
+ * Delete the NODE Dispatcher.
+ *
+ * Parameters:
+ * hDispObject: Node Dispatcher object.
+ * Returns:
+ * Requires:
+ * DISP_Init(void) called.
+ * Valid hDispObject.
+ * Ensures:
+ * hDispObject is invalid.
+ */
+ extern void DISP_Delete(struct DISP_OBJECT *hDispObject);
+
+/*
+ * ======== DISP_Exit ========
+ * Discontinue usage of DISP module.
+ *
+ * Parameters:
+ * Returns:
+ * Requires:
+ * DISP_Init(void) previously called.
+ * Ensures:
+ * Any resources acquired in DISP_Init(void) will be freed when last DISP
+ * client calls DISP_Exit(void).
+ */
+ extern void DISP_Exit(void);
+
+/*
+ * ======== DISP_Init ========
+ * Initialize the DISP module.
+ *
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Ensures:
+ */
+ extern bool DISP_Init(void);
+
+/*
+ * ======== DISP_NodeChangePriority ========
+ * Change the priority of a node currently running on the target.
+ *
+ * Parameters:
+ * hDispObject: Node Dispatcher object.
+ * hNode: Node object representing a node currently
+ * allocated or running on the DSP.
+ * ulFxnAddress: Address of RMS function for changing priority.
+ * nodeEnv: Address of node's environment structure.
+ * nPriority: New priority level to set node's priority to.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * Requires:
+ * DISP_Init(void) called.
+ * Valid hDispObject.
+ * hNode != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT
+ *hDispObject,
+ struct NODE_OBJECT *hNode,
+ u32 ulFxnAddr,
+ NODE_ENV nodeEnv,
+ s32 nPriority);
+
+/*
+ * ======== DISP_NodeCreate ========
+ * Create a node on the DSP by remotely calling the node's create function.
+ *
+ * Parameters:
+ * hDispObject: Node Dispatcher object.
+ * hNode: Node handle obtained from NODE_Allocate().
+ * ulFxnAddr: Address or RMS create node function.
+ * ulCreateFxn: Address of node's create function.
+ * pArgs: Arguments to pass to RMS node create function.
+ * pNodeEnv: Location to store node environment pointer on
+ * output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETASK: Unable to create the node's task or process on the DSP.
+ * DSP_ESTREAM: Stream creation failure on the DSP.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_EUSER: A user-defined failure occurred.
+ * DSP_EFAIL: A failure occurred, unable to create node.
+ * Requires:
+ * DISP_Init(void) called.
+ * Valid hDispObject.
+ * pArgs != NULL.
+ * hNode != NULL.
+ * pNodeEnv != NULL.
+ * NODE_GetType(hNode) != NODE_DEVICE.
+ * Ensures:
+ */
+ extern DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDispObject,
+ struct NODE_OBJECT *hNode,
+ u32 ulFxnAddr,
+ u32 ulCreateFxn,
+ IN CONST struct NODE_CREATEARGS
+ *pArgs,
+ OUT NODE_ENV *pNodeEnv);
+
+/*
+ * ======== DISP_NodeDelete ========
+ * Delete a node on the DSP by remotely calling the node's delete function.
+ *
+ * Parameters:
+ * hDispObject: Node Dispatcher object.
+ * hNode: Node object representing a node currently
+ * loaded on the DSP.
+ * ulFxnAddr: Address or RMS delete node function.
+ * ulDeleteFxn: Address of node's delete function.
+ * nodeEnv: Address of node's environment structure.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * Requires:
+ * DISP_Init(void) called.
+ * Valid hDispObject.
+ * hNode != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDispObject,
+ struct NODE_OBJECT *hNode,
+ u32 ulFxnAddr,
+ u32 ulDeleteFxn, NODE_ENV nodeEnv);
+
+/*
+ * ======== DISP_NodeRun ========
+ * Start execution of a node's execute phase, or resume execution of a node
+ * that has been suspended (via DISP_NodePause()) on the DSP.
+ *
+ * Parameters:
+ * hDispObject: Node Dispatcher object.
+ * hNode: Node object representing a node to be executed
+ * on the DSP.
+ * ulFxnAddr: Address or RMS node execute function.
+ * ulExecuteFxn: Address of node's execute function.
+ * nodeEnv: Address of node's environment structure.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * Requires:
+ * DISP_Init(void) called.
+ * Valid hDispObject.
+ * hNode != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDispObject,
+ struct NODE_OBJECT *hNode,
+ u32 ulFxnAddr,
+ u32 ulExecuteFxn, NODE_ENV nodeEnv);
+
+#endif /* DISP_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dispdefs.h b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
new file mode 100644
index 000000000000..401ad4f0fe36
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
@@ -0,0 +1,45 @@
+/*
+ * dispdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dispdefs.h ========
+ * Description:
+ * Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Aug-2000 jeh Added fields to DISP_ATTRS.
+ *! 06-Jul-2000 jeh Created.
+ */
+
+#ifndef DISPDEFS_
+#define DISPDEFS_
+
+ struct DISP_OBJECT;
+
+/* Node Dispatcher attributes */
+ struct DISP_ATTRS {
+ u32 ulChnlOffset; /* Offset of channel ids reserved for RMS */
+ /* Size of buffer for sending data to RMS */
+ u32 ulChnlBufSize;
+ DSP_PROCFAMILY procFamily; /* eg, 5000 */
+ DSP_PROCTYPE procType; /* eg, 5510 */
+ HANDLE hReserved1; /* Reserved for future use. */
+ u32 hReserved2; /* Reserved for future use. */
+ } ;
+
+#endif /* DISPDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dmm.h b/arch/arm/plat-omap/include/dspbridge/dmm.h
new file mode 100644
index 000000000000..ef37668f1cad
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dmm.h
@@ -0,0 +1,85 @@
+/*
+ * dmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dmm.h ========
+ * Purpose:
+ * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
+ * space that can be directly mapped to any MPU buffer or memory region
+ *
+ * Public Functions:
+ *
+ *! Revision History:
+ *! ================
+ *! 20-Feb-2004 sb: Created.
+ *!
+ */
+
+#ifndef DMM_
+#define DMM_
+
+#include <dspbridge/dbdefs.h>
+
+ struct DMM_OBJECT;
+
+/* DMM attributes used in DMM_Create() */
+ struct DMM_MGRATTRS {
+ u32 reserved;
+ } ;
+
+#define DMMPOOLSIZE 0x4000000
+
+/*
+ * ======== DMM_GetHandle ========
+ * Purpose:
+ * Return the dynamic memory manager object for this device.
+ * This is typically called from the client process.
+ */
+
+ extern DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
+ OUT struct DMM_OBJECT **phDmmMgr);
+
+ extern DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr,
+ u32 size,
+ u32 *pRsvAddr);
+
+ extern DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr,
+ u32 rsvAddr);
+
+ extern DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr,
+ u32 size);
+
+ extern DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr,
+ u32 addr,
+ u32 *pSize);
+
+ extern DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr);
+
+ extern DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr);
+
+ extern DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct DMM_MGRATTRS *pMgrAttrs);
+
+ extern bool DMM_Init(void);
+
+ extern void DMM_Exit(void);
+
+ extern DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr,
+ u32 addr, u32 size);
+ extern u32 *DMM_GetPhysicalAddrTable(void);
+#endif /* DMM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dpc.h b/arch/arm/plat-omap/include/dspbridge/dpc.h
new file mode 100644
index 000000000000..8c2050682eab
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dpc.h
@@ -0,0 +1,167 @@
+/*
+ * dpc.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dpc.h ========
+ * Purpose:
+ * Deferred Procedure Call(DPC) Services.
+ *
+ * Public Functions:
+ * DPC_Cancel
+ * DPC_Create
+ * DPC_Destroy
+ * DPC_Exit
+ * DPC_Init
+ * DPC_Schedule
+ *
+ *! Revision History:
+ *! ================
+ *! 31-Jan-2000 rr: DPC_Destroy ensures Suceess and DPC Object is NULL.
+ *! 21-Jan-2000 ag: Updated comments per code review.
+ *! 06-Jan-2000 ag: Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
+ *! 14-Jan-1998 gp: Added DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
+ *! 18-Aug-1997 cr: Added explicit CDECL identifiers.
+ *! 28-Jul-1996 gp: Created.
+ */
+
+#ifndef DPC_
+#define DPC_
+
+ struct DPC_OBJECT;
+
+/*
+ * ======== DPC_PROC ========
+ * Purpose:
+ * Deferred processing routine. Typically scheduled from an ISR to
+ * complete I/O processing.
+ * Parameters:
+ * pRefData: Ptr to user data: passed in via ISR_ScheduleDPC.
+ * Returns:
+ * Requires:
+ * The DPC should not block, or otherwise acquire resources.
+ * Interrupts to the processor are enabled.
+ * DPC_PROC executes in a critical section.
+ * Ensures:
+ * This DPC will not be reenterred on the same thread.
+ * However, the DPC may take hardware interrupts during execution.
+ * Interrupts to the processor are enabled.
+ */
+ typedef void(*DPC_PROC) (void *pRefData);
+
+/*
+ * ======== DPC_Cancel ========
+ * Purpose:
+ * Cancel a DPC previously scheduled by DPC_Schedule.
+ * Parameters:
+ * hDPC: A DPC object handle created in DPC_Create().
+ * Returns:
+ * DSP_SOK: Scheduled DPC, if any, is cancelled.
+ * DSP_SFALSE: No DPC is currently scheduled for execution.
+ * DSP_EHANDLE: Invalid hDPC.
+ * Requires:
+ * Ensures:
+ * If the DPC has already executed, is executing, or was not yet
+ * scheduled, this function will have no effect.
+ */
+ extern DSP_STATUS DPC_Cancel(IN struct DPC_OBJECT *hDPC);
+
+/*
+ * ======== DPC_Create ========
+ * Purpose:
+ * Create a DPC object, allowing a client's own DPC procedure to be
+ * scheduled for a call with client reference data.
+ * Parameters:
+ * phDPC: Pointer to location to store DPC object.
+ * pfnDPC: Client's DPC procedure.
+ * pRefData: Pointer to user-defined reference data.
+ * Returns:
+ * DSP_SOK: DPC object created.
+ * DSP_EPOINTER: phDPC == NULL or pfnDPC == NULL.
+ * DSP_EMEMORY: Insufficient memory.
+ * Requires:
+ * Must not be called at interrupt time.
+ * Ensures:
+ * DSP_SOK: DPC object is created;
+ * else: *phDPC is set to NULL.
+ */
+ extern DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC,
+ IN DPC_PROC pfnDPC,
+ IN void *pRefData);
+
+/*
+ * ======== DPC_Destroy ========
+ * Purpose:
+ * Cancel the last scheduled DPC, and deallocate a DPC object previously
+ * allocated with DPC_Create().Frees the Object only if the thread and
+ * the events are terminated successfuly.
+ * Parameters:
+ * hDPC: A DPC object handle created in DPC_Create().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDPC.
+ * Requires:
+ * All DPC's scheduled for the DPC object must have completed their
+ * processing.
+ * Ensures:
+ * (SUCCESS && hDPC is NULL) or DSP_EFAILED status
+ */
+ extern DSP_STATUS DPC_Destroy(IN struct DPC_OBJECT *hDPC);
+
+/*
+ * ======== DPC_Exit ========
+ * Purpose:
+ * Discontinue usage of the DPC module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * DPC_Init(void) was previously called.
+ * Ensures:
+ * Resources acquired in DPC_Init(void) are freed.
+ */
+ extern void DPC_Exit(void);
+
+/*
+ * ======== DPC_Init ========
+ * Purpose:
+ * Initialize the DPC module's private state.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public DPC functions.
+ */
+ extern bool DPC_Init(void);
+
+/*
+ * ======== DPC_Schedule ========
+ * Purpose:
+ * Schedule a deferred procedure call to be executed at a later time.
+ * Latency and order of DPC execution is platform specific.
+ * Parameters:
+ * hDPC: A DPC object handle created in DPC_Create().
+ * Returns:
+ * DSP_SOK: An event is scheduled for deferred processing.
+ * DSP_EHANDLE: Invalid hDPC.
+ * Requires:
+ * See requirements for DPC_PROC.
+ * Ensures:
+ * DSP_SOK: The DPC will not be called before this function returns.
+ */
+ extern DSP_STATUS DPC_Schedule(IN struct DPC_OBJECT *hDPC);
+
+#endif /* DPC_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
new file mode 100644
index 000000000000..14b018249de8
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/drv.h
@@ -0,0 +1,496 @@
+/*
+ * drv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== drv.h ========
+ * Purpose:
+ * DRV Resource allocation module. Driver Object gets Created
+ * at the time of Loading. It holds the List of Device Objects
+ * in the Syste,
+ *
+ * Public Functions:
+ * DRV_Create
+ * DRV_Destroy
+ * DRV_Exit
+ * DRV_GetDevObject
+ * DRV_GetDevExtension
+ * DRV_GetFirstDevObject
+ * DRV_GetNextDevObject
+ * DRV_GetNextDevExtension
+ * DRV_Init
+ * DRV_InsertDevObject
+ * DRV_RemoveDevObject
+ * DRV_RequestResources
+ * DRV_ReleaseResources
+ *
+ *! Revision History
+ *! ================
+ *! 10-Feb-2004 vp: Added OMAP24xx specific definitions.
+ *! 14-Aug-2000 rr: Cleaned up.
+ *! 27-Jul-2000 rr: DRV_RequestResources split into two(Request and Release)
+ *! Device extension created to hold the DevNodeString.
+ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
+ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
+ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
+ *! 12-Nov-1999 rr: New Flag defines for DRV_ASSIGN and DRV_RELEASE
+ *! 25-Oct-1999 rr: Resource Structure removed.
+ *! 15-Oct-1999 rr: New Resource structure created.
+ *! 05-Oct-1999 rr: Added DRV_RequestResources
+ *! Removed fxn'sDRV_RegisterMiniDriver(),
+ *! DRV_UnRegisterMiniDriver()
+ *! Removed Structures DSP_DRIVER & DRV_EXTENSION.
+ *!
+ *! 24-Sep-1999 rr: Added DRV_EXTENSION and DSP_DRIVER structures.
+ *!
+ */
+
+#ifndef DRV_
+#define DRV_
+
+#include <dspbridge/devdefs.h>
+
+#include <dspbridge/drvdefs.h>
+
+#define DRV_ASSIGN 1
+#define DRV_RELEASE 0
+
+#ifdef OMAP_3430
+/* Provide the DSP Internal memory windows that can be accessed from L3 address
+ * space */
+
+#define OMAP_GEM_BASE 0x107F8000
+#define OMAP_DSP_SIZE 0x00720000
+
+/* MEM1 is L2 RAM + L2 Cache space */
+#define OMAP_DSP_MEM1_BASE 0x5C7F8000
+#define OMAP_DSP_MEM1_SIZE 0x18000
+#define OMAP_DSP_GEM1_BASE 0x107F8000
+
+
+/* MEM2 is L1P RAM/CACHE space */
+#define OMAP_DSP_MEM2_BASE 0x5CE00000
+#define OMAP_DSP_MEM2_SIZE 0x8000
+#define OMAP_DSP_GEM2_BASE 0x10E00000
+
+/* MEM3 is L1D RAM/CACHE space */
+#define OMAP_DSP_MEM3_BASE 0x5CF04000
+#define OMAP_DSP_MEM3_SIZE 0x14000
+#define OMAP_DSP_GEM3_BASE 0x10F04000
+
+
+#define OMAP_IVA2_PRM_BASE 0x48306000
+#define OMAP_IVA2_PRM_SIZE 0x1000
+
+#define OMAP_IVA2_CM_BASE 0x48004000
+#define OMAP_IVA2_CM_SIZE 0x1000
+
+#define OMAP_PER_CM_BASE 0x48005000
+#define OMAP_PER_CM_SIZE 0x1000
+
+#define OMAP_PER_PRM_BASE 0x48307000
+#define OMAP_PER_PRM_SIZE 0x1000
+
+#define OMAP_CORE_PRM_BASE 0x48306A00
+#define OMAP_CORE_PRM_SIZE 0x1000
+
+#define OMAP_SYSC_BASE 0x48002000
+#define OMAP_SYSC_SIZE 0x1000
+
+#define OMAP_MBOX_BASE 0x48094000
+#define OMAP_MBOX_SIZE 0x1000
+
+#define OMAP_DMMU_BASE 0x5D000000
+#define OMAP_DMMU_SIZE 0x1000
+
+#define OMAP_PRCM_VDD1_DOMAIN 1
+#define OMAP_PRCM_VDD2_DOMAIN 2
+
+#else
+/* Provide the DSP Internal memory windows that can be accessed from L3 address
+ * space */
+ #define OMAP_GEM_BASE 0x107F8000
+#define OMAP_DSP_SIZE 0x00720000
+
+/* MEM1 is L2 RAM + L2 Cache space */
+#define OMAP_DSP_MEM1_BASE 0x5C7F8000
+#define OMAP_DSP_MEM1_SIZE 0x18000
+#define OMAP_DSP_GEM1_BASE 0x107F8000
+
+
+/* MEM2 is L1P RAM/CACHE space */
+#define OMAP_DSP_MEM2_BASE 0x5CE00000
+#define OMAP_DSP_MEM2_SIZE 0x8000
+#define OMAP_DSP_GEM2_BASE 0x10E00000
+
+/* MEM3 is L1D RAM/CACHE space */
+#define OMAP_DSP_MEM3_BASE 0x5CF04000
+#define OMAP_DSP_MEM3_SIZE 0x14000
+#define OMAP_DSP_GEM3_BASE 0x10F04000
+
+#define OMAP_IVA2_PRM_BASE 0x4A306000
+#define OMAP_IVA2_PRM_SIZE 0x2000
+
+#define OMAP_IVA2_CM1_BASE 0x4A004000
+#define OMAP_IVA2_CM1_SIZE 0x1000
+
+#define OMAP_IVA2_CM2_BASE 0x4A008000
+#define OMAP_IVA2_CM2_SIZE 0x2000
+
+
+#define OMAP_SYSC_BASE 0x4A002000
+#define OMAP_SYSC_SIZE 0x1000
+
+#define OMAP_MBOX_BASE 0x4A0F4000
+#define OMAP_MBOX_SIZE 0x1000
+
+#define OMAP_DMMU_BASE 0x4A066000
+#define OMAP_DMMU_SIZE 0x1000
+
+#define OMAP_PRCM_VDD1_DOMAIN 1
+#define OMAP_PRCM_VDD2_DOMAIN 2
+
+#endif
+
+#ifndef RES_CLEANUP_DISABLE
+
+/* GPP PROCESS CLEANUP Data structures */
+
+/* New structure (member of process context) abstracts NODE resource info */
+struct NODE_RES_OBJECT {
+ DSP_HNODE hNode;
+ s32 nodeAllocated; /* Node status */
+ s32 heapAllocated; /* Heap status */
+ s32 streamsAllocated; /* Streams status */
+ struct NODE_RES_OBJECT *next;
+} ;
+
+/* New structure (member of process context) abstracts DMM resource info */
+struct DMM_RES_OBJECT {
+ s32 dmmAllocated; /* DMM status */
+ u32 ulMpuAddr;
+ u32 ulDSPAddr;
+ u32 ulDSPResAddr;
+ u32 dmmSize;
+ HANDLE hProcessor;
+ struct DMM_RES_OBJECT *next;
+} ;
+
+/* New structure (member of process context) abstracts DMM resource info */
+struct DSPHEAP_RES_OBJECT {
+ s32 heapAllocated; /* DMM status */
+ u32 ulMpuAddr;
+ u32 ulDSPAddr;
+ u32 ulDSPResAddr;
+ u32 heapSize;
+ HANDLE hProcessor;
+ struct DSPHEAP_RES_OBJECT *next;
+} ;
+
+/* New structure (member of process context) abstracts stream resource info */
+struct STRM_RES_OBJECT {
+ s32 streamAllocated; /* Stream status */
+ DSP_HSTREAM hStream;
+ u32 uNumBufs;
+ u32 uDir;
+ struct STRM_RES_OBJECT *next;
+} ;
+
+/* Overall Bridge process resource usage state */
+enum GPP_PROC_RES_STATE {
+ PROC_RES_ALLOCATED,
+ PROC_RES_FREED
+} ;
+
+/* Process Context */
+struct PROCESS_CONTEXT{
+ /* Process State */
+ enum GPP_PROC_RES_STATE resState;
+
+ /* Process ID (Same as UNIX process ID) */
+ u32 pid;
+
+ /* Pointer to next process context
+ * (To maintain a linked list of process contexts) */
+ struct PROCESS_CONTEXT *next;
+
+ /* Processor info to which the process is related */
+ DSP_HPROCESSOR hProcessor;
+
+ /* DSP Node resources */
+ struct NODE_RES_OBJECT *pNodeList;
+
+ /* DMM resources */
+ struct DMM_RES_OBJECT *pDMMList;
+
+ /* DSP Heap resources */
+ struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
+
+ /* Stream resources */
+ struct STRM_RES_OBJECT *pSTRMList;
+} ;
+#endif
+
+/*
+ * ======== DRV_Create ========
+ * Purpose:
+ * Creates the Driver Object. This is done during the driver loading.
+ * There is only one Driver Object in the DSP/BIOS Bridge.
+ * Parameters:
+ * phDrvObject: Location to store created DRV Object handle.
+ * Returns:
+ * DSP_SOK: Sucess
+ * DSP_EMEMORY: Failed in Memory allocation
+ * DSP_EFAIL: General Failure
+ * Requires:
+ * DRV Initialized (cRefs > 0 )
+ * phDrvObject != NULL.
+ * Ensures:
+ * DSP_SOK: - *phDrvObject is a valid DRV interface to the device.
+ * - List of DevObject Created and Initialized.
+ * - List of DevNode String created and intialized.
+ * - Registry is updated with the DRV Object.
+ * !DSP_SOK: DRV Object not created
+ * Details:
+ * There is one Driver Object for the Driver representing
+ * the driver itself. It contains the list of device
+ * Objects and the list of Device Extensions in the system.
+ * Also it can hold other neccessary
+ * information in its storage area.
+ */
+ extern DSP_STATUS DRV_Create(struct DRV_OBJECT **phDrvObject);
+
+/*
+ * ======== DRV_Destroy ========
+ * Purpose:
+ * destroys the Dev Object list, DrvExt list
+ * and destroy the DRV object
+ * Called upon driver unLoading.or unsuccesful loading of the driver.
+ * Parameters:
+ * hDrvObject: Handle to Driver object .
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Failed to destroy DRV Object
+ * Requires:
+ * DRV Initialized (cRegs > 0 )
+ * hDrvObject is not NULL and a valid DRV handle .
+ * List of DevObject is Empty.
+ * List of DrvExt is Empty
+ * Ensures:
+ * DSP_SOK: - DRV Object destroyed and hDrvObject is not a valid
+ * DRV handle.
+ * - Registry is updated with "0" as the DRV Object.
+ */
+ extern DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDrvObject);
+
+/*
+ * ======== DRV_Exit ========
+ * Purpose:
+ * Exit the DRV module, freeing any modules initialized in DRV_Init.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * Ensures:
+ */
+ extern void DRV_Exit(void);
+
+/*
+ * ======== DRV_GetFirstDevObject ========
+ * Purpose:
+ * Returns the Ptr to the FirstDev Object in the List
+ * Parameters:
+ * Requires:
+ * DRV Initialized
+ * Returns:
+ * dwDevObject: Ptr to the First Dev Object as a u32
+ * 0 if it fails to retrieve the First Dev Object
+ * Ensures:
+ */
+ extern u32 DRV_GetFirstDevObject(void);
+
+/*
+ * ======== DRV_GetFirstDevExtension ========
+ * Purpose:
+ * Returns the Ptr to the First Device Extension in the List
+ * Parameters:
+ * Requires:
+ * DRV Initialized
+ * Returns:
+ * dwDevExtension: Ptr to the First Device Extension as a u32
+ * 0: Failed to Get the Device Extension
+ * Ensures:
+ */
+ extern u32 DRV_GetFirstDevExtension(void);
+
+/*
+ * ======== DRV_GetDevObject ========
+ * Purpose:
+ * Given a index, returns a handle to DevObject from the list
+ * Parameters:
+ * hDrvObject: Handle to the Manager
+ * phDevObject: Location to store the Dev Handle
+ * Requires:
+ * DRV Initialized
+ * uIndex >= 0
+ * hDrvObject is not NULL and Valid DRV Object
+ * phDevObject is not NULL
+ * Device Object List not Empty
+ * Returns:
+ * DSP_SOK: Success
+ * DSP_EFAIL: Failed to Get the Dev Object
+ * Ensures:
+ * DSP_SOK: *phDevObject != NULL
+ * DSP_EFAIL: *phDevObject = NULL
+ */
+ extern DSP_STATUS DRV_GetDevObject(u32 uIndex,
+ struct DRV_OBJECT *hDrvObject,
+ struct DEV_OBJECT **phDevObject);
+
+/*
+ * ======== DRV_GetNextDevObject ========
+ * Purpose:
+ * Returns the Ptr to the Next Device Object from the the List
+ * Parameters:
+ * hDevObject: Handle to the Device Object
+ * Requires:
+ * DRV Initialized
+ * hDevObject != 0
+ * Returns:
+ * dwDevObject: Ptr to the Next Dev Object as a u32
+ * 0: If it fail to get the next Dev Object.
+ * Ensures:
+ */
+ extern u32 DRV_GetNextDevObject(u32 hDevObject);
+
+/*
+ * ======== DRV_GetNextDevExtension ========
+ * Purpose:
+ * Returns the Ptr to the Next Device Extension from the the List
+ * Parameters:
+ * hDevExtension: Handle to the Device Extension
+ * Requires:
+ * DRV Initialized
+ * hDevExtension != 0.
+ * Returns:
+ * dwDevExtension: Ptr to the Next Dev Extension
+ * 0: If it fail to Get the next Dev Extension
+ * Ensures:
+ */
+ extern u32 DRV_GetNextDevExtension(u32 hDevExtension);
+
+/*
+ * ======== DRV_Init ========
+ * Purpose:
+ * Initialize the DRV module.
+ * Parameters:
+ * Returns:
+ * TRUE if success; FALSE otherwise.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS DRV_Init(void);
+
+/*
+ * ======== DRV_InsertDevObject ========
+ * Purpose:
+ * Insert a DeviceObject into the list of Driver object.
+ * Parameters:
+ * hDrvObject: Handle to DrvObject
+ * hDevObject: Handle to DeviceObject to insert.
+ * Returns:
+ * DSP_SOK: If successful.
+ * DSP_EFAIL: General Failure:
+ * Requires:
+ * hDrvObject != NULL and Valid DRV Handle.
+ * hDevObject != NULL.
+ * Ensures:
+ * DSP_SOK: Device Object is inserted and the List is not empty.
+ */
+ extern DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDrvObject,
+ struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== DRV_RemoveDevObject ========
+ * Purpose:
+ * Search for and remove a Device object from the given list of Device Obj
+ * objects.
+ * Parameters:
+ * hDrvObject: Handle to DrvObject
+ * hDevObject: Handle to DevObject to Remove
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Unable to find pDevObject.
+ * Requires:
+ * hDrvObject != NULL and a Valid DRV Handle.
+ * hDevObject != NULL.
+ * List exists and is not empty.
+ * Ensures:
+ * List either does not exist (NULL), or is not empty if it does exist.
+*/
+ extern DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDrvObject,
+ struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== DRV_RequestResources ========
+ * Purpose:
+ * Assigns the Resources or Releases them.
+ * Parameters:
+ * dwContext: Path to the driver Registry Key.
+ * pDevNodeString: Ptr to DevNode String stored in the Device Ext.
+ * Returns:
+ * TRUE if success; FALSE otherwise.
+ * Requires:
+ * Ensures:
+ * The Resources are assigned based on Bus type.
+ * The hardware is initialized. Resource information is
+ * gathered from the Registry(ISA, PCMCIA)or scanned(PCI)
+ * Resource structure is stored in the registry which will be
+ * later used by the CFG module.
+ */
+ extern DSP_STATUS DRV_RequestResources(IN u32 dwContext,
+ OUT u32 *pDevNodeString);
+
+/*
+ * ======== DRV_ReleaseResources ========
+ * Purpose:
+ * Assigns the Resources or Releases them.
+ * Parameters:
+ * dwContext: Path to the driver Registry Key.
+ * hDrvObject: Handle to the Driver Object.
+ * Returns:
+ * TRUE if success; FALSE otherwise.
+ * Requires:
+ * Ensures:
+ * The Resources are released based on Bus type.
+ * Resource structure is deleted from the registry
+ */
+ extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
+ struct DRV_OBJECT *hDrvObject);
+
+/*
+ * ======== DRV_ProcFreeDMMRes ========
+ * Purpose:
+ * Actual DMM De-Allocation.
+ * Parameters:
+ * hPCtxt: Path to the driver Registry Key.
+ * Returns:
+ * DSP_SOK if success;
+ */
+
+
+ extern DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt);
+
+#endif /* DRV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/drvdefs.h b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
new file mode 100644
index 000000000000..ed86010bf0f5
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
@@ -0,0 +1,34 @@
+/*
+ * drvdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== drvdefs.h ========
+ * Purpose:
+ * Definition of common include typedef between wmd.h and drv.h.
+ *
+ *! Revision History:
+ *! ================
+ *! 17-Jul-2000 rr: Created
+ */
+
+#ifndef DRVDEFS_
+#define DRVDEFS_
+
+/* WCD Driver Object */
+ struct DRV_OBJECT;
+
+#endif /* DRVDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/dspdrv.h b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
new file mode 100644
index 000000000000..f500ffb3b3fb
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
@@ -0,0 +1,106 @@
+/*
+ * dspdrv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dspdrv.h ========
+ * Purpose:
+ * This is the Stream Interface for the DDSP Class driver.
+ * All Device operations are performed via DeviceIOControl.
+ * Read, Seek and Write not used.
+ *
+ * Public Functions
+ * DSP_Close
+ * DSP_Deinit
+ * DSP_Init
+ * DSP_IOControl
+ * DSP_Open
+ * DSP_PowerUp
+ * DSP_PowerDown
+ *
+ *! Revision History
+ *! ================
+ *! 28-Jan-2000 rr: Type void changed to Void.
+ *! 02-Dec-1999 rr: MAX_DEV define moved from wcdce.c file.Code cleaned up.
+ *! 12-Nov-1999 rr: "#include<wncnxerr.h> removed.
+ *! 05-Oct-1999 rr Renamed the file name to wcdce.h Removed Bus Specific
+ *! code and #defines to PCCARD.h.
+ *! 24-Sep-1999 rr Changed the DSP_COMMON_WINDOW_SIZE to 0x4000(16k) for the
+ *! Memory windows.
+ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet driver.
+ *!
+ */
+
+#if !defined __DSPDRV_h__
+#define __DSPDRV_h__
+
+#define MAX_DEV 10 /* Max support of 10 devices */
+
+/*
+ * ======== DSP_Close ========
+ * Purpose:
+ * Called when the client application/driver unloads the DDSP DLL. Upon
+ * unloading, the DDSP DLL will call CloseFile().
+ * Parameters:
+ * dwDeviceContext: Handle returned by XXX_Open used to identify
+ * the open context of the device
+ * Returns:
+ * TRUE indicates the device is successfully closed. FALSE indicates
+ * otherwise.
+ * Requires:
+ * dwOpenContext!= NULL.
+ * Ensures:The Application instance owned objects are cleaned up.
+ */
+extern bool DSP_Close(u32 dwDeviceContext);
+
+/*
+ * ======== DSP_Deinit ========
+ * Purpose:
+ * This function is called by Device Manager to de-initialize a device.
+ * This function is not called by applications.
+ * Parameters:
+ * dwDeviceContext:Handle to the device context. The XXX_Init function
+ * creates and returns this identifier.
+ * Returns:
+ * TRUE indicates the device successfully de-initialized. Otherwise it
+ * returns FALSE.
+ * Requires:
+ * dwDeviceContext!= NULL. For a built in device this should never
+ * get called.
+ * Ensures:
+ */
+extern bool DSP_Deinit(u32 dwDeviceContext);
+
+/*
+ * ======== DSP_Init ========
+ * Purpose:
+ * This function is called by Device Manager to initialize a device.
+ * This function is not called by applications
+ * Parameters:
+ * dwContext: Specifies a pointer to a string containing the registry
+ * path to the active key for the stream interface driver.
+ * HKEY_LOCAL_MACHINE\Drivers\Active
+ * Returns:
+ * Returns a handle to the device context created. This is the our actual
+ * Device Object representing the DSP Device instance.
+ * Requires:
+ * Ensures:
+ * Succeeded: device context > 0
+ * Failed: device Context = 0
+ */
+extern u32 DSP_Init(OUT u32 *initStatus);
+
+#endif
diff --git a/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
new file mode 100644
index 000000000000..ea5f77f5181e
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
@@ -0,0 +1,505 @@
+/*
+ * dynamic_loader.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+
+#ifndef _DYNAMIC_LOADER_H_
+#define _DYNAMIC_LOADER_H_
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/*
+ * Dynamic Loader
+ *
+ * The function of the dynamic loader is to load a "module" containing
+ * instructions for a "target" processor into that processor. In the process
+ * it assigns memory for the module, resolves symbol references made by the
+ * module, and remembers symbols defined by the module.
+ *
+ * The dynamic loader is parameterized for a particular system by 4 classes
+ * that supply the module and system specific functions it requires
+ */
+ /* The read functions for the module image to be loaded */
+ struct Dynamic_Loader_Stream;
+
+ /* This class defines "host" symbol and support functions */
+ struct Dynamic_Loader_Sym;
+
+ /* This class defines the allocator for "target" memory */
+ struct Dynamic_Loader_Allocate;
+
+ /* This class defines the copy-into-target-memory functions */
+ struct Dynamic_Loader_Initialize;
+
+/*
+ * Option flags to modify the behavior of module loading
+ */
+#define DLOAD_INITBSS 0x1 /* initialize BSS sections to zero */
+#define DLOAD_BIGEND 0x2 /* require big-endian load module */
+#define DLOAD_LITTLE 0x4 /* require little-endian load module */
+
+ typedef void *DLOAD_mhandle; /* module handle for loaded modules */
+
+/*****************************************************************************
+ * Procedure Dynamic_Load_Module
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ * init Target-side memory initialization, or NULL for symbol read only
+ * options Option flags DLOAD_*
+ * mhandle A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ * The module image is read using *module. Target storage for the new image is
+ * obtained from *alloc. Symbols defined and referenced by the module are
+ * managed using *syms. The image is then relocated and references resolved
+ * as necessary, and the resulting executable bits are placed into target memory
+ * using *init.
+ *
+ * Returns:
+ * On a successful load, a module handle is placed in *mhandle, and zero is
+ * returned. On error, the number of errors detected is returned. Individual
+ * errors are reported during the load process using syms->Error_Report().
+ *****************************************************************************/
+ extern int Dynamic_Load_Module(
+ /* the source for the module image*/
+ struct Dynamic_Loader_Stream *module,
+ /* host support for symbols and storage*/
+ struct Dynamic_Loader_Sym *syms,
+ /* the target memory allocator*/
+ struct Dynamic_Loader_Allocate *alloc,
+ /* the target memory initializer*/
+ struct Dynamic_Loader_Initialize *init,
+ unsigned options, /* option flags*/
+ /* the returned module handle*/
+ DLOAD_mhandle *mhandle
+ );
+
+/*****************************************************************************
+ * Procedure Dynamic_Open_Module
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ * init Target-side memory initialization, or NULL for symbol read only
+ * options Option flags DLOAD_*
+ * mhandle A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ * The module image is read using *module. Target storage for the new image is
+ * obtained from *alloc. Symbols defined and referenced by the module are
+ * managed using *syms. The image is then relocated and references resolved
+ * as necessary, and the resulting executable bits are placed into target memory
+ * using *init.
+ *
+ * Returns:
+ * On a successful load, a module handle is placed in *mhandle, and zero is
+ * returned. On error, the number of errors detected is returned. Individual
+ * errors are reported during the load process using syms->Error_Report().
+ *****************************************************************************/
+ extern int Dynamic_Open_Module(
+ /* the source for the module image */
+ struct Dynamic_Loader_Stream *module,
+ /* host support for symbols and storage */
+ struct Dynamic_Loader_Sym *syms,
+ /* the target memory allocator */
+ struct Dynamic_Loader_Allocate *alloc,
+ /* the target memory initializer */
+ struct Dynamic_Loader_Initialize *init,
+ unsigned options, /* option flags */
+ /* the returned module handle */
+ DLOAD_mhandle *mhandle
+ );
+
+/*****************************************************************************
+ * Procedure Dynamic_Unload_Module
+ *
+ * Parameters:
+ * mhandle A module handle from Dynamic_Load_Module
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ *
+ * Effect:
+ * The module specified by mhandle is unloaded. Unloading causes all
+ * target memory to be deallocated, all symbols defined by the module to
+ * be purged, and any host-side storage used by the dynamic loader for
+ * this module to be released.
+ *
+ * Returns:
+ * Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->Error_Report().
+ *****************************************************************************/
+ extern int Dynamic_Unload_Module(DLOAD_mhandle mhandle, /* the module
+ * handle*/
+ /* host support for symbols and
+ * storage */
+ struct Dynamic_Loader_Sym *syms,
+ /* the target memory allocator*/
+ struct Dynamic_Loader_Allocate *alloc,
+ /* the target memory initializer*/
+ struct Dynamic_Loader_Initialize *init
+ );
+
+/*****************************************************************************
+ *****************************************************************************
+ * A class used by the dynamic loader for input of the module image
+ *****************************************************************************
+ *****************************************************************************/
+ struct Dynamic_Loader_Stream {
+/* public: */
+ /*************************************************************************
+ * read_buffer
+ *
+ * PARAMETERS :
+ * buffer Pointer to the buffer to fill
+ * bufsiz Amount of data desired in sizeof() units
+ *
+ * EFFECT :
+ * Reads the specified amount of data from the module input stream
+ * into the specified buffer. Returns the amount of data read in sizeof()
+ * units (which if less than the specification, represents an error).
+ *
+ * NOTES:
+ * In release 1 increments the file position by the number of bytes read
+ *
+ *************************************************************************/
+ int (*read_buffer) (struct Dynamic_Loader_Stream *thisptr,
+ void *buffer, unsigned bufsiz);
+
+ /*************************************************************************
+ * set_file_posn (release 1 only)
+ *
+ * PARAMETERS :
+ * posn Desired file position relative to start of file in sizeof() units.
+ *
+ * EFFECT :
+ * Adjusts the internal state of the stream object so that the next
+ * read_buffer call will begin to read at the specified offset from
+ * the beginning of the input module. Returns 0 for success, non-zero
+ * for failure.
+ *
+ *************************************************************************/
+ int (*set_file_posn) (struct Dynamic_Loader_Stream *thisptr,
+ /* to be eliminated in release 2*/
+ unsigned int posn);
+
+ };
+
+/*****************************************************************************
+ *****************************************************************************
+ * A class used by the dynamic loader for symbol table support and
+ * miscellaneous host-side functions
+ *****************************************************************************
+ *****************************************************************************/
+
+ typedef u32 LDR_ADDR;
+
+/*
+ * the structure of a symbol known to the dynamic loader
+ */
+ struct dynload_symbol {
+ LDR_ADDR value;
+ } ;
+
+ struct Dynamic_Loader_Sym {
+/* public: */
+ /*************************************************************************
+ * Find_Matching_Symbol
+ *
+ * PARAMETERS :
+ * name The name of the desired symbol
+ *
+ * EFFECT :
+ * Locates a symbol matching the name specified. A pointer to the
+ * symbol is returned if it exists; 0 is returned if no such symbol is
+ * found.
+ *
+ *************************************************************************/
+ struct dynload_symbol *(*Find_Matching_Symbol)
+ (struct Dynamic_Loader_Sym *
+ thisptr,
+ const char *name);
+
+ /*************************************************************************
+ * Add_To_Symbol_Table
+ *
+ * PARAMETERS :
+ * nname Pointer to the name of the new symbol
+ * moduleid An opaque module id assigned by the dynamic loader
+ *
+ * EFFECT :
+ * The new symbol is added to the table. A pointer to the symbol is
+ * returned, or NULL is returned for failure.
+ *
+ * NOTES:
+ * It is permissible for this function to return NULL; the effect is that
+ * the named symbol will not be available to resolve references in
+ * subsequent loads. Returning NULL will not cause the current load
+ * to fail.
+ *************************************************************************/
+ struct dynload_symbol *(*Add_To_Symbol_Table)
+ (struct Dynamic_Loader_Sym *
+ thisptr,
+ const char *nname,
+ unsigned moduleid);
+
+ /*************************************************************************
+ * Purge_Symbol_Table
+ *
+ * PARAMETERS :
+ * moduleid An opaque module id assigned by the dynamic loader
+ *
+ * EFFECT :
+ * Each symbol in the symbol table whose moduleid matches the argument
+ * is removed from the table.
+ *************************************************************************/
+ void (*Purge_Symbol_Table) (struct Dynamic_Loader_Sym *thisptr,
+ unsigned moduleid);
+
+ /*************************************************************************
+ * Allocate
+ *
+ * PARAMETERS :
+ * memsiz size of desired memory in sizeof() units
+ *
+ * EFFECT :
+ * Returns a pointer to some "host" memory for use by the dynamic
+ * loader, or NULL for failure.
+ * This function is serves as a replaceable form of "malloc" to
+ * allow the user to configure the memory usage of the dynamic loader.
+ *************************************************************************/
+ void *(*Allocate) (struct Dynamic_Loader_Sym *thisptr,
+ unsigned memsiz);
+
+ /*************************************************************************
+ * Deallocate
+ *
+ * PARAMETERS :
+ * memptr pointer to previously allocated memory
+ *
+ * EFFECT :
+ * Releases the previously allocated "host" memory.
+ *************************************************************************/
+ void (*Deallocate) (struct Dynamic_Loader_Sym *thisptr,
+ void *memptr);
+
+ /*************************************************************************
+ * Error_Report
+ *
+ * PARAMETERS :
+ * errstr pointer to an error string
+ * args additional arguments
+ *
+ * EFFECT :
+ * This function provides an error reporting interface for the dynamic
+ * loader. The error string and arguments are designed as for the
+ * library function vprintf.
+ *************************************************************************/
+ void (*Error_Report) (struct Dynamic_Loader_Sym *thisptr,
+ const char *errstr, va_list args);
+
+ }; /* class Dynamic_Loader_Sym */
+
+/*****************************************************************************
+ *****************************************************************************
+ * A class used by the dynamic loader to allocate and deallocate target memory.
+ *****************************************************************************
+ *****************************************************************************/
+
+ struct LDR_SECTION_INFO {
+ /* Name of the memory section assigned at build time */
+ const char *name;
+ LDR_ADDR run_addr; /* execution address of the section */
+ LDR_ADDR load_addr; /* load address of the section */
+ LDR_ADDR size; /* size of the section in addressable units */
+#ifndef _BIG_ENDIAN
+ u16 page; /* memory page or view */
+ u16 type; /* one of the section types below */
+#else
+ u16 type; /* one of the section types below */
+ u16 page; /* memory page or view */
+#endif
+ /* a context field for use by Dynamic_Loader_Allocate;
+ * ignored but maintained by the dynamic loader */
+ u32 context;
+ } ;
+
+/* use this macro to extract type of section from LDR_SECTION_INFO.type field */
+#define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
+
+/* type of section to be allocated */
+#define DLOAD_TEXT 0
+#define DLOAD_DATA 1
+#define DLOAD_BSS 2
+ /* internal use only, run-time cinit will be of type DLOAD_DATA */
+#define DLOAD_CINIT 3
+
+ struct Dynamic_Loader_Allocate {
+/* public: */
+
+ /*************************************************************************
+ * Function allocate
+ *
+ * Parameters:
+ * info A pointer to an information block for the section
+ * align The alignment of the storage in target AUs
+ *
+ * Effect:
+ * Allocates target memory for the specified section and fills in the
+ * load_addr and run_addr fields of the section info structure. Returns TRUE
+ * for success, FALSE for failure.
+ *
+ * Notes:
+ * Frequently load_addr and run_addr are the same, but if they are not
+ * load_addr is used with Dynamic_Loader_Initialize, and run_addr is
+ * used for almost all relocations. This function should always initialize
+ * both fields.
+ *************************************************************************/
+ int (*Allocate) (struct Dynamic_Loader_Allocate *thisptr,
+ struct LDR_SECTION_INFO *info, unsigned align);
+
+ /*************************************************************************
+ * Function deallocate
+ *
+ * Parameters:
+ * info A pointer to an information block for the section
+ *
+ * Effect:
+ * Releases the target memory previously allocated.
+ *
+ * Notes:
+ * The content of the info->name field is undefined on call to this function.
+ *************************************************************************/
+ void (*Deallocate) (struct Dynamic_Loader_Allocate *thisptr,
+ struct LDR_SECTION_INFO *info);
+
+ }; /* class Dynamic_Loader_Allocate */
+
+/*****************************************************************************
+ *****************************************************************************
+ * A class used by the dynamic loader to load data into a target. This class
+ * provides the interface-specific functions needed to load data.
+ *****************************************************************************
+ *****************************************************************************/
+
+ struct Dynamic_Loader_Initialize {
+/* public: */
+ /*************************************************************************
+ * Function connect
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Connect to the initialization interface. Returns TRUE for success,
+ * FALSE for failure.
+ *
+ * Notes:
+ * This function is called prior to use of any other functions in
+ * this interface.
+ *************************************************************************/
+ int (*connect) (struct Dynamic_Loader_Initialize *thisptr);
+
+ /*************************************************************************
+ * Function readmem
+ *
+ * Parameters:
+ * bufr Pointer to a word-aligned buffer for the result
+ * locn Target address of first data element
+ * info Section info for the section in which the address resides
+ * bytsiz Size of the data to be read in sizeof() units
+ *
+ * Effect:
+ * Fills the specified buffer with data from the target. Returns TRUE for
+ * success, FALSE for failure.
+ *************************************************************************/
+ int (*readmem) (struct Dynamic_Loader_Initialize *thisptr,
+ void *bufr,
+ LDR_ADDR locn,
+ struct LDR_SECTION_INFO *info,
+ unsigned bytsiz);
+
+ /*************************************************************************
+ * Function writemem
+ *
+ * Parameters:
+ * bufr Pointer to a word-aligned buffer of data
+ * locn Target address of first data element to be written
+ * info Section info for the section in which the address resides
+ * bytsiz Size of the data to be written in sizeof() units
+ *
+ * Effect:
+ * Writes the specified buffer to the target. Returns TRUE for success,
+ * FALSE for failure.
+ *************************************************************************/
+ int (*writemem) (struct Dynamic_Loader_Initialize *thisptr,
+ void *bufr,
+ LDR_ADDR locn,
+ struct LDR_SECTION_INFO *info,
+ unsigned bytsiz);
+
+ /*************************************************************************
+ * Function fillmem
+ *
+ * Parameters:
+ * locn Target address of first data element to be written
+ * info Section info for the section in which the address resides
+ * bytsiz Size of the data to be written in sizeof() units
+ * val Value to be written in each byte
+ * Effect:
+ * Fills the specified area of target memory. Returns TRUE for success,
+ * FALSE for failure.
+ *************************************************************************/
+ int (*fillmem) (struct Dynamic_Loader_Initialize *thisptr,
+ LDR_ADDR locn, struct LDR_SECTION_INFO *info,
+ unsigned bytsiz, unsigned val);
+
+ /*************************************************************************
+ * Function execute
+ *
+ * Parameters:
+ * start Starting address
+ *
+ * Effect:
+ * The target code at the specified starting address is executed.
+ *
+ * Notes:
+ * This function is called at the end of the dynamic load process
+ * if the input module has specified a starting address.
+ *************************************************************************/
+ int (*execute) (struct Dynamic_Loader_Initialize *thisptr,
+ LDR_ADDR start);
+
+ /*************************************************************************
+ * Function release
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Releases the connection to the load interface.
+ *
+ * Notes:
+ * This function is called at the end of the dynamic load process.
+ *************************************************************************/
+ void (*release) (struct Dynamic_Loader_Initialize *thisptr);
+
+ }; /* class Dynamic_Loader_Initialize */
+
+#endif /* _DYNAMIC_LOADER_H_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/errbase.h b/arch/arm/plat-omap/include/dspbridge/errbase.h
new file mode 100644
index 000000000000..f04c005c06ad
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/errbase.h
@@ -0,0 +1,509 @@
+/*
+ * errbase.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== errbase.h ========
+ * Description:
+ * Central repository for DSP/BIOS Bridge error and status code.
+ *
+ * Error codes are of the form:
+ * [<MODULE>]_E<ERRORCODE>
+ *
+ * Success codes are of the form:
+ * [<MODULE>]_S<SUCCESSCODE>
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Jan-2003 map Added DSP_SALREADYLOADED for persistent library checking
+ *! 23-Nov-2002 gp: Minor comment cleanup.
+ *! 13-May-2002 sg Added DSP_SALREADYASLEEP and DSP_SALREADYWAKE.
+ *! 18-Feb-2002 mk: Added DSP_EOVERLAYMEMORY, EFWRITE, ENOSECT.
+ *! 31-Jan-2002 mk: Added definitions of DSP_STRUE and DSP_SFALSE.
+ *! 29-Jan-2002 mk: Added definition of CFG_E_INSUFFICIENTBUFSIZE.
+ *! 24-Oct-2001 sp: Consolidated all the error codes into this file.
+ *! 24-Jul-2001 mk: Type-casted all definitions of WSX_STATUS types for
+ *! removal of compile warnings.
+ *! 22-Nov-1999 kc: Changes from code review.
+ *! 18-Aug-1999 rr: Ported From WSX.
+ *! 29-May-1996 gp: Removed WCD_ and WMD_ error ranges. Redefined format of
+ *! error codes.
+ *! 10-May-1996 gp: Created.
+ */
+
+#ifndef ERRBASE_
+#define ERRBASE_
+
+/* Base of generic errors and component errors */
+#define DSP_SBASE (DSP_STATUS)0x00008000
+#define DSP_EBASE (DSP_STATUS)0x80008000
+
+#define DSP_COMP_EBASE (DSP_STATUS)0x80040200
+#define DSP_COMP_ELAST (DSP_STATUS)0x80047fff
+
+/* SUCCESS Codes */
+
+/* Generic success code */
+#define DSP_SOK (DSP_SBASE + 0)
+
+/* GPP is already attached to this DSP processor */
+#define DSP_SALREADYATTACHED (DSP_SBASE + 1)
+
+/* This is the last object available for enumeration. */
+#define DSP_SENUMCOMPLETE (DSP_SBASE + 2)
+
+/* The DSP is already asleep. */
+#define DSP_SALREADYASLEEP (DSP_SBASE + 3)
+
+/* The DSP is already awake. */
+#define DSP_SALREADYAWAKE (DSP_SBASE + 4)
+
+/* TRUE */
+#define DSP_STRUE (DSP_SBASE + 5)
+
+/* FALSE */
+#define DSP_SFALSE (DSP_SBASE + 6)
+
+/* A library contains no dependent library references */
+#define DSP_SNODEPENDENTLIBS (DSP_SBASE + 7)
+
+/* A persistent library is already loaded by the dynamic loader */
+#define DSP_SALREADYLOADED (DSP_SBASE + 8)
+
+/* Some error occured, but it is OK to continue */
+#define DSP_OKTO_CONTINUE (DSP_SBASE + 9)
+
+/* FAILURE Codes */
+
+/* The caller does not have access privileges to call this function */
+#define DSP_EACCESSDENIED (DSP_EBASE + 0)
+
+/* The Specified Connection already exists */
+#define DSP_EALREADYCONNECTED (DSP_EBASE + 1)
+
+/* The GPP must be detached from the DSP before this function is called */
+#define DSP_EATTACHED (DSP_EBASE + 2)
+
+/* During enumeration a change in the number or properties of the objects
+ * has occurred. */
+#define DSP_ECHANGEDURINGENUM (DSP_EBASE + 3)
+
+/* An error occurred while parsing the DSP executable file */
+#define DSP_ECORRUPTFILE (DSP_EBASE + 4)
+
+/* A failure occurred during a delete operation */
+#define DSP_EDELETE (DSP_EBASE + 5)
+
+/* The specified direction is invalid */
+#define DSP_EDIRECTION (DSP_EBASE + 6)
+
+/* A stream has been issued the maximum number of buffers allowed in the
+ * stream at once ; buffers must be reclaimed from the stream before any
+ * more can be issued. */
+#define DSP_ESTREAMFULL (DSP_EBASE + 7)
+
+/* A general failure occurred */
+#define DSP_EFAIL (DSP_EBASE + 8)
+
+/* The specified executable file could not be found. */
+#define DSP_EFILE (DSP_EBASE + 9)
+
+/* The specified handle is invalid. */
+#define DSP_EHANDLE (DSP_EBASE + 0xa)
+
+/* An invalid argument was specified. */
+#define DSP_EINVALIDARG (DSP_EBASE + 0xb)
+
+/* A memory allocation failure occurred. */
+#define DSP_EMEMORY (DSP_EBASE + 0xc)
+
+/* The requested operation is invalid for this node type. */
+#define DSP_ENODETYPE (DSP_EBASE + 0xd)
+
+/* No error text was found for the specified error code. */
+#define DSP_ENOERRTEXT (DSP_EBASE + 0xe)
+
+/* No more connections can be made for this node. */
+#define DSP_ENOMORECONNECTIONS (DSP_EBASE + 0xf)
+
+/* The indicated operation is not supported. */
+#define DSP_ENOTIMPL (DSP_EBASE + 0x10)
+
+/* I/O is currently pending. */
+#define DSP_EPENDING (DSP_EBASE + 0x11)
+
+/* An invalid pointer was specified. */
+#define DSP_EPOINTER (DSP_EBASE + 0x12)
+
+/* A parameter is specified outside its valid range. */
+#define DSP_ERANGE (DSP_EBASE + 0x13)
+
+/* An invalid size parameter was specified. */
+#define DSP_ESIZE (DSP_EBASE + 0x14)
+
+/* A stream creation failure occurred on the DSP. */
+#define DSP_ESTREAM (DSP_EBASE + 0x15)
+
+/* A task creation failure occurred on the DSP. */
+#define DSP_ETASK (DSP_EBASE + 0x16)
+
+/* A timeout occurred before the requested operation could complete. */
+
+#define DSP_ETIMEOUT (DSP_EBASE + 0x17)
+
+/* A data truncation occurred, e.g., when requesting a descriptive error
+ * string, not enough space was allocated for the complete error message. */
+
+#define DSP_ETRUNCATED (DSP_EBASE + 0x18)
+
+/* A parameter is invalid. */
+#define DSP_EVALUE (DSP_EBASE + 0x1a)
+
+/* The state of the specified object is incorrect for the requested
+ * operation. */
+#define DSP_EWRONGSTATE (DSP_EBASE + 0x1b)
+
+/* Symbol not found in the COFF file. DSPNode_Create will return this if
+ * the iAlg function table for an xDAIS socket is not found in the COFF file.
+ * In this case, force the symbol to be linked into the COFF file.
+ * DSPNode_Create, DSPNode_Execute, and DSPNode_Delete will return this if
+ * the create, execute, or delete phase function, respectively, could not be
+ * found in the COFF file. */
+#define DSP_ESYMBOL (DSP_EBASE + 0x1c)
+
+/* UUID not found in registry. */
+#define DSP_EUUID (DSP_EBASE + 0x1d)
+
+/* Unable to read content of DCD data section ; this is typically caused by
+ * improperly configured nodes. */
+#define DSP_EDCDREADSECT (DSP_EBASE + 0x1e)
+
+/* Unable to decode DCD data section content ; this is typically caused by
+ * changes to DSP/BIOS Bridge data structures. */
+#define DSP_EDCDPARSESECT (DSP_EBASE + 0x1f)
+
+/* Unable to get pointer to DCD data section ; this is typically caused by
+ * improperly configured UUIDs. */
+#define DSP_EDCDGETSECT (DSP_EBASE + 0x20)
+
+/* Unable to load file containing DCD data section ; this is typically
+ * caused by a missing COFF file. */
+#define DSP_EDCDLOADBASE (DSP_EBASE + 0x21)
+
+/* The specified COFF file does not contain a valid node registration
+ * section. */
+#define DSP_EDCDNOAUTOREGISTER (DSP_EBASE + 0x22)
+
+/* A requested resource is not available. */
+#define DSP_ERESOURCE (DSP_EBASE + 0x28)
+
+/* A critical error has occurred, and the DSP is being re-started. */
+#define DSP_ERESTART (DSP_EBASE + 0x29)
+
+/* A DSP memory free operation failed. */
+#define DSP_EFREE (DSP_EBASE + 0x2a)
+
+/* A DSP I/O free operation failed. */
+#define DSP_EIOFREE (DSP_EBASE + 0x2b)
+
+/* Multiple instances are not allowed. */
+#define DSP_EMULINST (DSP_EBASE + 0x2c)
+
+/* A specified entity was not found. */
+#define DSP_ENOTFOUND (DSP_EBASE + 0x2d)
+
+/* A DSP I/O resource is not available. */
+#define DSP_EOUTOFIO (DSP_EBASE + 0x2e)
+
+/* A shared memory buffer contained in a message or stream could not be
+ * mapped to the GPP client process's virtual space. */
+#define DSP_ETRANSLATE (DSP_EBASE + 0x2f)
+
+/* File or section load write function failed to write to DSP */
+#define DSP_EFWRITE (DSP_EBASE + 0x31)
+
+/* Unable to find a named section in DSP executable */
+#define DSP_ENOSECT (DSP_EBASE + 0x32)
+
+/* Unable to open file */
+#define DSP_EFOPEN (DSP_EBASE + 0x33)
+
+/* Unable to read file */
+#define DSP_EFREAD (DSP_EBASE + 0x34)
+
+/* A non-existent memory segment identifier was specified */
+#define DSP_EOVERLAYMEMORY (DSP_EBASE + 0x37)
+
+/* Invalid segment ID */
+#define DSP_EBADSEGID (DSP_EBASE + 0x38)
+
+/* Invalid alignment */
+#define DSP_EALIGNMENT (DSP_EBASE + 0x39)
+
+/* Invalid stream mode */
+#define DSP_ESTRMMODE (DSP_EBASE + 0x3a)
+
+/* Nodes not connected */
+#define DSP_ENOTCONNECTED (DSP_EBASE + 0x3b)
+
+/* Not shared memory */
+#define DSP_ENOTSHAREDMEM (DSP_EBASE + 0x3c)
+
+/* Error occurred in a dynamic loader library function */
+#define DSP_EDYNLOAD (DSP_EBASE + 0x3d)
+
+/* Device in 'sleep/suspend' mode due to DPM */
+#define DSP_EDPMSUSPEND (DSP_EBASE + 0x3e)
+
+/* A node-specific error has occurred. */
+#define DSP_EUSER1 (DSP_EBASE + 0x40)
+#define DSP_EUSER2 (DSP_EBASE + 0x41)
+#define DSP_EUSER3 (DSP_EBASE + 0x42)
+#define DSP_EUSER4 (DSP_EBASE + 0x43)
+#define DSP_EUSER5 (DSP_EBASE + 0x44)
+#define DSP_EUSER6 (DSP_EBASE + 0x45)
+#define DSP_EUSER7 (DSP_EBASE + 0x46)
+#define DSP_EUSER8 (DSP_EBASE + 0x47)
+#define DSP_EUSER9 (DSP_EBASE + 0x48)
+#define DSP_EUSER10 (DSP_EBASE + 0x49)
+#define DSP_EUSER11 (DSP_EBASE + 0x4a)
+#define DSP_EUSER12 (DSP_EBASE + 0x4b)
+#define DSP_EUSER13 (DSP_EBASE + 0x4c)
+#define DSP_EUSER14 (DSP_EBASE + 0x4d)
+#define DSP_EUSER15 (DSP_EBASE + 0x4e)
+#define DSP_EUSER16 (DSP_EBASE + 0x4f)
+
+/* FAILURE Codes : DEV */
+#define DEV_EBASE (DSP_COMP_EBASE + 0x000)
+
+/* The mini-driver expected a newer version of the class driver. */
+#define DEV_E_NEWWMD (DEV_EBASE + 0x00)
+
+/* WMD_DRV_Entry function returned a NULL function interface table. */
+#define DEV_E_NULLWMDINTF (DEV_EBASE + 0x01)
+
+/* FAILURE Codes : LDR */
+#define LDR_EBASE (DSP_COMP_EBASE + 0x100)
+
+/* Insufficient memory to export class driver services. */
+#define LDR_E_NOMEMORY (LDR_EBASE + 0x00)
+
+/* Unable to find WMD file in system directory. */
+#define LDR_E_FILEUNABLETOOPEN (LDR_EBASE + 0x01)
+
+/* FAILURE Codes : CFG */
+#define CFG_EBASE (DSP_COMP_EBASE + 0x200)
+
+/* Invalid pointer passed into a configuration module function */
+#define CFG_E_INVALIDPOINTER (CFG_EBASE + 0x00)
+
+/* Invalid device node handle passed into a configuration module function. */
+#define CFG_E_INVALIDHDEVNODE (CFG_EBASE + 0x01)
+
+/* Unable to retrieve resource information from the registry. */
+#define CFG_E_RESOURCENOTAVAIL (CFG_EBASE + 0x02)
+
+/* Unable to find board name key in registry. */
+#define CFG_E_INVALIDBOARDNAME (CFG_EBASE + 0x03)
+
+/* Unable to find a device node in registry with given unit number. */
+#define CFG_E_INVALIDUNITNUM (CFG_EBASE + 0x04)
+
+/* Insufficient buffer size */
+#define CFG_E_INSUFFICIENTBUFSIZE (CFG_EBASE + 0x05)
+
+/* FAILURE Codes : BRD */
+#define BRD_EBASE (DSP_COMP_EBASE + 0x300)
+
+/* Board client does not have sufficient access rights for this operation. */
+#define BRD_E_ACCESSDENIED (BRD_EBASE + 0x00)
+
+/* Unable to find trace buffer symbols in the DSP executable COFF file. */
+#define BRD_E_NOTRACEBUFFER (BRD_EBASE + 0x01)
+
+/* Attempted to auto-start board, but no default DSP executable configured. */
+#define BRD_E_NOEXEC (BRD_EBASE + 0x02)
+
+/* The operation failed because it was started from a wrong state */
+#define BRD_E_WRONGSTATE (BRD_EBASE + 0x03)
+
+/* FAILURE Codes : COD */
+#define COD_EBASE (DSP_COMP_EBASE + 0x400)
+
+/* No symbol table is loaded for this board. */
+#define COD_E_NOSYMBOLSLOADED (COD_EBASE + 0x00)
+
+/* Symbol not found in for this board. */
+#define COD_E_SYMBOLNOTFOUND (COD_EBASE + 0x01)
+
+/* ZL DLL module is not exporting the correct function interface. */
+#define COD_E_NOZLFUNCTIONS (COD_EBASE + 0x02)
+
+/* Unable to initialize the ZL COFF parsing module. */
+#define COD_E_ZLCREATEFAILED (COD_EBASE + 0x03)
+
+/* Unable to open DSP executable COFF file. */
+#define COD_E_OPENFAILED (COD_EBASE + 0x04)
+
+/* Unable to parse DSP executable COFF file. */
+#define COD_E_LOADFAILED (COD_EBASE + 0x05)
+
+/* Unable to read DSP executable COFF file. */
+#define COD_E_READFAILED (COD_EBASE + 0x06)
+
+/* FAILURE Codes : CHNL */
+#define CHNL_EBASE (DSP_COMP_EBASE + 0x500)
+
+/* Attempt to created channel manager with too many channels. */
+#define CHNL_E_MAXCHANNELS (CHNL_EBASE + 0x00)
+
+/* No channel manager exists for this mini-driver. */
+#define CHNL_E_NOMGR (CHNL_EBASE + 0x01)
+
+/* No free channels are available. */
+#define CHNL_E_OUTOFSTREAMS (CHNL_EBASE + 0x02)
+
+/* Channel ID is out of range. */
+#define CHNL_E_BADCHANID (CHNL_EBASE + 0x03)
+
+/* Channel is already in use. */
+#define CHNL_E_CHANBUSY (CHNL_EBASE + 0x04)
+
+/* Invalid channel mode argument. */
+#define CHNL_E_BADMODE (CHNL_EBASE + 0x05)
+
+/* dwTimeOut parameter was CHNL_IOCNOWAIT, yet no I/O completions were
+ * queued. */
+#define CHNL_E_NOIOC (CHNL_EBASE + 0x06)
+
+/* I/O has been cancelled on this channel. */
+#define CHNL_E_CANCELLED (CHNL_EBASE + 0x07)
+
+/* End of stream was already requested on this output channel. */
+#define CHNL_E_EOS (CHNL_EBASE + 0x09)
+
+/* Unable to create the channel event object. */
+#define CHNL_E_CREATEEVENT (CHNL_EBASE + 0x0A)
+
+/* Board name and unit number do not identify a valid board name. */
+#define CHNL_E_BRDID (CHNL_EBASE + 0x0B)
+
+/* Invalid IRQ configured for this WMD for this system. */
+#define CHNL_E_INVALIDIRQ (CHNL_EBASE + 0x0C)
+
+/* DSP word size of zero configured for this device. */
+#define CHNL_E_INVALIDWORDSIZE (CHNL_EBASE + 0x0D)
+
+/* A zero length memory base was specified for a shared memory class driver. */
+#define CHNL_E_INVALIDMEMBASE (CHNL_EBASE + 0x0E)
+
+/* Memory map is not configured, or unable to map physical to linear
+ * address. */
+#define CHNL_E_NOMEMMAP (CHNL_EBASE + 0x0F)
+
+/* Attempted to create a channel manager when one already exists. */
+#define CHNL_E_MGREXISTS (CHNL_EBASE + 0x10)
+
+/* Unable to plug channel ISR for configured IRQ. */
+#define CHNL_E_ISR (CHNL_EBASE + 0x11)
+
+/* No free I/O request packets are available. */
+#define CHNL_E_NOIORPS (CHNL_EBASE + 0x12)
+
+/* Buffer size is larger than the size of physical channel. */
+#define CHNL_E_BUFSIZE (CHNL_EBASE + 0x13)
+
+/* User cannot mark end of stream on an input channel. */
+#define CHNL_E_NOEOS (CHNL_EBASE + 0x14)
+
+/* Wait for flush operation on an output channel timed out. */
+#define CHNL_E_WAITTIMEOUT (CHNL_EBASE + 0x15)
+
+/* User supplied hEvent must be specified with pstrEventName attribute */
+#define CHNL_E_BADUSEREVENT (CHNL_EBASE + 0x16)
+
+/* Illegal user event name specified */
+#define CHNL_E_USEREVENTNAME (CHNL_EBASE + 0x17)
+
+/* Unable to prepare buffer specified */
+#define CHNL_E_PREPFAILED (CHNL_EBASE + 0x18)
+
+/* Unable to Unprepare buffer specified */
+#define CHNL_E_UNPREPFAILED (CHNL_EBASE + 0x19)
+
+/* FAILURE Codes : SYNC */
+#define SYNC_EBASE (DSP_COMP_EBASE + 0x600)
+
+/* Wait on a kernel event failed. */
+#define SYNC_E_FAIL (SYNC_EBASE + 0x00)
+
+/* Timeout expired while waiting for event to be signalled. */
+#define SYNC_E_TIMEOUT (SYNC_EBASE + 0x01)
+
+/* FAILURE Codes : WMD */
+#define WMD_EBASE (DSP_COMP_EBASE + 0x700)
+
+/* A test of hardware assumptions or integrity failed. */
+#define WMD_E_HARDWARE (WMD_EBASE + 0x00)
+
+/* One or more configuration parameters violated WMD hardware assumptions. */
+#define WMD_E_BADCONFIG (WMD_EBASE + 0x01)
+
+/* Timeout occurred waiting for a response from the hardware. */
+#define WMD_E_TIMEOUT (WMD_EBASE + 0x02)
+
+/* FAILURE Codes : REG */
+#define REG_EBASE (DSP_COMP_EBASE + 0x800)
+
+/* Invalid subkey parameter. */
+#define REG_E_INVALIDSUBKEY (REG_EBASE + 0x00)
+
+/* Invalid entry parameter. */
+#define REG_E_INVALIDENTRY (REG_EBASE + 0x01)
+
+/* No more registry values. */
+#define REG_E_NOMOREITEMS (REG_EBASE + 0x02)
+
+/* Insufficient space to hold data in registry value. */
+#define REG_E_MOREDATA (REG_EBASE + 0x03)
+
+/* FAILURE Codes : KFILE */
+#define KFILE_EBASE (DSP_COMP_EBASE + 0x900)
+
+/* Invalid file handle. */
+#define E_KFILE_INVALIDHANDLE (KFILE_EBASE + 0x01)
+
+/* Bad file name. */
+#define E_KFILE_BADFILENAME (KFILE_EBASE + 0x02)
+
+/* Invalid file mode. */
+#define E_KFILE_INVALIDMODE (KFILE_EBASE + 0x03)
+
+/* No resources available. */
+#define E_KFILE_NORESOURCES (KFILE_EBASE + 0x04)
+
+/* Invalid file buffer . */
+#define E_KFILE_INVALIDBUFFER (KFILE_EBASE + 0x05)
+
+/* Bad origin argument. */
+#define E_KFILE_BADORIGINFLAG (KFILE_EBASE + 0x06)
+
+/* Invalid file offset value. */
+#define E_KFILE_INVALIDOFFSET (KFILE_EBASE + 0x07)
+
+/* General KFILE error condition */
+#define E_KFILE_ERROR (KFILE_EBASE + 0x08)
+
+#endif /* ERRBASE_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/gb.h b/arch/arm/plat-omap/include/dspbridge/gb.h
new file mode 100644
index 000000000000..f1477515d11d
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/gb.h
@@ -0,0 +1,85 @@
+/*
+ * gb.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== gb.h ========
+ * Generic bitmap manager.
+ *
+ *! Revision History
+ *! ================
+ */
+
+#ifndef GB_
+#define GB_
+
+#define GB_NOBITS (~0)
+#include <dspbridge/host_os.h>
+typedef s32 GB_BitNum;
+struct GB_TMap;
+
+/*
+ * ======== GB_clear ========
+ * Clear the bit in position bitn in the bitmap map. Bit positions are
+ * zero based.
+ */
+
+extern void GB_clear(struct GB_TMap *map, GB_BitNum bitn);
+
+/*
+ * ======== GB_create ========
+ * Create a bit map with len bits. Initially all bits are cleared.
+ */
+
+extern struct GB_TMap *GB_create(GB_BitNum len);
+
+/*
+ * ======== GB_delete ========
+ * Delete previously created bit map
+ */
+
+extern void GB_delete(struct GB_TMap *map);
+
+/*
+ * ======== GB_findandset ========
+ * Finds a clear bit, sets it, and returns the position
+ */
+
+extern GB_BitNum GB_findandset(struct GB_TMap *map);
+
+/*
+ * ======== GB_minclear ========
+ * GB_minclear returns the minimum clear bit position. If no bit is
+ * clear, GB_minclear returns -1.
+ */
+extern GB_BitNum GB_minclear(struct GB_TMap *map);
+
+/*
+ * ======== GB_set ========
+ * Set the bit in position bitn in the bitmap map. Bit positions are
+ * zero based.
+ */
+
+extern void GB_set(struct GB_TMap *map, GB_BitNum bitn);
+
+/*
+ * ======== GB_test ========
+ * Returns TRUE if the bit in position bitn is set in map; otherwise
+ * GB_test returns FALSE. Bit positions are zero based.
+ */
+
+extern bool GB_test(struct GB_TMap *map, GB_BitNum bitn);
+
+#endif /*GB_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/getsection.h b/arch/arm/plat-omap/include/dspbridge/getsection.h
new file mode 100644
index 000000000000..33ff50dd23cc
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/getsection.h
@@ -0,0 +1,118 @@
+/*
+ * getsection.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+#ifndef _GETSECTION_H_
+#define _GETSECTION_H_
+
+
+#include "dynamic_loader.h"
+
+/*
+ * Get Section Information
+ *
+ * This file provides an API add-on to the dynamic loader that allows the user
+ * to query section information and extract section data from dynamic load
+ * modules.
+ *
+ * NOTE:
+ * Functions in this API assume that the supplied Dynamic_Loader_Stream object
+ * supports the set_file_posn method.
+ */
+
+ /* opaque handle for module information */
+ typedef void *DLOAD_module_info;
+
+/*
+ * Procedure DLOAD_module_open
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side malloc/free and error reporting functions.
+ * Other methods are unused.
+ *
+ * Effect:
+ * Reads header information from a dynamic loader module using the specified
+ * stream object, and returns a handle for the module information. This
+ * handle may be used in subsequent query calls to obtain information
+ * contained in the module.
+ *
+ * Returns:
+ * NULL if an error is encountered, otherwise a module handle for use
+ * in subsequent operations.
+ */
+ extern DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream
+ *module,
+ struct Dynamic_Loader_Sym
+ *syms);
+
+/*
+ * Procedure DLOAD_GetSectionInfo
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ * sectionName Pointer to the string name of the section desired
+ * sectionInfo Address of a section info structure pointer to be initialized
+ *
+ * Effect:
+ * Finds the specified section in the module information, and fills in
+ * the provided LDR_SECTION_INFO structure.
+ *
+ * Returns:
+ * TRUE for success, FALSE for section not found
+ */
+ extern int DLOAD_GetSectionInfo(DLOAD_module_info minfo,
+ const char *sectionName,
+ const struct LDR_SECTION_INFO
+ ** const sectionInfo);
+
+/*
+ * Procedure DLOAD_GetSection
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ * sectionInfo Pointer to a section info structure for the desired section
+ * sectionData Buffer to contain the section initialized data
+ *
+ * Effect:
+ * Copies the initialized data for the specified section into the
+ * supplied buffer.
+ *
+ * Returns:
+ * TRUE for success, FALSE for section not found
+ */
+ extern int DLOAD_GetSection(DLOAD_module_info minfo,
+ const struct LDR_SECTION_INFO *sectionInfo,
+ void *sectionData);
+
+/*
+ * Procedure DLOAD_module_close
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ *
+ * Effect:
+ * Releases any storage associated with the module handle. On return,
+ * the module handle is invalid.
+ *
+ * Returns:
+ * Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->Error_Report(), where syms was
+ * an argument to DLOAD_module_open
+ */
+ extern void DLOAD_module_close(DLOAD_module_info minfo);
+
+#endif /* _GETSECTION_H_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/gh.h b/arch/arm/plat-omap/include/dspbridge/gh.h
new file mode 100644
index 000000000000..089a042dfb46
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/gh.h
@@ -0,0 +1,37 @@
+/*
+ * gh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== gh.h ========
+ *
+ *! Revision History
+ *! ================
+ */
+
+#ifndef GH_
+#define GH_
+#include <dspbridge/host_os.h>
+
+extern struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
+ u16(*hash) (void *, u16), bool(*match) (void *, void *),
+ void(*delete) (void *));
+extern void GH_delete(struct GH_THashTab *hashTab);
+extern void GH_exit(void);
+extern void *GH_find(struct GH_THashTab *hashTab, void *key);
+extern void GH_init(void);
+extern void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value);
+#endif /* GH_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/gs.h b/arch/arm/plat-omap/include/dspbridge/gs.h
new file mode 100644
index 000000000000..fd5ef27990f5
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/gs.h
@@ -0,0 +1,64 @@
+/*
+ * gs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== gs.h ========
+ * Memory allocation/release wrappers. This module allows clients to
+ * avoid OS spacific issues related to memory allocation. It also provides
+ * simple diagnostic capabilities to assist in the detection of memory
+ * leaks.
+ *! Revision History
+ *! ================
+ */
+
+#ifndef GS_
+#define GS_
+
+/*
+ * ======== GS_alloc ========
+ * Alloc size bytes of space. Returns pointer to space
+ * allocated, otherwise NULL.
+ */
+extern void *GS_alloc(u32 size);
+
+/*
+ * ======== GS_exit ========
+ * Module exit. Do not change to "#define GS_init()"; in
+ * some environments this operation must actually do some work!
+ */
+extern void GS_exit(void);
+
+/*
+ * ======== GS_free ========
+ * Free space allocated by GS_alloc() or GS_calloc().
+ */
+extern void GS_free(void *ptr);
+
+/*
+ * ======== GS_frees ========
+ * Free space allocated by GS_alloc() or GS_calloc() and assert that
+ * the size of the allocation is size bytes.
+ */
+extern void GS_frees(void *ptr, u32 size);
+
+/*
+ * ======== GS_init ========
+ * Module initialization. Do not change to "#define GS_init()"; in
+ * some environments this operation must actually do some work!
+ */
+extern void GS_init(void);
+
+#endif /*GS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/gt.h b/arch/arm/plat-omap/include/dspbridge/gt.h
new file mode 100644
index 000000000000..456c866383a0
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/gt.h
@@ -0,0 +1,315 @@
+/*
+ * gt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== gt.h ========
+ * Purpose:
+ * There are two definitions that affect which portions of trace
+ * are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
+ * GT_TRACE is set to 0 then all trace statements (except for assertions)
+ * will be compiled out of the client. If GT_ASSERT is set to 0 then
+ * assertions will be compiled out of the client. GT_ASSERT can not be
+ * set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
+ * GT_ASSERT == 1).
+ *
+ *! Revision History
+ *! ================
+ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace definitions
+ *! are WinCE Specific.
+ *! 03-Jan-1997 ge Replaced "GT_" prefix to GT_Config structure members
+ *! to eliminate preprocessor confusion with other macros.
+ */
+#include <linux/types.h>
+#ifndef GT_
+#define GT_
+
+#ifndef GT_TRACE
+#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
+#endif
+
+#include <dspbridge/host_os.h>
+
+#if !defined(GT_ASSERT) || GT_TRACE
+#define GT_ASSERT 1
+#endif
+
+struct GT_Config {
+ Fxn PRINTFXN;
+ Fxn PIDFXN;
+ Fxn TIDFXN;
+ Fxn ERRORFXN;
+};
+
+extern struct GT_Config *GT;
+
+struct GT_Mask {
+ char *modName;
+ u8 *flags;
+} ;
+
+/*
+ * New GT Class defenitions.
+ *
+ * The following are the explanations and how it could be used in the code
+ *
+ * - GT_ENTER On Entry to Functions
+ *
+ * - GT_1CLASS Display level of debugging status- Object/Automatic
+ * variables
+ * - GT_2CLASS ---- do ----
+ *
+ * - GT_3CLASS ---- do ---- + It can be used(recommended) for debug
+ * status in the ISR, IST
+ * - GT_4CLASS ---- do ----
+ *
+ * - GT_5CLASS Display entry for module init/exit functions
+ *
+ * - GT_6CLASS Warn whenever SERVICES function fails
+ *
+ * - GT_7CLASS Warn failure of Critical failures
+ *
+ */
+
+#define GT_ENTER ((u8)0x01)
+#define GT_1CLASS ((u8)0x02)
+#define GT_2CLASS ((u8)0x04)
+#define GT_3CLASS ((u8)0x08)
+#define GT_4CLASS ((u8)0x10)
+#define GT_5CLASS ((u8)0x20)
+#define GT_6CLASS ((u8)0x40)
+#define GT_7CLASS ((u8)0x80)
+
+#ifdef _LINT_
+
+/* LINTLIBRARY */
+
+/*
+ * ======== GT_assert ========
+ */
+/* ARGSUSED */
+void GT_assert(struct GT_Mask mask, s32 expr)
+{
+}
+
+/*
+ * ======== GT_config ========
+ */
+/* ARGSUSED */
+void GT_config(struct GT_Config config)
+{
+}
+
+/*
+ * ======== GT_create ========
+ */
+/* ARGSUSED */
+void GT_create(struct GT_Mask *mask, char *modName)
+{
+}
+
+/*
+ * ======== GT_curLine ========
+ * Purpose:
+ * Returns the current source code line number. Is useful for performing
+ * branch testing using trace. For example,
+ *
+ * GT_1trace(curTrace, GT_1CLASS,
+ * "in module XX_mod, executing line %u\n", GT_curLine());
+ */
+/* ARGSUSED */
+u16 GT_curLine(void)
+{
+ return (u16)NULL;
+}
+
+/*
+ * ======== GT_exit ========
+ */
+/* ARGSUSED */
+void GT_exit(void)
+{
+}
+
+/*
+ * ======== GT_init ========
+ */
+/* ARGSUSED */
+void GT_init(void)
+{
+}
+
+/*
+ * ======== GT_query ========
+ */
+/* ARGSUSED */
+bool GT_query(struct GT_Mask mask, u8 class)
+{
+ return false;
+}
+
+/*
+ * ======== GT_set ========
+ * sets trace mask according to settings
+ */
+
+/* ARGSUSED */
+void GT_set(char *settings)
+{
+}
+
+/*
+ * ======== GT_setprintf ========
+ * sets printf function
+ */
+
+/* ARGSUSED */
+void GT_setprintf(Fxn fxn)
+{
+}
+
+/* ARGSUSED */
+void GT_0trace(struct GT_Mask mask, u8 class, char *format)
+{
+}
+
+/* ARGSUSED */
+void GT_1trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_2trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_3trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_4trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_5trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_6trace(struct GT_Mask mask, u8 class, char *format, ...)
+{
+}
+
+#else
+
+#define GT_BOUND 26 /* 26 letters in alphabet */
+
+extern void _GT_create(struct GT_Mask *mask, char *modName);
+
+#define GT_exit()
+
+extern void GT_init(void);
+extern void _GT_set(char *str);
+extern s32 _GT_trace(struct GT_Mask *mask, char *format, ...);
+
+#if GT_ASSERT == 0
+
+#define GT_assert(mask, expr)
+#define GT_config(config)
+#define GT_configInit(config)
+#define GT_seterror(fxn)
+
+#else
+
+extern struct GT_Config _GT_params;
+
+#define GT_assert(mask, expr) \
+ (!(expr) ? \
+ printk("assertion violation: %s, line %d\n", \
+ __FILE__, __LINE__), NULL : NULL)
+
+#define GT_config(config) (_GT_params = *(config))
+#define GT_configInit(config) (*(config) = _GT_params)
+#define GT_seterror(fxn) (_GT_params.ERRORFXN = (Fxn)(fxn))
+
+#endif
+
+#if GT_TRACE == 0
+
+#define GT_curLine() ((u16)__LINE__)
+#define GT_create(mask, modName)
+#define GT_exit()
+#define GT_init()
+#define GT_set(settings)
+#define GT_setprintf(fxn)
+
+#define GT_query(mask, class) false
+
+#define GT_0trace(mask, class, format)
+#define GT_1trace(mask, class, format, arg1)
+#define GT_2trace(mask, class, format, arg1, arg2)
+#define GT_3trace(mask, class, format, arg1, arg2, arg3)
+#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4)
+#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
+#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
+
+#else /* GT_TRACE == 1 */
+
+
+#define GT_create(mask, modName) _GT_create((mask), (modName))
+#define GT_curLine() ((u16)__LINE__)
+#define GT_set(settings) _GT_set(settings)
+#define GT_setprintf(fxn) (_GT_params.PRINTFXN = (Fxn)(fxn))
+
+#define GT_query(mask, class) ((*(mask).flags & (class)))
+
+#define GT_0trace(mask, class, format) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format)) : 0)
+
+#define GT_1trace(mask, class, format, arg1) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1)) : 0)
+
+#define GT_2trace(mask, class, format, arg1, arg2) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
+
+#define GT_3trace(mask, class, format, arg1, arg2, arg3) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
+
+#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
+
+#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) : 0)
+
+#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
+ (arg6)) : 0)
+
+#endif /* GT_TRACE */
+
+#endif /* _LINT_ */
+
+#endif /* GTCE_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/host_os.h b/arch/arm/plat-omap/include/dspbridge/host_os.h
new file mode 100644
index 000000000000..0ceabe113b6c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/host_os.h
@@ -0,0 +1,96 @@
+/*
+ * host_os.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== windows.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
+ *! 16-Feb-2004 sb Added headers required for consistent_alloc
+ */
+
+#ifndef _HOST_OS_H_
+#define _HOST_OS_H_
+
+#include <linux/autoconf.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/syscalls.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <dspbridge/dbtype.h>
+#include <mach/clock.h>
+#include <linux/clk.h>
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+
+
+#ifdef OMAP_3430
+#define INT_MAIL_MPU_IRQ INT_24XX_MAIL_U0_MPU
+#define INT_DSP_MMU_IRQ INT_24XX_DSP_MMU
+#else
+#define INT_MAIL_MPU_IRQ INT_44XX_MAIL_U0_MPU
+#define INT_DSP_MMU_IRQ INT_44XX_DSP_MMU
+#endif
+
+struct dspbridge_platform_data {
+ void (*dsp_set_min_opp)(u8 opp_id);
+ u8 (*dsp_get_opp)(void);
+ void (*cpu_set_freq)(unsigned long f);
+ unsigned long (*cpu_get_freq)(void);
+ unsigned long mpu_speed[6];
+
+ u32 phys_mempool_base;
+ u32 phys_mempool_size;
+};
+
+#define PRCM_VDD1 1
+
+extern struct platform_device *omap_dspbridge_dev;
+
+#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
+extern void dspbridge_reserve_sdram(void);
+#else
+static inline void dspbridge_reserve_sdram(void) {}
+#endif
+
+extern unsigned long dspbridge_get_mempool_base(void);
+
+#endif
+
diff --git a/arch/arm/plat-omap/include/dspbridge/io.h b/arch/arm/plat-omap/include/dspbridge/io.h
new file mode 100644
index 000000000000..6dc63f2d1fe6
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/io.h
@@ -0,0 +1,132 @@
+/*
+ * io.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== io.h ========
+ * Description:
+ * The io module manages IO between CHNL and MSG.
+ *
+ * Public Functions:
+ * IO_Create
+ * IO_Destroy
+ * IO_Exit
+ * IO_Init
+ * IO_OnLoaded
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Nov-2000 jeh Created.
+ */
+
+#ifndef IO_
+#define IO_
+
+#include <dspbridge/cfgdefs.h>
+#include <dspbridge/devdefs.h>
+
+#include <dspbridge/iodefs.h>
+
+/*
+ * ======== IO_Create ========
+ * Purpose:
+ * Create an IO manager object, responsible for managing IO between
+ * CHNL and MSG.
+ * Parameters:
+ * phChnlMgr: Location to store a channel manager object on
+ * output.
+ * hDevObject: Handle to a device object.
+ * pMgrAttrs: IO manager attributes.
+ * pMgrAttrs->bIRQ: I/O IRQ number.
+ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
+ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
+ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
+ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
+ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
+ * Requires:
+ * IO_Init(void) called.
+ * phIOMgr != NULL.
+ * pMgrAttrs != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct IO_ATTRS *pMgrAttrs);
+
+/*
+ * ======== IO_Destroy ========
+ * Purpose:
+ * Destroy the IO manager.
+ * Parameters:
+ * hIOMgr: IOmanager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: hIOMgr was invalid.
+ * Requires:
+ * IO_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr);
+
+/*
+ * ======== IO_Exit ========
+ * Purpose:
+ * Discontinue usage of the IO module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * IO_Init(void) previously called.
+ * Ensures:
+ * Resources, if any acquired in IO_Init(void), are freed when the last
+ * client of IO calls IO_Exit(void).
+ */
+ extern void IO_Exit(void);
+
+/*
+ * ======== IO_Init ========
+ * Purpose:
+ * Initialize the IO module's private state.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occurred.
+ * Requires:
+ * Ensures:
+ * A requirement for each of the other public CHNL functions.
+ */
+ extern bool IO_Init(void);
+
+/*
+ * ======== IO_OnLoaded ========
+ * Purpose:
+ * Called when a program is loaded so IO manager can update its
+ * internal state.
+ * Parameters:
+ * hIOMgr: IOmanager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: hIOMgr was invalid.
+ * Requires:
+ * IO_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS IO_OnLoaded(struct IO_MGR *hIOMgr);
+
+#endif /* CHNL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/io_sm.h b/arch/arm/plat-omap/include/dspbridge/io_sm.h
new file mode 100644
index 000000000000..ba2104f286d5
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/io_sm.h
@@ -0,0 +1,338 @@
+/*
+ * io_sm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== io_sm.h ========
+ * Description:
+ * IO dispatcher for a shared memory channel driver.
+ * Also, includes macros to simulate SHM via port io calls.
+ *
+ * Public Functions:
+ * IO_Dispatch
+ * IO_DPC
+ * IO_ISR
+ * IO_RequestChnl
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 01-Mar-2004 vp: Added IVA releated functions.
+ *! 23-Apr-2003 sb: Fixed mailbox deadlock
+ *! 06-Feb-2003 kc Added IO_DDMAClearChnlDesc and IO_DDZCClearChnlDesc.
+ *! 21-Dec-2001 ag Removed unused param in IO_DDMAInitChnlDesc().
+ * Updated comments. Removed #ifdef CHNL_NOIPCINTR.
+ *! 05-Nov-2001 kc Updated IO_CALLISR macro.
+ *! 01-May-2001 jeh Removed IO_RequestMsg.
+ *! 29-Mar-2001 ag Added #ifdef CHNL_NOIPCINTR.
+ *! 04-Dec-2000 jeh Added IO_RequestMsg.
+ *! 26-Oct-2000 jeh Added IO_GetLong, IO_SetLong, IO_ReadValueLong, and
+ *! IO_WriteValueLong, for passing arg in SHM structure.
+ *! 20-Jan-2000 ag: Updated header comments per code review.
+ *! 05-Jan-2000 ag: Text format clean-up.
+ *! 02-Nov-1999 ag: Updated header descriptions.
+ *! 25-May-1999 jg: Removed assumption of 4 bytes / word.
+ *! 12-Aug-1996 gp: Created.
+ */
+
+#ifndef IOSM_
+#define IOSM_
+
+#include <dspbridge/_chnl_sm.h>
+#include <dspbridge/host_os.h>
+#include <dspbridge/iodefs.h>
+#include <syslink/notifydefs.h>
+
+#define IO_INPUT 0
+#define IO_OUTPUT 1
+#define IO_SERVICE 2
+#define IO_MAXSERVICE IO_SERVICE
+
+#define IO_MGRSIGNATURE 0x494f4D43 /* "IOGR" */
+
+#define DSPFieldAddr(type, field, base, wordsize) \
+ ((((s32)&(((type *)0)->field)) / wordsize) + (u32)base)
+
+/* Access can be different SM access word size (e.g. 16/32 bit words) */
+#define IO_SetValue(pContext, type, base, field, value) (base->field = value)
+#define IO_GetValue(pContext, type, base, field) (base->field)
+#define IO_OrValue(pContext, type, base, field, value) (base->field |= value)
+#define IO_AndValue(pContext, type, base, field, value) (base->field &= value)
+#define IO_SetLong(pContext, type, base, field, value) (base->field = value)
+#define IO_GetLong(pContext, type, base, field) (base->field)
+
+#define IO_DisableInterrupt(h) CHNLSM_DisableInterrupt(h)
+#define IO_EnableInterrupt(h) CHNLSM_EnableInterrupt(h)
+#define IO_CALLISR(h, pFlag, pwMBRegVal) CHNLSM_ISR(h, pFlag, pwMBRegVal)
+
+/*
+ * ======== IO_CancelChnl ========
+ * Purpose:
+ * Cancel IO on a given channel.
+ * Parameters:
+ * hIOMgr: IO Manager.
+ * ulChnl: Index of channel to cancel IO on.
+ * Returns:
+ * Requires:
+ * Valid hIOMgr.
+ * Ensures:
+ */
+ extern void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl);
+
+/*
+ * ======== IO_DPC ========
+ * Purpose:
+ * Deferred procedure call for shared memory channel driver ISR. Carries
+ * out the dispatch of I/O.
+ * Parameters:
+ * pRefData: Pointer to reference data registered via a call to
+ * DPC_Create().
+ * Returns:
+ * Requires:
+ * Must not block.
+ * Must not acquire resources.
+ * All data touched must be locked in memory if running in kernel mode.
+ * Ensures:
+ * Non-preemptible (but interruptible).
+ */
+ extern void IO_DPC(IN OUT void *pRefData);
+
+/*
+ * ======== IO_ISR ========
+ * Purpose:
+ * Main interrupt handler for the shared memory WMD channel manager.
+ * Calls the WMD's CHNLSM_ISR to determine if this interrupt is ours, then
+ * schedules a DPC to dispatch I/O..
+ * Parameters:
+ * pRefData: Pointer to the channel manager object for this board.
+ * Set in an initial call to ISR_Install().
+ * Returns:
+ * TRUE if interrupt handled; FALSE otherwise.
+ * Requires:
+ * Must be in locked memory if executing in kernel mode.
+ * Must only call functions which are in locked memory if Kernel mode.
+ * Must only call asynchronous services.
+ * Interrupts are disabled and EOI for this interrupt has been sent.
+ * Ensures:
+ */
+ void IO_ISR (IN unsigned long int procId,
+ IN void * pRefData,
+ struct pt_regs *reg);
+
+/*
+ * ======== IO_RequestChnl ========
+ * Purpose:
+ * Request I/O from the DSP. Sets flags in shared memory, then interrupts
+ * the DSP.
+ * Parameters:
+ * hIOMgr: IO manager handle.
+ * pChnl: Ptr to the channel requesting I/O.
+ * iMode: Mode of channel: {IO_INPUT | IO_OUTPUT}.
+ * Returns:
+ * Requires:
+ * pChnl != NULL
+ * Ensures:
+ */
+ extern void IO_RequestChnl(struct IO_MGR *hIOMgr,
+ struct CHNL_OBJECT *pChnl,
+ u32 iMode, OUT u16 *pwMbVal);
+
+/*
+ * ======== IO_Schedule ========
+ * Purpose:
+ * Schedule DPC for IO.
+ * Parameters:
+ * pIOMgr: Ptr to a I/O manager.
+ * Returns:
+ * Requires:
+ * pChnl != NULL
+ * Ensures:
+ */
+ extern void IO_Schedule(struct IO_MGR *hIOMgr);
+
+/*
+ * DSP-DMA IO functions
+ */
+
+/*
+ * ======== IO_DDMAInitChnlDesc ========
+ * Purpose:
+ * Initialize DSP DMA channel descriptor.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * uDDMAChnlId: DDMA channel identifier.
+ * uNumDesc: Number of buffer descriptors(equals # of IOReqs &
+ * Chirps)
+ * pDsp: Dsp address;
+ * Returns:
+ * Requires:
+ * uDDMAChnlId < DDMA_MAXDDMACHNLS
+ * uNumDesc > 0
+ * pVa != NULL
+ * pDspPa != NULL
+ *
+ * Ensures:
+ */
+ extern void IO_DDMAInitChnlDesc(struct IO_MGR *hIOMgr, u32 uDDMAChnlId,
+ u32 uNumDesc, void *pDsp);
+
+/*
+ * ======== IO_DDMAClearChnlDesc ========
+ * Purpose:
+ * Clear DSP DMA channel descriptor.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * uDDMAChnlId: DDMA channel identifier.
+ * Returns:
+ * Requires:
+ * uDDMAChnlId < DDMA_MAXDDMACHNLS
+ * Ensures:
+ */
+ extern void IO_DDMAClearChnlDesc(struct IO_MGR *hIOMgr,
+ u32 uDDMAChnlId);
+
+/*
+ * ======== IO_DDMARequestChnl ========
+ * Purpose:
+ * Request channel DSP-DMA from the DSP. Sets up SM descriptors and
+ * control fields in shared memory.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * pChnl: Ptr to channel object
+ * pChirp: Ptr to channel i/o request packet.
+ * Returns:
+ * Requires:
+ * pChnl != NULL
+ * pChnl->cIOReqs > 0
+ * pChirp != NULL
+ * Ensures:
+ */
+ extern void IO_DDMARequestChnl(struct IO_MGR *hIOMgr,
+ struct CHNL_OBJECT *pChnl,
+ struct CHNL_IRP *pChirp,
+ OUT u16 *pwMbVal);
+
+/*
+ * Zero-copy IO functions
+ */
+
+/*
+ * ======== IO_DDZCInitChnlDesc ========
+ * Purpose:
+ * Initialize ZCPY channel descriptor.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * uZId: zero-copy channel identifier.
+ * Returns:
+ * Requires:
+ * uDDMAChnlId < DDMA_MAXZCPYCHNLS
+ * hIOMgr != Null
+ * Ensures:
+ */
+ extern void IO_DDZCInitChnlDesc(struct IO_MGR *hIOMgr, u32 uZId);
+
+/*
+ * ======== IO_DDZCClearChnlDesc ========
+ * Purpose:
+ * Clear DSP ZC channel descriptor.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * uChnlId: ZC channel identifier.
+ * Returns:
+ * Requires:
+ * hIOMgr is valid
+ * uChnlId < DDMA_MAXZCPYCHNLS
+ * Ensures:
+ */
+ extern void IO_DDZCClearChnlDesc(struct IO_MGR *hIOMgr, u32 uChnlId);
+
+/*
+ * ======== IO_DDZCRequestChnl ========
+ * Purpose:
+ * Request zero-copy channel transfer. Sets up SM descriptors and
+ * control fields in shared memory.
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * pChnl: Ptr to channel object
+ * pChirp: Ptr to channel i/o request packet.
+ * Returns:
+ * Requires:
+ * pChnl != NULL
+ * pChnl->cIOReqs > 0
+ * pChirp != NULL
+ * Ensures:
+ */
+ extern void IO_DDZCRequestChnl(struct IO_MGR *hIOMgr,
+ struct CHNL_OBJECT *pChnl,
+ struct CHNL_IRP *pChirp,
+ OUT u16 *pwMbVal);
+
+/*
+ * ======== IO_SHMsetting ========
+ * Purpose:
+ * Sets the shared memory setting
+ * Parameters:
+ * hIOMgr: Handle to a I/O manager.
+ * desc: Shared memory type
+ * pArgs: Ptr to SHM setting
+ * Returns:
+ * Requires:
+ * hIOMgr != NULL
+ * pArgs != NULL
+ * Ensures:
+ */
+ extern DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr,
+ IN enum SHM_DESCTYPE desc,
+ IN void *pArgs);
+
+/*
+ * Misc functions for the CHNL_IO shared memory library:
+ */
+
+/* Maximum channel bufsize that can be used. */
+ extern u32 IO_BufSize(struct IO_MGR *hIOMgr);
+
+ extern u32 IO_ReadValue(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr);
+
+ extern void IO_WriteValue(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr, u32 dwValue);
+
+ extern u32 IO_ReadValueLong(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr);
+
+ extern void IO_WriteValueLong(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr, u32 dwValue);
+
+ extern void IO_OrSetValue(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr, u32 dwValue);
+
+ extern void IO_AndSetValue(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr, u32 dwValue);
+
+ extern void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal);
+
+ extern void IO_SM_init(void);
+
+/*
+ * ========PrintDspTraceBuffer ========
+ * Print DSP tracebuffer.
+ */
+ extern DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT
+ *hWmdContext);
+
+#endif /* IOSM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/iodefs.h b/arch/arm/plat-omap/include/dspbridge/iodefs.h
new file mode 100644
index 000000000000..f45890a82c05
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/iodefs.h
@@ -0,0 +1,45 @@
+/*
+ * iodefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== iodefs.h ========
+ * Description:
+ * System-wide channel objects and constants.
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Nov-2000 jeh Created.
+ */
+
+#ifndef IODEFS_
+#define IODEFS_
+
+#define IO_MAXIRQ 0xff /* Arbitrarily large number. */
+
+/* IO Objects: */
+ struct IO_MGR;
+
+/* IO manager attributes: */
+ struct IO_ATTRS {
+ u8 bIRQ; /* Channel's I/O IRQ number. */
+ bool fShared; /* TRUE if the IRQ is shareable. */
+ u32 uWordSize; /* DSP Word size. */
+ u32 dwSMBase; /* Physical base address of shared memory. */
+ u32 uSMLength; /* Size (in bytes) of shared memory. */
+ } ;
+
+#endif /* IODEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/kfile.h b/arch/arm/plat-omap/include/dspbridge/kfile.h
new file mode 100644
index 000000000000..23c89b0d91a3
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/kfile.h
@@ -0,0 +1,216 @@
+/*
+ * kfile.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== kfile.h ========
+ * Purpose:
+ * Provide file I/O management capabilities.
+ *
+ * Public Functions:
+ * KFILE_Close
+ * KFILE_Exit
+ * KFILE_Init
+ * KFILE_Open
+ * KFILE_Read
+ * KFILE_Seek
+ * KFILE_Tell
+ * KFILE_Write
+ *
+ * Notes:
+ * The KFILE module is not like most of the other DSP/BIOS Bridge modules
+ * in that it doesn't return WSX_STATUS type values. Rather, it's
+ * prototypes are meant to match the stdio file prototypes
+ * (ie, fopen, fclose, etc.).
+ *
+ *! Revision History
+ *! ================
+ *! 29-Oct-1999 kc: Clean up for code review.
+ *! 07-Jan-1998 cr: Clean up for code review.
+ *! 15-Aug-1997 cr: Added E_KFILE_ERROR for general error condition.
+ *! 04-Aug-1997 cr: Added explicit CDECL descriptions.
+ *! 11-Nov-1996 cr: Implemented changes based on code review.
+ *! 05-Nov-1996 cr: Cleaned up for code review.
+ *! 29-May-1996 gp: Added requirement that size != 0 in _Write() and _Read().
+ *! 28-May-1996 mg: Changed return values for Read/Write.
+ *! 14-Dec-1995 cr: Created.
+ */
+
+#ifndef KFILE_
+#define KFILE_
+
+/*
+ * Constants for KFILE_Seek. Note that these MUST be the same definitions as
+ * those defined for fseek.
+ */
+#define KFILE_SEEK_SET 0x00 /* seek from beginning of file */
+#define KFILE_SEEK_CUR 0x01 /* seek from current position */
+#define KFILE_SEEK_END 0x02 /* seek from end of file */
+
+ struct KFILE_FileObj;
+
+/*
+ * ======== KFILE_Close ========
+ * Purpose:
+ * This function closes a file's stream.
+ * Parameters:
+ * hFile: Handle of the file stream returned by KFILE_Open.
+ * Returns:
+ * E_KFILE_INVALIDHANDLE: bad handle.
+ * 0: success.
+ * E_KFILE_ERROR: unable to close specified handle.
+ * Requires:
+ * KFILE initialized.
+ * Ensures:
+ */
+ extern s32 KFILE_Close(IN struct KFILE_FileObj *hFile);
+
+/*
+ * ======== KFILE_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * KFILE initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void KFILE_Exit(void);
+
+/*
+ * ======== KFILE_Init ========
+ * Purpose:
+ * Initializes private state of KFILE module.
+ * Parameters:
+ * Returns:
+ * TRUE if success, else FALSE.
+ * Requires:
+ * Ensures:
+ * KFILE initialized.
+ */
+ extern bool KFILE_Init(void);
+
+/*
+ * ======== KFILE_Open ========
+ * Purpose:
+ * Opens a file for use.
+ * Parameters:
+ * pszFileName: Full path to name of the file to open.
+ * pszMode: String containing open status. Only the first
+ * character of the string is examined, for either
+ * "r" (read) or "w" (write) mode.
+ * Returns:
+ * A valid file handle if success, else NULL.
+ * Requires:
+ * - KFILE initialized.
+ * - pszMode != NULL.
+ * - pszFileName != NULL.
+ * Ensures:
+ */
+ extern struct KFILE_FileObj *KFILE_Open(IN CONST char *filename,
+ IN CONST char *mode);
+
+/*
+ * ======== KFILE_Read ========
+ * Purpose:
+ * This function reads a specified number of bytes into a buffer.
+ * Parameters:
+ * pBuffer: Array to which the file data is copied.
+ * cSize: Number of characters in each object.
+ * cCount: Number of objects to read in.
+ * hFile: Handle of the file stream returned by KFILE_Open.
+ * Returns:
+ * E_KFILE_INVALIDHANDLE: bad file handle.
+ * E_KFILE_ERROR: general failure.
+ * > 0: success; # of objects read from file.
+ * Requires:
+ * KFILE initialized.
+ * pBuffer is a valid pointer.
+ * Ensures:
+ */
+ extern s32 KFILE_Read(OUT void __user*buffer,
+ IN s32 size, IN s32 count,
+ IN struct KFILE_FileObj *hFile);
+
+/*
+ * ======== KFILE_Seek ========
+ * Purpose:
+ * This function sets the file position indicator. NOTE: we don't
+ * support seeking beyond the boundaries of a file.
+ * Parameters:
+ * hFile: Handle of the file stream returned by KFILE_Open.
+ * offset: Number of bytes from the origin to move.
+ * origin: File reference point, one of the following values:
+ * KFILE_SEEK_SET: Seek from beginning of file.
+ * KFILE_SEEK_CUR: Seek from current position.
+ * KFILE_SEEK_END: Seek from end of file.
+ * Returns:
+ * 0: success.
+ * E_KFILE_INVALIDHANDLE: bad handle.
+ * E_KFILE_BADORIGIN: invalid origin paramater.
+ * E_KFILE_ERROR: general failure.
+ * Requires:
+ * KFILE initialized.
+ * Ensures:
+ */
+ extern s32 KFILE_Seek(IN struct KFILE_FileObj *hFile,
+ IN s32 offset, IN s32 origin);
+
+/*
+ * ======== KFILE_Tell ========
+ * Purpose:
+ * This function reports the current value of the position indicator.
+ * Parameters:
+ * hFile: Handle of the file stream returned by KFILE_Open.
+ * Return value:
+ * > 0: success; returns # of bytes the position indicator is from
+ * beginning of file.
+ * E_KFILE_ERROR: general failure.
+ * E_KFILE_INVALIDHANDLE: bad file handle.
+ * Requires:
+ * KFILE initialized.
+ * Ensures:
+ */
+ extern s32 KFILE_Tell(IN struct KFILE_FileObj *hFile);
+
+/*
+ * ======== KFILE_Write ========
+ * Purpose:
+ * This function writes a number of objects to the stream.
+ * Parameters:
+ * pBuffer: Array from which the file data is written.
+ * cSize: Number of characters in each object.
+ * cCount: Number of objects to write out.
+ * hFile: Handle of the file stream returned by KFILE_Open.
+ * Returns:
+ * E_KFILE_INVALIDHANDLE: bad file handle.
+ * E_KFILE_ERROR: general failure.
+ * > 0: success; # of objects written to file.
+ * Requires:
+ * KFILE initialized.
+ * pBuffer != NULL.
+ * Postcondition:
+ * The file position indicator is advanced by the number of
+ * characters written.
+ */
+ extern s32 KFILE_Write(OUT void *buffer,
+ IN s32 size,
+ IN s32 count,
+ IN struct KFILE_FileObj *hFile);
+
+#endif /* KFILE_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/ldr.h b/arch/arm/plat-omap/include/dspbridge/ldr.h
new file mode 100644
index 000000000000..7e13c936aa9c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/ldr.h
@@ -0,0 +1,51 @@
+/*
+ * ldr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== ldr.h ========
+ * Purpose:
+ * Provide module loading services and symbol export services.
+ *
+ * Public Functions:
+ * LDR_Exit
+ * LDR_FreeModule
+ * LDR_GetProcAddress
+ * LDR_Init
+ * LDR_LoadModule
+ *
+ * Notes:
+ * This service is meant to be used by modules of the DSP/BIOS Bridge
+ * class driver.
+ *
+ *! Revision History:
+ *! ================
+ *! 22-Nov-1999 kc: Changes from code review.
+ *! 12-Nov-1999 kc: Removed declaration of unused loader object.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 12-Jan-1998 cr: Cleaned up for code review.
+ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
+ *! 11-Nov-1996 cr: Cleaned up for code review.
+ *! 16-May-1996 gp: Created.
+ */
+
+#ifndef LDR_
+#define LDR_
+
+/* Loader objects: */
+ struct LDR_MODULE;
+
+#endif /* LDR_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/list.h b/arch/arm/plat-omap/include/dspbridge/list.h
new file mode 100644
index 000000000000..2e3f995b6a29
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/list.h
@@ -0,0 +1,296 @@
+/*
+ * list.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== list.h ========
+ * Purpose:
+ * Declarations of list management control structures and definitions
+ * of inline list management functions.
+ *
+ * Public Functions:
+ * LST_Create
+ * LST_Delete
+ * LST_Exit
+ * LST_First
+ * LST_GetHead
+ * LST_InitElem
+ * LST_Init
+ * LST_InsertBefore
+ * LST_IsEmpty
+ * LST_Next
+ * LST_PutTail
+ * LST_RemoveElem
+ *
+ * Notes:
+ *
+ *! Revision History
+ *! ================
+ *! 10-Aug-2000 ag: Added LST_InsertBefore().
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 16-Aug-1997 cr: added explicit identifiers.
+ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v.1.1; renamed identifiers.
+ *! 21-Oct-1994 dh4: Cleaned / commented for code review.
+ *! 08-Jun-1994 dh4: Converted to SPM (added extern "C").
+ */
+
+#ifndef LIST_
+#define LIST_
+
+#include <dspbridge/host_os.h>
+
+#define LST_IsEmpty(l) (((l)->head.next == &(l)->head))
+
+ struct LST_ELEM {
+ struct LST_ELEM *next;
+ struct LST_ELEM *prev;
+ struct LST_ELEM *self;
+ } ;
+
+ struct LST_LIST {
+ struct LST_ELEM head;
+ } ;
+
+/*
+ * ======== LST_Create ========
+ * Purpose:
+ * Allocates and initializes a circular list.
+ * Details:
+ * Uses portable MEM_Calloc() function to allocate a list containing
+ * a single element and initializes that element to indicate that it
+ * is the "end of the list" (i.e., the list is empty).
+ * An empty list is indicated by the "next" pointer in the element
+ * at the head of the list pointing to the head of the list, itself.
+ * Parameters:
+ * Returns:
+ * Pointer to beginning of created list (success)
+ * NULL --> Allocation failed
+ * Requires:
+ * LST initialized.
+ * Ensures:
+ * Notes:
+ * The created list contains a single element. This element is the
+ * "empty" element, because its "next" and "prev" pointers point at
+ * the same location (the element itself).
+ */
+ extern struct LST_LIST *LST_Create(void);
+
+/*
+ * ======== LST_Delete ========
+ * Purpose:
+ * Removes a list by freeing its control structure's memory space.
+ * Details:
+ * Uses portable MEM_Free() function to deallocate the memory
+ * block pointed at by the input parameter.
+ * Parameters:
+ * pList: Pointer to list control structure of list to be deleted
+ * Returns:
+ * Void
+ * Requires:
+ * - LST initialized.
+ * - pList != NULL.
+ * Ensures:
+ * Notes:
+ * Must ONLY be used for empty lists, because it does not walk the
+ * chain of list elements. Calling this function on a non-empty list
+ * will cause a memory leak.
+ */
+ extern void LST_Delete(IN struct LST_LIST *pList);
+
+/*
+ * ======== LST_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * LST initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void LST_Exit(void);
+
+/*
+ * ======== LST_First ========
+ * Purpose:
+ * Returns a pointer to the first element of the list, or NULL if the list
+ * is empty.
+ * Parameters:
+ * pList: Pointer to list control structure.
+ * Returns:
+ * Pointer to first list element, or NULL.
+ * Requires:
+ * - LST initialized.
+ * - pList != NULL.
+ * Ensures:
+ */
+ extern struct LST_ELEM *LST_First(IN struct LST_LIST *pList);
+
+/*
+ * ======== LST_GetHead ========
+ * Purpose:
+ * Pops the head off the list and returns a pointer to it.
+ * Details:
+ * If the list is empty, returns NULL.
+ * Else, removes the element at the head of the list, making the next
+ * element the head of the list.
+ * The head is removed by making the tail element of the list point its
+ * "next" pointer at the next element after the head, and by making the
+ * "prev" pointer of the next element after the head point at the tail
+ * element. So the next element after the head becomes the new head of
+ * the list.
+ * Parameters:
+ * pList: Pointer to list control structure of list whose head
+ * element is to be removed
+ * Returns:
+ * Pointer to element that was at the head of the list (success)
+ * NULL No elements in list
+ * Requires:
+ * - head.self must be correctly set to &head.
+ * - LST initialized.
+ * - pList != NULL.
+ * Ensures:
+ * Notes:
+ * Because the tail of the list points forward (its "next" pointer) to
+ * the head of the list, and the head of the list points backward (its
+ * "prev" pointer) to the tail of the list, this list is circular.
+ */
+ extern struct LST_ELEM *LST_GetHead(IN struct LST_LIST *pList);
+
+/*
+ * ======== LST_Init ========
+ * Purpose:
+ * Initializes private state of LST module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE otherwise.
+ * Requires:
+ * Ensures:
+ * LST initialized.
+ */
+ extern bool LST_Init(void);
+
+/*
+ * ======== LST_InitElem ========
+ * Purpose:
+ * Initializes a list element to default (cleared) values
+ * Details:
+ * Parameters:
+ * pElem: Pointer to list element to be reset
+ * Returns:
+ * Requires:
+ * LST initialized.
+ * Ensures:
+ * Notes:
+ * This function must not be called to "reset" an element in the middle
+ * of a list chain -- that would break the chain.
+ *
+ */
+ extern void LST_InitElem(IN struct LST_ELEM *pListElem);
+
+/*
+ * ======== LST_InsertBefore ========
+ * Purpose:
+ * Insert the element before the existing element.
+ * Parameters:
+ * pList: Pointer to list control structure.
+ * pElem: Pointer to element in list to insert.
+ * pElemExisting: Pointer to existing list element.
+ * Returns:
+ * Requires:
+ * - LST initialized.
+ * - pList != NULL.
+ * - pElem != NULL.
+ * - pElemExisting != NULL.
+ * Ensures:
+ */
+ extern void LST_InsertBefore(IN struct LST_LIST *pList,
+ IN struct LST_ELEM *pElem,
+ IN struct LST_ELEM *pElemExisting);
+
+/*
+ * ======== LST_Next ========
+ * Purpose:
+ * Returns a pointer to the next element of the list, or NULL if the next
+ * element is the head of the list or the list is empty.
+ * Parameters:
+ * pList: Pointer to list control structure.
+ * pCurElem: Pointer to element in list to remove.
+ * Returns:
+ * Pointer to list element, or NULL.
+ * Requires:
+ * - LST initialized.
+ * - pList != NULL.
+ * - pCurElem != NULL.
+ * Ensures:
+ */
+ extern struct LST_ELEM *LST_Next(IN struct LST_LIST *pList,
+ IN struct LST_ELEM *pCurElem);
+
+/*
+ * ======== LST_PutTail ========
+ * Purpose:
+ * Adds the specified element to the tail of the list
+ * Details:
+ * Sets new element's "prev" pointer to the address previously held by
+ * the head element's prev pointer. This is the previous tail member of
+ * the list.
+ * Sets the new head's prev pointer to the address of the element.
+ * Sets next pointer of the previous tail member of the list to point to
+ * the new element (rather than the head, which it had been pointing at).
+ * Sets new element's next pointer to the address of the head element.
+ * Sets head's prev pointer to the address of the new element.
+ * Parameters:
+ * pList: Pointer to list control structure to which *pElem will be
+ * added
+ * pElem: Pointer to list element to be added
+ * Returns:
+ * Void
+ * Requires:
+ * *pElem and *pList must both exist.
+ * pElem->self = pElem before pElem is passed to this function.
+ * LST initialized.
+ * Ensures:
+ * Notes:
+ * Because the tail is always "just before" the head of the list (the
+ * tail's "next" pointer points at the head of the list, and the head's
+ * "prev" pointer points at the tail of the list), the list is circular.
+ * Warning: if pElem->self is not set beforehand, LST_GetHead() will
+ * return an erroneous pointer when it is called for this element.
+ */
+ extern void LST_PutTail(IN struct LST_LIST *pList,
+ IN struct LST_ELEM *pListElem);
+
+/*
+ * ======== LST_RemoveElem ========
+ * Purpose:
+ * Removes (unlinks) the given element from the list, if the list is not
+ * empty. Does not free the list element.
+ * Parameters:
+ * pList: Pointer to list control structure.
+ * pCurElem: Pointer to element in list to remove.
+ * Returns:
+ * Requires:
+ * - LST initialized.
+ * - pList != NULL.
+ * - pCurElem != NULL.
+ * Ensures:
+ */
+extern void LST_RemoveElem(IN struct LST_LIST *pList,
+ IN struct LST_ELEM *pCurElem);
+
+#endif /* LIST_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/mbx_sh.h b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
new file mode 100644
index 000000000000..be0909e7c58c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
@@ -0,0 +1,213 @@
+/*
+ * mbx_sh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== mbx_sh.h ========
+ * Definitions for shared mailbox cmd/data values.(used on both
+ * the GPP and DSP sides).
+ *
+ * Bridge usage of OMAP mailbox 1 is determined by the "class" of the
+ * mailbox interrupt's cmd value received. The class value are defined
+ * as a bit (10 thru 15) being set.
+ *
+ * Note: Only 16 bits of each is used. Other 16 bit data reg available.
+ *
+ * 16 bit Mbx bit defns:
+ *
+ * A). Exception/Error handling (Module DEH) : class = 0.
+ *
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|0|0|0|0|x|x|x|x|x|x|x|x|x|x|
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ *
+ *
+ * B: DSP-DMA link driver channels (DDMA) : class = 1.
+ *
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|0|0|0|1|b|b|b|b|b|c|c|c|c|c|
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ * where b -> buffer index (32 DDMA buffers/chnl max)
+ * c -> channel Id (32 DDMA chnls max)
+ *
+ *
+ *
+ *
+ * C: Proc-copy link driver channels (PCPY) : class = 2.
+ *
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|0|0|1|0|x|x|x|x|x|x|x|x|x|x|
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ *
+ * D: Zero-copy link driver channels (DDZC) : class = 4.
+ *
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|0|1|0|0|x|x|x|x|x|c|c|c|c|c|
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ * where x -> not used
+ * c -> channel Id (32 ZCPY chnls max)
+ *
+ *
+ * E: Power management : class = 8.
+ *
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|1|0|0|0|x|x|x|x|x|c|c|c|c|c|
+
+ * 0010 00xx xxxc cccc
+ * 0010 00nn pppp qqqq
+ * nn:
+ * 00 = reserved
+ * 01 = pwr state change
+ * 10 = opp pre-change
+ * 11 = opp post-change
+ *
+ * if nn = pwr state change:
+ * pppp = don't care
+ * qqqq:
+ * 0010 = hibernate
+ * 0010 0001 0000 0010
+ * 0110 = retention
+ * 0010 0001 0000 0110
+ * others reserved
+ *
+ * if nn = opp pre-change:
+ * pppp = current opp
+ * qqqq = next opp
+ *
+ * if nn = opp post-change:
+ * pppp = prev opp
+ * qqqq = current opp
+ *
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ * where x -> not used
+ * c -> Power management command
+ *
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Sep-2002 mr Added DEH reset const
+ *! 24-Apr-2002 sg Added more PM commands.
+ *! 04-Mar-2002 gv Added MBX_PM_CLASS
+ *! 22-Jan-2002 ag Bug fix in MBX_SETZCPYVAL(x) macro.
+ *! 21-Dec-2001 ag Added bit masks defns.
+ *! 17-Dec-2001 ag: created.
+ */
+
+#ifndef _MBX_SH_H
+#define _MBX_SH_H
+
+#define MBX_CLASS_MSK 0xFC00 /* Class bits are 10 thru 15 */
+#define MBX_VALUE_MSK 0x03FF /* Value is 0 thru 9 */
+
+#define MBX_DEH_CLASS 0x0000 /* DEH owns Mbx INTR */
+#define MBX_DDMA_CLASS 0x0400 /* DSP-DMA link drvr chnls owns INTR */
+#define MBX_PCPY_CLASS 0x0800 /* PROC-COPY " */
+#define MBX_ZCPY_CLASS 0x1000 /* ZERO-COPY " */
+#define MBX_PM_CLASS 0x2000 /* Power Management */
+#define MBX_DBG_CLASS 0x4000 /* For debugging purpose */
+
+/*
+ * Exception Handler codes
+ * Magic code used to determine if DSP signaled exception.
+ */
+#define MBX_DEH_BASE 0x0
+#define MBX_DEH_USERS_BASE 0x100 /* 256 */
+#define MBX_DEH_LIMIT 0x3FF /* 1023 */
+#define MBX_DEH_RESET 0x101 /* DSP RESET (DEH) */
+#define MBX_DEH_EMMU 0X103 /*DSP MMU FAULT RECOVERY*/
+
+/*
+ * Link driver command/status codes.
+ */
+/* DSP-DMA */
+#define MBX_DDMA_NUMCHNLBITS 5 /* # chnl Id: # bits available */
+#define MBX_DDMA_CHNLSHIFT 0 /* # of bits to shift */
+#define MBX_DDMA_CHNLMSK 0x01F /* bits 0 thru 4 */
+
+#define MBX_DDMA_NUMBUFBITS 5 /* buffer index: # of bits avail */
+#define MBX_DDMA_BUFSHIFT (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
+#define MBX_DDMA_BUFMSK 0x3E0 /* bits 5 thru 9 */
+
+/* Zero-Copy */
+#define MBX_ZCPY_NUMCHNLBITS 5 /* # chnl Id: # bits available */
+#define MBX_ZCPY_CHNLSHIFT 0 /* # of bits to shift */
+#define MBX_ZCPY_CHNLMSK 0x01F /* bits 0 thru 4 */
+
+/* Power Management Commands */
+#define MBX_PM_DSPIDLE (MBX_PM_CLASS + 0x0)
+#define MBX_PM_DSPWAKEUP (MBX_PM_CLASS + 0x1)
+#define MBX_PM_EMERGENCYSLEEP (MBX_PM_CLASS + 0x2)
+#define MBX_PM_SLEEPUNTILRESTART (MBX_PM_CLASS + 0x3)
+#define MBX_PM_DSPGLOBALIDLE_OFF (MBX_PM_CLASS + 0x4)
+#define MBX_PM_DSPGLOBALIDLE_ON (MBX_PM_CLASS + 0x5)
+#define MBX_PM_SETPOINT_PRENOTIFY (MBX_PM_CLASS + 0x6)
+#define MBX_PM_SETPOINT_POSTNOTIFY (MBX_PM_CLASS + 0x7)
+#define MBX_PM_DSPRETN (MBX_PM_CLASS + 0x8)
+#define MBX_PM_DSPRETENTION (MBX_PM_CLASS + 0x8)
+#define MBX_PM_DSPHIBERNATE (MBX_PM_CLASS + 0x9)
+#define MBX_PM_HIBERNATE_EN (MBX_PM_CLASS + 0xA)
+#define MBX_PM_OPP_REQ (MBX_PM_CLASS + 0xB)
+#define MBX_PM_OPP_CHG (MBX_PM_CLASS + 0xC)
+
+#define MBX_PM_TYPE_MASK 0x0300
+#define MBX_PM_TYPE_PWR_CHNG 0x0100
+#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
+#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
+#define MBX_PM_TYPE_OPP_MASK 0x0300
+#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
+/* DSP to MPU */
+#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
+#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
+#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
+#define MBX_PM_OPP_1 0
+#define MBX_PM_OPP_2 1
+#define MBX_PM_OPP_3 2
+#define MBX_PM_OPP_4 3
+#define MBX_OLDOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
+#define MBX_NEWOPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
+#define MBX_PREVOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
+#define MBX_CUROPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
+
+/* Bridge Debug Commands */
+#define MBX_DBG_SYSPRINTF (MBX_DBG_CLASS + 0x0)
+
+/*
+ * Useful macros
+ */
+/* DSP-DMA channel */
+#define MBX_SETDDMAVAL(x, y) (MBX_DDMA_CLASS | (x << MBX_DDMA_BUFSHIFT) | \
+ (y << MBX_DDMA_CHNLSHIFT))
+
+/* Zero-Copy channel */
+#define MBX_SETZCPYVAL(x) (MBX_ZCPY_CLASS | (x << MBX_ZCPY_CHNLSHIFT))
+
+#endif /* _MBX_SH_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/mem.h b/arch/arm/plat-omap/include/dspbridge/mem.h
new file mode 100644
index 000000000000..535ac3ab03e0
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/mem.h
@@ -0,0 +1,340 @@
+/*
+ * mem.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== mem.h ========
+ * Purpose:
+ * Memory management and address mapping services for the DSP/BIOS Bridge
+ * class driver and mini-driver.
+ *
+ * Public Functions:
+ * MEM_Alloc
+ * MEM_AllocObject
+ * MEM_AllocPhysMem
+ * MEM_Calloc
+ * MEM_Exit
+ * MEM_FlushCache
+ * MEM_Free
+ * MEM_FreeObject
+ * MEM_FreePhysMem
+ * MEM_GetNumPages
+ * MEM_Init
+ * MEM_IsValidHandle
+ * MEM_LinearAddress
+ * MEM_PageLock
+ * MEM_PageUnlock
+ * MEM_UnMapLinearAddress
+ * MEM_VirtualToPhysical
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
+ *! 01-Sep-2001 ag: Cleaned up notes for MEM_LinearAddress() does not
+ *! require phys address to be page aligned!
+ *! 02-Dec-1999 rr: stdwin.h included for retail build
+ *! 12-Nov-1999 kc: Added warning about use of MEM_LinearAddress.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 10-Aug-1999 kc: Based on wsx-c18.
+ *! 07-Jan-1998 gp: Added MEM_AllocUMB and MEM_UMBFree for User Mapped Buffers
+ *! used by WMD_CHNL.
+ *! 23-Dec-1997 cr: Code review cleanup, removed dead Ring 3 code.
+ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
+ *! 01-Nov-1996 gp: Updated based on code review.
+ *! 04-Sep-1996 gp: Added MEM_PageLock() and MEM_PageUnlock() services.
+ *! 14-Aug-1996 mg: Added MEM_GetPhysAddr() and MEM_GetNumPages()
+ *! 25-Jul-1996 gp: Added MEM_IsValidHandle() macro.
+ *! 10-May-1996 gp: Added MEM_Calloc().
+ *! 25-Apr-1996 gp: Added MEM_PhysicalAddress()
+ *! 17-Apr-1996 gp: Added MEM_Exit function; updated to latest naming standard.
+ *! 08-Apr-1996 gp: Created.
+ */
+
+#ifndef MEM_
+#define MEM_
+
+#include <dspbridge/host_os.h>
+#include <dspbridge/memdefs.h>
+
+/*
+ * ======== MEM_Alloc ========
+ * Purpose:
+ * Allocate memory from the paged or non-paged pools.
+ * Parameters:
+ * cBytes: Number of bytes to allocate.
+ * type: Type of memory to allocate; one of:
+ * MEM_PAGED: Allocate from pageable memory.
+ * MEM_NONPAGED: Allocate from page locked memory.
+ * Returns:
+ * Pointer to a block of memory;
+ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
+ * not one of MEM_PAGED or MEM_NONPAGED.
+ * Requires:
+ * MEM initialized.
+ * Ensures:
+ * The returned pointer, if not NULL, points to a valid memory block of
+ * the size requested.
+ */
+ extern void *MEM_Alloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
+
+/*
+ * ======== MEM_AllocObject ========
+ * Purpose:
+ * Allocate an object, and set it's signature.
+ * Parameters:
+ * pObj: Pointer to the new object.
+ * Obj: Type of the object to allocate.
+ * Signature: Magic field value. Must be non-zero.
+ * Returns:
+ * Requires:
+ * Same requirements as MEM_Calloc(); and
+ * The object structure has a dwSignature field. The compiler ensures
+ * this requirement.
+ * Ensures:
+ * A subsequent call to MEM_IsValidHandle() will succeed for this object.
+ */
+#define MEM_AllocObject(pObj, Obj, Signature) \
+{ \
+ pObj = MEM_Calloc(sizeof(Obj), MEM_NONPAGED); \
+ if (pObj) { \
+ pObj->dwSignature = Signature; \
+ } \
+}
+
+/* ======== MEM_AllocPhysMem ========
+ * Purpose:
+ * Allocate physically contiguous, uncached memory
+ * Parameters:
+ * cBytes: Number of bytes to allocate.
+ * ulAlign: Alignment Mask.
+ * pPhysicalAddress: Physical address of allocated memory.
+ * Returns:
+ * Pointer to a block of memory;
+ * NULL if memory couldn't be allocated, or if cBytes == 0.
+ * Requires:
+ * MEM initialized.
+ * Ensures:
+ * The returned pointer, if not NULL, points to a valid memory block of
+ * the size requested. Returned physical address refers to physical
+ * location of memory.
+ */
+ extern void *MEM_AllocPhysMem(IN u32 cBytes,
+ IN u32 ulAlign,
+ OUT u32 *pPhysicalAddress);
+
+/*
+ * ======== MEM_Calloc ========
+ * Purpose:
+ * Allocate zero-initialized memory from the paged or non-paged pools.
+ * Parameters:
+ * cBytes: Number of bytes to allocate.
+ * type: Type of memory to allocate; one of:
+ * MEM_PAGED: Allocate from pageable memory.
+ * MEM_NONPAGED: Allocate from page locked memory.
+ * Returns:
+ * Pointer to a block of zeroed memory;
+ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
+ * not one of MEM_PAGED or MEM_NONPAGED.
+ * Requires:
+ * MEM initialized.
+ * Ensures:
+ * The returned pointer, if not NULL, points to a valid memory block
+ * of the size requested.
+ */
+ extern void *MEM_Calloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
+
+/*
+ * ======== MEM_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * MEM is initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void MEM_Exit(void);
+
+/*
+ * ======== MEM_FlushCache ========
+ * Purpose:
+ * Performs system cache sync with discard
+ * Parameters:
+ * pMemBuf: Pointer to memory region to be flushed.
+ * pMemBuf: Size of the memory region to be flushed.
+ * Returns:
+ * Requires:
+ * MEM is initialized.
+ * Ensures:
+ * Cache is synchronized
+ */
+ extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
+
+/*
+ * ======== MEM_Free ========
+ * Purpose:
+ * Free the given block of system memory.
+ * Parameters:
+ * pMemBuf: Pointer to memory allocated by MEM_Calloc/Alloc().
+ * Returns:
+ * Requires:
+ * MEM initialized.
+ * pMemBuf is a valid memory address returned by MEM_Calloc/Alloc().
+ * Ensures:
+ * pMemBuf is no longer a valid pointer to memory.
+ */
+ extern void MEM_Free(IN void *pMemBuf);
+
+/*
+ * ======== MEM_FreePhysMem ========
+ * Purpose:
+ * Free the given block of physically contiguous memory.
+ * Parameters:
+ * pVirtualAddress: Pointer to virtual memory region allocated
+ * by MEM_AllocPhysMem().
+ * pPhysicalAddress: Pointer to physical memory region allocated
+ * by MEM_AllocPhysMem().
+ * cBytes: Size of the memory region allocated by MEM_AllocPhysMem().
+ * Returns:
+ * Requires:
+ * MEM initialized.
+ * pVirtualAddress is a valid memory address returned by
+ * MEM_AllocPhysMem()
+ * Ensures:
+ * pVirtualAddress is no longer a valid pointer to memory.
+ */
+ extern void MEM_FreePhysMem(void *pVirtualAddress,
+ u32 pPhysicalAddress, u32 cBytes);
+
+/*
+ * ======== MEM_FreeObject ========
+ * Purpose:
+ * Utility macro to invalidate an object's signature, and deallocate it.
+ * Parameters:
+ * pObj: Pointer to the object to free.
+ * Returns:
+ * Requires:
+ * Same requirements as MEM_Free().
+ * Ensures:
+ * A subsequent call to MEM_IsValidHandle() will fail for this object.
+ */
+#define MEM_FreeObject(pObj) \
+{ \
+ pObj->dwSignature = 0x00; \
+ MEM_Free(pObj); \
+}
+
+/*
+ * ======== MEM_GetNumPages ========
+ * Purpose:
+ * Calculate the number of pages corresponding to the supplied buffer.
+ * Parameters:
+ * pAddr: Linear (virtual) address of the buffer.
+ * cBytes: Number of bytes in the buffer.
+ * Returns:
+ * Number of pages.
+ * Requires:
+ * MEM initialized.
+ * Ensures:
+ * If cBytes > 0, number of pages returned > 0.
+ */
+ extern s32 MEM_GetNumPages(IN void *pAddr, IN u32 cBytes);
+
+/*
+ * ======== MEM_Init ========
+ * Purpose:
+ * Initializes private state of MEM module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * MEM initialized.
+ */
+ extern bool MEM_Init(void);
+
+/*
+ * ======== MEM_IsValidHandle ========
+ * Purpose:
+ * Validate the object handle.
+ * Parameters:
+ * hObj: Handle to object created with MEM_AllocObject().
+ * Sig: Expected signature u32.
+ * Returns:
+ * TRUE if handle is valid; FALSE otherwise.
+ * Requires:
+ * The object structure has a dwSignature field. Ensured by compiler.
+ * Ensures:
+ */
+#define MEM_IsValidHandle(hObj, Sig) \
+ ((hObj != NULL) && (hObj->dwSignature == Sig))
+
+/*
+ * ======== MEM_LinearAddress ========
+ * Purpose:
+ * Get the linear address corresponding to the given physical address.
+ * Parameters:
+ * pPhysAddr: Physical address to be mapped.
+ * cBytes: Number of bytes in physical range to map.
+ * Returns:
+ * The corresponding linear address, or NULL if unsuccessful.
+ * Requires:
+ * MEM initialized.
+ * Ensures:
+ * Notes:
+ * If valid linear address is returned, be sure to call
+ * MEM_UnmapLinearAddress().
+ */
+#define MEM_LinearAddress(pPhyAddr, cBytes) pPhyAddr
+
+/*
+ * ======== MEM_UnmapLinearAddress ========
+ * Purpose:
+ * Unmap the linear address mapped in MEM_LinearAddress.
+ * Parameters:
+ * pBaseAddr: Ptr to mapped memory (as returned by MEM_LinearAddress()).
+ * Returns:
+ * Requires:
+ * - MEM initialized.
+ * - pBaseAddr is a valid linear address mapped in MEM_LinearAddress.
+ * Ensures:
+ * - pBaseAddr no longer points to a valid linear address.
+ */
+#define MEM_UnmapLinearAddress(pBaseAddr)
+
+/*
+ * ======== MEM_ExtPhysPoolInit ========
+ * Purpose:
+ * Uses the physical memory chunk passed for internal consitent memory
+ * allocations.
+ * physical address based on the page frame address.
+ * Parameters:
+ * poolPhysBase starting address of the physical memory pool.
+ * poolSize size of the physical memory pool.
+ * Returns:
+ * none.
+ * Requires:
+ * - MEM initialized.
+ * - valid physical address for the base and size > 0
+ */
+ extern void MEM_ExtPhysPoolInit(IN u32 poolPhysBase,
+ IN u32 poolSize);
+
+#endif /* MEM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/memdefs.h b/arch/arm/plat-omap/include/dspbridge/memdefs.h
new file mode 100644
index 000000000000..a5bb25915b77
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/memdefs.h
@@ -0,0 +1,52 @@
+/*
+ * memdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== memdefs.h ========
+ * Purpose:
+ * Global MEM constants and types, shared between WSX, WCD, and WMD.
+ *
+ *! Revision History:
+ *! ================
+ *! 28-Aug-2001 ag: Added MEM_[SET][GET]VIRTUALSEGID.
+ *! 10-Aug-1999 kc: Based on wsx-c18.
+ *! 15-Nov-1996 gp: Renamed from wsxmem.h and moved to kwinos.
+ *! 21-Aug-1996 cr: Created from mem.h.
+ */
+
+#ifndef MEMDEFS_
+#define MEMDEFS_
+
+/* Memory Pool Attributes: */
+ enum MEM_POOLATTRS {
+ MEM_PAGED = 0,
+ MEM_NONPAGED = 1,
+ MEM_LARGEVIRTMEM = 2
+ } ;
+
+/*
+ * MEM_VIRTUALSEGID is used by Node & Strm to access virtual address space in
+ * the correct client process context.
+ */
+#define MEM_SETVIRTUALSEGID 0x10000000
+#define MEM_GETVIRTUALSEGID 0x20000000
+#define MEM_MASKVIRTUALSEGID (MEM_SETVIRTUALSEGID | MEM_GETVIRTUALSEGID)
+
+#define TO_VIRTUAL_UNCACHED(x) x
+#define INTREG_TO_VIRTUAL_UNCACHED(x) x
+
+#endif /* MEMDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/mgr.h b/arch/arm/plat-omap/include/dspbridge/mgr.h
new file mode 100644
index 000000000000..24c4472ee4fa
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/mgr.h
@@ -0,0 +1,234 @@
+/*
+ * mgr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== mgr.h ========
+ * Description:
+ * This is the Class driver RM module interface.
+ *
+ * Public Functions:
+ * MGR_Create
+ * MGR_Destroy
+ * MGR_EnumNodeInfo
+ * MGR_EnumProcessorInfo
+ * MGR_Exit
+ * MGR_GetDCDHandle
+ * MGR_Init
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 15-Oct-2002 kc: Removed legacy PERF definitions.
+ *! 11-Jul-2001 jeh Added CFG_HDEVNODE parameter to MGR_Create().
+ *! 22-Nov-2000 kc: Added MGR_GetPerfData for acquiring PERF stats.
+ *! 03-Nov-2000 rr: Added MGR_GetDCDHandle. Modified after code review.
+ *! 25-Sep-2000 rr: Updated to Version 0.9
+ *! 14-Aug-2000 rr: Cleaned up.
+ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
+ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types).
+ *! 20-Jun-2000 rr: Created.
+ */
+
+#ifndef MGR_
+#define MGR_
+
+#include <dspbridge/mgrpriv.h>
+
+#define MAX_EVENTS 32
+
+/*
+ * ======== MGR_WaitForBridgeEvents ========
+ * Purpose:
+ * Block on any Bridge event(s)
+ * Parameters:
+ * aNotifications : array of pointers to notification objects.
+ * uCount : number of elements in above array
+ * puIndex : index of signaled event object
+ * uTimeout : timeout interval in milliseocnds
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_ETIMEOUT : Wait timed out. *puIndex is undetermined.
+ * Details:
+ */
+
+ DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION
+ **aNotifications,
+ u32 uCount, OUT u32 *puIndex,
+ u32 uTimeout);
+
+/*
+ * ======== MGR_Create ========
+ * Purpose:
+ * Creates the Manager Object. This is done during the driver loading.
+ * There is only one Manager Object in the DSP/BIOS Bridge.
+ * Parameters:
+ * phMgrObject: Location to store created MGR Object handle.
+ * hDevNode: Device object as known to Windows system.
+ * Returns:
+ * DSP_SOK: Success
+ * DSP_EMEMORY: Failed to Create the Object
+ * DSP_EFAIL: General Failure
+ * Requires:
+ * MGR Initialized (cRefs > 0 )
+ * phMgrObject != NULL.
+ * Ensures:
+ * DSP_SOK: *phMgrObject is a valid MGR interface to the device.
+ * MGR Object stores the DCD Manager Handle.
+ * MGR Object stored in the Regsitry.
+ * !DSP_SOK: MGR Object not created
+ * Details:
+ * DCD Dll is loaded and MGR Object stores the handle of the DLL.
+ */
+ extern DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **hMgrObject,
+ struct CFG_DEVNODE *hDevNode);
+
+/*
+ * ======== MGR_Destroy ========
+ * Purpose:
+ * Destroys the MGR object. Called upon driver unloading.
+ * Parameters:
+ * hMgrObject: Handle to Manager object .
+ * Returns:
+ * DSP_SOK: Success.
+ * DCD Manager freed; MGR Object destroyed;
+ * MGR Object deleted from the Registry.
+ * DSP_EFAIL: Failed to destroy MGR Object
+ * Requires:
+ * MGR Initialized (cRefs > 0 )
+ * hMgrObject is a valid MGR handle .
+ * Ensures:
+ * DSP_SOK: MGR Object destroyed and hMgrObject is Invalid MGR
+ * Handle.
+ */
+ extern DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject);
+
+/*
+ * ======== MGR_EnumNodeInfo ========
+ * Purpose:
+ * Enumerate and get configuration information about nodes configured
+ * in the node database.
+ * Parameters:
+ * uNode: The node index (base 0).
+ * pNDBProps: Ptr to the DSP_NDBPROPS structure for output.
+ * uNDBPropsSize: Size of the DSP_NDBPROPS structure.
+ * puNumNodes: Location where the number of nodes configured
+ * in the database will be returned.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EINVALIDARG: Parameter uNode is > than the number of nodes.
+ * configutred in the system
+ * DSP_ECHANGEDURINGENUM: During Enumeration there has been a change in
+ * the number of nodes configured or in the
+ * the properties of the enumerated nodes.
+ * DSP_EFAIL: Failed to querry the Node Data Base
+ * Requires:
+ * pNDBPROPS is not null
+ * uNDBPropsSize >= sizeof(DSP_NDBPROPS)
+ * puNumNodes is not null
+ * MGR Initialized (cRefs > 0 )
+ * Ensures:
+ * SUCCESS on successful retreival of data and *puNumNodes > 0 OR
+ * DSP_FAILED && *puNumNodes == 0.
+ * Details:
+ */
+ extern DSP_STATUS MGR_EnumNodeInfo(u32 uNode,
+ OUT struct DSP_NDBPROPS *pNDBProps,
+ u32 uNDBPropsSize,
+ OUT u32 *puNumNodes);
+
+/*
+ * ======== MGR_EnumProcessorInfo ========
+ * Purpose:
+ * Enumerate and get configuration information about available DSP
+ * processors
+ * Parameters:
+ * uProcessor: The processor index (zero-based).
+ * pProcessorInfo: Ptr to the DSP_PROCESSORINFO structure .
+ * uProcessorInfoSize: Size of DSP_PROCESSORINFO structure.
+ * puNumProcs: Location where the number of DSPs configured
+ * in the database will be returned
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EINVALIDARG: Parameter uProcessor is > than the number of
+ * DSP Processors in the system.
+ * DSP_EFAIL: Failed to querry the Node Data Base
+ * Requires:
+ * pProcessorInfo is not null
+ * puNumProcs is not null
+ * uProcessorInfoSize >= sizeof(DSP_PROCESSORINFO)
+ * MGR Initialized (cRefs > 0 )
+ * Ensures:
+ * SUCCESS on successful retreival of data and *puNumProcs > 0 OR
+ * DSP_FAILED && *puNumProcs == 0.
+ * Details:
+ */
+ extern DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
+ OUT struct DSP_PROCESSORINFO *
+ pProcessorInfo,
+ u32 uProcessorInfoSize,
+ OUT u32 *puNumProcs);
+/*
+ * ======== MGR_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * MGR is initialized.
+ * Ensures:
+ * When reference count == 0, MGR's private resources are freed.
+ */
+ extern void MGR_Exit(void);
+
+/*
+ * ======== MGR_GetDCDHandle ========
+ * Purpose:
+ * Retrieves the MGR handle. Accessor Function
+ * Parameters:
+ * hMGRHandle: Handle to the Manager Object
+ * phDCDHandle: Ptr to receive the DCD Handle.
+ * Returns:
+ * DSP_SOK: Sucess
+ * DSP_EFAIL: Failure to get the Handle
+ * Requires:
+ * MGR is initialized.
+ * phDCDHandle != NULL
+ * Ensures:
+ * DSP_SOK and *phDCDHandle != NULL ||
+ * DSP_EFAIL and *phDCDHandle == NULL
+ */
+ extern DSP_STATUS MGR_GetDCDHandle(IN struct MGR_OBJECT
+ *hMGRHandle,
+ OUT u32 *phDCDHandle);
+
+/*
+ * ======== MGR_Init ========
+ * Purpose:
+ * Initialize MGR's private state, keeping a reference count on each
+ * call. Intializes the DCD.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * TRUE: A requirement for the other public MGR functions.
+ */
+ extern bool MGR_Init(void);
+
+#endif /* MGR_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/mgrpriv.h b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
new file mode 100644
index 000000000000..4a34086e6cc7
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
@@ -0,0 +1,55 @@
+/*
+ * mgrpriv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== mgrpriv.h ========
+ * Description:
+ * Global MGR constants and types, shared by PROC, MGR, and WCD.
+ *
+ *! Revision History:
+ *! ================
+ *! 29-July-2001 ag: added MGR_PROCESSOREXTINFO.
+ *! 05-July-2000 rr: Created
+ */
+
+#ifndef MGRPRIV_
+#define MGRPRIV_
+
+/*
+ * OMAP1510 specific
+ */
+#define MGR_MAXTLBENTRIES 32
+
+/* RM MGR Object */
+ struct MGR_OBJECT;
+
+ struct MGR_TLBENTRY {
+ u32 ulDspVirt; /* DSP virtual address */
+ u32 ulGppPhys; /* GPP physical address */
+ } ;
+
+/*
+ * The DSP_PROCESSOREXTINFO structure describes additional extended
+ * capabilities of a DSP processor not exposed to user.
+ */
+ struct MGR_PROCESSOREXTINFO {
+ struct DSP_PROCESSORINFO tyBasic; /* user processor info */
+ /* private dsp mmu entries */
+ struct MGR_TLBENTRY tyTlb[MGR_MAXTLBENTRIES];
+ } ;
+
+#endif /* MGRPRIV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/msg.h b/arch/arm/plat-omap/include/dspbridge/msg.h
new file mode 100644
index 000000000000..f2872cc68ae0
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/msg.h
@@ -0,0 +1,106 @@
+/*
+ * msg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== msg.h ========
+ * Description:
+ * DSP/BIOS Bridge MSG Module.
+ *
+ * Public Functions:
+ * MSG_Create
+ * MSG_Delete
+ * MSG_Exit
+ * MSG_Init
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! =================
+ *! 17-Nov-2000 jeh Removed MSG_Get, MSG_Put, MSG_CreateQueue,
+ *! MSG_DeleteQueue, and MSG_RegisterNotify, since these
+ *! are now part of mini-driver.
+ *! 12-Sep-2000 jeh Created.
+ */
+
+#ifndef MSG_
+#define MSG_
+
+#include <dspbridge/devdefs.h>
+#include <dspbridge/msgdefs.h>
+
+/*
+ * ======== MSG_Create ========
+ * Purpose:
+ * Create an object to manage message queues. Only one of these objects
+ * can exist per device object. The MSG manager must be created before
+ * the IO Manager.
+ * Parameters:
+ * phMsgMgr: Location to store MSG manager handle on output.
+ * hDevObject: The device object.
+ * msgCallback: Called whenever an RMS_EXIT message is received.
+ * Returns:
+ * Requires:
+ * MSG_Init(void) called.
+ * phMsgMgr != NULL.
+ * hDevObject != NULL.
+ * msgCallback != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
+ struct DEV_OBJECT *hDevObject,
+ MSG_ONEXIT msgCallback);
+
+/*
+ * ======== MSG_Delete ========
+ * Purpose:
+ * Delete a MSG manager allocated in MSG_Create().
+ * Parameters:
+ * hMsgMgr: Handle returned from MSG_Create().
+ * Returns:
+ * Requires:
+ * MSG_Init(void) called.
+ * Valid hMsgMgr.
+ * Ensures:
+ */
+ extern void MSG_Delete(struct MSG_MGR *hMsgMgr);
+
+/*
+ * ======== MSG_Exit ========
+ * Purpose:
+ * Discontinue usage of MSG module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * MSG_Init(void) successfully called before.
+ * Ensures:
+ * Any resources acquired in MSG_Init(void) will be freed when last MSG
+ * client calls MSG_Exit(void).
+ */
+ extern void MSG_Exit(void);
+
+/*
+ * ======== MSG_Init ========
+ * Purpose:
+ * Initialize the MSG module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Ensures:
+ */
+ extern bool MSG_Init(void);
+
+#endif /* MSG_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/msgdefs.h b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
new file mode 100644
index 000000000000..8ea4551abddd
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
@@ -0,0 +1,43 @@
+/*
+ * msgdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== msgdefs.h ========
+ * Description:
+ * Global MSG constants and types.
+ *
+ *! Revision History
+ *! ================
+ *! 09-May-2001 jeh Removed MSG_TODSP, MSG_FROMDSP.
+ *! 17-Nov-2000 jeh Added MSGMGR_SIGNATURE.
+ *! 12-Sep-2000 jeh Created.
+ */
+
+#ifndef MSGDEFS_
+#define MSGDEFS_
+
+#define MSGMGR_SIGNATURE 0x4d47534d /* "MGSM" */
+
+/* MSG Objects: */
+ struct MSG_MGR;
+ struct MSG_QUEUE;
+
+/* Function prototype for callback to be called on RMS_EXIT message received */
+ typedef void(*MSG_ONEXIT) (HANDLE h, s32 nStatus);
+
+#endif /* MSGDEFS_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/nldr.h b/arch/arm/plat-omap/include/dspbridge/nldr.h
new file mode 100644
index 000000000000..09158469bdbf
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/nldr.h
@@ -0,0 +1,81 @@
+/*
+ * nldr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== nldr.h ========
+ *
+ * Description:
+ * DSP/BIOS Bridge dynamic loader interface. See the file dldrdefs.h
+ * for a description of these functions.
+ *
+ * Public Functions:
+ * NLDR_Allocate
+ * NLDR_Create
+ * NLDR_Delete
+ * NLDR_Exit
+ * NLDR_Free
+ * NLDR_GetFxnAddr
+ * NLDR_Init
+ * NLDR_Load
+ * NLDR_Unload
+ *
+ * Notes:
+ *
+ *! Revision History
+ *! ================
+ *! 31-Jul-2002 jeh Removed function header comments.
+ *! 17-Apr-2002 jeh Created.
+ */
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/dbdcddef.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/rmm.h>
+#include <dspbridge/nldrdefs.h>
+
+#ifndef NLDR_
+#define NLDR_
+
+ extern DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr,
+ void *pPrivRef,
+ IN CONST struct DCD_NODEPROPS
+ *pNodeProps,
+ OUT struct NLDR_NODEOBJECT **phNldrNode,
+ IN bool *pfPhaseSplit);
+
+ extern DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct NLDR_ATTRS *pAttrs);
+
+ extern void NLDR_Delete(struct NLDR_OBJECT *hNldr);
+ extern void NLDR_Exit(void);
+ extern void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode);
+
+ extern DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode,
+ char *pstrFxn, u32 *pulAddr);
+
+ extern DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
+ OUT struct RMM_TargetObj
+ **phRmmMgr);
+
+ extern bool NLDR_Init(void);
+ extern DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+ extern DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+
+#endif /* NLDR_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/nldrdefs.h b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
new file mode 100644
index 000000000000..84b36a387263
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
@@ -0,0 +1,307 @@
+/*
+ * nldrdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== nldrdefs.h ========
+ * Description:
+ * Global Dynamic + static/overlay Node loader (NLDR) constants and types.
+ *
+ *! Revision History
+ *! ================
+ *! 07-Apr-2003 map Consolidated dldrdefs.h into nldrdefs.h
+ *! 05-Aug-2002 jeh Created.
+ */
+
+#ifndef NLDRDEFS_
+#define NLDRDEFS_
+
+#include <dspbridge/dbdcddef.h>
+#include <dspbridge/devdefs.h>
+
+#define NLDR_MAXPATHLENGTH 255
+/* NLDR Objects: */
+ struct NLDR_OBJECT;
+ struct NLDR_NODEOBJECT;
+
+/*
+ * ======== NLDR_LOADTYPE ========
+ * Load types for a node. Must match values in node.h55.
+ */
+ enum NLDR_LOADTYPE {
+ NLDR_STATICLOAD, /* Linked in base image, not overlay */
+ NLDR_DYNAMICLOAD, /* Dynamically loaded node */
+ NLDR_OVLYLOAD /* Linked in base image, overlay node */
+ } ;
+
+/*
+ * ======== NLDR_OVLYFXN ========
+ * Causes code or data to be copied from load address to run address. This
+ * is the "COD_WRITEFXN" that gets passed to the DBLL_Library and is used as
+ * the ZL write function.
+ *
+ * Parameters:
+ * pPrivRef: Handle to identify the node.
+ * ulDspRunAddr: Run address of code or data.
+ * ulDspLoadAddr: Load address of code or data.
+ * ulNumBytes: Number of (GPP) bytes to copy.
+ * nMemSpace: RMS_CODE or RMS_DATA.
+ * Returns:
+ * ulNumBytes: Success.
+ * 0: Failure.
+ * Requires:
+ * Ensures:
+ */
+ typedef u32(*NLDR_OVLYFXN) (void *pPrivRef, u32 ulDspRunAddr,
+ u32 ulDspLoadAddr,
+ u32 ulNumBytes, u32 nMemSpace);
+
+/*
+ * ======== NLDR_WRITEFXN ========
+ * Write memory function. Used for dynamic load writes.
+ * Parameters:
+ * pPrivRef: Handle to identify the node.
+ * ulDspAddr: Address of code or data.
+ * pBuf: Code or data to be written
+ * ulNumBytes: Number of (GPP) bytes to write.
+ * nMemSpace: DBLL_DATA or DBLL_CODE.
+ * Returns:
+ * ulNumBytes: Success.
+ * 0: Failure.
+ * Requires:
+ * Ensures:
+ */
+ typedef u32(*NLDR_WRITEFXN) (void *pPrivRef,
+ u32 ulDspAddr, void *pBuf,
+ u32 ulNumBytes, u32 nMemSpace);
+
+/*
+ * ======== NLDR_ATTRS ========
+ * Attributes passed to NLDR_Create function.
+ */
+ struct NLDR_ATTRS {
+ NLDR_OVLYFXN pfnOvly;
+ NLDR_WRITEFXN pfnWrite;
+ u16 usDSPWordSize;
+ u16 usDSPMauSize;
+ } ;
+
+/*
+ * ======== NLDR_PHASE ========
+ * Indicates node create, delete, or execute phase function.
+ */
+ enum NLDR_PHASE {
+ NLDR_CREATE,
+ NLDR_DELETE,
+ NLDR_EXECUTE,
+ NLDR_NOPHASE
+ } ;
+
+/*
+ * Typedefs of loader functions imported from a DLL, or defined in a
+ * function table.
+ */
+
+/*
+ * ======== NLDR_Allocate ========
+ * Allocate resources to manage the loading of a node on the DSP.
+ *
+ * Parameters:
+ * hNldr: Handle of loader that will load the node.
+ * pPrivRef: Handle to identify the node.
+ * pNodeProps: Pointer to a DCD_NODEPROPS for the node.
+ * phNldrNode: Location to store node handle on output. This handle
+ * will be passed to NLDR_Load/NLDR_Unload.
+ * pfPhaseSplit: pointer to boolean variable referenced in node.c
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldr.
+ * pNodeProps != NULL.
+ * phNldrNode != NULL.
+ * Ensures:
+ * DSP_SOK: IsValidNode(*phNldrNode).
+ * error: *phNldrNode == NULL.
+ */
+ typedef DSP_STATUS(*NLDR_ALLOCATEFXN) (struct NLDR_OBJECT *hNldr,
+ void *pPrivRef,
+ IN CONST struct DCD_NODEPROPS
+ *pNodeProps,
+ OUT struct NLDR_NODEOBJECT
+ **phNldrNode,
+ OUT bool *pfPhaseSplit);
+
+/*
+ * ======== NLDR_Create ========
+ * Create a loader object. This object handles the loading and unloading of
+ * create, delete, and execute phase functions of nodes on the DSP target.
+ *
+ * Parameters:
+ * phNldr: Location to store loader handle on output.
+ * hDevObject: Device for this processor.
+ * pAttrs: Loader attributes.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * Requires:
+ * NLDR_Init(void) called.
+ * phNldr != NULL.
+ * hDevObject != NULL.
+ * pAttrs != NULL.
+ * Ensures:
+ * DSP_SOK: Valid *phNldr.
+ * error: *phNldr == NULL.
+ */
+ typedef DSP_STATUS(*NLDR_CREATEFXN) (OUT struct NLDR_OBJECT **phNldr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct NLDR_ATTRS
+ *pAttrs);
+
+/*
+ * ======== NLDR_Delete ========
+ * Delete the NLDR loader.
+ *
+ * Parameters:
+ * hNldr: Node manager object.
+ * Returns:
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldr.
+ * Ensures:
+ * hNldr invalid
+ */
+ typedef void(*NLDR_DELETEFXN) (struct NLDR_OBJECT *hNldr);
+
+/*
+ * ======== NLDR_Exit ========
+ * Discontinue usage of NLDR module.
+ *
+ * Parameters:
+ * Returns:
+ * Requires:
+ * NLDR_Init(void) successfully called before.
+ * Ensures:
+ * Any resources acquired in NLDR_Init(void) will be freed when last NLDR
+ * client calls NLDR_Exit(void).
+ */
+ typedef void(*NLDR_EXITFXN) (void);
+
+/*
+ * ======== NLDR_Free ========
+ * Free resources allocated in NLDR_Allocate.
+ *
+ * Parameters:
+ * hNldrNode: Handle returned from NLDR_Allocate().
+ * Returns:
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldrNode.
+ * Ensures:
+ */
+ typedef void(*NLDR_FREEFXN) (struct NLDR_NODEOBJECT *hNldrNode);
+
+/*
+ * ======== NLDR_GetFxnAddr ========
+ * Get address of create, delete, or execute phase function of a node on
+ * the DSP.
+ *
+ * Parameters:
+ * hNldrNode: Handle returned from NLDR_Allocate().
+ * pstrFxn: Name of function.
+ * pulAddr: Location to store function address.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ESYMBOL: Address of function not found.
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldrNode.
+ * pulAddr != NULL;
+ * pstrFxn != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*NLDR_GETFXNADDRFXN) (struct NLDR_NODEOBJECT
+ *hNldrNode,
+ char *pstrFxn, u32 *pulAddr);
+
+/*
+ * ======== NLDR_Init ========
+ * Initialize the NLDR module.
+ *
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Ensures:
+ */
+ typedef bool(*NLDR_INITFXN) (void);
+
+/*
+ * ======== NLDR_Load ========
+ * Load create, delete, or execute phase function of a node on the DSP.
+ *
+ * Parameters:
+ * hNldrNode: Handle returned from NLDR_Allocate().
+ * phase: Type of function to load (create, delete, or execute).
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * DSP_EOVERLAYMEMORY: Can't overlay phase because overlay memory
+ * is already in use.
+ * DSP_EDYNLOAD: Failure in dynamic loader library.
+ * DSP_EFWRITE: Failed to write phase's code or date to target.
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldrNode.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*NLDR_LOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+
+/*
+ * ======== NLDR_Unload ========
+ * Unload create, delete, or execute phase function of a node on the DSP.
+ *
+ * Parameters:
+ * hNldrNode: Handle returned from NLDR_Allocate().
+ * phase: Node function to unload (create, delete, or execute).
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * Requires:
+ * NLDR_Init(void) called.
+ * Valid hNldrNode.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*NLDR_UNLOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+
+/*
+ * ======== NLDR_FXNS ========
+ */
+ struct NLDR_FXNS {
+ NLDR_ALLOCATEFXN pfnAllocate;
+ NLDR_CREATEFXN pfnCreate;
+ NLDR_DELETEFXN pfnDelete;
+ NLDR_EXITFXN pfnExit;
+ NLDR_FREEFXN pfnFree;
+ NLDR_GETFXNADDRFXN pfnGetFxnAddr;
+ NLDR_INITFXN pfnInit;
+ NLDR_LOADFXN pfnLoad;
+ NLDR_UNLOADFXN pfnUnload;
+ } ;
+
+#endif /* NLDRDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/node.h b/arch/arm/plat-omap/include/dspbridge/node.h
new file mode 100644
index 000000000000..d253962b348a
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/node.h
@@ -0,0 +1,619 @@
+/*
+ * node.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== node.h ========
+ * Description:
+ * DSP/BIOS Bridge Node Manager.
+ *
+ * Public Functions:
+ * NODE_Allocate
+ * NODE_AllocMsgBuf
+ * NODE_ChangePriority
+ * NODE_Connect
+ * NODE_Create
+ * NODE_CreateMgr
+ * NODE_Delete
+ * NODE_DeleteMgr
+ * NODE_EnumNodes
+ * NODE_Exit
+ * NODE_FreeMsgBuf
+ * NODE_GetAttr
+ * NODE_GetMessage
+ * NODE_GetProcessor
+ * NODE_Init
+ * NODE_OnExit
+ * NODE_Pause
+ * NODE_PutMessage
+ * NODE_RegisterNotify
+ * NODE_Run
+ * NODE_Terminate
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! =================
+ *! 23-Apr-2001 jeh Updated with code review changes.
+ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID to return codes.
+ *! 17-Nov-2000 jeh Added NODE_OnExit().
+ *! 27-Oct-2000 jeh Added timeouts to NODE_GetMessage, NODE_PutMessage.
+ *! 12-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Removed
+ *! NODE_RegisterAllNodes().
+ *! 07-Sep-2000 jeh Changed type HANDLE in NODE_RegisterNotify to
+ *! DSP_HNOTIFICATION. Added DSP_STRMATTR param to
+ *! NODE_Connect(). Removed NODE_GetMessageStream().
+ *! 17-Jul-2000 jeh Updated function header descriptions.
+ *! 19-Jun-2000 jeh Created.
+ */
+
+#ifndef NODE_
+#define NODE_
+
+#include <dspbridge/procpriv.h>
+
+#include <dspbridge/nodedefs.h>
+#include <dspbridge/dispdefs.h>
+#include <dspbridge/nldrdefs.h>
+
+/*
+ * ======== NODE_Allocate ========
+ * Purpose:
+ * Allocate GPP resources to manage a node on the DSP.
+ * Parameters:
+ * hProcessor: Handle of processor that is allocating the node.
+ * pNodeId: Pointer to a DSP_UUID for the node.
+ * pArgs: Optional arguments to be passed to the node.
+ * pAttrIn: Optional pointer to node attributes (priority,
+ * timeout...)
+ * phNode: Location to store node handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * DSP_EUUID: Node UUID has not been registered.
+ * DSP_ESYMBOL: iAlg functions not found for a DAIS node.
+ * DSP_ERANGE: pAttrIn != NULL and pAttrIn->iPriority out of
+ * range.
+ * DSP_EFAIL: A failure occured, unable to allocate node.
+ * DSP_EWRONGSTATE: Proccessor is not in the running state.
+ * Requires:
+ * NODE_Init(void) called.
+ * hProcessor != NULL.
+ * pNodeId != NULL.
+ * phNode != NULL.
+ * Ensures:
+ * DSP_SOK: IsValidNode(*phNode).
+ * error: *phNode == NULL.
+ */
+ extern DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
+ IN CONST struct DSP_UUID *pNodeId,
+ OPTIONAL IN CONST struct DSP_CBDATA
+ *pArgs,
+ OPTIONAL IN CONST struct DSP_NODEATTRIN
+ *pAttrIn,
+ OUT struct NODE_OBJECT **phNode);
+
+/*
+ * ======== NODE_AllocMsgBuf ========
+ * Purpose:
+ * Allocate and Prepare a buffer whose descriptor will be passed to a
+ * Node within a (DSP_MSG)message
+ * Parameters:
+ * hNode: The node handle.
+ * uSize: The size of the buffer to be allocated.
+ * pAttr: Pointer to a DSP_BUFFERATTR structure.
+ * pBuffer: Location to store the address of the allocated
+ * buffer on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid node handle.
+ * DSP_EMEMORY: Insufficent memory.
+ * DSP_EFAIL: General Failure.
+ * DSP_ESIZE: Invalid Size.
+ * Requires:
+ * NODE_Init(void) called.
+ * pBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_AllocMsgBuf(struct NODE_OBJECT *hNode,
+ u32 uSize,
+ OPTIONAL struct DSP_BUFFERATTR
+ *pAttr,
+ OUT u8 **pBuffer);
+
+/*
+ * ======== NODE_ChangePriority ========
+ * Purpose:
+ * Change the priority of an allocated node.
+ * Parameters:
+ * hNode: Node handle returned from NODE_Allocate.
+ * nPriority: New priority level to set node's priority to.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ERANGE: nPriority is out of range.
+ * DSP_ENODETYPE: The specified node is not a task node.
+ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED, NODE_PAUSED,
+ * or NODE_RUNNING state.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_ERESTART: A critical error has occurred and the DSP is
+ * being restarted.
+ * DSP_EFAIL: Unable to change node's runtime priority level.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ * DSP_SOK && (Node's current priority == nPriority)
+ */
+ extern DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode,
+ s32 nPriority);
+
+/*
+ * ======== NODE_CloseOrphans ========
+ * Purpose:
+ * Delete all nodes whose owning processor is being destroyed.
+ * Parameters:
+ * hNodeMgr: Node manager object.
+ * hProc: Handle to processor object being destroyed.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Unable to delete all nodes belonging to hProc.
+ * Requires:
+ * Valid hNodeMgr.
+ * hProc != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_CloseOrphans(struct NODE_MGR *hNodeMgr,
+ struct PROC_OBJECT *hProc);
+
+/*
+ * ======== NODE_Connect ========
+ * Purpose:
+ * Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
+ * case that the connnection is being made between a node on the DSP and
+ * the GPP, one of the node handles (either hNode1 or hNode2) must be
+ * the constant NODE_HGPPNODE.
+ * Parameters:
+ * hNode1: Handle of first node to connect to second node. If
+ * this is a connection from the GPP to hNode2, hNode1
+ * must be the constant NODE_HGPPNODE. Otherwise, hNode1
+ * must be a node handle returned from a successful call
+ * to Node_Allocate().
+ * hNode2: Handle of second node. Must be either NODE_HGPPNODE
+ * if this is a connection from DSP node to GPP, or a
+ * node handle returned from a successful call to
+ * NODE_Allocate().
+ * uStream1: Output stream index on first node, to be connected
+ * to second node's input stream. Value must range from
+ * 0 <= uStream1 < number of output streams.
+ * uStream2: Input stream index on second node. Value must range
+ * from 0 <= uStream2 < number of input streams.
+ * pAttrs: Stream attributes (NULL ==> use defaults).
+ * pConnParam: A pointer to a DSP_CBDATA structure that defines
+ * connection parameter for device nodes to pass to DSP
+ * side.
+ * If the value of this parameter is NULL, then this API
+ * behaves like DSPNode_Connect. This parameter will have
+ * length of the string and the null terminated string in
+ * DSP_CBDATA struct. This can be extended in future tp
+ * pass binary data.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode1 or hNode2.
+ * DSP_EMEMORY: Insufficient host memory.
+ * DSP_EVALUE: A stream index parameter is invalid.
+ * DSP_EALREADYCONNECTED: A connection already exists for one of the
+ * indices uStream1 or uStream2.
+ * DSP_EWRONGSTATE: Either hNode1 or hNode2 is not in the
+ * NODE_ALLOCATED state.
+ * DSP_ENOMORECONNECTIONS: No more connections available.
+ * DSP_EFAIL: Attempt to make an illegal connection (eg,
+ * Device node to device node, or device node to
+ * GPP), the two nodes are on different DSPs.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1,
+ u32 uStream1,
+ struct NODE_OBJECT *hNode2,
+ u32 uStream2,
+ OPTIONAL IN struct DSP_STRMATTR *pAttrs,
+ OPTIONAL IN struct DSP_CBDATA
+ *pConnParam);
+
+/*
+ * ======== NODE_Create ========
+ * Purpose:
+ * Create a node on the DSP by remotely calling the node's create
+ * function. If necessary, load code that contains the node's create
+ * function.
+ * Parameters:
+ * hNode: Node handle returned from NODE_Allocate().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ESYMBOL: Create function not found in the COFF file.
+ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED state.
+ * DSP_EMEMORY: Memory allocation failure on the DSP.
+ * DSP_ETASK: Unable to create node's task or process on the DSP.
+ * DSP_ESTREAM: Stream creation failure on the DSP.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_EUSER1-16: A user-defined failure occurred on the DSP.
+ * DSP_EFAIL: A failure occurred, unable to create node.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== NODE_CreateMgr ========
+ * Purpose:
+ * Create a NODE Manager object. This object handles the creation,
+ * deletion, and execution of nodes on the DSP target. The NODE Manager
+ * also maintains a pipe map of used and available node connections.
+ * Each DEV object should have exactly one NODE Manager object.
+ *
+ * Parameters:
+ * phNodeMgr: Location to store node manager handle on output.
+ * hDevObject: Device for this processor.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * NODE_Init(void) called.
+ * phNodeMgr != NULL.
+ * hDevObject != NULL.
+ * Ensures:
+ * DSP_SOK: Valide *phNodeMgr.
+ * error: *phNodeMgr == NULL.
+ */
+ extern DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
+ struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== NODE_Delete ========
+ * Purpose:
+ * Delete resources allocated in NODE_Allocate(). If the node was
+ * created, delete the node on the DSP by remotely calling the node's
+ * delete function. Loads the node's delete function if necessary.
+ * GPP side resources are freed after node's delete function returns.
+ * Parameters:
+ * hNode: Node handle returned from NODE_Allocate().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_EDELETE: A deletion failure occurred.
+ * DSP_EUSER1-16: Node specific failure occurred on the DSP.
+ * DSP_EFAIL: A failure occurred in deleting the node.
+ * DSP_ESYMBOL: Delete function not found in the COFF file.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ * DSP_SOK: hNode is invalid.
+ */
+ extern DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== NODE_DeleteMgr ========
+ * Purpose:
+ * Delete the NODE Manager.
+ * Parameters:
+ * hNodeMgr: Node manager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * Requires:
+ * NODE_Init(void) called.
+ * Valid hNodeMgr.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr);
+
+/*
+ * ======== NODE_EnumNodes ========
+ * Purpose:
+ * Enumerate the nodes currently allocated for the DSP.
+ * Parameters:
+ * hNodeMgr: Node manager returned from NODE_CreateMgr().
+ * aNodeTab: Array to copy node handles into.
+ * uNodeTabSize: Number of handles that can be written to aNodeTab.
+ * puNumNodes: Location where number of node handles written to
+ * aNodeTab will be written.
+ * puAllocated: Location to write total number of allocated nodes.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ESIZE: aNodeTab is too small to hold all node handles.
+ * Requires:
+ * Valid hNodeMgr.
+ * aNodeTab != NULL || uNodeTabSize == 0.
+ * puNumNodes != NULL.
+ * puAllocated != NULL.
+ * Ensures:
+ * - (DSP_ESIZE && *puNumNodes == 0)
+ * - || (DSP_SOK && *puNumNodes <= uNodeTabSize) &&
+ * (*puAllocated == *puNumNodes)
+ */
+ extern DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr,
+ IN DSP_HNODE *aNodeTab,
+ u32 uNodeTabSize,
+ OUT u32 *puNumNodes,
+ OUT u32 *puAllocated);
+
+/*
+ * ======== NODE_Exit ========
+ * Purpose:
+ * Discontinue usage of NODE module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * NODE_Init(void) successfully called before.
+ * Ensures:
+ * Any resources acquired in NODE_Init(void) will be freed when last NODE
+ * client calls NODE_Exit(void).
+ */
+ extern void NODE_Exit(void);
+
+/*
+ * ======== NODE_FreeMsgBuf ========
+ * Purpose:
+ * Free a message buffer previously allocated with NODE_AllocMsgBuf.
+ * Parameters:
+ * hNode: The node handle.
+ * pBuffer: (Address) Buffer allocated by NODE_AllocMsgBuf.
+ * pAttr: Same buffer attributes passed to NODE_AllocMsgBuf.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid node handle.
+ * DSP_EFAIL: Failure to free the buffer.
+ * Requires:
+ * NODE_Init(void) called.
+ * pBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode,
+ IN u8 *pBuffer,
+ OPTIONAL struct DSP_BUFFERATTR
+ *pAttr);
+
+/*
+ * ======== NODE_GetAttr ========
+ * Purpose:
+ * Copy the current attributes of the specified node into a DSP_NODEATTR
+ * structure.
+ * Parameters:
+ * hNode: Node object allocated from NODE_Allocate().
+ * pAttr: Pointer to DSP_NODEATTR structure to copy node's
+ * attributes.
+ * uAttrSize: Size of pAttr.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * Requires:
+ * NODE_Init(void) called.
+ * pAttr != NULL.
+ * Ensures:
+ * DSP_SOK: *pAttrs contains the node's current attributes.
+ */
+ extern DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
+ OUT struct DSP_NODEATTR *pAttr,
+ u32 uAttrSize);
+
+/*
+ * ======== NODE_GetMessage ========
+ * Purpose:
+ * Retrieve a message from a node on the DSP. The node must be either a
+ * message node, task node, or XDAIS socket node.
+ * If a message is not available, this function will block until a
+ * message is available, or the node's timeout value is reached.
+ * Parameters:
+ * hNode: Node handle returned from NODE_Allocate().
+ * pMessage: Pointer to DSP_MSG structure to copy the
+ * message into.
+ * uTimeout: Timeout in milliseconds to wait for message.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ENODETYPE: Cannot retrieve messages from this type of node.
+ * DSP_ETIMEOUT: Timeout occurred and no message is available.
+ * DSP_EFAIL: Error occurred while trying to retrieve a message.
+ * Requires:
+ * NODE_Init(void) called.
+ * pMessage != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode,
+ OUT struct DSP_MSG *pMessage,
+ u32 uTimeout);
+
+/*
+ * ======== NODE_GetNldrObj ========
+ * Purpose:
+ * Retrieve the Nldr manager
+ * Parameters:
+ * hNodeMgr: Node Manager
+ * phNldrObj: Pointer to a Nldr manager handle
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
+ OUT struct NLDR_OBJECT **phNldrObj);
+
+/*
+ * ======== NODE_Init ========
+ * Purpose:
+ * Initialize the NODE module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Ensures:
+ */
+ extern bool NODE_Init(void);
+
+/*
+ * ======== NODE_OnExit ========
+ * Purpose:
+ * Gets called when RMS_EXIT is received for a node. PROC needs to pass
+ * this function as a parameter to MSG_Create(). This function then gets
+ * called by the mini-driver when an exit message for a node is received.
+ * Parameters:
+ * hNode: Handle of the node that the exit message is for.
+ * nStatus: Return status of the node's execute phase.
+ * Returns:
+ * Ensures:
+ */
+ void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus);
+
+/*
+ * ======== NODE_Pause ========
+ * Purpose:
+ * Suspend execution of a node currently running on the DSP.
+ * Parameters:
+ * hNode: Node object representing a node currently
+ * running on the DSP.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ENODETYPE: Node is not a task or socket node.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_EWRONGSTSATE: Node is not in NODE_RUNNING state.
+ * DSP_EFAIL: Failed to pause node.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== NODE_PutMessage ========
+ * Purpose:
+ * Send a message to a message node, task node, or XDAIS socket node.
+ * This function will block until the message stream can accommodate
+ * the message, or a timeout occurs. The message will be copied, so Msg
+ * can be re-used immediately after return.
+ * Parameters:
+ * hNode: Node handle returned by NODE_Allocate().
+ * pMsg: Location of message to be sent to the node.
+ * uTimeout: Timeout in msecs to wait.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ENODETYPE: Messages can't be sent to this type of node.
+ * DSP_ETIMEOUT: Timeout occurred before message could be set.
+ * DSP_EWRONGSTATE: Node is in invalid state for sending messages.
+ * DSP_EFAIL: Unable to send message.
+ * Requires:
+ * NODE_Init(void) called.
+ * pMsg != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
+ IN CONST struct DSP_MSG *pMsg,
+ u32 uTimeout);
+
+/*
+ * ======== NODE_RegisterNotify ========
+ * Purpose:
+ * Register to be notified on specific events for this node.
+ * Parameters:
+ * hNode: Node handle returned by NODE_Allocate().
+ * uEventMask: Mask of types of events to be notified about.
+ * uNotifyType: Type of notification to be sent.
+ * hNotification: Handle to be used for notification.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * DSP_EVALUE: uEventMask is invalid.
+ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
+ * supported.
+ * Requires:
+ * NODE_Init(void) called.
+ * hNotification != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode,
+ u32 uEventMask, u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+/*
+ * ======== NODE_Run ========
+ * Purpose:
+ * Start execution of a node's execute phase, or resume execution of
+ * a node that has been suspended (via NODE_Pause()) on the DSP. Load
+ * the node's execute function if necessary.
+ * Parameters:
+ * hNode: Node object representing a node currently
+ * running on the DSP.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ENODETYPE: hNode doesn't represent a message, task or dais
+ * socket node.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_EWRONGSTSATE: Node is not in NODE_PAUSED or NODE_CREATED state.
+ * DSP_EFAIL: Unable to start or resume execution.
+ * DSP_ESYMBOL: Execute function not found in the COFF file.
+ * Requires:
+ * NODE_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== NODE_Terminate ========
+ * Purpose:
+ * Signal a node running on the DSP that it should exit its execute
+ * phase function.
+ * Parameters:
+ * hNode: Node object representing a node currently
+ * running on the DSP.
+ * pStatus: Location to store execute-phase function return
+ * value (DSP_EUSER1-16).
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
+ * DSP_ENODETYPE: Type of node specified cannot be terminated.
+ * DSP_EWRONGSTATE: Operation not valid for the current node state.
+ * DSP_EFAIL: Unable to terminate the node.
+ * Requires:
+ * NODE_Init(void) called.
+ * pStatus != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode,
+ OUT DSP_STATUS *pStatus);
+
+
+
+/*
+ * ======== NODE_GetUUIDProps ========
+ * Purpose:
+ * Fetch Node properties given the UUID
+ * Parameters:
+ *
+ */
+ extern DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
+ IN CONST struct DSP_UUID *pNodeId,
+ OUT struct DSP_NDBPROPS
+ *pNodeProps);
+
+#endif /* NODE_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/nodedefs.h b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
new file mode 100644
index 000000000000..cdc0c4bf8c96
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
@@ -0,0 +1,40 @@
+/*
+ * nodedefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== nodedefs.h ========
+ * Description:
+ * Global NODE constants and types, shared by PROCESSOR, NODE, and DISP.
+ *
+ *! Revision History
+ *! ================
+ *! 23-Apr-2001 jeh Removed NODE_MGRATTRS.
+ *! 21-Sep-2000 jeh Removed NODE_TYPE enum.
+ *! 17-Jul-2000 jeh Changed order of node types to match rms_sh.h.
+ *! 20-Jun-2000 jeh Created.
+ */
+
+#ifndef NODEDEFS_
+#define NODEDEFS_
+
+#define NODE_SUSPENDEDPRI -1
+
+/* NODE Objects: */
+ struct NODE_MGR;
+ struct NODE_OBJECT;
+
+#endif /* NODEDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/nodepriv.h b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
new file mode 100644
index 000000000000..d28b29b15d61
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
@@ -0,0 +1,202 @@
+/*
+ * nodepriv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== nodepriv.h ========
+ * Description:
+ * Private node header shared by NODE and DISP.
+ *
+ * Public Functions:
+ * NODE_GetChannelId
+ * NODE_GetStrmMgr
+ * NODE_GetTimeout
+ * NODE_GetType
+ * NODE_GetLoadType
+ *
+ *! Revision History
+ *! ================
+ *! 19-Nov-2002 map Added NODE_GetLoadType
+ *! 13-Feb-2002 jeh Added uSysStackSize to NODE_TASKARGS.
+ *! 23-Apr-2001 jeh Removed unused typedefs, defines.
+ *! 10-Oct-2000 jeh Added alignment to NODE_STRMDEF.
+ *! 20-Jun-2000 jeh Created.
+ */
+
+#ifndef NODEPRIV_
+#define NODEPRIV_
+
+#include <dspbridge/strmdefs.h>
+#include <dspbridge/nodedefs.h>
+#include <dspbridge/nldrdefs.h>
+
+/* DSP address of node environment structure */
+ typedef u32 NODE_ENV;
+
+/*
+ * Node create structures
+ */
+
+/* Message node */
+ struct NODE_MSGARGS {
+ u32 uMaxMessages; /* Max # of simultaneous messages for node */
+ u32 uSegid; /* Segment for allocating message buffers */
+ u32 uNotifyType; /* Notify type (SEM_post, SWI_post, etc.) */
+ u32 uArgLength; /* Length in 32-bit words of arg data block */
+ u8 *pData; /* Argument data for node */
+ } ;
+
+ struct NODE_STRMDEF {
+ u32 uBufsize; /* Size of buffers for SIO stream */
+ u32 uNumBufs; /* max # of buffers in SIO stream at once */
+ u32 uSegid; /* Memory segment id to allocate buffers */
+ u32 uTimeout; /* Timeout for blocking SIO calls */
+ u32 uAlignment; /* Buffer alignment */
+ char *szDevice; /* Device name for stream */
+ } ;
+
+/* Task node */
+ struct NODE_TASKARGS {
+ struct NODE_MSGARGS msgArgs;
+ s32 nPriority;
+ u32 uStackSize;
+ u32 uSysStackSize;
+ u32 uStackSeg;
+ u32 uDSPHeapResAddr; /* DSP virtual heap address */
+ u32 uDSPHeapAddr; /* DSP virtual heap address */
+ u32 uHeapSize; /* Heap size */
+ u32 uGPPHeapAddr; /* GPP virtual heap address */
+ u32 uProfileID; /* Profile ID */
+ u32 uNumInputs;
+ u32 uNumOutputs;
+ u32 ulDaisArg; /* Address of iAlg object */
+ struct NODE_STRMDEF *strmInDef;
+ struct NODE_STRMDEF *strmOutDef;
+ } ;
+
+/*
+ * ======== NODE_CREATEARGS ========
+ */
+ struct NODE_CREATEARGS {
+ union {
+ struct NODE_MSGARGS msgArgs;
+ struct NODE_TASKARGS taskArgs;
+ } asa;
+ } ;
+
+/*
+ * ======== NODE_GetChannelId ========
+ * Purpose:
+ * Get the channel index reserved for a stream connection between the
+ * host and a node. This index is reserved when NODE_Connect() is called
+ * to connect the node with the host. This index should be passed to
+ * the CHNL_Open function when the stream is actually opened.
+ * Parameters:
+ * hNode: Node object allocated from NODE_Allocate().
+ * uDir: Input (DSP_TONODE) or output (DSP_FROMNODE).
+ * uIndex: Stream index.
+ * pulId: Location to store channel index.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_ENODETYPE: Not a task or DAIS socket node.
+ * DSP_EVALUE: The node's stream corresponding to uIndex and uDir
+ * is not a stream to or from the host.
+ * Requires:
+ * NODE_Init(void) called.
+ * Valid uDir.
+ * pulId != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode,
+ u32 uDir,
+ u32 uIndex, OUT u32 *pulId);
+
+/*
+ * ======== NODE_GetStrmMgr ========
+ * Purpose:
+ * Get the STRM manager for a node.
+ * Parameters:
+ * hNode: Node allocated with NODE_Allocate().
+ * phStrmMgr: Location to store STRM manager on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * Requires:
+ * phStrmMgr != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
+ struct STRM_MGR **phStrmMgr);
+
+/*
+ * ======== NODE_GetTimeout ========
+ * Purpose:
+ * Get the timeout value of a node.
+ * Parameters:
+ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
+ * Returns:
+ * Node's timeout value.
+ * Requires:
+ * Valid hNode.
+ * Ensures:
+ */
+ extern u32 NODE_GetTimeout(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== NODE_GetType ========
+ * Purpose:
+ * Get the type (device, message, task, or XDAIS socket) of a node.
+ * Parameters:
+ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
+ * Returns:
+ * Node type: NODE_DEVICE, NODE_TASK, NODE_XDAIS, or NODE_GPP.
+ * Requires:
+ * Valid hNode.
+ * Ensures:
+ */
+ extern enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode);
+
+/*
+ * ======== GetNodeInfo ========
+ * Purpose:
+ * Get node information without holding semaphore.
+ * Parameters:
+ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
+ * Returns:
+ * Node info: priority, device owner, no. of streams, execution state
+ * NDB properties.
+ * Requires:
+ * Valid hNode.
+ * Ensures:
+ */
+ extern void GetNodeInfo(struct NODE_OBJECT *hNode,
+ struct DSP_NODEINFO *pNodeInfo);
+
+/*
+ * ======== NODE_GetLoadType ========
+ * Purpose:
+ * Get the load type (dynamic, overlay, static) of a node.
+ * Parameters:
+ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
+ * Returns:
+ * Node type: NLDR_DYNAMICLOAD, NLDR_OVLYLOAD, NLDR_STATICLOAD
+ * Requires:
+ * Valid hNode.
+ * Ensures:
+ */
+ extern enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode);
+
+#endif /* NODEPRIV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
new file mode 100644
index 000000000000..5a0992abc7e0
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
@@ -0,0 +1,146 @@
+/*
+ * ntfy.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== ntfy.h ========
+ * Purpose:
+ * Manage lists of notification events.
+ *
+ * Public Functions:
+ * NTFY_Create
+ * NTFY_Delete
+ * NTFY_Exit
+ * NTFY_Init
+ * NTFY_Notify
+ * NTFY_Register
+ *
+ *! Revision History:
+ *! =================
+ *! 05-Nov-2001 kc: Updated NTFY_Register.
+ *! 07-Sep-2000 jeh Created.
+ */
+
+#ifndef NTFY_
+#define NTFY_
+
+ struct NTFY_OBJECT;
+
+/*
+ * ======== NTFY_Create ========
+ * Purpose:
+ * Create an empty list of notifications.
+ * Parameters:
+ * phNtfy: Location to store handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * Requires:
+ * NTFY_Init(void) called.
+ * phNtfy != NULL.
+ * Ensures:
+ * DSP_SUCCEEDED(status) <==> IsValid(*phNtfy).
+ */
+ extern DSP_STATUS NTFY_Create(OUT struct NTFY_OBJECT **phNtfy);
+
+/*
+ * ======== NTFY_Delete ========
+ * Purpose:
+ * Free resources allocated in NTFY_Create.
+ * Parameters:
+ * hNtfy: Handle returned from NTFY_Create().
+ * Returns:
+ * Requires:
+ * NTFY_Init(void) called.
+ * IsValid(hNtfy).
+ * Ensures:
+ */
+ extern void NTFY_Delete(IN struct NTFY_OBJECT *hNtfy);
+
+/*
+ * ======== NTFY_Exit ========
+ * Purpose:
+ * Discontinue usage of NTFY module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * NTFY_Init(void) successfully called before.
+ * Ensures:
+ */
+ extern void NTFY_Exit(void);
+
+/*
+ * ======== NTFY_Init ========
+ * Purpose:
+ * Initialize the NTFY module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Ensures:
+ */
+ extern bool NTFY_Init(void);
+
+/*
+ * ======== NTFY_Notify ========
+ * Purpose:
+ * Execute notify function (signal event or post message) for every
+ * element in the notification list that is to be notified about the
+ * event specified in uEventMask.
+ * Parameters:
+ * hNtfy: Handle returned from NTFY_Create().
+ * uEventMask: The type of event that has occurred.
+ * Returns:
+ * Requires:
+ * NTFY_Init(void) called.
+ * IsValid(hNtfy).
+ * Ensures:
+ */
+ extern void NTFY_Notify(IN struct NTFY_OBJECT *hNtfy,
+ IN u32 uEventMask);
+
+/*
+ * ======== NTFY_Register ========
+ * Purpose:
+ * Add a notification element to the list. If the notification is already
+ * registered, and uEventMask != 0, the notification will get posted for
+ * events specified in the new event mask. If the notification is already
+ * registered and uEventMask == 0, the notification will be unregistered.
+ * Parameters:
+ * hNtfy: Handle returned from NTFY_Create().
+ * hNotification: Handle to a DSP_NOTIFICATION object.
+ * uEventMask: Events to be notified about.
+ * uNotifyType: Type of notification: DSP_SIGNALEVENT.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory.
+ * DSP_EVALUE: uEventMask is 0 and hNotification was not
+ * previously registered.
+ * DSP_EHANDLE: NULL hNotification, hNotification event name
+ * too long, or hNotification event name NULL.
+ * Requires:
+ * NTFY_Init(void) called.
+ * IsValid(hNtfy).
+ * hNotification != NULL.
+ * uNotifyType is DSP_SIGNALEVENT
+ * Ensures:
+ */
+ extern DSP_STATUS NTFY_Register(IN struct NTFY_OBJECT *hNtfy,
+ IN struct DSP_NOTIFICATION
+ *hNotification,
+ IN u32 uEventMask,
+ IN u32 uNotifyType);
+
+#endif /* NTFY_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/proc.h b/arch/arm/plat-omap/include/dspbridge/proc.h
new file mode 100644
index 000000000000..486652e944e7
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/proc.h
@@ -0,0 +1,648 @@
+/*
+ * proc.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== proc.h ========
+ * Description:
+ * This is the Class driver RM module interface.
+ *
+ * Public Functions:
+ * PROC_Attach
+ * PROC_Create
+ * PROC_Ctrl (OEM-function)
+ * PROC_Destroy
+ * PROC_Detach
+ * PROC_EnumNodes
+ * PROC_Exit
+ * PROC_FlushMemory
+ * PROC_GetDevObject (OEM-function)
+ * PROC_GetResourceInfo
+ * PROC_GetState
+ * PROC_GetProcessorId
+ * PROC_GetTrace (OEM-function)
+ * PROC_Init
+ * PROC_Load (OEM-function)
+ * PROC_Map
+ * PROC_NotifyAllclients
+ * PROC_NotifyClients (OEM-function)
+ * PROC_RegisterNotify
+ * PROC_ReserveMemory
+ * PROC_Start (OEM-function)
+ * PROC_UnMap
+ * PROC_UnReserveMemory
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
+ *! 09-Feb-2003 vp: Added PROC_GetProcessorID function
+ *! 29-Nov-2000 rr: Incorporated code review changes.
+ *! 28-Sep-2000 rr: Updated to Version 0.9.
+ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
+ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types). GetTrace added.
+ *! 27-Jun-2000 rr: Created from dspapi.h
+ */
+
+#ifndef PROC_
+#define PROC_
+
+#include <dspbridge/cfgdefs.h>
+#include <dspbridge/devdefs.h>
+
+/*
+ * ======== PROC_Attach ========
+ * Purpose:
+ * Prepare for communication with a particular DSP processor, and return
+ * a handle to the processor object. The PROC Object gets created
+ * Parameters:
+ * uProcessor : The processor index (zero-based).
+ * hMgrObject : Handle to the Manager Object
+ * pAttrIn : Ptr to the DSP_PROCESSORATTRIN structure.
+ * A NULL value means use default values.
+ * phProcessor : Ptr to location to store processor handle.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EFAIL : General failure.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_SALREADYATTACHED: Success; Processor already attached.
+ * Requires:
+ * phProcessor != NULL.
+ * PROC Initialized.
+ * Ensures:
+ * DSP_EFAIL, and *phProcessor == NULL, OR
+ * Success and *phProcessor is a Valid Processor handle OR
+ * DSP_SALREADYATTACHED and *phProcessor is a Valid Processor.
+ * Details:
+ * When pAttrIn is NULL, the default timeout value is 10 seconds.
+ */
+ extern DSP_STATUS PROC_Attach(u32 uProcessor,
+ OPTIONAL CONST struct DSP_PROCESSORATTRIN
+ *pAttrIn,
+ OUT DSP_HPROCESSOR *phProcessor);
+
+/*
+ * ======== PROC_AutoStart =========
+ * Purpose:
+ * A Particular device gets loaded with the default image
+ * if the AutoStart flag is set.
+ * Parameters:
+ * hDevObject : Handle to the Device
+ * Returns:
+ * DSP_SOK : On Successful Loading
+ * DSP_EFILE : No DSP exec file found.
+ * DSP_EFAIL : General Failure
+ * Requires:
+ * hDevObject != NULL.
+ * hDevNode != NULL.
+ * PROC Initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
+ struct DEV_OBJECT *hDevObject);
+
+/*
+ * ======== PROC_Ctrl ========
+ * Purpose:
+ * Pass control information to the GPP device driver managing the DSP
+ * processor. This will be an OEM-only function, and not part of the
+ * 'Bridge application developer's API.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * dwCmd : Private driver IOCTL cmd ID.
+ * pArgs : Ptr to an driver defined argument structure.
+ * Returns:
+ * DSP_SOK : SUCCESS
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_ETIMEOUT: A Timeout Occured before the Control information
+ * could be sent.
+ * DSP_EACCESSDENIED: Client does not have the access rights required
+ * to call this function.
+ * DSP_ERESTART: A Critical error has occured and the DSP is being
+ * restarted.
+ * DSP_EFAIL : General Failure.
+ * Requires:
+ * PROC Initialized.
+ * Ensures
+ * Details:
+ * This function Calls WMD_BRD_Ioctl.
+ */
+ extern DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor,
+ u32 dwCmd, IN struct DSP_CBDATA *pArgs);
+
+/*
+ * ======== PROC_Detach ========
+ * Purpose:
+ * Close a DSP processor and de-allocate all (GPP) resources reserved
+ * for it. The Processor Object is deleted.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : InValid Handle.
+ * DSP_EFAIL : General failure.
+ * Requires:
+ * PROC Initialized.
+ * Ensures:
+ * PROC Object is destroyed.
+ */
+ extern DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor);
+
+/*
+ * ======== PROC_EnumNodes ========
+ * Purpose:
+ * Enumerate the nodes currently allocated on a processor.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * aNodeTab : The first Location of an array allocated for node
+ * handles.
+ * uNodeTabSize: The number of (DSP_HNODE) handles that can be held
+ * to the memory the client has allocated for aNodeTab
+ * puNumNodes : Location where DSPProcessor_EnumNodes will return
+ * the number of valid handles written to aNodeTab
+ * puAllocated : Location where DSPProcessor_EnumNodes will return
+ * the number of nodes that are allocated on the DSP.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_ESIZE : The amount of memory allocated for aNodeTab is
+ * insufficent. That is the number of nodes actually
+ * allocated on the DSP is greater than the value
+ * specified for uNodeTabSize.
+ * DSP_EFAIL : Unable to get Resource Information.
+ * Details:
+ * Requires
+ * puNumNodes is not NULL.
+ * puAllocated is not NULL.
+ * aNodeTab is not NULL.
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor,
+ IN DSP_HNODE *aNodeTab,
+ IN u32 uNodeTabSize,
+ OUT u32 *puNumNodes,
+ OUT u32 *puAllocated);
+
+/*
+ * ======== PROC_GetResourceInfo ========
+ * Purpose:
+ * Enumerate the resources currently available on a processor.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * uResourceType: Type of resource .
+ * pResourceInfo: Ptr to the DSP_RESOURCEINFO structure.
+ * uResourceInfoSize: Size of the structure.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EWRONGSTATE: The processor is not in the PROC_RUNNING state.
+ * DSP_ETIMEOUT: A timeout occured before the DSP responded to the
+ * querry.
+ * DSP_ERESTART: A Critical error has occured and the DSP is being
+ * restarted.
+ * DSP_EFAIL : Unable to get Resource Information
+ * Requires:
+ * pResourceInfo is not NULL.
+ * Parameter uResourceType is Valid.[TBD]
+ * uResourceInfoSize is >= sizeof DSP_RESOURCEINFO struct.
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ * This function currently returns
+ * DSP_ENOTIMPL, and does not write any data to the pResourceInfo struct.
+ */
+ extern DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor,
+ u32 uResourceType,
+ OUT struct DSP_RESOURCEINFO *
+ pResourceInfo,
+ u32 uResourceInfoSize);
+
+/*
+ * ======== PROC_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * PROC is initialized.
+ * Ensures:
+ * When reference count == 0, PROC's private resources are freed.
+ */
+ extern void PROC_Exit(void);
+
+/*
+ * ======== PROC_GetDevObject =========
+ * Purpose:
+ * Returns the DEV Hanlde for a given Processor handle
+ * Parameters:
+ * hProcessor : Processor Handle
+ * phDevObject : Location to store the DEV Handle.
+ * Returns:
+ * DSP_SOK : Success; *phDevObject has Dev handle
+ * DSP_EFAIL : Failure; *phDevObject is zero.
+ * Requires:
+ * phDevObject is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * DSP_SOK : *phDevObject is not NULL
+ * DSP_EFAIL : *phDevObject is NULL.
+ */
+ extern DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
+ struct DEV_OBJECT **phDevObject);
+
+/*
+ * ======== PROC_Init ========
+ * Purpose:
+ * Initialize PROC's private state, keeping a reference count on each
+ * call.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * TRUE: A requirement for the other public PROC functions.
+ */
+ extern bool PROC_Init(void);
+
+/*
+ * ======== PROC_GetState ========
+ * Purpose:
+ * Report the state of the specified DSP processor.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pProcStatus : Ptr to location to store the DSP_PROCESSORSTATE
+ * structure.
+ * uStateInfoSize: Size of DSP_PROCESSORSTATE.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure while querying processor state.
+ * Requires:
+ * pProcStatus is not NULL
+ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
+ OUT struct DSP_PROCESSORSTATE
+ *pProcStatus,
+ u32 uStateInfoSize);
+
+/*
+ * ======== PROC_GetProcessorID ========
+ * Purpose:
+ * Report the state of the specified DSP processor.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * procID : Processor ID
+ *
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure while querying processor state.
+ * Requires:
+ * pProcStatus is not NULL
+ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProcessor,
+ u32 *procID);
+
+/*
+ * ======== PROC_GetTrace ========
+ * Purpose:
+ * Retrieve the trace buffer from the specified DSP processor.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pBuf : Ptr to buffer to hold trace output.
+ * uMaxSize : Maximum size of the output buffer.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure while retireving processor trace
+ * Buffer.
+ * Requires:
+ * pBuf is not NULL
+ * uMaxSize is > 0.
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf,
+ u32 uMaxSize);
+
+/*
+ * ======== PROC_Load ========
+ * Purpose:
+ * Reset a processor and load a new base program image.
+ * This will be an OEM-only function.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * iArgc : The number of Arguments(strings)in the aArgV[]
+ * aArgv : An Array of Arguments(Unicode Strings)
+ * aEnvp : An Array of Environment settings(Unicode Strings)
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EFILE : The DSP Execuetable was not found.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_ECORRUTFILE: Unable to Parse the DSP Execuetable
+ * DSP_EATTACHED: Abort because a GPP Client is attached to the
+ * specified Processor
+ * DSP_EACCESSDENIED: Client does not have the required access rights
+ * to reset and load the Processor
+ * DSP_EFAIL : Unable to Load the Processor
+ * Requires:
+ * aArgv is not NULL
+ * iArgc is > 0
+ * PROC Initialized.
+ * Ensures:
+ * Success and ProcState == PROC_LOADED
+ * or DSP_FAILED status.
+ * Details:
+ * Does not implement access rights to control which GPP application
+ * can load the processor.
+ */
+ extern DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor,
+ IN CONST s32 iArgc, IN CONST char **aArgv,
+ IN CONST char **aEnvp);
+
+/*
+ * ======== PROC_RegisterNotify ========
+ * Purpose:
+ * Register to be notified of specific processor events
+ * Parameters:
+ * hProcessor : The processor handle.
+ * uEventMask : Mask of types of events to be notified about.
+ * uNotifyType : Type of notification to be sent.
+ * hNotification: Handle to be used for notification.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle or hNotification.
+ * DSP_EVALUE : Parameter uEventMask is Invalid
+ * DSP_ENOTIMP : The notification type specified in uNotifyMask
+ * is not supported.
+ * DSP_EFAIL : Unable to register for notification.
+ * Requires:
+ * hNotification is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor,
+ u32 uEventMask, u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+/*
+ * ======== PROC_NotifyClients ========
+ * Purpose:
+ * Notify the Processor Clients
+ * Parameters:
+ * hProc : The processor handle.
+ * uEvents : Event to be notified about.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : Failure to Set or Reset the Event
+ * Requires:
+ * uEvents is Supported or Valid type of Event
+ * hProc is a valid handle
+ * PROC Initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc,
+ u32 uEvents);
+
+/*
+ * ======== PROC_NotifyAllClients ========
+ * Purpose:
+ * Notify the Processor Clients
+ * Parameters:
+ * hProc : The processor handle.
+ * uEvents : Event to be notified about.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : Failure to Set or Reset the Event
+ * Requires:
+ * uEvents is Supported or Valid type of Event
+ * hProc is a valid handle
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ * NODE And STRM would use this function to notify their clients
+ * about the state changes in NODE or STRM.
+ */
+ extern DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc,
+ u32 uEvents);
+
+/*
+ * ======== PROC_Start ========
+ * Purpose:
+ * Start a processor running.
+ * Processor must be in PROC_LOADED state.
+ * This will be an OEM-only function, and not part of the 'Bridge
+ * application developer's API.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
+ * DSP_EFAIL : Unable to start the processor.
+ * Requires:
+ * PROC Initialized.
+ * Ensures:
+ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
+ * Details:
+ */
+ extern DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor);
+
+/*
+ * ======== PROC_Stop ========
+ * Purpose:
+ * Start a processor running.
+ * Processor must be in PROC_LOADED state.
+ * This will be an OEM-only function, and not part of the 'Bridge
+ * application developer's API.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
+ * DSP_EFAIL : Unable to start the processor.
+ * Requires:
+ * PROC Initialized.
+ * Ensures:
+ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
+ * Details:
+ */
+ extern DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor);
+
+/*
+ * ======== PROC_FlushMemory ========
+ * Purpose:
+ * Flushes a buffer from the MPU data cache.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pMpuAddr : Buffer start address
+ * ulSize : Buffer size
+ * ulFlags : Reserved.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * Requires:
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ * All the arguments are currently ignored.
+ */
+ extern DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor,
+ void *pMpuAddr,
+ u32 ulSize, u32 ulFlags);
+
+
+/*
+ * ======== PROC_InvalidateMemory ========
+ * Purpose:
+ * Invalidates a buffer from the MPU data cache.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pMpuAddr : Buffer start address
+ * ulSize : Buffer size
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * Requires:
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ * All the arguments are currently ignored.
+ */
+ extern DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor,
+ void *pMpuAddr,
+ u32 ulSize);
+
+/*
+ * ======== PROC_Map ========
+ * Purpose:
+ * Maps a MPU buffer to DSP address space.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pMpuAddr : Starting address of the memory region to map.
+ * ulSize : Size of the memory region to map.
+ * pReqAddr : Requested DSP start address. Offset-adjusted actual
+ * mapped address is in the last argument.
+ * ppMapAddr : Ptr to DSP side mapped u8 address.
+ * ulMapAttr : Optional endianness attributes, virt to phys flag.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * DSP_EMEMORY : MPU side memory allocation error.
+ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
+ * : address.
+ * Requires:
+ * pMpuAddr is not NULL
+ * ulSize is not zero
+ * ppMapAddr is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor,
+ void *pMpuAddr,
+ u32 ulSize,
+ void *pReqAddr,
+ void **ppMapAddr, u32 ulMapAttr);
+
+/*
+ * ======== PROC_ReserveMemory ========
+ * Purpose:
+ * Reserve a virtually contiguous region of DSP address space.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * ulSize : Size of the address space to reserve.
+ * ppRsvAddr : Ptr to DSP side reserved u8 address.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * DSP_EMEMORY : Cannot reserve chunk of this size.
+ * Requires:
+ * ppRsvAddr is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
+ u32 ulSize, void **ppRsvAddr);
+
+/*
+ * ======== PROC_UnMap ========
+ * Purpose:
+ * Removes a MPU buffer mapping from the DSP address space.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pMapAddr : Starting address of the mapped memory region.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * DSP_ENOTFOUND : Cannot find a mapped region starting with this
+ * : address.
+ * Requires:
+ * pMapAddr is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr);
+
+/*
+ * ======== PROC_UnReserveMemory ========
+ * Purpose:
+ * Frees a previously reserved region of DSP address space.
+ * Parameters:
+ * hProcessor : The processor handle.
+ * pRsvAddr : Ptr to DSP side reservedBYTE address.
+ * Returns:
+ * DSP_SOK : Success.
+ * DSP_EHANDLE : Invalid processor handle.
+ * DSP_EFAIL : General failure.
+ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
+ * : address.
+ * Requires:
+ * pRsvAddr is not NULL
+ * PROC Initialized.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
+ void *pRsvAddr);
+
+#endif /* PROC_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/procpriv.h b/arch/arm/plat-omap/include/dspbridge/procpriv.h
new file mode 100644
index 000000000000..21d4b3e0861c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/procpriv.h
@@ -0,0 +1,35 @@
+/*
+ * procpriv.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== procpriv.h ========
+ * Description:
+ * Global PROC constants and types, shared by PROC, MGR, and WCD.
+ *
+ *! Revision History:
+ *! ================
+ *! 05-July-2000 rr: Created
+ */
+
+#ifndef PROCPRIV_
+#define PROCPRIV_
+
+/* RM PROC Object */
+ struct PROC_OBJECT;
+
+#endif /* PROCPRIV_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/pwr.h b/arch/arm/plat-omap/include/dspbridge/pwr.h
new file mode 100644
index 000000000000..a6645ca4f045
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/pwr.h
@@ -0,0 +1,129 @@
+/*
+ * pwr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== pwr.h ========
+ *
+ * Public Functions:
+ *
+ * PWR_SleepDSP
+ * PWR_WakeDSP
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 06-Jun-2002 sg Replaced dspdefs.h with includes of dbdefs.h and errbase.h.
+ *! 13-May-2002 sg Added DSP_SAREADYASLEEP and DSP_SALREADYAWAKE.
+ *! 09-May-2002 sg Updated, added timeouts.
+ *! 02-May-2002 sg Initial.
+ */
+
+#ifndef PWR_
+#define PWR_
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/pwr_sh.h>
+
+/*
+ * ======== PWR_SleepDSP ========
+ * Signal the DSP to go to sleep.
+ *
+ * Parameters:
+ * sleepCode: New sleep state for DSP. (Initially, valid codes
+ * are PWR_DEEPSLEEP or PWR_EMERGENCYDEEPSLEEP; both of
+ * these codes will simply put the DSP in deep sleep.)
+ *
+ * timeout: Maximum time (msec) that PWR should wait for
+ * confirmation that the DSP sleep state has been
+ * reached. If PWR should simply send the command to
+ * the DSP to go to sleep and then return (i.e.,
+ * asynchrounous sleep), the timeout should be
+ * specified as zero.
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_SALREADYASLEEP: Success, but the DSP was already asleep.
+ * DSP_EINVALIDARG: The specified sleepCode is not supported.
+ * DSP_ETIMEOUT: A timeout occured while waiting for DSP sleep
+ * confirmation.
+ * DSP_EFAIL: General failure, unable to send sleep command to
+ * the DSP.
+ */
+ extern DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode,
+ IN CONST u32 timeout);
+
+/*
+ * ======== PWR_WakeDSP ========
+ * Signal the DSP to wake from sleep.
+ *
+ * Parameters:
+ * timeout: Maximum time (msec) that PWR should wait for
+ * confirmation that the DSP is awake. If PWR should
+ * simply send a command to the DSP to wake and then
+ * return (i.e., asynchrounous wake), timeout should
+ * be specified as zero.
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
+ * DSP_ETIMEOUT: A timeout occured while waiting for wake
+ * confirmation.
+ * DSP_EFAIL: General failure, unable to send wake command to
+ * the DSP.
+ */
+ extern DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout);
+
+/*
+ * ======== PWR_PM_PreScale ========
+ * Prescale notification to DSP.
+ *
+ * Parameters:
+ * voltage_domain: The voltage domain for which notification is sent
+ * level: The level of voltage domain
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
+ * DSP_ETIMEOUT: A timeout occured while waiting for wake
+ * confirmation.
+ * DSP_EFAIL: General failure, unable to send wake command to
+ * the DSP.
+ */
+ extern DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level);
+
+/*
+ * ======== PWR_PM_PostScale ========
+ * PostScale notification to DSP.
+ *
+ * Parameters:
+ * voltage_domain: The voltage domain for which notification is sent
+ * level: The level of voltage domain
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
+ * DSP_ETIMEOUT: A timeout occured while waiting for wake
+ * confirmation.
+ * DSP_EFAIL: General failure, unable to send wake command to
+ * the DSP.
+ */
+ extern DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain,
+ u32 level);
+
+#endif /* PWR_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/pwr_sh.h b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
new file mode 100644
index 000000000000..40f1b84bd4c7
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
@@ -0,0 +1,41 @@
+/*
+ * pwr_sh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== pwr_sh.h ========
+ *
+ * Power Manager shared definitions (used on both GPP and DSP sides).
+ *
+ *! Revision History
+ *! ================
+ *! 17-Apr-2002 sg: Initial.
+ */
+
+#ifndef PWR_SH_
+#define PWR_SH_
+
+#include <dspbridge/mbx_sh.h>
+
+/* valid sleep command codes that can be sent by GPP via mailbox: */
+#define PWR_DEEPSLEEP MBX_PM_DSPIDLE
+#define PWR_EMERGENCYDEEPSLEEP MBX_PM_EMERGENCYSLEEP
+#define PWR_SLEEPUNTILRESTART MBX_PM_SLEEPUNTILRESTART
+#define PWR_WAKEUP MBX_PM_DSPWAKEUP
+#define PWR_AUTOENABLE MBX_PM_PWRENABLE
+#define PWR_AUTODISABLE MBX_PM_PWRDISABLE
+#define PWR_RETENTION MBX_PM_DSPRETN
+
+#endif /* PWR_SH_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/reg.h b/arch/arm/plat-omap/include/dspbridge/reg.h
new file mode 100644
index 000000000000..5b3495202971
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/reg.h
@@ -0,0 +1,257 @@
+/*
+ * reg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== reg.h ========
+ * Purpose:
+ * Provide registry functions.
+ *
+ * Public Functions:
+ * REG_DeleteValue
+ * REG_EnumKey
+ * REG_EnumValue
+ * REG_Exit
+ * REG_GetValue
+ * REG_Init
+ * REG_SetValue
+ *
+ *! Revision History:
+ *! =================
+ *! 30-Oct-2000 kc: Updated REG_SetValue & REG_GetValue; renamed
+ *! REG_DeleteEntry to REG_DeleteValue.
+ *! 29-Sep-2000 kc: Updated a REG functions for code review.
+ *! 12-Aug-2000 kc: Renamed REG_EnumValue to REG_EnumKey. Re-implemented
+ *! REG_EnumValue.
+ *! 03-Feb-2000 rr: REG_EnumValue Fxn Added
+ *! 13-Dec-1999 rr: windows.h removed
+ *! 02-Dec-1999 rr: windows.h included for retail build
+ *! 22-Nov-1999 kc: Changes from code review.
+ *! 29-Dec-1997 cr: Changes from code review.
+ *! 27-Oct-1997 cr: Added REG_DeleteValue.
+ *! 20-Oct-1997 cr: Added ability to pass bValue = NULL to REG_GetValue
+ *! and return size of reg entry in pdwValueSize.
+ *! 29-Sep-1997 cr: Added REG_SetValue
+ *! 29-Aug-1997 cr: Created.
+ */
+
+#ifndef _REG_H
+#define _REG_H
+
+#include <linux/types.h>
+
+/* ------------------------- Defines, Data Structures, Typedefs for Linux */
+#ifndef UNDER_CE
+
+#ifndef REG_SZ
+#define REG_SZ 1
+#endif
+
+#ifndef REG_BINARY
+#define REG_BINARY 3
+#endif
+
+#ifndef REG_DWORD
+#define REG_DWORD 4
+#endif
+
+#endif /* UNDER_CE */
+
+#define REG_MAXREGPATHLENGTH 255
+
+/*
+ * ======== REG_DeleteValue ========
+ * Purpose:
+ * Deletes a registry entry. NOTE: A registry entry is not the same as
+ * a registry key.
+ * Parameters:
+ * phKey: Currently reserved; must be NULL.
+ * pstrSubkey: Path to key to open.
+ * pstrValue: Name of entry to delete.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * - REG initialized.
+ * - pstrSubkey & pstrValue are non-NULL values.
+ * - phKey is NULL.
+ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
+ * - length of pstrValue < REG_MAXREGPATHLENGTH.
+ * Ensures:
+ * Details:
+ */
+ extern DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey,
+ IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue);
+
+/*
+ * ======== REG_EnumKey ========
+ * Purpose:
+ * Enumerates subkeys of the specified path to the registry key
+ * Retrieves the name of the subkey(given the index) and
+ * appends with the orignal path to form the full path.
+ * Parameters:
+ * phKey: Currently reserved; must be NULL.
+ * pstrKey The name of the registry key to be enumerated.
+ * dwIndex Specifies the index of the subkey to retrieve.
+ * pstrSubkey: Pointer to buffer that receives full path name of the
+ * specified key + the sub-key
+ * pdwValueSize: Specifies bytes of memory pstrSubkey points to on input,
+ * on output, specifies actual memory bytes written into.
+ * If there is no sub key,pdwValueSize returns NULL.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * - REG initialized.
+ * - pstrKey is non-NULL value.
+ * - pdwValueSize is a valid pointer.
+ * - phKey is NULL.
+ * - length of pstrKey < REG_MAXREGPATHLENGTH.
+ * Ensures:
+ * - strlen(pstrSubkey) is > strlen(pstrKey) &&
+ * - strlen(pstrSubkey) is < REG_MAXREGPATHLENGTH
+ */
+ extern DSP_STATUS REG_EnumKey(OPTIONAL IN HANDLE *phKey,
+ IN u32 dwIndex, IN CONST char *pstrKey,
+ IN OUT char *pstrSubkey,
+ IN OUT u32 *pdwValueSize);
+
+/*
+ * ======== REG_EnumValue ========
+ * Purpose:
+ * Enumerates values of a specified key. Retrieves each value name and
+ * the data associated with the value.
+ * Parameters:
+ * phKey: Currently reserved; must be NULL.
+ * dwIndex: Specifies the index of the value to retrieve.
+ * pstrKey: The name of the registry key to be enumerated.
+ * pstrValue: Pointer to buffer that receives the name of the value.
+ * pdwValueSize: Specifies bytes of memory pstrValue points to on input,
+ * On output, specifies actual memory bytes written into.
+ * If there is no value, pdwValueSize returns NULL
+ * pstrData: Pointer to buffer that receives the data of a value.
+ * pdwDataSize: Specifies bytes of memory in pstrData on input and
+ * bytes of memory written into pstrData on output.
+ * If there is no data, pdwDataSize returns NULL.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * REG initialized.
+ * phKey is NULL.
+ * pstrKey is a non-NULL value.
+ * pstrValue, pstrData, pdwValueSize and pdwDataSize are valid pointers.
+ * Length of pstrKey is less than REG_MAXREGPATHLENGTH.
+ * Ensures:
+ */
+ extern DSP_STATUS REG_EnumValue(IN HANDLE *phKey,
+ IN u32 dwIndex,
+ IN CONST char *pstrKey,
+ IN OUT char *pstrValue,
+ IN OUT u32 *pdwValueSize,
+ IN OUT char *pstrData,
+ IN OUT u32 *pdwDataSize);
+
+/*
+ * ======== REG_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * REG initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void REG_Exit(void);
+
+/*
+ * ======== REG_GetValue ========
+ * Purpose:
+ * Retrieve a value from the registry.
+ * Parameters:
+ * phKey: Currently reserved; must be NULL.
+ * pstrSubkey: Path to key to open.
+ * pstrEntry: Name of entry to retrieve.
+ * pbValue: Upon return, points to retrieved value.
+ * pdwValueSize: Specifies bytes of memory pbValue points to on input,
+ * on output, specifies actual memory bytes written into.
+ * If pbValue is NULL, pdwValueSize reports the size of
+ * the entry in pstrEntry.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * - REG initialized.
+ * - pstrSubkey & pstrEntry are non-NULL values.
+ * - pbValue is a valid pointer.
+ * - phKey is NULL.
+ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
+ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
+ * Ensures:
+ */
+ extern DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey,
+ IN CONST char *pstrSubkey,
+ IN CONST char *pstrEntry,
+ OUT u8 *pbValue,
+ IN OUT u32 *pdwValueSize);
+
+/*
+ * ======== REG_Init ========
+ * Purpose:
+ * Initializes private state of REG module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * REG initialized.
+ */
+ extern bool REG_Init(void);
+
+/*
+ * ======== REG_SetValue ========
+ * Purpose:
+ * Set a value in the registry.
+ * Parameters:
+ * phKey: Handle to open reg key, or NULL if pSubkey is full path.
+ * pstrSubkey: Path to key to open, could be based on phKey.
+ * pstrEntry: Name of entry to set.
+ * dwType: Data type of new registry value.
+ * pbValue: Points to buffer containing new data.
+ * dwValueSize: Specifies bytes of memory bValue points to.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * - REG initialized.
+ * - pstrSubkey & pstrEntry are non-NULL values.
+ * - pbValue is a valid pointer.
+ * - phKey is NULL.
+ * - dwValuSize > 0.
+ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
+ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
+ * Ensures:
+ */
+ extern DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey,
+ IN CONST char *pstrSubKey,
+ IN CONST char *pstrEntry,
+ IN CONST u32 dwType,
+ IN u8 *pbValue, IN u32 dwValueSize);
+
+#endif /* _REG_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
new file mode 100644
index 000000000000..b43fa163f4c2
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
@@ -0,0 +1,88 @@
+/*
+ * resourcecleanup.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#ifndef RES_CLEANUP_DISABLE
+
+#include <dspbridge/nodepriv.h>
+#include <dspbridge/drv.h>
+
+
+extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
+ struct DRV_OBJECT *hDrvObject);
+
+extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
+ HANDLE hPCtxt);
+
+extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
+
+extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
+
+extern DSP_STATUS DRV_ProcUpdatestate(HANDLE pCtxt,
+ enum GPP_PROC_RES_STATE resState);
+
+extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
+
+extern DSP_STATUS DRV_GetProcContext(u32 phProcess,
+ struct DRV_OBJECT *hDrvObject,
+ HANDLE hPCtxt, DSP_HNODE hNode,
+ u32 pMapAddr);
+
+extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
+
+extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
+ HANDLE hPCtxt, HANDLE hProcess);
+
+extern DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE nodeRes,
+ HANDLE pCtxt);
+
+extern DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE nodeRes,
+ HANDLE pCtxt);
+
+extern void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status);
+
+extern DSP_STATUS DRV_RemoveNodeResElement(HANDLE nodeRes, HANDLE status);
+
+extern void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status);
+
+extern DSP_STATUS DRV_UpdateDMMResElement(HANDLE dmmRes, u32 pMpuAddr,
+ u32 ulSize, u32 pReqAddr,
+ u32 ppMapAddr, HANDLE hProcesso);
+
+extern DSP_STATUS DRV_InsertDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
+
+extern DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE dmmRes,
+ HANDLE pCtxt);
+
+extern DSP_STATUS DRV_RemoveDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
+
+extern DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE STRMRes,
+ HANDLE pCtxt);
+
+extern DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
+ HANDLE pPctxt);
+
+extern DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
+ HANDLE pCtxt);
+
+extern DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE STRMRes, HANDLE pCtxt);
+
+extern DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE pCtxt);
+
+extern DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf, u32 *pSize);
+
+extern enum NODE_STATE NODE_GetState(HANDLE hNode);
+
+#endif
diff --git a/arch/arm/plat-omap/include/dspbridge/rmm.h b/arch/arm/plat-omap/include/dspbridge/rmm.h
new file mode 100644
index 000000000000..5b14b8fd5ace
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/rmm.h
@@ -0,0 +1,199 @@
+/*
+ * rmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== rmm.h ========
+ *
+ * This memory manager provides general heap management and arbitrary
+ * alignment for any number of memory segments, and management of overlay
+ * memory.
+ *
+ * Public functions:
+ * RMM_alloc
+ * RMM_create
+ * RMM_delete
+ * RMM_exit
+ * RMM_free
+ * RMM_init
+ *
+ *! Revision History
+ *! ================
+ *! 25-Jun-2002 jeh Added RMM_Addr. Removed RMM_reserve, RMM_stat.
+ *! 15-Oct-2001 jeh Based on rm.h in gen tree.
+ */
+
+#ifndef RMM_
+#define RMM_
+
+/*
+ * ======== RMM_Addr ========
+ * DSP address + segid
+ */
+struct RMM_Addr {
+ u32 addr;
+ s32 segid;
+} ;
+
+/*
+ * ======== RMM_Segment ========
+ * Memory segment on the DSP available for remote allocations.
+ */
+struct RMM_Segment {
+ u32 base; /* Base of the segment */
+ u32 length; /* Size of the segment (target MAUs) */
+ s32 space; /* Code or data */
+ u32 number; /* Number of Allocated Blocks */
+} ;
+
+/*
+ * ======== RMM_Target ========
+ */
+struct RMM_TargetObj;
+
+/*
+ * ======== RMM_alloc ========
+ *
+ * RMM_alloc is used to remotely allocate or reserve memory on the DSP.
+ *
+ * Parameters:
+ * target - Target returned from RMM_create().
+ * segid - Memory segment to allocate from.
+ * size - Size (target MAUS) to allocate.
+ * align - alignment.
+ * dspAddr - If reserve is FALSE, the location to store allocated
+ * address on output, otherwise, the DSP address to
+ * reserve.
+ * reserve - If TRUE, reserve the memory specified by dspAddr.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation on GPP failed.
+ * DSP_EOVERLAYMEMORY: Cannot "allocate" overlay memory because it's
+ * already in use.
+ * Requires:
+ * RMM initialized.
+ * Valid target.
+ * dspAddr != NULL.
+ * size > 0
+ * reserve || target->numSegs > 0.
+ * Ensures:
+ */
+extern DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
+ u32 align, u32 *dspAdr, bool reserve);
+
+/*
+ * ======== RMM_create ========
+ * Create a target object with memory segments for remote allocation. If
+ * segTab == NULL or numSegs == 0, memory can only be reserved through
+ * RMM_alloc().
+ *
+ * Parameters:
+ * pTarget: - Location to store target on output.
+ * segTab: - Table of memory segments.
+ * numSegs: - Number of memory segments.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failed.
+ * Requires:
+ * RMM initialized.
+ * pTarget != NULL.
+ * numSegs == 0 || segTab != NULL.
+ * Ensures:
+ * Success: Valid *pTarget.
+ * Failure: *pTarget == NULL.
+ */
+extern DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
+ struct RMM_Segment segTab[], u32 numSegs);
+
+/*
+ * ======== RMM_delete ========
+ * Delete target allocated in RMM_create().
+ *
+ * Parameters:
+ * target - Target returned from RMM_create().
+ * Returns:
+ * Requires:
+ * RMM initialized.
+ * Valid target.
+ * Ensures:
+ */
+extern void RMM_delete(struct RMM_TargetObj *target);
+
+/*
+ * ======== RMM_exit ========
+ * Exit the RMM module
+ *
+ * Parameters:
+ * Returns:
+ * Requires:
+ * RMM_init successfully called.
+ * Ensures:
+ */
+extern void RMM_exit(void);
+
+/*
+ * ======== RMM_free ========
+ * Free or unreserve memory allocated through RMM_alloc().
+ *
+ * Parameters:
+ * target: - Target returned from RMM_create().
+ * segid: - Segment of memory to free.
+ * dspAddr: - Address to free or unreserve.
+ * size: - Size of memory to free or unreserve.
+ * reserved: - TRUE if memory was reserved only, otherwise FALSE.
+ * Returns:
+ * Requires:
+ * RMM initialized.
+ * Valid target.
+ * reserved || segid < target->numSegs.
+ * reserve || [dspAddr, dspAddr + size] is a valid memory range.
+ * Ensures:
+ */
+extern bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 dspAddr,
+ u32 size, bool reserved);
+
+/*
+ * ======== RMM_init ========
+ * Initialize the RMM module
+ *
+ * Parameters:
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Failure.
+ * Requires:
+ * Ensures:
+ */
+extern bool RMM_init(void);
+
+/*
+ * ======== RMM_stat ========
+ * Obtain memory segment status
+ *
+ * Parameters:
+ * segid: Segment ID of the dynamic loading segment.
+ * pMemStatBuf: Pointer to allocated buffer into which memory stats are
+ * placed.
+ * Returns:
+ * TRUE: Success.
+ * FALSE: Failure.
+ * Requires:
+ * segid < target->numSegs
+ * Ensures:
+ */
+extern bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
+ struct DSP_MEMSTAT *pMemStatBuf);
+
+#endif /* RMM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/rms_sh.h b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
new file mode 100644
index 000000000000..5d4b49aee8d9
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
@@ -0,0 +1,125 @@
+/*
+ * rms_sh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== rms_sh.h ========
+ *
+ * DSP/BIOS Bridge Resource Manager Server shared definitions (used on both
+ * GPP and DSP sides).
+ *
+ *! Revision History
+ *! ================
+ *! 24-Mar-2003 vp Merged updates required for CCS2.2 transition.
+ *! 24-Feb-2003 kc Rearranged order of node types to temporarily support
+ *! legacy message node code
+ *! 23-Nov-2002 gp Converted tabs -> spaces, to fix formatting.
+ *! 13-Feb-2002 jeh Added sysstacksize element to RMS_MoreTaskArgs.
+ *! 11-Dec-2000 sg Added 'misc' element to RMS_MoreTaskArgs.
+ *! 04-Dec-2000 ag Added RMS_BUFDESC command code.
+ *! C/R code value changed to allow ORing of system/user codes.
+ *! 10-Oct-2000 sg Added 'align' field to RMS_StrmDef.
+ *! 09-Oct-2000 sg Moved pre-defined message codes here from rmsdefs.h.
+ *! 02-Oct-2000 sg Changed ticks to msec.
+ *! 24-Aug-2000 sg Moved definitions that will be exposed to app developers
+ *! to a separate file, rmsdefs.h.
+ *! 10-Aug-2000 sg Added RMS_COMMANDBUFSIZE and RMS_RESPONSEBUFSIZE; added
+ *! pre-defined command/response codes; more comments.
+ *! 09-Aug-2000 sg Added RMS_ETASK.
+ *! 08-Aug-2000 jeh Define RMS_WORD for GPP, rename DSP_MSG to RMS_DSPMSG.
+ *! Added RMS_MsgArgs, RMS_MoreTaskArgs.
+ *! 25-Jul-2000 sg: Changed SIO to STRM.
+ *! 30-Jun-2000 sg: Initial.
+ */
+
+#ifndef RMS_SH_
+#define RMS_SH_
+
+#include <dspbridge/rmstypes.h>
+
+/* Node Types: */
+#define RMS_TASK 1 /* Task node */
+#define RMS_DAIS 2 /* xDAIS socket node */
+#define RMS_MSG 3 /* Message node */
+
+/* Memory Types: */
+#define RMS_CODE 0 /* Program space */
+#define RMS_DATA 1 /* Data space */
+#define RMS_IO 2 /* I/O space */
+
+/* RM Server Command and Response Buffer Sizes: */
+#define RMS_COMMANDBUFSIZE 256 /* Size of command buffer */
+#define RMS_RESPONSEBUFSIZE 16 /* Size of response buffer */
+
+/* Pre-Defined Command/Response Codes: */
+#define RMS_EXIT 0x80000000 /* GPP->Node: shutdown */
+#define RMS_EXITACK 0x40000000 /* Node->GPP: ack shutdown */
+#define RMS_BUFDESC 0x20000000 /* Arg1 SM buf, Arg2 is SM size */
+#define RMS_KILLTASK 0x10000000 /* GPP->Node: Kill Task */
+#define RMS_USER 0x0 /* Start of user-defined msg codes */
+#define RMS_MAXUSERCODES 0xfff /* Maximum user defined C/R Codes */
+
+
+/* RM Server RPC Command Structure: */
+ struct RMS_Command {
+ RMS_WORD fxn; /* Server function address */
+ RMS_WORD arg1; /* First argument */
+ RMS_WORD arg2; /* Second argument */
+ RMS_WORD data; /* Function-specific data array */
+ } ;
+
+/*
+ * The RMS_StrmDef structure defines the parameters for both input and output
+ * streams, and is passed to a node's create function.
+ */
+ struct RMS_StrmDef {
+ RMS_WORD bufsize; /* Buffer size (in DSP words) */
+ RMS_WORD nbufs; /* Max number of bufs in stream */
+ RMS_WORD segid; /* Segment to allocate buffers */
+ RMS_WORD align; /* Alignment for allocated buffers */
+ RMS_WORD timeout; /* Timeout (msec) for blocking calls */
+ RMS_CHAR name[1]; /* Device Name (terminated by '\0') */
+ } ;
+
+/* Message node create args structure: */
+ struct RMS_MsgArgs {
+ RMS_WORD maxMessages; /* Max # simultaneous msgs to node */
+ RMS_WORD segid; /* Mem segment for NODE_allocMsgBuf */
+ RMS_WORD notifyType; /* Type of message notification */
+ RMS_WORD argLength; /* Length (in DSP chars) of arg data */
+ RMS_WORD argData; /* Arg data for node */
+ } ;
+
+/* Partial task create args structure */
+ struct RMS_MoreTaskArgs {
+ RMS_WORD priority; /* Task's runtime priority level */
+ RMS_WORD stackSize; /* Task's stack size */
+ RMS_WORD sysstackSize; /* Task's system stack size (55x) */
+ RMS_WORD stackSeg; /* Memory segment for task's stack */
+ RMS_WORD heapAddr; /* base address of the node memory heap in
+ * external memory (DSP virtual address) */
+ RMS_WORD heapSize; /* size in MAUs of the node memory heap in
+ * external memory */
+ RMS_WORD misc; /* Misc field. Not used for 'normal'
+ * task nodes; for xDAIS socket nodes
+ * specifies the IALG_Fxn pointer.
+ */
+ /* # input STRM definition structures */
+ RMS_WORD numInputStreams;
+ } ;
+
+#endif /* RMS_SH_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/rmstypes.h b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
new file mode 100644
index 000000000000..13d752e393ab
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
@@ -0,0 +1,40 @@
+/*
+ * rmstypes.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== rmstypes.h ========
+ *
+ * DSP/BIOS Bridge Resource Manager Server shared data type definitions.
+ *
+ *! Revision History
+ *! ================
+ *! 06-Oct-2000 sg Added LgFxn type.
+ *! 05-Oct-2000 sg Changed RMS_STATUS to LgUns.
+ *! 31-Aug-2000 sg Added RMS_DSPMSG.
+ *! 25-Aug-2000 sg Initial.
+ */
+
+#ifndef RMSTYPES_
+#define RMSTYPES_
+#include <linux/types.h>
+/*
+ * DSP-side definitions.
+ */
+#include <dspbridge/std.h>
+typedef u32 RMS_WORD;
+typedef char RMS_CHAR;
+
+#endif /* RMSTYPES_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/services.h b/arch/arm/plat-omap/include/dspbridge/services.h
new file mode 100644
index 000000000000..35bab0db4ae6
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/services.h
@@ -0,0 +1,63 @@
+/*
+ * services.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== services.h ========
+ * Purpose:
+ * Provide loading and unloading of SERVICES modules.
+ *
+ * Public Functions:
+ * SERVICES_Exit(void)
+ * SERVICES_Init(void)
+ *
+ *! Revision History:
+ *! ================
+ *! 01-Feb-2000 kc: Created.
+ */
+
+#ifndef SERVICES_
+#define SERVICES_
+
+#include <dspbridge/host_os.h>
+/*
+ * ======== SERVICES_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * SERVICES initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void SERVICES_Exit(void);
+
+/*
+ * ======== SERVICES_Init ========
+ * Purpose:
+ * Initializes SERVICES modules.
+ * Parameters:
+ * Returns:
+ * TRUE if all modules initialized; otherwise FALSE.
+ * Requires:
+ * Ensures:
+ * SERVICES modules initialized.
+ */
+ extern bool SERVICES_Init(void);
+
+#endif /* SERVICES_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/std.h b/arch/arm/plat-omap/include/dspbridge/std.h
new file mode 100644
index 000000000000..ec849f4e903d
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/std.h
@@ -0,0 +1,143 @@
+/*
+ * std.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * ======== std.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 16-Feb-2004 vp GNU compiler 3.x defines inline keyword. Added
+ *! appropriate macros not to redefine inline keyword in
+ *! this file.
+ *! 24-Oct-2002 ashu defined _TI_ and _FIXED_ symbols for 28x.
+ *! 24-Oct-2002 ashu defined _TI_ for 24x.
+ *! 01-Mar-2002 kln changed LARGE_MODEL and Arg definition for 28x
+ *! 01-Feb-2002 kln added definitions for 28x
+ *! 08-Dec-2000 kw: added 'ArgToInt' and 'ArgToPtr' macros
+ *! 30-Nov-2000 mf: Added _64_, _6x_; removed _7d_
+ *! 30-May-2000 srid: Added __TMS320C55X__ for 55x; Arg is void * for 55 .
+ *! 18-Jun-1999 dr: Added '_TI_', fixed __inline for SUN4, added inline
+ *! 10-Feb-1999 rt: Added '55' support, changed 54's symbol to _TMS320C5XX
+ *! 29-Aug-1998 mf: fixed typo, removed obsolete targets
+ *! 08-Jun-1998 mf: _67_ is synonym for _7d_
+ *! 10-Oct-1997 rt; added _7d_ for Raytheon C7DSP triggered by _TMS320C6700
+ *! 04-Aug-1997 cc: added _29_ for _TMS320C2XX
+ *! 11-Jul-1997 dlr: _5t_, and STD_SPOXTASK keyword for Tasking
+ *! 12-Jun-1997 mf: _TMS320C60 -> _TMS320C6200
+ *! 13-Feb-1997 mf: _62_, with 32-bit LgInt
+ *! 26-Nov-1996 kw: merged bios-c00's and wsx-a27's <dspbridge/std.h> changes
+ *! *and* revision history
+ *! 12-Sep-1996 kw: added C54x #ifdef's
+ *! 21-Aug-1996 mf: removed #define main smain for _21_
+ *! 14-May-1996 gp: def'd out INT, FLOAT, and COMPLEX defines for WSX.
+ *! 11-Apr-1996 kw: define _W32_ based on _WIN32 (defined by MS compiler)
+ *! 07-Mar-1996 mg: added Win32 support
+ *! 06-Sep-1995 dh: added _77_ dynamic stack support via fxns77.h
+ *! 27-Jun-1995 dh: added _77_ support
+ *! 16-Mar-1995 mf: for _21_: #define main smain
+ *! 01-Mar-1995 mf: set _20_ and _60_ (as well as _21_ for both)
+ *! 22-Feb-1995 mf: Float is float for _SUN_ and _80_
+ *! 22-Dec-1994 mf: Added _80_ definition, for PP or MP.
+ *! 09-Dec-1994 mf: Added _53_ definition.
+ *! Added definitions of _30_, etc.
+ *! 23-Aug-1994 dh removed _21_ special case (kw)
+ *! 17-Aug-1994 dh added _51_ support
+ *! 03-Aug-1994 kw updated _80_ support
+ *! 30-Jun-1994 kw added _80_ support
+ *! 05-Apr-1994 kw: Added _SUN_ to _FLOAT_ definition
+ *! 01-Mar-1994 kw: Made Bool an int (was u16) for _56_ (more efficient).
+ *! Added _53_ support.
+ */
+
+#ifndef STD_
+#define STD_
+
+#include <linux/types.h>
+
+/*
+ * ======== _TI_ ========
+ * _TI_ is defined for all TI targets
+ */
+#if defined(_29_) || defined(_30_) || defined(_40_) || defined(_50_) || \
+ defined(_54_) || defined(_55_) || defined(_6x_) || defined(_80_) || \
+ defined(_28_) || defined(_24_)
+#define _TI_ 1
+#endif
+
+/*
+ * ======== _FLOAT_ ========
+ * _FLOAT_ is defined for all targets that natively support floating point
+ */
+#if defined(_SUN_) || defined(_30_) || defined(_40_) || defined(_67_) || \
+ defined(_80_)
+#define _FLOAT_ 1
+#endif
+
+/*
+ * ======== _FIXED_ ========
+ * _FIXED_ is defined for all fixed point target architectures
+ */
+#if defined(_29_) || defined(_50_) || defined(_54_) || defined(_55_) || \
+ defined(_62_) || defined(_64_) || defined(_28_)
+#define _FIXED_ 1
+#endif
+
+/*
+ * ======== _TARGET_ ========
+ * _TARGET_ is defined for all target architectures (as opposed to
+ * host-side software)
+ */
+#if defined(_FIXED_) || defined(_FLOAT_)
+#define _TARGET_ 1
+#endif
+
+/*
+ * 8, 16, 32-bit type definitions
+ *
+ * Sm* - 8-bit type
+ * Md* - 16-bit type
+ * Lg* - 32-bit type
+ *
+ * *s32 - signed type
+ * *u32 - unsigned type
+ * *Bits - unsigned type (bit-maps)
+ */
+
+/*
+ * Aliases for standard C types
+ */
+
+typedef s32(*Fxn) (void); /* generic function type */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*
+ * These macros are used to cast 'Arg' types to 's32' or 'Ptr'.
+ * These macros were added for the 55x since Arg is not the same
+ * size as s32 and Ptr in 55x large model.
+ */
+#if defined(_28l_) || defined(_55l_)
+#define ArgToInt(A) ((s32)((long)(A) & 0xffff))
+#define ArgToPtr(A) ((Ptr)(A))
+#else
+#define ArgToInt(A) ((s32)(A))
+#define ArgToPtr(A) ((Ptr)(A))
+#endif
+
+#endif /* STD_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/strm.h b/arch/arm/plat-omap/include/dspbridge/strm.h
new file mode 100644
index 000000000000..58256152abce
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/strm.h
@@ -0,0 +1,441 @@
+/*
+ * strm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== strm.h ========
+ * Description:
+ * DSPBridge Stream Manager.
+ *
+ * Public Functions:
+ * STRM_AllocateBuffer
+ * STRM_Close
+ * STRM_Create
+ * STRM_Delete
+ * STRM_Exit
+ * STRM_FreeBuffer
+ * STRM_GetEventHandle
+ * STRM_GetInfo
+ * STRM_Idle
+ * STRM_Init
+ * STRM_Issue
+ * STRM_Open
+ * STRM_PrepareBuffer
+ * STRM_Reclaim
+ * STRM_RegisterNotify
+ * STRM_Select
+ * STRM_UnprepareBuffer
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! =================
+ *! 15-Nov-2001 ag Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
+ *! Added DSP_ESIZE error to STRM_AllocateBuffer().
+ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
+ *! 10-May-2001 jeh Code review cleanup.
+ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
+ *! 06-Feb-2001 kc Updated DBC_Ensure for STRM_Select().
+ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open().
+ *! 25-Sep-2000 jeh Created.
+ */
+
+#ifndef STRM_
+#define STRM_
+
+#include <dspbridge/dev.h>
+
+#include <dspbridge/strmdefs.h>
+
+/*
+ * ======== STRM_AllocateBuffer ========
+ * Purpose:
+ * Allocate data buffer(s) for use with a stream.
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * uSize: Size (GPP bytes) of the buffer(s).
+ * uNumBufs: Number of buffers to allocate.
+ * apBuffer: Array to hold buffer addresses.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_EMEMORY: Insufficient memory.
+ * DSP_EFAIL: Failure occurred, unable to allocate buffers.
+ * DSP_ESIZE: uSize must be > 0 bytes.
+ * Requires:
+ * STRM_Init(void) called.
+ * apBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm,
+ u32 uSize,
+ OUT u8 **apBuffer,
+ u32 uNumBufs);
+
+/*
+ * ======== STRM_Close ========
+ * Purpose:
+ * Close a stream opened with STRM_Open().
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_EPENDING: Some data buffers issued to the stream have not
+ * been reclaimed.
+ * DSP_EFAIL: Failure to close stream.
+ * Requires:
+ * STRM_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm);
+
+/*
+ * ======== STRM_Create ========
+ * Purpose:
+ * Create a STRM manager object. This object holds information about the
+ * device needed to open streams.
+ * Parameters:
+ * phStrmMgr: Location to store handle to STRM manager object on
+ * output.
+ * hDev: Device for this processor.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * DSP_EFAIL: General failure.
+ * Requires:
+ * STRM_Init(void) called.
+ * phStrmMgr != NULL.
+ * hDev != NULL.
+ * Ensures:
+ * DSP_SOK: Valid *phStrmMgr.
+ * error: *phStrmMgr == NULL.
+ */
+ extern DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr,
+ struct DEV_OBJECT *hDev);
+
+/*
+ * ======== STRM_Delete ========
+ * Purpose:
+ * Delete the STRM Object.
+ * Parameters:
+ * hStrmMgr: Handle to STRM manager object from STRM_Create.
+ * Returns:
+ * Requires:
+ * STRM_Init(void) called.
+ * Valid hStrmMgr.
+ * Ensures:
+ * hStrmMgr is not valid.
+ */
+ extern void STRM_Delete(struct STRM_MGR *hStrmMgr);
+
+/*
+ * ======== STRM_Exit ========
+ * Purpose:
+ * Discontinue usage of STRM module.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * STRM_Init(void) successfully called before.
+ * Ensures:
+ */
+ extern void STRM_Exit(void);
+
+/*
+ * ======== STRM_FreeBuffer ========
+ * Purpose:
+ * Free buffer(s) allocated with STRM_AllocateBuffer.
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * apBuffer: Array containing buffer addresses.
+ * uNumBufs: Number of buffers to be freed.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid stream handle.
+ * DSP_EFAIL: Failure occurred, unable to free buffers.
+ * Requires:
+ * STRM_Init(void) called.
+ * apBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm,
+ u8 **apBuffer, u32 uNumBufs);
+
+/*
+ * ======== STRM_GetEventHandle ========
+ * Purpose:
+ * Get stream's user event handle. This function is used when closing
+ * a stream, so the event can be closed.
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * phEvent: Location to store event handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * Requires:
+ * STRM_Init(void) called.
+ * phEvent != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_GetEventHandle(struct STRM_OBJECT *hStrm,
+ OUT HANDLE *phEvent);
+
+/*
+ * ======== STRM_GetInfo ========
+ * Purpose:
+ * Get information about a stream. User's DSP_STREAMINFO is contained
+ * in STRM_INFO struct. STRM_INFO also contains Bridge private info.
+ * Parameters:
+ * hStrm: Stream handle returned from STRM_Open().
+ * pStreamInfo: Location to store stream info on output.
+ * uSteamInfoSize: Size of user's DSP_STREAMINFO structure.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_ESIZE: uStreamInfoSize < sizeof(DSP_STREAMINFO).
+ * DSP_EFAIL: Unable to get stream info.
+ * Requires:
+ * STRM_Init(void) called.
+ * pStreamInfo != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
+ OUT struct STRM_INFO *pStreamInfo,
+ u32 uStreamInfoSize);
+
+/*
+ * ======== STRM_Idle ========
+ * Purpose:
+ * Idle a stream and optionally flush output data buffers.
+ * If this is an output stream and fFlush is TRUE, all data currently
+ * enqueued will be discarded.
+ * If this is an output stream and fFlush is FALSE, this function
+ * will block until all currently buffered data is output, or the timeout
+ * specified has been reached.
+ * After a successful call to STRM_Idle(), all buffers can immediately
+ * be reclaimed.
+ * Parameters:
+ * hStrm: Stream handle returned from STRM_Open().
+ * fFlush: If TRUE, discard output buffers.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_ETIMEOUT: A timeout occurred before the stream could be idled.
+ * DSP_ERESTART: A critical error occurred, DSP is being restarted.
+ * DSP_EFAIL: Unable to idle stream.
+ * Requires:
+ * STRM_Init(void) called.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush);
+
+/*
+ * ======== STRM_Init ========
+ * Purpose:
+ * Initialize the STRM module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialization succeeded, FALSE otherwise.
+ * Requires:
+ * Ensures:
+ */
+ extern bool STRM_Init(void);
+
+/*
+ * ======== STRM_Issue ========
+ * Purpose:
+ * Send a buffer of data to a stream.
+ * Parameters:
+ * hStrm: Stream handle returned from STRM_Open().
+ * pBuf: Pointer to buffer of data to be sent to the stream.
+ * ulBytes: Number of bytes of data in the buffer.
+ * ulBufSize: Actual buffer size in bytes.
+ * dwArg: A user argument that travels with the buffer.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_ESTREAMFULL: The stream is full.
+ * DSP_EFAIL: Failure occurred, unable to issue buffer.
+ * Requires:
+ * STRM_Init(void) called.
+ * pBuf != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf,
+ u32 ulBytes, u32 ulBufSize,
+ IN u32 dwArg);
+
+/*
+ * ======== STRM_Open ========
+ * Purpose:
+ * Open a stream for sending/receiving data buffers to/from a task of
+ * DAIS socket node on the DSP.
+ * Parameters:
+ * hNode: Node handle returned from NODE_Allocate().
+ * uDir: DSP_TONODE or DSP_FROMNODE.
+ * uIndex: Stream index.
+ * pAttr: Pointer to structure containing attributes to be
+ * applied to stream. Cannot be NULL.
+ * phStrm: Location to store stream handle on output.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hNode.
+ * DSP_EDIRECTION: Invalid uDir.
+ * DSP_EVALUE: Invalid uIndex.
+ * DSP_ENODETYPE: hNode is not a task or DAIS socket node.
+ * DSP_EFAIL: Unable to open stream.
+ * Requires:
+ * STRM_Init(void) called.
+ * phStrm != NULL.
+ * pAttr != NULL.
+ * Ensures:
+ * DSP_SOK: *phStrm is valid.
+ * error: *phStrm == NULL.
+ */
+ extern DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir,
+ u32 uIndex, IN struct STRM_ATTR *pAttr,
+ OUT struct STRM_OBJECT **phStrm);
+
+/*
+ * ======== STRM_PrepareBuffer ========
+ * Purpose:
+ * Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
+ * for use with a stream.
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * uSize: Size (GPP bytes) of the buffer.
+ * pBuffer: Buffer address.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_EFAIL: Failure occurred, unable to prepare buffer.
+ * Requires:
+ * STRM_Init(void) called.
+ * pBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_PrepareBuffer(struct STRM_OBJECT *hStrm,
+ u32 uSize,
+ u8 *pBuffer);
+
+/*
+ * ======== STRM_Reclaim ========
+ * Purpose:
+ * Request a buffer back from a stream.
+ * Parameters:
+ * hStrm: Stream handle returned from STRM_Open().
+ * pBufPtr: Location to store pointer to reclaimed buffer.
+ * pulBytes: Location where number of bytes of data in the
+ * buffer will be written.
+ * pulBufSize: Location where actual buffer size will be written.
+ * pdwArg: Location where user argument that travels with
+ * the buffer will be written.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_ETIMEOUT: A timeout occurred before a buffer could be
+ * retrieved.
+ * DSP_EFAIL: Failure occurred, unable to reclaim buffer.
+ * Requires:
+ * STRM_Init(void) called.
+ * pBufPtr != NULL.
+ * pulBytes != NULL.
+ * pdwArg != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm,
+ OUT u8 **pBufPtr, u32 *pulBytes,
+ u32 *pulBufSize, u32 *pdwArg);
+
+/*
+ * ======== STRM_RegisterNotify ========
+ * Purpose:
+ * Register to be notified on specific events for this stream.
+ * Parameters:
+ * hStrm: Stream handle returned by STRM_Open().
+ * uEventMask: Mask of types of events to be notified about.
+ * uNotifyType: Type of notification to be sent.
+ * hNotification: Handle to be used for notification.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_EMEMORY: Insufficient memory on GPP.
+ * DSP_EVALUE: uEventMask is invalid.
+ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
+ * supported.
+ * Requires:
+ * STRM_Init(void) called.
+ * hNotification != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm,
+ u32 uEventMask, u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+/*
+ * ======== STRM_Select ========
+ * Purpose:
+ * Select a ready stream.
+ * Parameters:
+ * aStrmTab: Array of stream handles returned from STRM_Open().
+ * nStrms: Number of stream handles in array.
+ * pMask: Location to store mask of ready streams on output.
+ * uTimeout: Timeout value (milliseconds).
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ERANGE: nStrms out of range.
+
+ * DSP_EHANDLE: Invalid stream handle in array.
+ * DSP_ETIMEOUT: A timeout occurred before a stream became ready.
+ * DSP_EFAIL: Failure occurred, unable to select a stream.
+ * Requires:
+ * STRM_Init(void) called.
+ * aStrmTab != NULL.
+ * nStrms > 0.
+ * pMask != NULL.
+ * Ensures:
+ * DSP_SOK: *pMask != 0 || uTimeout == 0.
+ * Error: *pMask == 0.
+ */
+ extern DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab,
+ u32 nStrms,
+ OUT u32 *pMask, u32 uTimeout);
+
+/*
+ * ======== STRM_UnprepareBuffer ========
+ * Purpose:
+ * Unprepare a data buffer that was previously prepared for a stream
+ * with DSPStream_PrepareBuffer(), and that will no longer be used with
+ * the stream.
+ * Parameter:
+ * hStrm: Stream handle returned from STRM_Open().
+ * uSize: Size (GPP bytes) of the buffer.
+ * pBuffer: Buffer address.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hStrm.
+ * DSP_EFAIL: Failure occurred, unable to unprepare buffer.
+ * Requires:
+ * STRM_Init(void) called.
+ * pBuffer != NULL.
+ * Ensures:
+ */
+ extern DSP_STATUS STRM_UnprepareBuffer(struct STRM_OBJECT *hStrm,
+ u32 uSize,
+ u8 *pBuffer);
+
+#endif /* STRM_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/strmdefs.h b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
new file mode 100644
index 000000000000..44d217af1f39
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
@@ -0,0 +1,57 @@
+/*
+ * strmdefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== strmdefs.h ========
+ * Purpose:
+ * Global STRM constants and types.
+ *
+ *! Revision History
+ *! ================
+ *! 19-Nov-2001 ag Added STRM_INFO..
+ *! 25-Sep-2000 jeh Created.
+ */
+
+#ifndef STRMDEFS_
+#define STRMDEFS_
+
+#define STRM_MAXEVTNAMELEN 32
+
+ struct STRM_MGR;
+
+ struct STRM_OBJECT;
+
+ struct STRM_ATTR {
+ HANDLE hUserEvent;
+ char *pstrEventName;
+ void *pVirtBase; /* Process virtual base address of
+ * mapped SM */
+ u32 ulVirtSize; /* Size of virtual space in bytes */
+ struct DSP_STREAMATTRIN *pStreamAttrIn;
+ } ;
+
+ struct STRM_INFO {
+ enum DSP_STRMMODE lMode; /* transport mode of
+ * stream(DMA, ZEROCOPY..) */
+ u32 uSegment; /* Segment strm allocs from. 0 is local mem */
+ void *pVirtBase; /* " " Stream'process virt base */
+ struct DSP_STREAMINFO *pUser; /* User's stream information
+ * returned */
+ } ;
+
+#endif /* STRMDEFS_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/sync.h b/arch/arm/plat-omap/include/dspbridge/sync.h
new file mode 100644
index 000000000000..fa3ff8d26c6c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/sync.h
@@ -0,0 +1,340 @@
+/*
+ * sync.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== sync.h ========
+ * Purpose:
+ * Provide synchronization services.
+ *
+ * Public Functions:
+ * SYNC_CloseEvent
+ * SYNC_DeleteCS
+ * SYNC_EnterCS
+ * SYNC_Exit
+ * SYNC_Init
+ * SYNC_InitializeCS
+ * SYNC_LeaveCS
+ * SYNC_OpenEvent
+ * SYNC_PostMessage
+ * SYNC_ResetEvent
+ * SYNC_SetEvent
+ * SYNC_WaitOnEvent
+ * SYNC_WaitOnMultipleEvents
+ *
+ *! Revision History:
+ *! ================
+ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
+ *! 01-Dec-1999 ag: Added #define SYNC_MAXNAMELENGTH.
+ *! 04-Nov-1999 kc: Added critical section functions and objects to SYNC.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 24-Sep-1999 kc: Added WinCE notes.
+ *! 20-Oct-1997 gp: Removed unused SYNC_ critical section and must complete fxns
+ *! Added SYNC_HOBJECT, SYNC_ATTRS, and object validation, and
+ *! merged SYNC_DestroyEvent into SYNC_CloseEvent, and merged
+ *! SYNC_CreateEvent into SYNC_OpenEvent.
+ *! 07-Oct-1997 gp: Added SYNC_Create/DestroyEvent (for NT testing).
+ *! 06-Oct-1997 gp: Added SYNC_OpenEvent.
+ *! 03-Jun-1997 gp: Added SYNC_{Begin|End}CritSection() functions.
+ *! 03-Jan-1997 gp: Added SYNC_INFINITE define.
+ *! 05-Aug-1996 gp: Created.
+ */
+
+#ifndef _SYNC_H
+#define _SYNC_H
+
+#define SIGNATURECS 0x53435953 /* "SYCS" (in reverse) */
+#define SIGNATUREDPCCS 0x53445953 /* "SYDS" (in reverse) */
+
+/* Special timeout value indicating an infinite wait: */
+#define SYNC_INFINITE 0xffffffff
+
+/* Maximum string length of a named event */
+#define SYNC_MAXNAMELENGTH 32
+
+/* Generic SYNC object: */
+ struct SYNC_OBJECT;
+
+/* Generic SYNC CS object: */
+struct SYNC_CSOBJECT {
+ u32 dwSignature; /* used for object validation */
+ struct semaphore sem;
+} ;
+
+/* SYNC object attributes: */
+ struct SYNC_ATTRS {
+ HANDLE hUserEvent; /* Platform's User Mode synch. object. */
+ HANDLE hKernelEvent; /* Platform's Kernel Mode sync. object. */
+ u32 dwReserved1; /* For future expansion. */
+ u32 dwReserved2; /* For future expansion. */
+ } ;
+
+/*
+ * ======== SYNC_CloseEvent ========
+ * Purpose:
+ * Close this event handle, freeing resources allocated in SYNC_OpenEvent
+ * if necessary.
+ * Parameters:
+ * hEvent: Handle to a synchronization event, created/opened in
+ * SYNC_OpenEvent.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EFAIL: Failed to close event handle.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * SYNC initialized.
+ * Ensures:
+ * Any subsequent usage of hEvent would be invalid.
+ */
+ extern DSP_STATUS SYNC_CloseEvent(IN struct SYNC_OBJECT *hEvent);
+
+/*
+ * ======== SYNC_DeleteCS ========
+ * Purpose:
+ * Delete a critical section.
+ * Parameters:
+ * hCSObj: critical section handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_DeleteCS(IN struct SYNC_CSOBJECT *hCSObj);
+
+/*
+ * ======== SYNC_EnterCS ========
+ * Purpose:
+ * Enter the critical section.
+ * Parameters:
+ * hCSObj: critical section handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_EnterCS(IN struct SYNC_CSOBJECT *hCSObj);
+
+/*
+ * ======== SYNC_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * SYNC initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern void SYNC_Exit(void);
+
+/*
+ * ======== SYNC_Init ========
+ * Purpose:
+ * Initializes private state of SYNC module.
+ * Parameters:
+ * Returns:
+ * TRUE if initialized; FALSE if error occured.
+ * Requires:
+ * Ensures:
+ * SYNC initialized.
+ */
+ extern bool SYNC_Init(void);
+
+/*
+ * ======== SYNC_InitializeCS ========
+ * Purpose:
+ * Initialize the critical section.
+ * Parameters:
+ * hCSObj: critical section handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Out of memory.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj);
+
+/*
+ * ======== SYNC_InitializeDPCCS ========
+ * Purpose:
+ * Initialize the critical section between process context and DPC.
+ * Parameters:
+ * hCSObj: critical section handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Out of memory.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT
+ **phCSObj);
+
+/*
+ * ======== SYNC_LeaveCS ========
+ * Purpose:
+ * Leave the critical section.
+ * Parameters:
+ * hCSObj: critical section handle.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_LeaveCS(IN struct SYNC_CSOBJECT *hCSObj);
+
+/*
+ * ======== SYNC_OpenEvent ========
+ * Purpose:
+ * Create/open and initialize an event object for thread synchronization,
+ * which is initially in the non-signalled state.
+ * Parameters:
+ * phEvent: Pointer to location to receive the event object handle.
+ * pAttrs: Pointer to SYNC_ATTRS object containing initial SYNC
+ * SYNC_OBJECT attributes. If this pointer is NULL, then
+ * SYNC_OpenEvent will create and manage an OS specific
+ * syncronization object.
+ * pAttrs->hUserEvent: Platform's User Mode synchronization object.
+ *
+ * The behaviour of the SYNC methods depend on the value of
+ * the hUserEvent attr:
+ *
+ * 1. (hUserEvent == NULL):
+ * A user mode event is created.
+ * 2. (hUserEvent != NULL):
+ * A user mode event is supplied by the caller of SYNC_OpenEvent().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Unable to create user mode event.
+ * DSP_EMEMORY: Insufficient memory.
+ * DSP_EINVALIDARG SYNC_ATTRS values are invalid.
+ * Requires:
+ * - SYNC initialized.
+ * - phEvent != NULL.
+ * Ensures:
+ * If function succeeded, pEvent->hEvent must be a valid event handle.
+ */
+ extern DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
+ IN OPTIONAL struct SYNC_ATTRS
+ *pAttrs);
+
+/*
+ * ========= SYNC_PostMessage ========
+ * Purpose:
+ * To post a windows message
+ * Parameters:
+ * hWindow: Handle to the window
+ * uMsg: Message to be posted
+ * Returns:
+ * DSP_SOK: Success
+ * DSP_EFAIL: Post message failed
+ * DSP_EHANDLE: Invalid Window handle
+ * Requires:
+ * SYNC initialized
+ * Ensures
+ */
+ extern DSP_STATUS SYNC_PostMessage(IN HANDLE hWindow, IN u32 uMsg);
+
+/*
+ * ======== SYNC_ResetEvent ========
+ * Purpose:
+ * Reset a syncronization event object state to non-signalled.
+ * Parameters:
+ * hEvent: Handle to a sync event.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EFAIL: Failed to reset event.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * SYNC initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_ResetEvent(IN struct SYNC_OBJECT *hEvent);
+
+/*
+ * ======== SYNC_SetEvent ========
+ * Purpose:
+ * Signal the event. Will unblock one waiting thread.
+ * Parameters:
+ * hEvent: Handle to an event object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Failed to signal event.
+ * DSP_EHANDLE: Invalid handle.
+ * Requires:
+ * SYNC initialized.
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_SetEvent(IN struct SYNC_OBJECT *hEvent);
+
+/*
+ * ======== SYNC_WaitOnEvent ========
+ * Purpose:
+ * Wait for an event to be signalled, up to the specified timeout.
+ * Parameters:
+ * hEvent: Handle to an event object.
+ * dwTimeOut: The time-out interval, in milliseconds.
+ * The function returns if the interval elapses, even if
+ * the object's state is nonsignaled.
+ * If zero, the function tests the object's state and
+ * returns immediately.
+ * If SYNC_INFINITE, the function's time-out interval
+ * never elapses.
+ * Returns:
+ * DSP_SOK: The object was signalled.
+ * DSP_EHANDLE: Invalid handle.
+ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
+ * SYNC_E_TIMEOUT: Timeout expired while waiting for event to be signalled.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_WaitOnEvent(IN struct SYNC_OBJECT *hEvent,
+ IN u32 dwTimeOut);
+
+/*
+ * ======== SYNC_WaitOnMultipleEvents ========
+ * Purpose:
+ * Wait for any of an array of events to be signalled, up to the
+ * specified timeout.
+ * Note: dwTimeOut must be SYNC_INFINITE to signal infinite wait.
+ * Parameters:
+ * hSyncEvents: Array of handles to event objects.
+ * uCount: Number of event handles.
+ * dwTimeOut: The time-out interval, in milliseconds.
+ * The function returns if the interval elapses, even if
+ * no event is signalled.
+ * If zero, the function tests the object's state and
+ * returns immediately.
+ * If SYNC_INFINITE, the function's time-out interval
+ * never elapses.
+ * puIndex: Location to store index of event that was signalled.
+ * Returns:
+ * DSP_SOK: The object was signalled.
+ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
+ * SYNC_E_TIMEOUT: Timeout expired before event was signalled.
+ * DSP_EMEMORY: Memory allocation failed.
+ * Requires:
+ * Ensures:
+ */
+ extern DSP_STATUS SYNC_WaitOnMultipleEvents(IN struct SYNC_OBJECT
+ **hSyncEvents,
+ IN u32 uCount,
+ IN u32 dwTimeout,
+ OUT u32 *puIndex);
+
+#endif /* _SYNC_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/util.h b/arch/arm/plat-omap/include/dspbridge/util.h
new file mode 100644
index 000000000000..e6815caf2d2b
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/util.h
@@ -0,0 +1,122 @@
+/*
+ * util.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== util.h ========
+ * Purpose:
+ * Provide general purpose utility functions.
+ *
+ * Public Functions:
+ * UTIL_CDTestDll
+ * UTIL_CmdLineToArgs
+ * UTIL_Exit
+ * UTIL_GetSysInfo
+ * UTIL_Init
+ */
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#include <dspbridge/utildefs.h>
+
+/*
+ * ======== UTIL_CDTestDll ========
+ * Purpose:
+ * Provides test entry point in class driver context.
+ * Parameters:
+ * cArgc: test module command line input count.
+ * ppArgv: test module command line args.
+ * Returns:
+ * 0 if successful, a negative value otherwise.
+ * Requires:
+ * UTIL initialized.
+ * Ensures:
+ */
+ extern u32 UTIL_CDTestDll(IN s32 cArgc, IN char **ppArgv);
+
+/*
+ * ======== UTIL_CmdLineToArgs ========
+ * Purpose:
+ * This function re-creates C-style cmd line argc & argv from WinMain()
+ * cmd line args.
+ * Parameters:
+ * s8 *pszProgName - The name of the program currently being executed.
+ * s8 *argv[] - The argument vector.
+ * s8 *pCmdLine - The pointer to the command line.
+ * bool fHasProgName - Indicats whether a program name is supplied.
+ * Returns:
+ * Returns the number of arguments found.
+ * Requires:
+ * UTIL initialized.
+ * Ensures:
+ */
+ extern s32 UTIL_CmdLineToArgs(IN char *pszProgName,
+ IN char *argv[UTIL_MAXARGVS],
+ IN char *pCmdLine, IN bool fHasProgName);
+
+/*
+ * ======== UTIL_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ * Parameters:
+ * Returns:
+ * Requires:
+ * UTIL initialized.
+ * Ensures:
+ * Resources used by module are freed when cRef reaches zero.
+ */
+ extern inline void UTIL_Exit(void)
+ {
+ }
+/*
+ * ======== UTIL_GetSysInfo ========
+ * Purpose:
+ * This function return platform specific system information.
+ *
+ * Parameters:
+ * pSysInfo - address to store the system information.
+ * Returns:
+ * DSP_SOK
+ * S_FAIL
+ * Requires:
+ * UTIL initialized.
+ * pSysInfo != NULL
+ * Ensures:
+ */
+ extern DSP_STATUS UTIL_GetSysInfo(OUT struct UTIL_SYSINFO *pSysInfo);
+
+/*
+ * ======== UTIL_Init ========
+ * Purpose:
+ * Initializes private state of UTIL module.
+ * Parameters:
+ * Returns:
+ * TRUE if success, else FALSE.
+ * Requires:
+ * Ensures:
+ * UTIL initialized.
+ */
+ extern inline bool UTIL_Init(void)
+ {
+ return true;
+ }
+
+#endif /* _UTIL_H */
diff --git a/arch/arm/plat-omap/include/dspbridge/utildefs.h b/arch/arm/plat-omap/include/dspbridge/utildefs.h
new file mode 100644
index 000000000000..bd53a5a8408c
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/utildefs.h
@@ -0,0 +1,51 @@
+/*
+ * utildefs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== utildefs.h ========
+ * Purpose:
+ * Global UTIL constants and types, shared between WCD and DSPSYS.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 kc Removed wIOPort* entries from UTIL_HOSTCONFIG.
+ *! 12-Aug-2000 ag Added UTIL_SYSINFO typedef.
+ *! 08-Oct-1999 rr Adopted for WinCE where test fxns will be added in util.h
+ *! 26-Dec-1996 cr Created.
+ */
+
+#ifndef UTILDEFS_
+#define UTILDEFS_
+
+/* constants taken from configmg.h */
+#define UTIL_MAXMEMREGS 9
+#define UTIL_MAXIOPORTS 20
+#define UTIL_MAXIRQS 7
+#define UTIL_MAXDMACHNLS 7
+
+/* misc. constants */
+#define UTIL_MAXARGVS 10
+
+/* Platform specific important info */
+ struct UTIL_SYSINFO {
+ /* Granularity of page protection; usually 1k or 4k */
+ u32 dwPageSize;
+ u32 dwAllocationGranularity; /* VM granularity, usually 64K */
+ u32 dwNumberOfProcessors; /* Used as sanity check */
+ } ;
+
+#endif /* UTILDEFS_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/uuidutil.h b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
new file mode 100644
index 000000000000..af4aaec563f7
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
@@ -0,0 +1,74 @@
+/*
+ * uuidutil.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== uuidutil.h ========
+ * Description:
+ * This file contains the specification of UUID helper functions.
+ *
+ *! Revision History
+ *! ================
+ *! 09-Nov-2000 kc: Modified description of UUID utility functions.
+ *! 29-Sep-2000 kc: Appended "UUID_" prefix to UUID helper functions.
+ *! 10-Aug-2000 kc: Created.
+ *!
+ */
+
+#ifndef UUIDUTIL_
+#define UUIDUTIL_
+
+#define MAXUUIDLEN 37
+
+/*
+ * ======== UUID_UuidToString ========
+ * Purpose:
+ * Converts a DSP_UUID to an ANSI string.
+ * Parameters:
+ * pUuid: Pointer to a DSP_UUID object.
+ * pszUuid: Pointer to a buffer to receive a NULL-terminated UUID
+ * string.
+ * size: Maximum size of the pszUuid string.
+ * Returns:
+ * Requires:
+ * pUuid & pszUuid are non-NULL values.
+ * Ensures:
+ * Lenghth of pszUuid is less than MAXUUIDLEN.
+ * Details:
+ * UUID string limit currently set at MAXUUIDLEN.
+ */
+ void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
+ s32 size);
+
+/*
+ * ======== UUID_UuidFromString ========
+ * Purpose:
+ * Converts an ANSI string to a DSP_UUID.
+ * Parameters:
+ * pszUuid: Pointer to a string that represents a DSP_UUID object.
+ * pUuid: Pointer to a DSP_UUID object.
+ * Returns:
+ * Requires:
+ * pUuid & pszUuid are non-NULL values.
+ * Ensures:
+ * Details:
+ * We assume the string representation of a UUID has the following format:
+ * "12345678_1234_1234_1234_123456789abc".
+ */
+ extern void UUID_UuidFromString(IN char *pszUuid,
+ OUT struct DSP_UUID *pUuid);
+
+#endif /* UUIDUTIL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wcd.h b/arch/arm/plat-omap/include/dspbridge/wcd.h
new file mode 100644
index 000000000000..5a7d47ae0bab
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wcd.h
@@ -0,0 +1,61 @@
+/*
+ * wcd.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wcd.h ========
+ * Description:
+ * 'Bridge class driver library functions, object definitions, and
+ * return error/status codes. To be included by 'Bridge mini drivers.
+ *
+ * Public Functions:
+ * See mem.h and dbg.h.
+ *
+ * Notes:
+ * 'Bridge Class Driver services exported to WMD's are initialized by the
+ * WCD on behalf of the WMD. WMD's must not call module Init/Exit
+ * functions.
+ *
+ * To ensure WMD binary compatibility across different platforms,
+ * for the same processor, a WMD must restrict its usage of system
+ * services to those exported by the 'Bridge class library.
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Jun-2000 jeh Added dev.h
+ *! 01-Nov-1999 ag: #WINCE# WCD_MAJOR_VERSION=8 & WCD_MINOR_VERSION=0 to match
+ *! dll stamps.
+ *! 0.80 - 0.89 Alpha, 0.90 - 0.99 Beta, 1.00 - 1.10 FCS.
+ *! 17-Sep-1997 gp: Changed size of CFG_HOSTRES structure; and ISR_Install API;
+ *! Changed WCD_MINOR_VERSION 3 -> 4.
+ *! 15-Sep-1997 gp: Moved WCD_(Un)registerMinidriver to drv.
+ *! 25-Jul-1997 cr: Added WCD_UnregisterMinidriver.
+ *! 22-Jul-1997 cr: Added WCD_RegisterMinidriver, WCD_MINOR_VERSION 2 -> 3.
+ *! 12-Nov-1996 gp: Defined port io macros.
+ *! 07-Nov-1996 gp: Updated for code review.
+ *! 16-Jul-1996 gp: Added CHNL fxns; updated WCD lib version to 2.
+ *! 10-May-1996 gp: Separated WMD def.s' into wmd.h.
+ *! 03-May-1996 gp: Created.
+ */
+
+#ifndef WCD_
+#define WCD_
+
+/* This WCD Library Version: */
+#define WCD_MAJOR_VERSION (u32)8 /* .8x - Alpha, .9x - Beta, 1.x FCS */
+#define WCD_MINOR_VERSION (u32)0
+
+#endif /* WCD_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wcdioctl.h b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
new file mode 100644
index 000000000000..1579a3c33332
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
@@ -0,0 +1,519 @@
+/*
+ * wcdioctl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== wcdioctl.h ========
+ * Purpose:
+ * Contains structures and commands that are used for interaction
+ * between the DDSP API and class driver.
+ *
+ *! Revision History
+ *! ================
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping structs & offsets
+ *! 15-Oct-2002 kc Updated definitions for private PERF module.
+ *! 16-Aug-2002 map Added ARGS_MGR_REGISTEROBJECT & ARGS_MGR_UNREGISTEROBJECT
+ *! Added CMD_MGR_REGISTEROBJECT_OFFSET &
+ *! CMD_MGR_UNREGISTEROBJECT_OFFSET
+ *! 15-Jan-2002 ag Added actaul bufSize to ARGS_STRM_[RECLAIM][ISSUE].
+ *! 15-Nov-2001 ag change to STRMINFO in ARGS_STRM_GETINFO.
+ *! 11-Sep-2001 ag ARGS_CMM_GETHANDLE defn uses DSP_HPROCESSOR.
+ *! 23-Apr-2001 jeh Added pStatus to NODE_TERMINATE args.
+ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
+ *! 22-Nov-2000 kc: Added CMD_MGR_GETPERF_DATA_OFFSET for acquiring PERF stats.
+ *! 27-Oct-2000 jeh Added timeouts to NODE_GETMESSAGE, NODE_PUTMESSAGE args.
+ *! Removed NODE_GETMESSAGESTRM args.
+ *! 11-Oct-2000 ag: Added SM mgr(CMM) args.
+ *! 27-Sep-2000 jeh Removed struct DSP_BUFFERATTR param from
+ *! ARGS_STRM_ALLOCATEBUFFER.
+ *! 25-Sep-2000 rr: Updated to Version 0.9
+ *! 07-Sep-2000 jeh Changed HANDLE to DSP_HNOTIFICATION in RegisterNotify args.
+ *! Added DSP_STRMATTR to DSPNode_Connect args.
+ *! 04-Aug-2000 rr: MEM and UTIL added to RM.
+ *! 27-Jul-2000 rr: NODE, MGR,STRM and PROC added
+ *! 27-Jun-2000 rr: Modifed to Use either PM or DSP/BIOS Bridge
+ *! IFDEF to build for PM or DSP/BIOS Bridge
+ *! 28-Jan-2000 rr: NT_CMD_FROM_OFFSET moved out to dsptrap.h
+ *! 24-Jan-2000 rr: Merged with Scott's code.
+ *! 21-Jan-2000 sg: In ARGS_CHNL_GETMODE changed mode to be u32 to be
+ *! consistent with chnldefs.h.
+ *! 11-Jan-2000 rr: CMD_CFG_GETCDVERSION_OFFSET added.
+ *! 12-Nov-1999 rr: CMD_BRD_MONITOR_OFFSET added
+ *! 09-Nov-1999 kc: Added MEMRY and enabled CMD_BRD_IOCTL_OFFSET.
+ *! 05-Nov-1999 ag: Added CHNL.
+ *! 02-Nov-1999 kc: Removed field from ARGS_UTIL_TESTDLL.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 08-Oct-1999 rr: Util control offsets added.
+ *! 13-Sep-1999 kc: Added ARGS_UTIL_TESTDLL for PM test infrastructure.
+ *! 19-Aug-1999 rr: Created from WSX. Minimal Implementaion of BRD_Start and BRD
+ *! and BRD_Stop. IOCTL Offsets and CTRL Code.
+ */
+
+#ifndef WCDIOCTL_
+#define WCDIOCTL_
+
+#include <dspbridge/mem.h>
+#include <dspbridge/cmm.h>
+#include <dspbridge/strmdefs.h>
+#include <dspbridge/dbdcd.h>
+
+union Trapped_Args {
+
+ /* MGR Module */
+ struct {
+ u32 uNode;
+ struct DSP_NDBPROPS __user *pNDBProps;
+ u32 uNDBPropsSize;
+ u32 __user *puNumNodes;
+ } ARGS_MGR_ENUMNODE_INFO;
+
+ struct {
+ u32 uProcessor;
+ struct DSP_PROCESSORINFO __user *pProcessorInfo;
+ u32 uProcessorInfoSize;
+ u32 __user *puNumProcs;
+ } ARGS_MGR_ENUMPROC_INFO;
+
+ struct {
+ struct DSP_UUID *pUuid;
+ enum DSP_DCDOBJTYPE objType;
+ char *pszPathName;
+ } ARGS_MGR_REGISTEROBJECT;
+
+ struct {
+ struct DSP_UUID *pUuid;
+ enum DSP_DCDOBJTYPE objType;
+ } ARGS_MGR_UNREGISTEROBJECT;
+
+ struct {
+ struct DSP_NOTIFICATION __user*__user *aNotifications;
+ u32 uCount;
+ u32 __user *puIndex;
+ u32 uTimeout;
+ } ARGS_MGR_WAIT;
+
+ /* PROC Module */
+ struct {
+ u32 uProcessor;
+ struct DSP_PROCESSORATTRIN __user *pAttrIn;
+ DSP_HPROCESSOR __user *phProcessor;
+ } ARGS_PROC_ATTACH;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 dwCmd;
+ struct DSP_CBDATA __user *pArgs;
+ } ARGS_PROC_CTRL;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ } ARGS_PROC_DETACH;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ DSP_HNODE __user *aNodeTab;
+ u32 uNodeTabSize;
+ u32 __user *puNumNodes;
+ u32 __user *puAllocated;
+ } ARGS_PROC_ENUMNODE_INFO;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 uResourceType;
+ struct DSP_RESOURCEINFO *pResourceInfo;
+ u32 uResourceInfoSize;
+ } ARGS_PROC_ENUMRESOURCES;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ struct DSP_PROCESSORSTATE __user *pProcStatus;
+ u32 uStateInfoSize;
+ } ARGS_PROC_GETSTATE;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u8 __user *pBuf;
+
+ #ifndef RES_CLEANUP_DISABLE
+ u8 __user *pSize;
+ #endif
+ u32 uMaxSize;
+ } ARGS_PROC_GETTRACE;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ s32 iArgc;
+ char __user*__user *aArgv;
+ char *__user *aEnvp;
+ } ARGS_PROC_LOAD;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 uEventMask;
+ u32 uNotifyType;
+ struct DSP_NOTIFICATION __user *hNotification;
+ } ARGS_PROC_REGISTER_NOTIFY;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ } ARGS_PROC_START;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 ulSize;
+ void *__user *ppRsvAddr;
+ } ARGS_PROC_RSVMEM;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 ulSize;
+ void *pRsvAddr;
+ } ARGS_PROC_UNRSVMEM;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ void *pMpuAddr;
+ u32 ulSize;
+ void *pReqAddr;
+ void *__user *ppMapAddr;
+ u32 ulMapAttr;
+ } ARGS_PROC_MAPMEM;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ u32 ulSize;
+ void *pMapAddr;
+ } ARGS_PROC_UNMAPMEM;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ void *pMpuAddr;
+ u32 ulSize;
+ u32 ulFlags;
+ } ARGS_PROC_FLUSHMEMORY;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ } ARGS_PROC_STOP;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ void *pMpuAddr;
+ u32 ulSize;
+ } ARGS_PROC_INVALIDATEMEMORY;
+
+
+ /* NODE Module */
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ struct DSP_UUID __user *pNodeID;
+ struct DSP_CBDATA __user *pArgs;
+ struct DSP_NODEATTRIN __user *pAttrIn;
+ DSP_HNODE __user *phNode;
+ } ARGS_NODE_ALLOCATE;
+
+ struct {
+ DSP_HNODE hNode;
+ u32 uSize;
+ struct DSP_BUFFERATTR __user *pAttr;
+ u8 *__user *pBuffer;
+ } ARGS_NODE_ALLOCMSGBUF;
+
+ struct {
+ DSP_HNODE hNode;
+ s32 iPriority;
+ } ARGS_NODE_CHANGEPRIORITY;
+
+ struct {
+ DSP_HNODE hNode;
+ u32 uStream;
+ DSP_HNODE hOtherNode;
+ u32 uOtherStream;
+ struct DSP_STRMATTR __user *pAttrs;
+ struct DSP_CBDATA __user *pConnParam;
+ } ARGS_NODE_CONNECT;
+
+ struct {
+ DSP_HNODE hNode;
+ } ARGS_NODE_CREATE;
+
+ struct {
+ DSP_HNODE hNode;
+ } ARGS_NODE_DELETE;
+
+ struct {
+ DSP_HNODE hNode;
+ struct DSP_BUFFERATTR __user *pAttr;
+ u8 *pBuffer;
+ } ARGS_NODE_FREEMSGBUF;
+
+ struct {
+ DSP_HNODE hNode;
+ struct DSP_NODEATTR __user *pAttr;
+ u32 uAttrSize;
+ } ARGS_NODE_GETATTR;
+
+ struct {
+ DSP_HNODE hNode;
+ struct DSP_MSG __user *pMessage;
+ u32 uTimeout;
+ } ARGS_NODE_GETMESSAGE;
+
+ struct {
+ DSP_HNODE hNode;
+ } ARGS_NODE_PAUSE;
+
+ struct {
+ DSP_HNODE hNode;
+ struct DSP_MSG __user *pMessage;
+ u32 uTimeout;
+ } ARGS_NODE_PUTMESSAGE;
+
+ struct {
+ DSP_HNODE hNode;
+ u32 uEventMask;
+ u32 uNotifyType;
+ struct DSP_NOTIFICATION __user *hNotification;
+ } ARGS_NODE_REGISTERNOTIFY;
+
+ struct {
+ DSP_HNODE hNode;
+ } ARGS_NODE_RUN;
+
+ struct {
+ DSP_HNODE hNode;
+ DSP_STATUS __user *pStatus;
+ } ARGS_NODE_TERMINATE;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ struct DSP_UUID __user *pNodeID;
+ struct DSP_NDBPROPS __user *pNodeProps;
+ } ARGS_NODE_GETUUIDPROPS;
+
+ /* STRM module */
+
+ struct {
+ DSP_HSTREAM hStream;
+ u32 uSize;
+ u8 *__user *apBuffer;
+ u32 uNumBufs;
+ } ARGS_STRM_ALLOCATEBUFFER;
+
+ struct {
+ DSP_HSTREAM hStream;
+ } ARGS_STRM_CLOSE;
+
+ struct {
+ DSP_HSTREAM hStream;
+ u8 *__user *apBuffer;
+ u32 uNumBufs;
+ } ARGS_STRM_FREEBUFFER;
+
+ struct {
+ DSP_HSTREAM hStream;
+ HANDLE *phEvent;
+ } ARGS_STRM_GETEVENTHANDLE;
+
+ struct {
+ DSP_HSTREAM hStream;
+ struct STRM_INFO __user *pStreamInfo;
+ u32 uStreamInfoSize;
+ } ARGS_STRM_GETINFO;
+
+ struct {
+ DSP_HSTREAM hStream;
+ bool bFlush;
+ } ARGS_STRM_IDLE;
+
+ struct {
+ DSP_HSTREAM hStream;
+ u8 *pBuffer;
+ u32 dwBytes;
+ u32 dwBufSize;
+ u32 dwArg;
+ } ARGS_STRM_ISSUE;
+
+ struct {
+ DSP_HNODE hNode;
+ u32 uDirection;
+ u32 uIndex;
+ struct STRM_ATTR __user *pAttrIn;
+ DSP_HSTREAM __user *phStream;
+ } ARGS_STRM_OPEN;
+
+ struct {
+ DSP_HSTREAM hStream;
+ u8 *__user *pBufPtr;
+ u32 __user *pBytes;
+ u32 __user *pBufSize;
+ u32 __user *pdwArg;
+ } ARGS_STRM_RECLAIM;
+
+ struct {
+ DSP_HSTREAM hStream;
+ u32 uEventMask;
+ u32 uNotifyType;
+ struct DSP_NOTIFICATION __user *hNotification;
+ } ARGS_STRM_REGISTERNOTIFY;
+
+ struct {
+ DSP_HSTREAM __user *aStreamTab;
+ u32 nStreams;
+ u32 __user *pMask;
+ u32 uTimeout;
+ } ARGS_STRM_SELECT;
+
+ /* CMM Module */
+ struct {
+ struct CMM_OBJECT *hCmmMgr;
+ u32 uSize;
+ struct CMM_ATTRS *pAttrs;
+ OUT void **ppBufVA;
+ } ARGS_CMM_ALLOCBUF;
+
+ struct {
+ struct CMM_OBJECT *hCmmMgr;
+ void *pBufPA;
+ u32 ulSegId;
+ } ARGS_CMM_FREEBUF;
+
+ struct {
+ DSP_HPROCESSOR hProcessor;
+ struct CMM_OBJECT *__user *phCmmMgr;
+ } ARGS_CMM_GETHANDLE;
+
+ struct {
+ struct CMM_OBJECT *hCmmMgr;
+ struct CMM_INFO __user *pCmmInfo;
+ } ARGS_CMM_GETINFO;
+
+ /* MEM Module */
+ struct {
+ u32 cBytes;
+ enum MEM_POOLATTRS type;
+ void *pMem;
+ } ARGS_MEM_ALLOC;
+
+ struct {
+ u32 cBytes;
+ enum MEM_POOLATTRS type;
+ void *pMem;
+ } ARGS_MEM_CALLOC;
+
+ struct {
+ void *pMem;
+ } ARGS_MEM_FREE;
+
+ struct {
+ void *pBuffer;
+ u32 cSize;
+ void *pLockedBuffer;
+ } ARGS_MEM_PAGELOCK;
+
+ struct {
+ void *pBuffer;
+ u32 cSize;
+ } ARGS_MEM_PAGEUNLOCK;
+
+ /* UTIL module */
+ struct {
+ s32 cArgc;
+ char **ppArgv;
+ } ARGS_UTIL_TESTDLL;
+} ;
+
+#define CMD_BASE 101
+
+/* MGR module offsets */
+#define CMD_MGR_BASE_OFFSET CMD_BASE
+#define CMD_MGR_ENUMNODE_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 0)
+#define CMD_MGR_ENUMPROC_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 1)
+#define CMD_MGR_REGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 2)
+#define CMD_MGR_UNREGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 3)
+#define CMD_MGR_WAIT_OFFSET (CMD_MGR_BASE_OFFSET + 4)
+
+#ifndef RES_CLEANUP_DISABLE
+#define CMD_MGR_RESOUCES_OFFSET (CMD_MGR_BASE_OFFSET + 5)
+#define CMD_MGR_END_OFFSET CMD_MGR_RESOUCES_OFFSET
+#else
+#define CMD_MGR_END_OFFSET CMD_MGR_WAIT_OFFSET
+#endif
+
+#define CMD_PROC_BASE_OFFSET (CMD_MGR_END_OFFSET + 1)
+#define CMD_PROC_ATTACH_OFFSET (CMD_PROC_BASE_OFFSET + 0)
+#define CMD_PROC_CTRL_OFFSET (CMD_PROC_BASE_OFFSET + 1)
+#define CMD_PROC_DETACH_OFFSET (CMD_PROC_BASE_OFFSET + 2)
+#define CMD_PROC_ENUMNODE_OFFSET (CMD_PROC_BASE_OFFSET + 3)
+#define CMD_PROC_ENUMRESOURCES_OFFSET (CMD_PROC_BASE_OFFSET + 4)
+#define CMD_PROC_GETSTATE_OFFSET (CMD_PROC_BASE_OFFSET + 5)
+#define CMD_PROC_GETTRACE_OFFSET (CMD_PROC_BASE_OFFSET + 6)
+#define CMD_PROC_LOAD_OFFSET (CMD_PROC_BASE_OFFSET + 7)
+#define CMD_PROC_REGISTERNOTIFY_OFFSET (CMD_PROC_BASE_OFFSET + 8)
+#define CMD_PROC_START_OFFSET (CMD_PROC_BASE_OFFSET + 9)
+#define CMD_PROC_RSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 10)
+#define CMD_PROC_UNRSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 11)
+#define CMD_PROC_MAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 12)
+#define CMD_PROC_UNMAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 13)
+#define CMD_PROC_FLUSHMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 14)
+#define CMD_PROC_STOP_OFFSET (CMD_PROC_BASE_OFFSET + 15)
+#define CMD_PROC_INVALIDATEMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 16)
+#define CMD_PROC_END_OFFSET CMD_PROC_INVALIDATEMEMORY_OFFSET
+
+
+#define CMD_NODE_BASE_OFFSET (CMD_PROC_END_OFFSET + 1)
+#define CMD_NODE_ALLOCATE_OFFSET (CMD_NODE_BASE_OFFSET + 0)
+#define CMD_NODE_ALLOCMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 1)
+#define CMD_NODE_CHANGEPRIORITY_OFFSET (CMD_NODE_BASE_OFFSET + 2)
+#define CMD_NODE_CONNECT_OFFSET (CMD_NODE_BASE_OFFSET + 3)
+#define CMD_NODE_CREATE_OFFSET (CMD_NODE_BASE_OFFSET + 4)
+#define CMD_NODE_DELETE_OFFSET (CMD_NODE_BASE_OFFSET + 5)
+#define CMD_NODE_FREEMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 6)
+#define CMD_NODE_GETATTR_OFFSET (CMD_NODE_BASE_OFFSET + 7)
+#define CMD_NODE_GETMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 8)
+#define CMD_NODE_PAUSE_OFFSET (CMD_NODE_BASE_OFFSET + 9)
+#define CMD_NODE_PUTMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 10)
+#define CMD_NODE_REGISTERNOTIFY_OFFSET (CMD_NODE_BASE_OFFSET + 11)
+#define CMD_NODE_RUN_OFFSET (CMD_NODE_BASE_OFFSET + 12)
+#define CMD_NODE_TERMINATE_OFFSET (CMD_NODE_BASE_OFFSET + 13)
+#define CMD_NODE_GETUUIDPROPS_OFFSET (CMD_NODE_BASE_OFFSET + 14)
+#define CMD_NODE_END_OFFSET CMD_NODE_GETUUIDPROPS_OFFSET
+
+#define CMD_STRM_BASE_OFFSET (CMD_NODE_END_OFFSET + 1)
+#define CMD_STRM_ALLOCATEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 0)
+#define CMD_STRM_CLOSE_OFFSET (CMD_STRM_BASE_OFFSET + 1)
+#define CMD_STRM_FREEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 2)
+#define CMD_STRM_GETEVENTHANDLE_OFFSET (CMD_STRM_BASE_OFFSET + 3)
+#define CMD_STRM_GETINFO_OFFSET (CMD_STRM_BASE_OFFSET + 4)
+#define CMD_STRM_IDLE_OFFSET (CMD_STRM_BASE_OFFSET + 5)
+#define CMD_STRM_ISSUE_OFFSET (CMD_STRM_BASE_OFFSET + 6)
+#define CMD_STRM_OPEN_OFFSET (CMD_STRM_BASE_OFFSET + 7)
+#define CMD_STRM_RECLAIM_OFFSET (CMD_STRM_BASE_OFFSET + 8)
+#define CMD_STRM_REGISTERNOTIFY_OFFSET (CMD_STRM_BASE_OFFSET + 9)
+#define CMD_STRM_SELECT_OFFSET (CMD_STRM_BASE_OFFSET + 10)
+#define CMD_STRM_END_OFFSET CMD_STRM_SELECT_OFFSET
+
+/* Communication Memory Manager (UCMM) */
+#define CMD_CMM_BASE_OFFSET (CMD_STRM_END_OFFSET + 1)
+#define CMD_CMM_ALLOCBUF_OFFSET (CMD_CMM_BASE_OFFSET + 0)
+#define CMD_CMM_FREEBUF_OFFSET (CMD_CMM_BASE_OFFSET + 1)
+#define CMD_CMM_GETHANDLE_OFFSET (CMD_CMM_BASE_OFFSET + 2)
+#define CMD_CMM_GETINFO_OFFSET (CMD_CMM_BASE_OFFSET + 3)
+#define CMD_CMM_END_OFFSET CMD_CMM_GETINFO_OFFSET
+
+#define CMD_BASE_END_OFFSET CMD_CMM_END_OFFSET
+#endif /* WCDIOCTL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wmd.h b/arch/arm/plat-omap/include/dspbridge/wmd.h
new file mode 100644
index 000000000000..f584038827b8
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmd.h
@@ -0,0 +1,1193 @@
+/*
+ * wmd.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmd.h ========
+ * Purpose:
+ * 'Bridge mini driver entry point and interface function declarations.
+ *
+ * Public Functions:
+ * WMD_DRV_Entry
+ *
+ * Notes:
+ * The 'Bridge class driver obtains it's function interface to
+ * the 'Bridge mini driver via a call to WMD_DRV_Entry().
+ *
+ * 'Bridge Class Driver services exported to WMD's are initialized by the
+ * WCD on behalf of the WMD.
+ *
+ * WMD function DBC Requires and Ensures are also made by the WCD on
+ * behalf of the WMD, to simplify the WMD code.
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs - WMD_BRD_MemMap/UnMap
+ *! 01-Mar-2004 vp Added filename argument to WMD_DRV_Entry function.
+ *! 29-Aug-2002 map Added WMD_BRD_MemWrite()
+ *! 26-Aug-2002 map Added WMD_BRD_MemCopy()
+ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
+ *! 05-Nov-2001 kc: Added error handling DEH functions.
+ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify().
+ *! 17-Nov-2000 jeh Added WMD_MSG and WMD_IO definitions.
+ *! 01-Nov-2000 jeh Added more error codes to WMD_CHNL_RegisterNotify().
+ *! 13-Oct-2000 jeh Added dwArg to WMD_CHNL_AddIOReq(), added WMD_CHNL_IDLE
+ *! and WMD_CHNL_RegisterNotify for DSPStream support.
+ *! 17-Jan-2000 rr: WMD_BRD_SETSTATE Added.
+ *! 30-Jul-1997 gp: Split wmd IOCTL space into reserved and private.
+ *! 07-Nov-1996 gp: Updated for code review.
+ *! 18-Oct-1996 gp: Added WMD_E_HARDWARE return code from WMD_BRD_Monitor.
+ *! 09-Sep-1996 gp: Subtly altered the semantics of WMD_CHNL_GetInfo().
+ *! 02-Aug-1996 gp: Ensured on BRD_Start that interrupts to the PC are enabled.
+ *! 11-Jul-1996 gp: Added CHNL interface. Note stronger DBC_Require conditions.
+ *! 29-May-1996 gp: Removed WCD_ prefix from functions imported from WCD.LIB.
+ *! 29-May-1996 gp: Made OUT param first in WMD_DEV_Create().
+ *! 09-May-1996 gp: Created.
+ */
+
+#ifndef WMD_
+#define WMD_
+
+#include <dspbridge/brddefs.h>
+#include <dspbridge/cfgdefs.h>
+#include <dspbridge/chnlpriv.h>
+#include <dspbridge/dehdefs.h>
+#include <dspbridge/devdefs.h>
+#include <dspbridge/iodefs.h>
+#include <dspbridge/msgdefs.h>
+
+/*
+ * Any IOCTLS at or above this value are reserved for standard WMD
+ * interfaces.
+ */
+#define WMD_RESERVEDIOCTLBASE 0x8000
+
+/* Handle to mini-driver's private device context. */
+ struct WMD_DEV_CONTEXT;
+
+/*---------------------------------------------------------------------------*/
+/* 'Bridge MINI DRIVER FUNCTION TYPES */
+/*---------------------------------------------------------------------------*/
+
+/*
+ * ======== WMD_BRD_Monitor ========
+ * Purpose:
+ * Bring the board to the BRD_IDLE (monitor) state.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device context.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_HARDWARE: A test of hardware assumptions/integrity failed.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL
+ * Ensures:
+ * DSP_SOK: Board is in BRD_IDLE state;
+ * else: Board state is indeterminate.
+ */
+ typedef DSP_STATUS(
+ *WMD_BRD_MONITOR) (struct WMD_DEV_CONTEXT
+ *hDevContext);
+
+/*
+ * ======== WMD_BRD_SETSTATE ========
+ * Purpose:
+ * Sets the Mini driver state
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * ulBrdState: Board state
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * ulBrdState <= BRD_LASTSTATE.
+ * Ensures:
+ * ulBrdState <= BRD_LASTSTATE.
+ * Update the Board state to the specified state.
+ */
+ typedef DSP_STATUS(
+ *WMD_BRD_SETSTATE) (struct WMD_DEV_CONTEXT
+ *hDevContext, u32 ulBrdState);
+
+/*
+ * ======== WMD_BRD_Start ========
+ * Purpose:
+ * Bring board to the BRD_RUNNING (start) state.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device context.
+ * dwDSPAddr: DSP address at which to start execution.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL
+ * Board is in monitor (BRD_IDLE) state.
+ * Ensures:
+ * DSP_SOK: Board is in BRD_RUNNING state.
+ * Interrupts to the PC are enabled.
+ * else: Board state is indeterminate.
+ */
+ typedef DSP_STATUS(*WMD_BRD_START) (struct WMD_DEV_CONTEXT
+ *hDevContext, u32 dwDSPAddr);
+
+/*
+ * ======== WMD_BRD_MemCopy ========
+ * Purpose:
+ * Copy memory from one DSP address to another
+ * Parameters:
+ * pDevContext: Pointer to context handle
+ * ulDspDestAddr: DSP address to copy to
+ * ulDspSrcAddr: DSP address to copy from
+ * ulNumBytes: Number of bytes to copy
+ * ulMemType: What section of memory to copy to
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * pDevContext != NULL
+ * Ensures:
+ * DSP_SOK: Board is in BRD_RUNNING state.
+ * Interrupts to the PC are enabled.
+ * else: Board state is indeterminate.
+ */
+ typedef DSP_STATUS(*WMD_BRD_MEMCOPY) (struct WMD_DEV_CONTEXT
+ *hDevContext,
+ u32 ulDspDestAddr,
+ u32 ulDspSrcAddr,
+ u32 ulNumBytes, u32 ulMemType);
+/*
+ * ======== WMD_BRD_MemWrite ========
+ * Purpose:
+ * Write a block of host memory into a DSP address, into a given memory
+ * space. Unlike WMD_BRD_Write, this API does reset the DSP
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * dwDSPAddr: Address on DSP board (Destination).
+ * pHostBuf: Pointer to host buffer (Source).
+ * ulNumBytes: Number of bytes to transfer.
+ * ulMemType: Memory space on DSP to which to transfer.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * pHostBuf != NULL.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_BRD_MEMWRITE) (struct WMD_DEV_CONTEXT
+ *hDevContext,
+ IN u8 *pHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes,
+ u32 ulMemType);
+
+/*
+ * ======== WMD_BRD_MemMap ========
+ * Purpose:
+ * Map a MPU memory region to a DSP/IVA memory space
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * ulMpuAddr: MPU memory region start address.
+ * ulVirtAddr: DSP/IVA memory region u8 address.
+ * ulNumBytes: Number of bytes to map.
+ * mapAttrs: Mapping attributes (e.g. endianness).
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_BRD_MEMMAP) (struct WMD_DEV_CONTEXT
+ *hDevContext, u32 ulMpuAddr,
+ u32 ulVirtAddr, u32 ulNumBytes,
+ u32 ulMapAttrs);
+
+/*
+ * ======== WMD_BRD_MemUnMap ========
+ * Purpose:
+ * UnMap an MPU memory region from DSP/IVA memory space
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * ulVirtAddr: DSP/IVA memory region u8 address.
+ * ulNumBytes: Number of bytes to unmap.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_BRD_MEMUNMAP) (struct WMD_DEV_CONTEXT
+ *hDevContext,
+ u32 ulVirtAddr,
+ u32 ulNumBytes);
+
+/*
+ * ======== WMD_BRD_Stop ========
+ * Purpose:
+ * Bring board to the BRD_STOPPED state.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device context.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL
+ * Ensures:
+ * DSP_SOK: Board is in BRD_STOPPED (stop) state;
+ * Interrupts to the PC are disabled.
+ * else: Board state is indeterminate.
+ */
+ typedef DSP_STATUS(*WMD_BRD_STOP) (struct WMD_DEV_CONTEXT
+ *hDevContext);
+
+/*
+ * ======== WMD_BRD_Status ========
+ * Purpose:
+ * Report the current state of the board.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device context.
+ * pdwState: Ptr to BRD status variable.
+ * Returns:
+ * DSP_SOK:
+ * Requires:
+ * pdwState != NULL;
+ * hDevContext != NULL
+ * Ensures:
+ * *pdwState is one of {BRD_STOPPED, BRD_IDLE, BRD_RUNNING, BRD_UNKNOWN};
+ */
+ typedef DSP_STATUS(*
+ WMD_BRD_STATUS) (struct WMD_DEV_CONTEXT *hDevContext,
+ OUT BRD_STATUS * pdwState);
+
+/*
+ * ======== WMD_BRD_Read ========
+ * Purpose:
+ * Read a block of DSP memory, from a given memory space, into a host
+ * buffer.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * pHostBuf: Pointer to host buffer (Destination).
+ * dwDSPAddr: Address on DSP board (Source).
+ * ulNumBytes: Number of bytes to transfer.
+ * ulMemType: Memory space on DSP from which to transfer.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * pHostBuf != NULL.
+ * Ensures:
+ * Will not write more than ulNumBytes bytes into pHostBuf.
+ */
+typedef DSP_STATUS(*WMD_BRD_READ) (struct WMD_DEV_CONTEXT *hDevContext,
+ OUT u8 *pHostBuf,
+ u32 dwDSPAddr,
+ u32 ulNumBytes,
+ u32 ulMemType);
+
+/*
+ * ======== WMD_BRD_Write ========
+ * Purpose:
+ * Write a block of host memory into a DSP address, into a given memory
+ * space.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * dwDSPAddr: Address on DSP board (Destination).
+ * pHostBuf: Pointer to host buffer (Source).
+ * ulNumBytes: Number of bytes to transfer.
+ * ulMemType: Memory space on DSP to which to transfer.
+ * Returns:
+ * DSP_SOK: Success.
+ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
+ * DSP_EFAIL: Other, unspecified error.
+ * Requires:
+ * hDevContext != NULL;
+ * pHostBuf != NULL.
+ * Ensures:
+ */
+typedef DSP_STATUS(*WMD_BRD_WRITE)(struct WMD_DEV_CONTEXT *hDevContext,
+ IN u8 *pHostBuf,
+ u32 dwDSPAddr,
+ u32 ulNumBytes,
+ u32 ulMemType);
+
+/*
+ * ======== WMD_CHNL_Create ========
+ * Purpose:
+ * Create a channel manager object, responsible for opening new channels
+ * and closing old ones for a given 'Bridge board.
+ * Parameters:
+ * phChnlMgr: Location to store a channel manager object on output.
+ * hDevObject: Handle to a device object.
+ * pMgrAttrs: Channel manager attributes.
+ * pMgrAttrs->cChannels: Max channels
+ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
+ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
+ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
+ * pMgrAttrs->dwSMBase: Base physical address of shared memory, if any.
+ * pMgrAttrs->uSMLength: Bytes of shared memory block.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * CHNL_E_ISR: Unable to plug ISR for given IRQ.
+ * CHNL_E_NOMEMMAP: Couldn't map physical address to a virtual one.
+ * Requires:
+ * phChnlMgr != NULL.
+ * pMgrAttrs != NULL
+ * pMgrAttrs field are all valid:
+ * 0 < cChannels <= CHNL_MAXCHANNELS.
+ * bIRQ <= 15.
+ * uWordSize > 0.
+ * IsValidHandle(hDevObject)
+ * No channel manager exists for this board.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_CHNL_CREATE)(OUT struct CHNL_MGR
+ **phChnlMgr,
+ struct DEV_OBJECT
+ *hDevObject,
+ IN CONST struct
+ CHNL_MGRATTRS *pMgrAttrs);
+
+/*
+ * ======== WMD_CHNL_Destroy ========
+ * Purpose:
+ * Close all open channels, and destroy the channel manager.
+ * Parameters:
+ * hChnlMgr: Channel manager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: hChnlMgr was invalid.
+ * Requires:
+ * Ensures:
+ * DSP_SOK: Cancels I/O on each open channel. Closes each open channel.
+ * CHNL_Create may subsequently be called for the same device.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_DESTROY) (struct CHNL_MGR
+ *hChnlMgr);
+/*
+ * ======== WMD_DEH_Notify ========
+ * Purpose:
+ * When notified of DSP error, take appropriate action.
+ * Parameters:
+ * hDehMgr: Handle to DEH manager object.
+ * ulEventMask: Indicate the type of exception
+ * dwErrInfo: Error information
+ * Returns:
+ *
+ * Requires:
+ * hDehMgr != NULL;
+ * ulEventMask with a valid exception
+ * Ensures:
+ */
+ typedef void (*WMD_DEH_NOTIFY)(struct DEH_MGR *hDehMgr,
+ u32 ulEventMask, u32 dwErrInfo);
+
+
+/*
+ * ======== WMD_CHNL_Open ========
+ * Purpose:
+ * Open a new half-duplex channel to the DSP board.
+ * Parameters:
+ * phChnl: Location to store a channel object handle.
+ * hChnlMgr: Handle to channel manager, as returned by CHNL_GetMgr().
+ * uMode: One of {CHNL_MODETODSP, CHNL_MODEFROMDSP} specifies
+ * direction of data transfer.
+ * uChnlId: If CHNL_PICKFREE is specified, the channel manager will
+ * select a free channel id (default);
+ * otherwise this field specifies the id of the channel.
+ * pAttrs: Channel attributes. Attribute fields are as follows:
+ * pAttrs->uIOReqs: Specifies the maximum number of I/O requests which can
+ * be pending at any given time. All request packets are
+ * preallocated when the channel is opened.
+ * pAttrs->hEvent: This field allows the user to supply an auto reset
+ * event object for channel I/O completion notifications.
+ * It is the responsibility of the user to destroy this
+ * object AFTER closing the channel.
+ * This channel event object can be retrieved using
+ * CHNL_GetEventHandle().
+ * pAttrs->hReserved: The kernel mode handle of this event object.
+ *
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: hChnlMgr is invalid.
+ * DSP_EMEMORY: Insufficient memory for requested resources.
+ * DSP_EINVALIDARG: Invalid number of IOReqs.
+ * CHNL_E_OUTOFSTREAMS: No free channels available.
+ * CHNL_E_BADCHANID: Channel ID is out of range.
+ * CHNL_E_CHANBUSY: Channel is in use.
+ * CHNL_E_NOIORPS: No free IO request packets available for
+ * queuing.
+ * Requires:
+ * phChnl != NULL.
+ * pAttrs != NULL.
+ * pAttrs->hEvent is a valid event handle.
+ * pAttrs->hReserved is the kernel mode handle for pAttrs->hEvent.
+ * Ensures:
+ * DSP_SOK: *phChnl is a valid channel.
+ * else: *phChnl is set to NULL if (phChnl != NULL);
+ */
+ typedef DSP_STATUS(*WMD_CHNL_OPEN) (OUT struct CHNL_OBJECT
+ **phChnl,
+ struct CHNL_MGR *hChnlMgr,
+ CHNL_MODE uMode,
+ u32 uChnlId,
+ CONST IN OPTIONAL struct
+ CHNL_ATTRS *pAttrs);
+
+/*
+ * ======== WMD_CHNL_Close ========
+ * Purpose:
+ * Ensures all pending I/O on this channel is cancelled, discards all
+ * queued I/O completion notifications, then frees the resources allocated
+ * for this channel, and makes the corresponding logical channel id
+ * available for subsequent use.
+ * Parameters:
+ * hChnl: Handle to a channel object.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * Requires:
+ * No thread must be blocked on this channel's I/O completion event.
+ * Ensures:
+ * DSP_SOK: hChnl is no longer valid.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_CLOSE) (struct CHNL_OBJECT *hChnl);
+
+/*
+ * ======== WMD_CHNL_AddIOReq ========
+ * Purpose:
+ * Enqueue an I/O request for data transfer on a channel to the DSP.
+ * The direction (mode) is specified in the channel object. Note the DSP
+ * address is specified for channels opened in direct I/O mode.
+ * Parameters:
+ * hChnl: Channel object handle.
+ * pHostBuf: Host buffer address source.
+ * cBytes: Number of PC bytes to transfer. A zero value indicates
+ * that this buffer is the last in the output channel.
+ * A zero value is invalid for an input channel.
+ *! cBufSize: Actual buffer size in host bytes.
+ * dwDspAddr: DSP address for transfer. (Currently ignored).
+ * dwArg: A user argument that travels with the buffer.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * DSP_EPOINTER: pHostBuf is invalid.
+ * CHNL_E_NOEOS: User cannot mark EOS on an input channel.
+ * CHNL_E_CANCELLED: I/O has been cancelled on this channel. No further
+ * I/O is allowed.
+ * CHNL_E_EOS: End of stream was already marked on a previous
+ * IORequest on this channel. No further I/O is expected.
+ * CHNL_E_BUFSIZE: Buffer submitted to this output channel is larger than
+ * the size of the physical shared memory output window.
+ * Requires:
+ * Ensures:
+ * DSP_SOK: The buffer will be transferred if the channel is ready;
+ * otherwise, will be queued for transfer when the channel becomes
+ * ready. In any case, notifications of I/O completion are
+ * asynchronous.
+ * If cBytes is 0 for an output channel, subsequent CHNL_AddIOReq's
+ * on this channel will fail with error code CHNL_E_EOS. The
+ * corresponding IOC for this I/O request will have its status flag
+ * set to CHNL_IOCSTATEOS.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_ADDIOREQ) (struct CHNL_OBJECT
+ *hChnl,
+ void *pHostBuf,
+ u32 cBytes,
+ u32 cBufSize,
+ OPTIONAL u32 dwDspAddr,
+ u32 dwArg);
+
+/*
+ * ======== WMD_CHNL_GetIOC ========
+ * Purpose:
+ * Dequeue an I/O completion record, which contains information about the
+ * completed I/O request.
+ * Parameters:
+ * hChnl: Channel object handle.
+ * dwTimeOut: A value of CHNL_IOCNOWAIT will simply dequeue the
+ * first available IOC.
+ * pIOC: On output, contains host buffer address, bytes
+ * transferred, and status of I/O completion.
+ * pIOC->status: See chnldefs.h.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hChnl.
+ * DSP_EPOINTER: pIOC is invalid.
+ * CHNL_E_NOIOC: CHNL_IOCNOWAIT was specified as the dwTimeOut parameter
+ * yet no I/O completions were queued.
+ * Requires:
+ * dwTimeOut == CHNL_IOCNOWAIT.
+ * Ensures:
+ * DSP_SOK: if there are any remaining IOC's queued before this call
+ * returns, the channel event object will be left in a signalled
+ * state.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_GETIOC) (struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut,
+ OUT struct CHNL_IOC *pIOC);
+
+/*
+ * ======== WMD_CHNL_CancelIO ========
+ * Purpose:
+ * Return all I/O requests to the client which have not yet been
+ * transferred. The channel's I/O completion object is
+ * signalled, and all the I/O requests are queued as IOC's, with the
+ * status field set to CHNL_IOCSTATCANCEL.
+ * This call is typically used in abort situations, and is a prelude to
+ * CHNL_Close();
+ * Parameters:
+ * hChnl: Channel object handle.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * Requires:
+ * Ensures:
+ * Subsequent I/O requests to this channel will not be accepted.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_CANCELIO) (struct CHNL_OBJECT
+ *hChnl);
+
+/*
+ * ======== WMD_CHNL_FlushIO ========
+ * Purpose:
+ * For an output stream (to the DSP), indicates if any IO requests are in
+ * the output request queue. For input streams (from the DSP), will
+ * cancel all pending IO requests.
+ * Parameters:
+ * hChnl: Channel object handle.
+ * dwTimeOut: Timeout value for flush operation.
+ * Returns:
+ * DSP_SOK: Success;
+ * S_CHNLIOREQUEST: Returned if any IORequests are in the output queue.
+ * DSP_EHANDLE: Invalid hChnl.
+ * Requires:
+ * Ensures:
+ * DSP_SOK: No I/O requests will be pending on this channel.
+ */
+ typedef DSP_STATUS(*WMD_CHNL_FLUSHIO) (struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut);
+
+/*
+ * ======== WMD_CHNL_GetInfo ========
+ * Purpose:
+ * Retrieve information related to a channel.
+ * Parameters:
+ * hChnl: Handle to a valid channel object, or NULL.
+ * pInfo: Location to store channel info.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * DSP_EPOINTER: pInfo == NULL.
+ * Requires:
+ * Ensures:
+ * DSP_SOK: pInfo points to a filled in CHNL_INFO struct,
+ * if (pInfo != NULL).
+ */
+ typedef DSP_STATUS(*WMD_CHNL_GETINFO) (struct CHNL_OBJECT *hChnl,
+ OUT struct CHNL_INFO
+ *pChnlInfo);
+
+/*
+ * ======== WMD_CHNL_GetMgrInfo ========
+ * Purpose:
+ * Retrieve information related to the channel manager.
+ * Parameters:
+ * hChnlMgr: Handle to a valid channel manager, or NULL.
+ * uChnlID: Channel ID.
+ * pMgrInfo: Location to store channel manager info.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnlMgr.
+ * DSP_EPOINTER: pMgrInfo == NULL.
+ * CHNL_E_BADCHANID: Invalid channel ID.
+ * Requires:
+ * Ensures:
+ * DSP_SOK: pMgrInfo points to a filled in CHNL_MGRINFO
+ * struct, if (pMgrInfo != NULL).
+ */
+ typedef DSP_STATUS(*WMD_CHNL_GETMGRINFO) (struct CHNL_MGR
+ *hChnlMgr,
+ u32 uChnlID,
+ OUT struct CHNL_MGRINFO
+ *pMgrInfo);
+
+/*
+ * ======== WMD_CHNL_Idle ========
+ * Purpose:
+ * Idle a channel. If this is an input channel, or if this is an output
+ * channel and fFlush is TRUE, all currently enqueued buffers will be
+ * dequeued (data discarded for output channel).
+ * If this is an output channel and fFlush is FALSE, this function
+ * will block until all currently buffered data is output, or the timeout
+ * specified has been reached.
+ *
+ * Parameters:
+ * hChnl: Channel object handle.
+ * dwTimeOut: If output channel and fFlush is FALSE, timeout value
+ * to wait for buffers to be output. (Not used for
+ * input channel).
+ * fFlush: If output channel and fFlush is TRUE, discard any
+ * currently buffered data. If FALSE, wait for currently
+ * buffered data to be output, or timeout, whichever
+ * occurs first. fFlush is ignored for input channel.
+ * Returns:
+ * DSP_SOK: Success;
+ * DSP_EHANDLE: Invalid hChnl.
+ * CHNL_E_WAITTIMEOUT: Timeout occured before channel could be idled.
+ * Requires:
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_CHNL_IDLE) (struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut,
+ bool fFlush);
+
+/*
+ * ======== WMD_CHNL_RegisterNotify ========
+ * Purpose:
+ * Register for notification of events on a channel.
+ * Parameters:
+ * hChnl: Channel object handle.
+ * uEventMask: Type of events to be notified about: IO completion
+ * (DSP_STREAMIOCOMPLETION) or end of stream
+ * (DSP_STREAMDONE).
+ * uNotifyType: DSP_SIGNALEVENT.
+ * hNotification: Handle of a DSP_NOTIFICATION object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory.
+ * DSP_EVALUE: uEventMask is 0 and hNotification was not
+ * previously registered.
+ * DSP_EHANDLE: NULL hNotification, hNotification event name
+ * too long, or hNotification event name NULL.
+ * Requires:
+ * Valid hChnl.
+ * hNotification != NULL.
+ * (uEventMask & ~(DSP_STREAMIOCOMPLETION | DSP_STREAMDONE)) == 0.
+ * uNotifyType == DSP_SIGNALEVENT.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_CHNL_REGISTERNOTIFY)
+ (struct CHNL_OBJECT *hChnl,
+ u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification);
+
+/*
+ * ======== WMD_DEV_Create ========
+ * Purpose:
+ * Complete creation of the device object for this board.
+ * Parameters:
+ * phDevContext: Ptr to location to store a WMD device context.
+ * hDevObject: Handle to a Device Object, created and managed by WCD.
+ * pConfig: Ptr to configuration parameters provided by the Windows
+ * Configuration Manager during device loading.
+ * pDspConfig: DSP resources, as specified in the registry key for this
+ * device.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Unable to allocate memory for device context.
+ * WMD_E_BADCONFIG: One or more of the host or DSP configuration
+ * parameters did not satisfy hardware assumptions
+ * made by this WMD.
+ * Requires:
+ * phDevContext != NULL;
+ * hDevObject != NULL;
+ * pConfig != NULL;
+ * pDspConfig != NULL;
+ * Fields in pConfig and pDspConfig contain valid values.
+ * Ensures:
+ * DSP_SOK: All mini-driver specific DSP resource and other
+ * board context has been allocated.
+ * DSP_EMEMORY: WMD failed to allocate resources.
+ * Any acquired resources have been freed. The WCD will
+ * not call WMD_DEV_Destroy() if WMD_DEV_Create() fails.
+ * Details:
+ * Called during the CONFIGMG's Device_Init phase. Based on host and
+ * DSP configuration information, create a board context, a handle to
+ * which is passed into other WMD BRD and CHNL functions. The
+ * board context contains state information for the device. Since the
+ * addresses of all IN pointer parameters may be invalid when this
+ * function returns, they must not be stored into the device context
+ * structure.
+ */
+ typedef DSP_STATUS(*WMD_DEV_CREATE) (OUT struct WMD_DEV_CONTEXT
+ **phDevContext,
+ struct DEV_OBJECT
+ *hDevObject,
+ IN CONST struct CFG_HOSTRES
+ *pConfig,
+ IN CONST struct CFG_DSPRES
+ *pDspConfig);
+
+/*
+ * ======== WMD_DEV_Ctrl ========
+ * Purpose:
+ * Mini-driver specific interface.
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device info.
+ * dwCmd: WMD defined command code.
+ * pArgs: Pointer to an arbitrary argument structure.
+ * Returns:
+ * DSP_SOK or DSP_EFAIL. Actual command error codes should be passed back
+ * in the pArgs structure, and are defined by the WMD implementor.
+ * Requires:
+ * All calls are currently assumed to be synchronous. There are no
+ * IOCTL completion routines provided.
+ * Ensures:
+ */
+typedef DSP_STATUS(*WMD_DEV_CTRL)(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwCmd,
+ IN OUT void *pArgs);
+
+/*
+ * ======== WMD_DEV_Destroy ========
+ * Purpose:
+ * Deallocate WMD device extension structures and all other resources
+ * acquired by the mini-driver.
+ * No calls to other mini driver functions may subsequently
+ * occur, except for WMD_DEV_Create().
+ * Parameters:
+ * hDevContext: Handle to mini-driver defined device information.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Failed to release a resource previously acquired.
+ * Requires:
+ * hDevContext != NULL;
+ * Ensures:
+ * DSP_SOK: Device context is freed.
+ */
+ typedef DSP_STATUS(*WMD_DEV_DESTROY) (struct WMD_DEV_CONTEXT
+ *hDevContext);
+
+/*
+ * ======== WMD_DEH_Create ========
+ * Purpose:
+ * Create an object that manages DSP exceptions from the GPP.
+ * Parameters:
+ * phDehMgr: Location to store DEH manager on output.
+ * hDevObject: Handle to DEV object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EFAIL: Creation failed.
+ * Requires:
+ * hDevObject != NULL;
+ * phDehMgr != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_DEH_CREATE) (OUT struct DEH_MGR
+ **phDehMgr,
+ struct DEV_OBJECT
+ *hDevObject);
+
+/*
+ * ======== WMD_DEH_Destroy ========
+ * Purpose:
+ * Destroy the DEH object.
+ * Parameters:
+ * hDehMgr: Handle to DEH manager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Destroy failed.
+ * Requires:
+ * hDehMgr != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_DEH_DESTROY) (struct DEH_MGR *hDehMgr);
+
+/*
+ * ======== WMD_DEH_RegisterNotify ========
+ * Purpose:
+ * Register for DEH event notification.
+ * Parameters:
+ * hDehMgr: Handle to DEH manager object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Destroy failed.
+ * Requires:
+ * hDehMgr != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_DEH_REGISTERNOTIFY)
+ (struct DEH_MGR *hDehMgr,
+ u32 uEventMask, u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification);
+
+/*
+ * ======== WMD_DEH_GetInfo ========
+ * Purpose:
+ * Get DSP exception info.
+ * Parameters:
+ * phDehMgr: Location to store DEH manager on output.
+ * pErrInfo: Ptr to error info structure.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Creation failed.
+ * Requires:
+ * phDehMgr != NULL;
+ * pErrorInfo != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_DEH_GETINFO) (struct DEH_MGR *phDehMgr,
+ struct DSP_ERRORINFO *pErrInfo);
+
+/*
+ * ======== WMD_IO_Create ========
+ * Purpose:
+ * Create an object that manages I/O between CHNL and MSG.
+ * Parameters:
+ * phIOMgr: Location to store IO manager on output.
+ * hChnlMgr: Handle to channel manager.
+ * hMsgMgr: Handle to message manager.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EFAIL: Creation failed.
+ * Requires:
+ * hDevObject != NULL;
+ * Channel manager already created;
+ * Message manager already created;
+ * pMgrAttrs != NULL;
+ * phIOMgr != NULL;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_IO_CREATE) (OUT struct IO_MGR **phIOMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct IO_ATTRS *pMgrAttrs);
+
+/*
+ * ======== WMD_IO_Destroy ========
+ * Purpose:
+ * Destroy object created in WMD_IO_Create.
+ * Parameters:
+ * hIOMgr: IO Manager.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Memory allocation failure.
+ * DSP_EFAIL: Creation failed.
+ * Requires:
+ * Valid hIOMgr;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_IO_DESTROY) (struct IO_MGR *hIOMgr);
+
+/*
+ * ======== WMD_IO_OnLoaded ========
+ * Purpose:
+ * Called whenever a program is loaded to update internal data. For
+ * example, if shared memory is used, this function would update the
+ * shared memory location and address.
+ * Parameters:
+ * hIOMgr: IO Manager.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Internal failure occurred.
+ * Requires:
+ * Valid hIOMgr;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_IO_ONLOADED) (struct IO_MGR *hIOMgr);
+
+/*
+ * ======== WMD_IO_GETPROCLOAD ========
+ * Purpose:
+ * Called to get the Processor's current and predicted load
+ * Parameters:
+ * hIOMgr: IO Manager.
+ * pProcLoadStat Processor Load statistics
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EFAIL: Internal failure occurred.
+ * Requires:
+ * Valid hIOMgr;
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_IO_GETPROCLOAD)(struct IO_MGR *hIOMgr,
+ struct DSP_PROCLOADSTAT *pProcLoadStat);
+
+/*
+ * ======== WMD_MSG_Create ========
+ * Purpose:
+ * Create an object to manage message queues. Only one of these objects
+ * can exist per device object.
+ * Parameters:
+ * phMsgMgr: Location to store MSG manager on output.
+ * hDevObject: Handle to a device object.
+ * msgCallback: Called whenever an RMS_EXIT message is received.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory.
+ * Requires:
+ * phMsgMgr != NULL.
+ * msgCallback != NULL.
+ * hDevObject != NULL.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_MSG_CREATE)
+ (OUT struct MSG_MGR **phMsgMgr,
+ struct DEV_OBJECT *hDevObject,
+ MSG_ONEXIT msgCallback);
+
+/*
+ * ======== WMD_MSG_CreateQueue ========
+ * Purpose:
+ * Create a MSG queue for sending or receiving messages from a Message
+ * node on the DSP.
+ * Parameters:
+ * hMsgMgr: MSG queue manager handle returned from
+ * WMD_MSG_Create.
+ * phMsgQueue: Location to store MSG queue on output.
+ * dwId: Identifier for messages (node environment pointer).
+ * uMaxMsgs: Max number of simultaneous messages for the node.
+ * h: Handle passed to hMsgMgr->msgCallback().
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory.
+ * Requires:
+ * phMsgQueue != NULL.
+ * h != NULL.
+ * uMaxMsgs > 0.
+ * Ensures:
+ * phMsgQueue !=NULL <==> DSP_SOK.
+ */
+ typedef DSP_STATUS(*WMD_MSG_CREATEQUEUE)
+ (struct MSG_MGR *hMsgMgr,
+ OUT struct MSG_QUEUE **phMsgQueue,
+ u32 dwId, u32 uMaxMsgs, HANDLE h);
+
+/*
+ * ======== WMD_MSG_Delete ========
+ * Purpose:
+ * Delete a MSG manager allocated in WMD_MSG_Create().
+ * Parameters:
+ * hMsgMgr: Handle returned from WMD_MSG_Create().
+ * Returns:
+ * Requires:
+ * Valid hMsgMgr.
+ * Ensures:
+ */
+ typedef void(*WMD_MSG_DELETE) (struct MSG_MGR *hMsgMgr);
+
+/*
+ * ======== WMD_MSG_DeleteQueue ========
+ * Purpose:
+ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
+ * Parameters:
+ * hMsgQueue: Handle to MSG queue returned from
+ * WMD_MSG_CreateQueue.
+ * Returns:
+ * Requires:
+ * Valid hMsgQueue.
+ * Ensures:
+ */
+ typedef void(*WMD_MSG_DELETEQUEUE) (struct MSG_QUEUE *hMsgQueue);
+
+/*
+ * ======== WMD_MSG_Get ========
+ * Purpose:
+ * Get a message from a MSG queue.
+ * Parameters:
+ * hMsgQueue: Handle to MSG queue returned from
+ * WMD_MSG_CreateQueue.
+ * pMsg: Location to copy message into.
+ * uTimeout: Timeout to wait for a message.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETIMEOUT: Timeout occurred.
+ * DSP_EFAIL: No frames available for message (uMaxMessages too
+ * small).
+ * Requires:
+ * Valid hMsgQueue.
+ * pMsg != NULL.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_MSG_GET) (struct MSG_QUEUE *hMsgQueue,
+ struct DSP_MSG *pMsg,
+ u32 uTimeout);
+
+/*
+ * ======== WMD_MSG_Put ========
+ * Purpose:
+ * Put a message onto a MSG queue.
+ * Parameters:
+ * hMsgQueue: Handle to MSG queue returned from
+ * WMD_MSG_CreateQueue.
+ * pMsg: Pointer to message.
+ * uTimeout: Timeout to wait for a message.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_ETIMEOUT: Timeout occurred.
+ * DSP_EFAIL: No frames available for message (uMaxMessages too
+ * small).
+ * Requires:
+ * Valid hMsgQueue.
+ * pMsg != NULL.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_MSG_PUT) (struct MSG_QUEUE *hMsgQueue,
+ IN CONST struct DSP_MSG *pMsg,
+ u32 uTimeout);
+
+/*
+ * ======== WMD_MSG_RegisterNotify ========
+ * Purpose:
+ * Register notification for when a message is ready.
+ * Parameters:
+ * hMsgQueue: Handle to MSG queue returned from
+ * WMD_MSG_CreateQueue.
+ * uEventMask: Type of events to be notified about: Must be
+ * DSP_NODEMESSAGEREADY, or 0 to unregister.
+ * uNotifyType: DSP_SIGNALEVENT.
+ * hNotification: Handle of notification object.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Insufficient memory.
+ * Requires:
+ * Valid hMsgQueue.
+ * hNotification != NULL.
+ * uNotifyType == DSP_SIGNALEVENT.
+ * uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0.
+ * Ensures:
+ */
+ typedef DSP_STATUS(*WMD_MSG_REGISTERNOTIFY)
+ (struct MSG_QUEUE *hMsgQueue,
+ u32 uEventMask, u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification);
+
+/*
+ * ======== WMD_MSG_SetQueueId ========
+ * Purpose:
+ * Set message queue id to node environment. Allows WMD_MSG_CreateQueue
+ * to be called in NODE_Allocate, before the node environment is known.
+ * Parameters:
+ * hMsgQueue: Handle to MSG queue returned from
+ * WMD_MSG_CreateQueue.
+ * dwId: Node environment pointer.
+ * Returns:
+ * Requires:
+ * Valid hMsgQueue.
+ * dwId != 0.
+ * Ensures:
+ */
+ typedef void(*WMD_MSG_SETQUEUEID) (struct MSG_QUEUE *hMsgQueue,
+ u32 dwId);
+
+/*
+ * 'Bridge Mini Driver (WMD) interface function table.
+ *
+ * The information in this table is filled in by the specific mini-driver,
+ * and copied into the 'Bridge class driver's own space. If any interface
+ * function field is set to a value of NULL, then the class driver will
+ * consider that function not implemented, and return the error code
+ * DSP_ENOTIMPL when a WMD client attempts to call that function.
+ *
+ * This function table contains WCD version numbers, which are used by the
+ * WMD loader to help ensure backwards compatility between older WMD's and a
+ * newer 'Bridge Class Driver. These must be set to WCD_MAJOR_VERSION
+ * and WCD_MINOR_VERSION, respectively.
+ *
+ * A mini-driver need not export a CHNL interface. In this case, *all* of
+ * the WMD_CHNL_* entries must be set to NULL.
+ */
+ struct WMD_DRV_INTERFACE {
+ u32 dwWCDMajorVersion; /* Set to WCD_MAJOR_VERSION. */
+ u32 dwWCDMinorVersion; /* Set to WCD_MINOR_VERSION. */
+ WMD_DEV_CREATE pfnDevCreate; /* Create device context */
+ WMD_DEV_DESTROY pfnDevDestroy; /* Destroy device context */
+ WMD_DEV_CTRL pfnDevCntrl; /* Optional vendor interface */
+ WMD_BRD_MONITOR pfnBrdMonitor; /* Load and/or start monitor */
+ WMD_BRD_START pfnBrdStart; /* Start DSP program. */
+ WMD_BRD_STOP pfnBrdStop; /* Stop/reset board. */
+ WMD_BRD_STATUS pfnBrdStatus; /* Get current board status. */
+ WMD_BRD_READ pfnBrdRead; /* Read board memory */
+ WMD_BRD_WRITE pfnBrdWrite; /* Write board memory. */
+ WMD_BRD_SETSTATE pfnBrdSetState; /* Sets the Board State */
+ WMD_BRD_MEMCOPY pfnBrdMemCopy; /* Copies DSP Memory */
+ WMD_BRD_MEMWRITE pfnBrdMemWrite; /* Write DSP Memory w/o halt */
+ WMD_BRD_MEMMAP pfnBrdMemMap; /* Maps MPU mem to DSP mem */
+ WMD_BRD_MEMUNMAP pfnBrdMemUnMap; /* Unmaps MPU mem to DSP mem */
+ WMD_CHNL_CREATE pfnChnlCreate; /* Create channel manager. */
+ WMD_CHNL_DESTROY pfnChnlDestroy; /* Destroy channel manager. */
+ WMD_CHNL_OPEN pfnChnlOpen; /* Create a new channel. */
+ WMD_CHNL_CLOSE pfnChnlClose; /* Close a channel. */
+ WMD_CHNL_ADDIOREQ pfnChnlAddIOReq; /* Req I/O on a channel. */
+ WMD_CHNL_GETIOC pfnChnlGetIOC; /* Wait for I/O completion. */
+ WMD_CHNL_CANCELIO pfnChnlCancelIO; /* Cancl I/O on a channel. */
+ WMD_CHNL_FLUSHIO pfnChnlFlushIO; /* Flush I/O. */
+ WMD_CHNL_GETINFO pfnChnlGetInfo; /* Get channel specific info */
+ /* Get channel manager info. */
+ WMD_CHNL_GETMGRINFO pfnChnlGetMgrInfo;
+ WMD_CHNL_IDLE pfnChnlIdle; /* Idle the channel */
+ /* Register for notif. */
+ WMD_CHNL_REGISTERNOTIFY pfnChnlRegisterNotify;
+ WMD_DEH_CREATE pfnDehCreate; /* Create DEH manager */
+ WMD_DEH_DESTROY pfnDehDestroy; /* Destroy DEH manager */
+ WMD_DEH_NOTIFY pfnDehNotify; /* Notify of DSP error */
+ /* register for deh notif. */
+ WMD_DEH_REGISTERNOTIFY pfnDehRegisterNotify;
+ WMD_DEH_GETINFO pfnDehGetInfo; /* register for deh notif. */
+ WMD_IO_CREATE pfnIOCreate; /* Create IO manager */
+ WMD_IO_DESTROY pfnIODestroy; /* Destroy IO manager */
+ WMD_IO_ONLOADED pfnIOOnLoaded; /* Notify of program loaded */
+ /* Get Processor's current and predicted load */
+ WMD_IO_GETPROCLOAD pfnIOGetProcLoad;
+ WMD_MSG_CREATE pfnMsgCreate; /* Create message manager */
+ /* Create message queue */
+ WMD_MSG_CREATEQUEUE pfnMsgCreateQueue;
+ WMD_MSG_DELETE pfnMsgDelete; /* Delete message manager */
+ /* Delete message queue */
+ WMD_MSG_DELETEQUEUE pfnMsgDeleteQueue;
+ WMD_MSG_GET pfnMsgGet; /* Get a message */
+ WMD_MSG_PUT pfnMsgPut; /* Send a message */
+ /* Register for notif. */
+ WMD_MSG_REGISTERNOTIFY pfnMsgRegisterNotify;
+ /* Set message queue id */
+ WMD_MSG_SETQUEUEID pfnMsgSetQueueId;
+ } ;
+
+/*
+ * ======== WMD_DRV_Entry ========
+ * Purpose:
+ * Registers WMD functions with the class driver. Called only once
+ * by the WCD. The caller will first check WCD version compatibility, and
+ * then copy the interface functions into its own memory space.
+ * Parameters:
+ * ppDrvInterface Pointer to a location to receive a pointer to the
+ * mini driver interface.
+ * Returns:
+ * Requires:
+ * The code segment this function resides in must expect to be discarded
+ * after completion.
+ * Ensures:
+ * ppDrvInterface pointer initialized to WMD's function interface.
+ * No system resources are acquired by this function.
+ * Details:
+ * Win95: Called during the Device_Init phase.
+ */
+ void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
+ IN CONST char *pstrWMDFileName);
+
+#endif /* WMD_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wmdchnl.h b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
new file mode 100644
index 000000000000..2c1f072ff5e6
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
@@ -0,0 +1,90 @@
+/*
+ * wmdchnl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmdchnl.h ========
+ * Description:
+ * Declares the upper edge channel class library functions required by
+ * all WMD / WCD driver interface tables. These functions are implemented
+ * by every class of WMD channel library.
+ *
+ * Public Functions:
+ *
+ * Notes:
+ * The function comment headers reside with the function typedefs in wmd.h.
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
+ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
+ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream
+ *! support.
+ *! 11-Jul-1996 gp: Created.
+ */
+
+#ifndef WMDCHNL_
+#define WMDCHNL_
+
+ extern DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CHNL_MGRATTRS
+ *pMgrAttrs);
+
+ extern DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
+
+ extern DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
+ struct CHNL_MGR *hChnlMgr,
+ CHNL_MODE uMode,
+ u32 uChnlId,
+ CONST IN OPTIONAL struct CHNL_ATTRS
+ *pAttrs);
+
+ extern DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl);
+
+ extern DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl,
+ void *pHostBuf,
+ u32 cBytes, u32 cBufSize,
+ OPTIONAL u32 dwDspAddr,
+ u32 dwArg);
+
+ extern DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut,
+ OUT struct CHNL_IOC *pIOC);
+
+ extern DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl);
+
+ extern DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut);
+
+ extern DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
+ OUT struct CHNL_INFO *pInfo);
+
+ extern DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr,
+ u32 uChnlID,
+ OUT struct CHNL_MGRINFO
+ *pMgrInfo);
+
+ extern DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl,
+ u32 dwTimeOut, bool fFlush);
+
+ extern DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl,
+ u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+#endif /* WMDCHNL_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wmddeh.h b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
new file mode 100644
index 000000000000..60704da248d5
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
@@ -0,0 +1,66 @@
+/*
+ * wmddeh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmddeh.h ========
+ * Description:
+ * Defines upper edge DEH functions required by all WMD/WCD driver
+ * interface tables.
+ *
+ * Public Functions:
+ * WMD_DEH_Create
+ * IVA_DEH_Create
+ * WMD_DEH_Destroy
+ * WMD_DEH_GetInfo
+ * WMD_DEH_RegisterNotify
+ * WMD_DEH_Notify
+ *
+ * Notes:
+ * Function comment headers reside with the function typedefs in wmd.h.
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Dec-2004 hn: added IVA_DEH_Create.
+ *! 13-Sep-2001 kc: created.
+ */
+
+#ifndef WMDDEH_
+#define WMDDEH_
+
+#include <dspbridge/devdefs.h>
+
+#include <dspbridge/dehdefs.h>
+
+ extern DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
+ struct DEV_OBJECT *hDevObject);
+
+ extern DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr);
+
+ extern DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
+ struct DSP_ERRORINFO *pErrInfo);
+
+ extern DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr,
+ u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+ extern void WMD_DEH_Notify(struct DEH_MGR *hDehMgr,
+ u32 ulEventMask, u32 dwErrInfo);
+
+ extern void WMD_DEH_ReleaseDummyMem(void);
+#endif /* WMDDEH_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wmdio.h b/arch/arm/plat-omap/include/dspbridge/wmdio.h
new file mode 100644
index 000000000000..85254745d8cf
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmdio.h
@@ -0,0 +1,53 @@
+/*
+ * wmdio.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmdio.h ========
+ * Description:
+ * Declares the upper edge IO functions required by
+ * all WMD / WCD driver interface tables.
+ *
+ * Public Functions:
+ *
+ * Notes:
+ * Function comment headers reside with the function typedefs in wmd.h.
+ *
+ *! Revision History:
+ *! ================
+ *! 27-Feb-2004 vp Added IVA releated function.
+ *! 06-Nov-2000 jeh Created.
+ */
+
+#ifndef WMDIO_
+#define WMDIO_
+
+#include <dspbridge/devdefs.h>
+#include <dspbridge/iodefs.h>
+
+ extern DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct IO_ATTRS *pMgrAttrs);
+
+ extern DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr);
+
+ extern DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr);
+
+ extern DSP_STATUS IVA_IO_OnLoaded(struct IO_MGR *hIOMgr);
+ extern DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
+ OUT struct DSP_PROCLOADSTAT *pProcStat);
+
+#endif /* WMDIO_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/wmdioctl.h b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
new file mode 100644
index 000000000000..a41c61aa38eb
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
@@ -0,0 +1,91 @@
+/*
+ * wmdioctl.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmdioctl.h ========
+ * Description:
+ * BRIDGE Minidriver BRD_IOCtl reserved command definitions.
+ *
+ *! Revision History
+ *! ================
+ *! 19-Apr-2004 sb Updated HW typedefs
+ *! 16-Feb-2004 vp Added MMU endianness attributes to WMDIOCTL_EXTPROC
+ *! 21-Mar-2003 sb Changed WMDIOCTL_NUMOFMMUTLB from 7 to 32
+ *! 14-May-2001 sg Added codes for PWR.
+ *! 10-Aug-2001 ag Added _SETMMUCONFIG ioctl used for DSP-MMU init.
+ *! 16-Nov-1999 rajesh ?
+ *! 18-Jun-1998 ag Moved EMIF, SDRAM_C, & CE space init to ENBLEXTMEM ioctl.
+ *! Added ENBLEXTMEM, RESETDSP, UNRESETDSP & ASSERTSIG ioctls.
+ *! 07-Jun-1998 ag Added JTAG_SELECT, MAP_TBC, GET_CONFIGURATION ioctls.
+ *! 26-Jan-1998 jeh: Added START, RECV, and SEND ioctls.
+ *! 07-Nov-1997 nn: Added command to interrupt DSP for interrupt test.
+ *! 20-Oct-1997 nn: Added commands for getting and resetting interrupt count.
+ *! 17-Oct-1997 gp: Moved to src/wmd. Standardized prefix.
+ *! 08-Oct-1997 nn: Created.
+ */
+
+#ifndef WMDIOCTL_
+#define WMDIOCTL_
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/* Any IOCTLS at or above this value are reserved for standard WMD interfaces.*/
+#define WMDIOCTL_RESERVEDBASE 0x8000
+
+#define WMDIOCTL_CHNLREAD (WMDIOCTL_RESERVEDBASE + 0x10)
+#define WMDIOCTL_CHNLWRITE (WMDIOCTL_RESERVEDBASE + 0x20)
+#define WMDIOCTL_GETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x30)
+#define WMDIOCTL_RESETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x40)
+#define WMDIOCTL_INTERRUPTDSP (WMDIOCTL_RESERVEDBASE + 0x50)
+#define WMDIOCTL_SETMMUCONFIG (WMDIOCTL_RESERVEDBASE + 0x60) /* DMMU */
+#define WMDIOCTL_PWRCONTROL (WMDIOCTL_RESERVEDBASE + 0x70) /* PWR */
+
+/* attention, modifiers:
+ * Some of these control enumerations are made visible to user for power
+ * control, so any changes to this list, should also be updated in the user
+ * header file 'dbdefs.h' ***/
+/* These ioctls are reserved for PWR power commands for the DSP */
+#define WMDIOCTL_DEEPSLEEP (WMDIOCTL_PWRCONTROL + 0x0)
+#define WMDIOCTL_EMERGENCYSLEEP (WMDIOCTL_PWRCONTROL + 0x1)
+#define WMDIOCTL_WAKEUP (WMDIOCTL_PWRCONTROL + 0x2)
+#define WMDIOCTL_PWRENABLE (WMDIOCTL_PWRCONTROL + 0x3)
+#define WMDIOCTL_PWRDISABLE (WMDIOCTL_PWRCONTROL + 0x4)
+#define WMDIOCTL_CLK_CTRL (WMDIOCTL_PWRCONTROL + 0x7)
+#define WMDIOCTL_PWR_HIBERNATE (WMDIOCTL_PWRCONTROL + 0x8) /*DSP Initiated
+ * Hibernate*/
+#define WMDIOCTL_PRESCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0x9)
+#define WMDIOCTL_POSTSCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0xA)
+#define WMDIOCTL_CONSTRAINT_REQUEST (WMDIOCTL_PWRCONTROL + 0xB)
+
+/* Number of actual DSP-MMU TLB entrries */
+#define WMDIOCTL_NUMOFMMUTLB 32
+
+struct WMDIOCTL_EXTPROC {
+ u32 ulDspVa; /* DSP virtual address */
+ u32 ulGppPa; /* GPP physical address */
+ /* GPP virtual address. __va does not work for ioremapped addresses */
+ u32 ulGppVa;
+ u32 ulSize; /* Size of the mapped memory in bytes */
+ enum HW_Endianism_t endianism;
+ enum HW_MMUMixedSize_t mixedMode;
+ enum HW_ElementSize_t elemSize;
+};
+
+#endif /* WMDIOCTL_ */
+
diff --git a/arch/arm/plat-omap/include/dspbridge/wmdmsg.h b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
new file mode 100644
index 000000000000..81198d47173b
--- /dev/null
+++ b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
@@ -0,0 +1,70 @@
+/*
+ * wmdmsg.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== wmdmsg.h ========
+ * Description:
+ * Declares the upper edge message class library functions required by
+ * all WMD / WCD driver interface tables. These functions are
+ * implemented by every class of WMD channel library.
+ *
+ * Public Functions:
+ *
+ * Notes:
+ * Function comment headers reside with the function typedefs in wmd.h.
+ *
+ *! Revision History:
+ *! ================
+ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify(). Added
+ *! WMD_MSG_SetQueueId().
+ *! 17-Nov-2000 jeh Created.
+ */
+
+#ifndef WMDMSG_
+#define WMDMSG_
+
+#include <dspbridge/msgdefs.h>
+
+ extern DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
+ struct DEV_OBJECT *hDevObject,
+ MSG_ONEXIT msgCallback);
+
+ extern DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
+ OUT struct MSG_QUEUE **phMsgQueue,
+ u32 dwId, u32 uMaxMsgs,
+ HANDLE h);
+
+ extern void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr);
+
+ extern void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue);
+
+ extern DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
+ struct DSP_MSG *pMsg, u32 uTimeout);
+
+ extern DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
+ IN CONST struct DSP_MSG *pMsg,
+ u32 uTimeout);
+
+ extern DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue,
+ u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION
+ *hNotification);
+
+ extern void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId);
+
+#endif /* WMDMSG_ */
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 4b8b0d65cbf2..7661abd9902c 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -65,6 +65,10 @@ struct dpll_data {
u8 recal_en_bit;
u8 recal_st_bit;
# endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+ struct clk *clk_hsd_bypass;
+#endif
};
#endif
@@ -156,6 +160,7 @@ extern const struct clkops clkops_null;
#define RATE_IN_243X (1 << 2)
#define RATE_IN_343X (1 << 3) /* rates common to all 343X */
#define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */
+#define RATE_IN_443X (1 << 5)
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h
index b9d0dd2da89b..ec45dffaec34 100644
--- a/arch/arm/plat-omap/include/mach/clockdomain.h
+++ b/arch/arm/plat-omap/include/mach/clockdomain.h
@@ -1,13 +1,15 @@
/*
* arch/arm/plat-omap/include/mach/clockdomain.h
*
- * OMAP2/3 clockdomain framework functions
+ * OMAP2/3/4 clockdomain framework functions
*
* Copyright (C) 2008 Texas Instruments, Inc.
* Copyright (C) 2008 Nokia Corporation
*
* Written by Paul Walmsley
*
+ * Updated with OMAP4 specific supprot by Abhijit Pagare <abhijitpagare@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.
@@ -34,7 +36,7 @@
#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO 0x0
#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO 0x1
-/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
+/* OMAP3XXX and OMAP44xx CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO 0x0
#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP 0x1
#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP 0x2
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h
index fdeab421b4dc..878c4f96c2d3 100644
--- a/arch/arm/plat-omap/include/mach/common.h
+++ b/arch/arm/plat-omap/include/mach/common.h
@@ -55,6 +55,7 @@ struct omap_globals {
void __iomem *ctrl; /* System Control Module */
void __iomem *prm; /* Power and Reset Management */
void __iomem *cm; /* Clock Management */
+ void __iomem *cm2;
};
void omap2_set_globals_242x(void);
diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h
index 8140dbccb7bc..e97a15c95ea8 100644
--- a/arch/arm/plat-omap/include/mach/control.h
+++ b/arch/arm/plat-omap/include/mach/control.h
@@ -25,10 +25,13 @@
IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
#define OMAP343X_CTRL_REGADDR(reg) \
IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#define OMAP44XX_CTRL_REGADDR(reg) \
+ IO_ADDRESS(OMAP44XX_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))
+#define OMAP44XX_CTRL_REGADDR(reg) IO_ADDRESS(OMAP44XX_CTRL_BASE + (reg))
#endif /* __ASSEMBLY__ */
/*
diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h
index 11e73d9e8928..3f5e62302dbb 100644
--- a/arch/arm/plat-omap/include/mach/cpu.h
+++ b/arch/arm/plat-omap/include/mach/cpu.h
@@ -264,6 +264,7 @@ IS_OMAP_SUBCLASS(343x, 0x343)
* cpu_is_omap2423(): True for OMAP2423
* cpu_is_omap2430(): True for OMAP2430
* cpu_is_omap3430(): True for OMAP3430
+ * cpu_is_omap4430(): True for OMAP4430
*/
#define GET_OMAP_TYPE ((omap_rev() >> 16) & 0xffff)
@@ -393,7 +394,7 @@ IS_OMAP_TYPE(3430, 0x3430)
#define OMAP3430_REV_ES3_0 0x34303034
#define OMAP3430_REV_ES3_1 0x34304034
-#define OMAP443X_CLASS 0x44300034
+#define OMAP443X_CLASS 0x44300044
/*
* omap_chip bits
@@ -416,6 +417,7 @@ IS_OMAP_TYPE(3430, 0x3430)
#define CHIP_IS_OMAP3430ES2 (1 << 4)
#define CHIP_IS_OMAP3430ES3_0 (1 << 5)
#define CHIP_IS_OMAP3430ES3_1 (1 << 6)
+#define CHIP_IS_OMAP4430 (1 << 7)
#define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
new file mode 100644
index 000000000000..9fd60a726599
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/display.h
@@ -0,0 +1,600 @@
+/*
+ * linux/include/asm-arm/arch-omap/display.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARCH_OMAP_DISPLAY_H
+#define __ASM_ARCH_OMAP_DISPLAY_H
+
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <asm/atomic.h>
+
+#define DISPC_IRQ_FRAMEDONE (1 << 0)
+ /* OMAP4: FRAMEDONE1: for prim LCD*/
+#define DISPC_IRQ_VSYNC (1 << 1)
+ /* OMAP4: VSYNC1: for prim LCD*/
+#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
+#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
+ /* OMAP4: ACBIAS1: for prim LCD*/
+#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
+#define DISPC_IRQ_GFX_END_WIN (1 << 7)
+#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
+#define DISPC_IRQ_OCP_ERR (1 << 9)
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
+#define DISPC_IRQ_VID1_END_WIN (1 << 11)
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
+#define DISPC_IRQ_VID2_END_WIN (1 << 13)
+#define DISPC_IRQ_SYNC_LOST (1 << 14)
+ /* OMAP4: SYNCLOST1: for prim LCD*/
+#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
+#define DISPC_IRQ_WAKEUP (1 << 16)
+
+#ifdef CONFIG_ARCH_OMAP4
+#define DISPC_IRQ_SYNC_LOST_2 (1 << 17)
+#define DISPC_IRQ_VSYNC2 (1 << 18)
+#define DISPC_IRQ_VID3_END_WIN (1 << 19)
+#define DISPC_IRQ_VID3_FIFO_UNDERFLOW (1 << 20)
+ /* VID3_BUF_UNDERFLOW*/
+#define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21)
+#define DISPC_IRQ_FRAMEDONE2 (1 << 22)
+#define DISPC_IRQ_FRAMEDONE_WB (1 << 23)
+#define DISPC_IRQ_FRAMEDONE_DIG (1 << 24) /* FRAMEDONE_TV*/
+#define DISPC_IRQ_WB_BUF_OVERFLOW (1 << 25)
+#endif
+
+struct omap_dss_device;
+struct omap_overlay_manager;
+
+enum omap_display_type {
+ OMAP_DISPLAY_TYPE_NONE = 0,
+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
+ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
+ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
+ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
+ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
+};
+
+enum omap_plane {
+ OMAP_DSS_GFX = 0,
+ OMAP_DSS_VIDEO1 = 1,
+ OMAP_DSS_VIDEO2 = 2
+#ifdef CONFIG_ARCH_OMAP4
+ , OMAP_DSS_VIDEO3 = 3
+#endif
+};
+
+enum omap_channel {
+ OMAP_DSS_CHANNEL_LCD = 0,
+ OMAP_DSS_CHANNEL_DIGIT = 1,
+#ifdef CONFIG_ARCH_OMAP4
+ OMAP_DSS_CHANNEL_LCD2 = 2,
+#endif
+};
+
+enum omap_color_mode {
+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12x, 16-bit container */
+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
+
+#ifdef CONFIG_ARCH_OMAP4
+ OMAP_DSS_COLOR_NV12 = 1 << 14, /* NV12 format: YUV 4:2:0 */
+ OMAP_DSS_COLOR_RGBA12 = 1 << 15, /* RGBA12 - 4444 */
+ OMAP_DSS_COLOR_XRGB12 = 1 << 16, /* xRGB12, 16-bit container */
+ OMAP_DSS_COLOR_ARGB16_1555 = 1 << 17, /* ARGB16-1555 */
+ OMAP_DSS_COLOR_RGBX24_32_ALGN = 1 << 18, /* 32-msb aligned 24bit */
+ OMAP_DSS_COLOR_XRGB15 = 1 << 19, /* xRGB15: 1555*/
+#endif
+
+ OMAP_DSS_COLOR_GFX_OMAP3 =
+ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+ OMAP_DSS_COLOR_VID_OMAP3 =
+#ifdef CONFIG_ARCH_OMAP4
+ OMAP_DSS_COLOR_NV12 | OMAP_DSS_COLOR_RGBA12 |
+ OMAP_DSS_COLOR_XRGB12 | OMAP_DSS_COLOR_ARGB16_1555 |
+ OMAP_DSS_COLOR_RGBX24_32_ALGN | OMAP_DSS_COLOR_XRGB15 |
+#endif
+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
+ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+};
+
+enum omap_lcd_display_type {
+ OMAP_DSS_LCD_DISPLAY_STN,
+ OMAP_DSS_LCD_DISPLAY_TFT,
+};
+
+enum omap_dss_load_mode {
+ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
+ OMAP_DSS_LOAD_CLUT_ONLY = 1,
+ OMAP_DSS_LOAD_FRAME_ONLY = 2,
+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
+};
+
+enum omap_dss_trans_key_type {
+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+enum omap_rfbi_te_mode {
+ OMAP_DSS_RFBI_TE_MODE_1 = 1,
+ OMAP_DSS_RFBI_TE_MODE_2 = 2,
+};
+
+enum omap_panel_config {
+ OMAP_DSS_LCD_IVS = 1<<0,
+ OMAP_DSS_LCD_IHS = 1<<1,
+ OMAP_DSS_LCD_IPC = 1<<2,
+ OMAP_DSS_LCD_IEO = 1<<3,
+ OMAP_DSS_LCD_RF = 1<<4,
+ OMAP_DSS_LCD_ONOFF = 1<<5,
+
+ OMAP_DSS_LCD_TFT = 1<<20,
+};
+
+enum omap_dss_venc_type {
+ OMAP_DSS_VENC_TYPE_COMPOSITE,
+ OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+enum omap_display_caps {
+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
+};
+
+enum omap_dss_update_mode {
+ OMAP_DSS_UPDATE_DISABLED = 0,
+ OMAP_DSS_UPDATE_AUTO,
+ OMAP_DSS_UPDATE_MANUAL,
+};
+
+enum omap_dss_display_state {
+ OMAP_DSS_DISPLAY_DISABLED = 0,
+ OMAP_DSS_DISPLAY_ACTIVE,
+ OMAP_DSS_DISPLAY_SUSPENDED,
+};
+
+/* XXX perhaps this should be removed */
+enum omap_dss_overlay_managers {
+ OMAP_DSS_OVL_MGR_LCD,
+ OMAP_DSS_OVL_MGR_TV,
+#ifdef CONFIG_ARCH_OMAP4
+ OMAP_DSS_OVL_MGR_LCD2,
+#endif
+};
+
+enum omap_dss_rotation_type {
+ OMAP_DSS_ROT_DMA = 0,
+ OMAP_DSS_ROT_VRFB = 1,
+#ifdef CONFIG_ARCH_OMAP4
+ OMAP_DSS_ROT_TILER = 2,
+#endif
+};
+
+enum omap_overlay_caps {
+ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
+ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
+};
+
+enum omap_overlay_manager_caps {
+ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
+};
+
+#ifdef CONFIG_ARCH_OMAP4
+enum omap_overlay_zorder {
+ OMAP_DSS_OVL_ZORDER_0 = 0x0,
+ OMAP_DSS_OVL_ZORDER_1 = 0x1,
+ OMAP_DSS_OVL_ZORDER_2 = 0x2,
+ OMAP_DSS_OVL_ZORDER_3 = 0x3,
+};
+#endif
+
+/* RFBI */
+
+struct rfbi_timings {
+ int cs_on_time;
+ int cs_off_time;
+ int we_on_time;
+ int we_off_time;
+ int re_on_time;
+ int re_off_time;
+ int we_cycle_time;
+ int re_cycle_time;
+ int cs_pulse_width;
+ int access_time;
+
+ int clk_div;
+
+ u32 tim[5]; /* set by rfbi_convert_timings() */
+
+ int converted;
+};
+
+void omap_rfbi_write_command(const void *buf, u32 len);
+void omap_rfbi_read_data(void *buf, u32 len);
+void omap_rfbi_write_data(const void *buf, u32 len);
+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
+ u16 x, u16 y,
+ u16 w, u16 h);
+int omap_rfbi_enable_te(bool enable, unsigned line);
+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+ unsigned hs_pulse_time, unsigned vs_pulse_time,
+ int hs_pol_inv, int vs_pol_inv, int extif_div);
+
+/* DSI */
+void dsi_bus_lock(void);
+void dsi_bus_unlock(void);
+int dsi_vc_dcs_write(int channel, u8 *data, int len);
+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
+int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
+int dsi_vc_send_bta_sync(int channel);
+int dsi_vc_send_null(int channel);
+
+/* Board specific data */
+struct omap_dss_board_info {
+ int (*get_last_off_on_transaction_id)(struct device *dev);
+ int num_devices;
+ struct omap_dss_device **devices;
+ struct omap_dss_device *default_device;
+};
+
+struct omap_video_timings {
+ /* Unit: pixels */
+ u16 x_res;
+ /* Unit: pixels */
+ u16 y_res;
+ /* Unit: KHz */
+ u32 pixel_clock;
+ /* Unit: pixel clocks */
+ u16 hsw; /* Horizontal synchronization pulse width */
+ /* Unit: pixel clocks */
+ u16 hfp; /* Horizontal front porch */
+ /* Unit: pixel clocks */
+ u16 hbp; /* Horizontal back porch */
+ /* Unit: line clocks */
+ u16 vsw; /* Vertical synchronization pulse width */
+ /* Unit: line clocks */
+ u16 vfp; /* Vertical front porch */
+ /* Unit: line clocks */
+ u16 vbp; /* Vertical back porch */
+};
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+/* Hardcoded timings for tv modes. Venc only uses these to
+ * identify the mode, and does not actually use the configs
+ * itself. However, the configs should be something that
+ * a normal monitor can also show */
+const extern struct omap_video_timings omap_dss_pal_timings;
+const extern struct omap_video_timings omap_dss_ntsc_timings;
+#endif
+
+struct omap_overlay_info {
+ bool enabled;
+
+ u32 paddr;
+ void __iomem *vaddr;
+ u16 screen_width;
+ u16 width;
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
+ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+
+ u16 pos_x;
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
+ u8 global_alpha;
+#ifdef CONFIG_ARCH_OMAP4
+ u32 p_uv_addr; /* relevant for NV12 format only */
+ enum omap_overlay_zorder zorder;
+#endif
+};
+
+struct omap_overlay {
+ struct kobject kobj;
+ struct list_head list;
+
+ /* static fields */
+ const char *name;
+ int id;
+ enum omap_color_mode supported_modes;
+ enum omap_overlay_caps caps;
+
+ /* dynamic fields */
+ struct omap_overlay_manager *manager;
+ struct omap_overlay_info info;
+
+ /* if true, info has been changed, but not applied() yet */
+ bool info_dirty;
+
+ int (*set_manager)(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr);
+ int (*unset_manager)(struct omap_overlay *ovl);
+
+ int (*set_overlay_info)(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+ void (*get_overlay_info)(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+
+ int (*wait_for_go)(struct omap_overlay *ovl);
+};
+
+struct omap_overlay_manager_info {
+ u32 default_color;
+
+ enum omap_dss_trans_key_type trans_key_type;
+ u32 trans_key;
+ bool trans_enabled;
+
+ bool alpha_enabled;
+};
+
+struct omap_overlay_manager {
+ struct kobject kobj;
+ struct list_head list;
+
+ /* static fields */
+ const char *name;
+ int id;
+ enum omap_overlay_manager_caps caps;
+ int num_overlays;
+ struct omap_overlay **overlays;
+ enum omap_display_type supported_displays;
+
+ /* dynamic fields */
+ struct omap_dss_device *device;
+ struct omap_overlay_manager_info info;
+
+ bool device_changed;
+ /* if true, info has been changed but not applied() yet */
+ bool info_dirty;
+
+ int (*set_device)(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev);
+ int (*unset_device)(struct omap_overlay_manager *mgr);
+
+ int (*set_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+ void (*get_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+
+ int (*apply)(struct omap_overlay_manager *mgr);
+ int (*wait_for_go)(struct omap_overlay_manager *mgr);
+};
+
+struct omap_dss_device {
+ struct device dev;
+
+ enum omap_display_type type;
+
+ union {
+ struct {
+ u8 data_lines;
+ } dpi;
+
+ struct {
+ u8 channel;
+ u8 data_lines;
+ } rfbi;
+
+ struct {
+ u8 datapairs;
+ unsigned pad_off_pe:1; /* pull pads if disabled */
+ unsigned pad_off_pu:1; /* pull up */
+ } sdi;
+
+ struct {
+ u8 clk_lane;
+ u8 clk_pol;
+ u8 data1_lane;
+ u8 data1_pol;
+ u8 data2_lane;
+ u8 data2_pol;
+ unsigned long lp_clk_hz;
+ unsigned long ddr_clk_hz;
+
+ bool ext_te;
+ u8 ext_te_gpio;
+ } dsi;
+
+ struct {
+ enum omap_dss_venc_type type;
+ } venc;
+ } phy;
+
+ struct {
+ struct omap_video_timings timings;
+
+ int acbi; /* ac-bias pin transitions per interrupt */
+ /* Unit: line clocks */
+ int acb; /* ac-bias pin frequency */
+
+ enum omap_panel_config config;
+
+ u8 recommended_bpp;
+
+ struct omap_dss_device *ctrl;
+ } panel;
+
+ struct {
+ u8 pixel_size;
+ struct rfbi_timings rfbi_timings;
+ struct omap_dss_device *panel;
+ } ctrl;
+
+ int reset_gpio;
+
+ int max_backlight_level;
+
+ const char *name;
+
+ /* used to match device to driver */
+ const char *driver_name;
+
+ void *data;
+
+ struct omap_dss_driver *driver;
+
+ /* helper variable for driver suspend/resume */
+ bool activate_after_resume;
+
+ enum omap_display_caps caps;
+
+ struct omap_overlay_manager *manager;
+
+ enum omap_dss_display_state state;
+
+ enum omap_channel channel;
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*disable)(struct omap_dss_device *dssdev);
+
+ int (*suspend)(struct omap_dss_device *dssdev);
+ int (*resume)(struct omap_dss_device *dssdev);
+
+ void (*get_resolution)(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres);
+ int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
+
+ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+ int (*update)(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h);
+ int (*sync)(struct omap_dss_device *dssdev);
+ int (*wait_vsync)(struct omap_dss_device *dssdev);
+
+ int (*set_update_mode)(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode);
+ enum omap_dss_update_mode (*get_update_mode)
+ (struct omap_dss_device *dssdev);
+
+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
+ int (*get_te)(struct omap_dss_device *dssdev);
+ int (*wait_for_te)(struct omap_dss_device *dssdev);
+
+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
+
+ bool (*get_mirror)(struct omap_dss_device *dssdev);
+ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
+
+ int (*run_test)(struct omap_dss_device *dssdev, int test);
+ int (*memory_read)(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h);
+
+ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
+ u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+ /* platform specific */
+ int (*platform_enable)(struct omap_dss_device *dssdev);
+ void (*platform_disable)(struct omap_dss_device *dssdev);
+ int (*set_backlight)(struct omap_dss_device *dssdev, int level);
+ int (*get_backlight)(struct omap_dss_device *dssdev);
+};
+
+struct omap_dss_driver {
+ struct device_driver driver;
+
+ int (*probe)(struct omap_dss_device *);
+ void (*remove)(struct omap_dss_device *);
+
+ int (*enable)(struct omap_dss_device *display);
+ void (*disable)(struct omap_dss_device *display);
+ int (*suspend)(struct omap_dss_device *display);
+ int (*resume)(struct omap_dss_device *display);
+ int (*run_test)(struct omap_dss_device *display, int test);
+
+ void (*setup_update)(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h);
+
+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
+ int (*wait_for_te)(struct omap_dss_device *dssdev);
+
+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
+
+ bool (*get_mirror)(struct omap_dss_device *dssdev);
+ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
+
+ int (*memory_read)(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h);
+};
+
+int omap_dss_register_driver(struct omap_dss_driver *);
+void omap_dss_unregister_driver(struct omap_dss_driver *);
+
+int omap_dss_register_device(struct omap_dss_device *);
+void omap_dss_unregister_device(struct omap_dss_device *);
+
+void omap_dss_get_device(struct omap_dss_device *dssdev);
+void omap_dss_put_device(struct omap_dss_device *dssdev);
+#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
+struct omap_dss_device *omap_dss_find_device(void *data,
+ int (*match)(struct omap_dss_device *dssdev, void *data));
+
+int omap_dss_start_device(struct omap_dss_device *dssdev);
+void omap_dss_stop_device(struct omap_dss_device *dssdev);
+
+int omap_dss_get_num_overlay_managers(void);
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
+
+int omap_dss_get_num_overlays(void);
+struct omap_overlay *omap_dss_get_overlay(int num);
+
+typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+
+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout);
+
+#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
+#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
+
+#endif
diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h
index 923cf213f316..afddb8256341 100755
--- a/arch/arm/plat-omap/include/mach/dma.h
+++ b/arch/arm/plat-omap/include/mach/dma.h
@@ -112,8 +112,12 @@
#define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22)
#define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24)
#define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */
+#define OMAP1_DMA_COLOR(n) 0
#define OMAP1_DMA_CCEN(n) 0
#define OMAP1_DMA_CCFN(n) 0
+#define OMAP1_DMA_CDP(n) 0
+#define OMAP1_DMA_CNDP(n) 0
+#define OMAP1_DMA_CCDN(n) 0
/* Channel specific registers only on omap2 */
#define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c)
@@ -122,15 +126,17 @@
#define OMAP_DMA4_CCFN(n) (0x60 * (n) + 0xc0)
#define OMAP_DMA4_COLOR(n) (0x60 * (n) + 0xc4)
-#define OMAP_DMA4_CDP_REG(n) (0x60 * (n) + 0xd0)
-#define OMAP_DMA4_CNDP_REG(n) (0x60 * (n) + 0xd4)
-#define OMAP_DMA4_CCDN_REG(n) (0x60 * (n) + 0xd8)
+#define OMAP_DMA4_CDP(n) (0x60 * (n) + 0xd0)
+#define OMAP_DMA4_CNDP(n) (0x60 * (n) + 0xd4)
+#define OMAP_DMA4_CCDN(n) (0x60 * (n) + 0xd8)
/* Dummy defines to keep multi-omap compiles happy */
#define OMAP1_DMA_REVISION 0
#define OMAP1_DMA_IRQSTATUS_L0 0
#define OMAP1_DMA_IRQENABLE_L0 0
#define OMAP1_DMA_OCP_SYSCONFIG 0
+#define OMAP1_DMA_CAPS_0 0
+
#define OMAP_DMA4_HW_ID 0
#define OMAP_DMA4_CAPS_0_L 0
#define OMAP_DMA4_CAPS_0_U 0
@@ -335,6 +341,7 @@
#define OMAP44XX_DMA_UART4_DMA_TX 55 /* S_DMA_54 */
#define OMAP44XX_DMA_UART4_DMA_RX 56 /* S_DMA_55 */
#define OMAP44XX_DMA_MMC4_DMA_TX 57 /* S_DMA_56 */
+#define OMAP44XX_DMA_MMC4_DMA_RX 58 /* S_DMA_57 */
#define OMAP44XX_DMA_MMC5_DMA_TX 59 /* S_DMA_58 */
#define OMAP44XX_DMA_MMC5_DMA_RX 60 /* S_DMA_59 */
#define OMAP44XX_DMA_MCPDM_UP 65 /* S_DMA_64 */
@@ -551,6 +558,83 @@ struct omap_dma_channel_params {
#endif
};
+struct omap_dma_sglist_type1_params {
+ u32 src_addr;
+ u32 dst_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+ u32 color;
+ u32 csdp;
+ u32 clnk_ctrl;
+ u32 ccr;
+};
+
+struct omap_dma_sglist_type2a_params {
+ u32 src_addr;
+ u32 dst_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type2b_params {
+ u32 src_or_dest_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type3a_params {
+ u32 src_addr;
+ u32 dst_addr;
+};
+
+struct omap_dma_sglist_type3b_params {
+ u32 src_or_dest_addr;
+};
+
+enum omap_dma_sglist_descriptor_select {
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
+};
+
+union omap_dma_sglist_node_type{
+ struct omap_dma_sglist_type1_params t1;
+ struct omap_dma_sglist_type2a_params t2a;
+ struct omap_dma_sglist_type2b_params t2b;
+ struct omap_dma_sglist_type3a_params t3a;
+ struct omap_dma_sglist_type3b_params t3b;
+};
+
+struct omap_dma_sglist_node {
+
+ /* Common elements for all descriptors */
+ u32 next_desc_add_ptr;
+ u32 num_of_elem;
+ /* Type specific elements */
+ union omap_dma_sglist_node_type sg_node;
+ /* Control fields */
+ int flags;
+ /* Fields that can be set in flags variable */
+ #define OMAP_DMA_LIST_SRC_VALID (1)
+ #define OMAP_DMA_LIST_DST_VALID (2)
+ #define OMAP_DMA_LIST_NOTIFY_BLOCK_END (4)
+ u32 desc_type;
+ struct omap_dma_sglist_node *next;
+};
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name,
@@ -630,6 +714,59 @@ extern int omap_modify_dma_chain_params(int chain_id,
struct omap_dma_channel_params params);
extern int omap_dma_chain_status(int chain_id);
#endif
+/* omap_request_dma_sglist:
+ * Request to setup a DMA channel to transfer in linked list mode of nelem
+ * elements. The memory for the list will be allocated and returned in
+ * elems structure
+ */
+extern int omap_request_dma_sglist(int dev_id, const char *dev_name,
+ void (*callback) (int channel_id, u16 ch_status, void *data),
+ int *listid, int nelem, struct omap_dma_sglist_node **elems);
+/* omap_set_dma_sglist_params
+ * Provide the configuration parameters for the sglist channel
+ * sghead should contain a fully populated list of nelems
+ * which completely describe the transfer. chparams, if not NULL, will
+ * set the appropriate parameters directly into the DMA register.
+ * If chparams is NULL, fastmode will be enabled automatically
+ */
+extern int omap_set_dma_sglist_params(const int listid,
+ struct omap_dma_sglist_node *sghead,
+ struct omap_dma_channel_params *chparams);
+/* omap_start_dma_sglist_transfers
+ * Starts the linked list based DMA transfer for the specified listid
+ * If no pause is required, -1 is to be set in pauseafter.
+ * Else, the transfer will suspend after pauseafter elements.
+ */
+extern int omap_start_dma_sglist_transfers(const int listid,
+ const int pauseafter);
+/* omap_resume_dma_sglist_transfers
+ * Resumes the previously paused transfer.
+ * Can be again set to pause at pauseafter node of the linked list
+ * The index is absolute (from the head of the list)
+ */
+extern int omap_resume_dma_sglist_transfers(const int listid,
+ const int pauseafter);
+/* omap_release_dma_sglist
+ * Releases the list based DMA channel and the associated list descriptors
+ */
+extern int omap_release_dma_sglist(const int listid);
+/* omap_get_completed_sglist_nodes
+ * Returns the number of completed elements in the linked list
+ * The value is transient if the API is invoked for an ongoing transfer
+ */
+int omap_get_completed_sglist_nodes(const int listid);
+/* omap_dma_sglist_is_paused
+ * Returns non zero if the linked list is currently in pause state
+ */
+int omap_dma_sglist_is_paused(const int listid);
+/* omap_dma_set_sglist_fastmode
+ * Set or clear the fastmode status of the transfer
+ * In fastmode, DMA register settings are updated from the first element
+ * of the linked list, before initiating the tranfer.
+ * In non-fastmode, the first element is used only after completing the
+ * transfer as already configured in the registers
+ */
+void omap_dma_set_sglist_fastmode(const int listid, const int fastmode);
/* LCD DMA functions */
extern int omap_request_lcd_dma(void (*callback)(u16 status, void *data),
diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h
index fb7cb7723990..8725136695c5 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -503,6 +503,7 @@
#define INT_44XX_FPKA_READY_IRQ (50 + IRQ_GIC_START)
#define INT_44XX_SHA1MD51_IRQ (51 + IRQ_GIC_START)
#define INT_44XX_RNG_IRQ (52 + IRQ_GIC_START)
+#define INT_44XX_MMC5_IRQ (59 + IRQ_GIC_START)
#define INT_44XX_I2C3_IRQ (61 + IRQ_GIC_START)
#define INT_44XX_FPKA_ERROR_IRQ (64 + IRQ_GIC_START)
#define INT_44XX_PBIAS_IRQ (75 + IRQ_GIC_START)
@@ -511,7 +512,10 @@
#define INT_44XX_TLL_IRQ (78 + IRQ_GIC_START)
#define INT_44XX_PARTHASH_IRQ (79 + IRQ_GIC_START)
#define INT_44XX_MMC3_IRQ (94 + IRQ_GIC_START)
-
+#define INT_44XX_MMC4_IRQ (96 + IRQ_GIC_START)
+#define INT_44XX_MCPDM_IRQ (112 + IRQ_GIC_START)
+#define INT_44XX_SYS_NIRQ2 (119 + IRQ_GIC_START)
+#define INT_44XX_DUCATI_MMU_IRQ (100 + IRQ_GIC_START)
/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and
* 16 MPUIO lines */
@@ -551,8 +555,20 @@
#endif
#define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS)
+#define TWL6030_IRQ_BASE (OMAP_FPGA_IRQ_END)
+#ifdef CONFIG_TWL6030_CORE
+#define TWL6030_BASE_NR_IRQS 20
+#else
+#define TWL6030_BASE_NR_IRQS 0
+#endif
+#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
+
/* Total number of interrupts depends on the enabled blocks above */
+#ifdef CONFIG_TWL4030_CORE
#define NR_IRQS TWL4030_GPIO_IRQ_END
+#else
+#define NR_IRQS TWL6030_IRQ_END
+#endif
#define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32))
diff --git a/arch/arm/plat-omap/include/mach/mailbox.h b/arch/arm/plat-omap/include/mach/mailbox.h
index b7a6991814ec..b11d8f363f42 100644
--- a/arch/arm/plat-omap/include/mach/mailbox.h
+++ b/arch/arm/plat-omap/include/mach/mailbox.h
@@ -8,7 +8,6 @@
#include <linux/blkdev.h>
typedef u32 mbox_msg_t;
-typedef void (mbox_receiver_t)(mbox_msg_t msg);
struct omap_mbox;
typedef int __bitwise omap_mbox_irq_t;
@@ -29,8 +28,10 @@ struct omap_mbox_ops {
int (*fifo_empty)(struct omap_mbox *mbox);
int (*fifo_full)(struct omap_mbox *mbox);
/* irq */
- void (*enable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
- void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+ void (*enable_irq)(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq);
+ void (*disable_irq)(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq);
void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
/* ctx */
@@ -64,7 +65,7 @@ struct omap_mbox {
void (*err_notify)(void);
};
-int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg, void *);
+int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
void omap_mbox_init_seq(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *);
@@ -93,4 +94,16 @@ static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
mbox->ops->restore_ctx(mbox);
}
+static inline void omap_mbox_enable_irq(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq)
+{
+ mbox->ops->enable_irq(mbox, irq);
+}
+
+static inline void omap_mbox_disable_irq(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq)
+{
+ mbox->ops->disable_irq(mbox, irq);
+}
+
#endif /* MAILBOX_H */
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h
index bb154ea76769..ec6f81e06d39 100644
--- a/arch/arm/plat-omap/include/mach/mcbsp.h
+++ b/arch/arm/plat-omap/include/mach/mcbsp.h
@@ -53,6 +53,11 @@
#define OMAP34XX_MCBSP4_BASE 0x49026000
#define OMAP34XX_MCBSP5_BASE 0x48096000
+#define OMAP44XX_MCBSP1_BASE 0x49022000
+#define OMAP44XX_MCBSP2_BASE 0x49024000
+#define OMAP44XX_MCBSP3_BASE 0x49026000
+#define OMAP44XX_MCBSP4_BASE 0x48074000
+
#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
#define OMAP_MCBSP_REG_DRR2 0x00
@@ -98,7 +103,8 @@
#define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX
#define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX
-#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+ defined(CONFIG_ARCH_OMAP4)
#define OMAP_MCBSP_REG_DRR2 0x00
#define OMAP_MCBSP_REG_DRR1 0x04
diff --git a/arch/arm/plat-omap/include/mach/mcspi.h b/arch/arm/plat-omap/include/mach/mcspi.h
index 1254e4945b6f..c065ce72d433 100644
--- a/arch/arm/plat-omap/include/mach/mcspi.h
+++ b/arch/arm/plat-omap/include/mach/mcspi.h
@@ -1,8 +1,24 @@
#ifndef _OMAP2_MCSPI_H
#define _OMAP2_MCSPI_H
+#define OMAP2_MCSPI_MASTER 0
+#define OMAP2_MCSPI_SLAVE 1
+
struct omap2_mcspi_platform_config {
unsigned short num_cs;
+
+ /* SPI is master or slave */
+ unsigned short mode;
+
+ /* Use only DMA for data transfers */
+ unsigned short dma_mode;
+
+ /* Force chip select mode */
+ unsigned short force_cs_mode;
+
+ /* FIFO depth in bytes, max value 64 */
+ unsigned short fifo_depth;
+
};
struct omap2_mcspi_device_config {
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h
index 81d5b36534b3..c84a6d43bf90 100644
--- a/arch/arm/plat-omap/include/mach/mmc.h
+++ b/arch/arm/plat-omap/include/mach/mmc.h
@@ -25,11 +25,18 @@
#define OMAP24XX_NR_MMC 2
#define OMAP34XX_NR_MMC 3
+#define OMAP44XX_NR_MMC 5
#define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE
-#define HSMMC_SIZE 0x200
+#define OMAP3_HSMMC_SIZE 0x200
+#define OMAP4_HSMMC_SIZE 0x1000
#define OMAP2_MMC1_BASE 0x4809c000
#define OMAP2_MMC2_BASE 0x480b4000
#define OMAP3_MMC3_BASE 0x480ad000
+#define OMAP4_MMC4_BASE 0x480d1000
+#define OMAP4_MMC5_BASE 0x480d5000
+#define OMAP4_MMC_REG_OFFSET 0x100
+#define HSMMC5 (1 << 4)
+#define HSMMC4 (1 << 3)
#define HSMMC3 (1 << 2)
#define HSMMC2 (1 << 1)
#define HSMMC1 (1 << 0)
diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h
index 80281c458baf..2390c40a6636 100644
--- a/arch/arm/plat-omap/include/mach/mux.h
+++ b/arch/arm/plat-omap/include/mach/mux.h
@@ -208,7 +208,7 @@ struct pin_config {
const unsigned int mux_reg;
unsigned char debug;
-#if defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
u16 mux_val; /* Wake-up, off mode, pull, mux mode */
#endif
@@ -859,6 +859,89 @@ enum omap34xx_index {
H17_34XX_SDRC_CKE1,
};
+enum omap44xx_index {
+
+ AA3_4430_McSPI1_CLK,
+ Y2_4430_McSPI1_SIMO,
+ Y3_4430_McSPI1_SOMI,
+ Y4_4430_McSPI1_CS0,
+ Y4_4430_McSPI1_CS1,
+ Y4_4430_McSPI1_CS2,
+ Y4_4430_McSPI1_CS3,
+
+ AA3_4430_McBSP1_CLK,
+ Y2_4430_McBSP1_DX,
+ Y3_4430_McBSP1_DR,
+ Y4_4430_McBSP1_FSX,
+
+ PAD0_4430_UNIPRO_TX0,
+ PAD1_4430_UNIPRO_TY0,
+ PAD0_4430_UNIPRO_TX1,
+ PAD1_4430_UNIPRO_TY1,
+ PAD0_4430_UNIPRO_TX2,
+ PAD1_4430_UNIPRO_TY2,
+ PAD0_4430_UNIPRO_RX0,
+ PAD1_4430_UNIPRO_RY0,
+ PAD0_4430_UNIPRO_RX1,
+ PAD1_4430_UNIPRO_RY1,
+ PAD0_4430_UNIPRO_RX2,
+ PAD1_4430_UNIPRO_RY2,
+
+ A1_4430_MMC1_CLK,
+ C1_4430_MMC1_CMD,
+ D0_4430_MMC1_DAT0,
+ D1_4430_MMC1_DAT1,
+ D2_4430_MMC1_DAT2,
+ D3_4430_MMC1_DAT3,
+ D4_4430_MMC1_DAT4,
+ D5_4430_MMC1_DAT5,
+ D6_4430_MMC1_DAT6,
+ D7_4430_MMC1_DAT7,
+
+ A1_4430_MMC2_CLK,
+ C1_4430_MMC2_CMD,
+ D0_4430_MMC2_DAT0,
+ D1_4430_MMC2_DAT1,
+ D2_4430_MMC2_DAT2,
+ D3_4430_MMC2_DAT3,
+ D4_4430_MMC2_DAT4,
+ D5_4430_MMC2_DAT5,
+ D6_4430_MMC2_DAT6,
+ D7_4430_MMC2_DAT7,
+
+ A1_4430_MMC3_CLK,
+ C1_4430_MMC3_CMD,
+ D0_4430_MMC3_DAT0,
+ D1_4430_MMC3_DAT1,
+ D2_4430_MMC3_DAT2,
+ D3_4430_MMC3_DAT3,
+
+ A1_4430_MMC4_CLK,
+ C1_4430_MMC4_CMD,
+ D0_4430_MMC4_DAT0,
+ D1_4430_MMC4_DAT1,
+ D2_4430_MMC4_DAT2,
+ D3_4430_MMC4_DAT3,
+
+ A1_4430_MMC5_CLK,
+ C1_4430_MMC5_CMD,
+ D0_4430_MMC5_DAT0,
+ D1_4430_MMC5_DAT1,
+ D2_4430_MMC5_DAT2,
+ D3_4430_MMC5_DAT3,
+
+ PAD1_4430_SYS_NIRQ1,
+ PAD0_4430_SYS_NIRQ2,
+
+ AG25_4430_ABE_PDM_UL_DATA,
+ AF25_4430_ABE_PDM_DL_DATA,
+ AE25_4430_ABE_PDM_FRAME,
+ AF26_4430_ABE_PDM_LB_CLK,
+ AH26_4430_ABE_PDM_CLKS,
+ AA27_4430_GPIO_127,
+
+};
+
struct omap_mux_cfg {
struct pin_config *pins;
unsigned long size;
diff --git a/arch/arm/plat-omap/include/mach/omap-serial.h b/arch/arm/plat-omap/include/mach/omap-serial.h
new file mode 100644
index 000000000000..b2ab2bcea7a2
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/omap-serial.h
@@ -0,0 +1,156 @@
+/*
+ * arch/arm/plat-omap/include/mach/omap-serial.h
+ *
+ * Driver for OMAP3430 UART controller.
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * Authors:
+ * Govindraj R <govindraj.raja@ti.com>
+ * Thara Gopinath <thara@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.
+ */
+
+#ifndef __OMAP_SERIAL_H__
+#define __OMAP_SERIAL_H__
+
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+#include <../arch/arm/mach-omap2/prm.h>
+#include <../arch/arm/mach-omap2/pm.h>
+#include <../arch/arm/mach-omap2/prm-regbits-34xx.h>
+#include <mach/control.h>
+#endif
+
+/* TI OMAP CONSOLE */
+#define PORT_OMAP 86
+#define DRIVER_NAME "omap-hsuart"
+
+/* tty device name used by omap-serial driver,
+ * in bootargs we specify as console=ttyO0 if uart1
+ * is used as console uart.
+ */
+#define DEVICE_NAME "ttyO"
+
+/*
+ * We default to IRQ0 for the "no irq" hack. Some
+ * machine types want others as well - they're free
+ * to redefine this in their header file.
+ */
+#define is_real_interrupt(irq) ((irq) != 0)
+
+#if defined(CONFIG_SERIAL_OMAP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#define OMAP_MDR1_DISABLE 0x07
+#define OMAP_MDR1_MODE13X 0x03
+#define OMAP_MDR1_MODE16X 0x00
+#define OMAP_MODE13X_SPEED 230400
+
+#define CONSOLE_NAME "console="
+
+#define UART_CLK (48000000)
+#define QUART_CLK (1843200)
+
+#define QUART (0x3)
+
+#define SLEEP_TIMEOUT (5 * HZ)
+#define RX_TIMEOUT (3 * HZ)
+
+struct uart_dma_info {
+ int dma_enabled;
+ int rx_dma_bufsize;
+ int rx_timeout;
+ };
+
+struct omap_uart_state {
+ int clocked;
+ struct clk *ick;
+ struct clk *fck;
+ int num;
+ int can_sleep;
+
+ void __iomem *wk_st;
+ void __iomem *wk_en;
+ u32 wk_mask;
+ u32 padconf;
+
+#ifdef CONFIG_PM
+ struct timer_list timer;
+ u32 timeout;
+ int context_valid;
+ /* Registers to be saved/restored for OFF-mode */
+ u16 dll;
+ u16 dlh;
+ u16 ier;
+ u16 sysc;
+ u16 scr;
+ u16 wer;
+#endif
+};
+
+struct uart_omap_dma {
+ u8 uart_dma_tx;
+ u8 uart_dma_rx;
+ int rx_dma_channel;
+ int tx_dma_channel;
+ /* Physical adress of RX DMA buffer */
+ dma_addr_t rx_buf_dma_phys;
+ /* Physical adress of TX DMA buffer */
+ dma_addr_t tx_buf_dma_phys;
+ /*
+ * Buffer for rx dma.It is not required for tx because the buffer
+ * comes from port structure
+ */
+ unsigned int uart_base;
+ unsigned char *rx_buf;
+ unsigned int prev_rx_dma_pos;
+ int tx_buf_size;
+ int tx_dma_state;
+ int rx_dma_state;
+ spinlock_t tx_lock;
+ spinlock_t rx_lock;
+ /* timer to poll activity on rx dma */
+ struct timer_list rx_timer;
+ int rx_buf_size;
+ int rx_timeout;
+};
+
+struct uart_omap_port {
+ struct uart_port port;
+ struct uart_omap_dma uart_dma;
+ struct platform_device *pdev;
+
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char fcr;
+ unsigned char efr;
+
+ int use_dma;
+ int is_buf_dma_alloced;
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+ unsigned int lsr_break_flag;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+ char name[20];
+ spinlock_t uart_lock;
+ unsigned long port_activity;
+};
+
+extern void omap_uart_idle_init(int num);
+extern char *saved_command_line;
+
+extern void omap_serial_early_init(void);
+
+#endif /* __OMAP_SERIAL_H__ */
diff --git a/arch/arm/plat-omap/include/mach/omap44xx.h b/arch/arm/plat-omap/include/mach/omap44xx.h
index 713b6d26f9eb..75d596e859ea 100644
--- a/arch/arm/plat-omap/include/mach/omap44xx.h
+++ b/arch/arm/plat-omap/include/mach/omap44xx.h
@@ -25,11 +25,13 @@
#define L3_ABE_44XX_BASE 0x49000000
#define OMAP4430_32KSYNCT_BASE 0x4a304000
-#define OMAP4430_CM_BASE 0x4a004000
-#define OMAP4430_PRM_BASE 0x48306000
+#define OMAP4430_CM1_BASE 0x4A004000
+#define OMAP4430_CM_BASE OMAP4430_CM1_BASE
+#define OMAP4430_CM2_BASE 0x4A008000
+#define OMAP4430_PRM_BASE 0x4A306000
#define OMAP44XX_GPMC_BASE 0x50000000
#define OMAP443X_SCM_BASE 0x4a002000
-#define OMAP443X_CTRL_BASE OMAP443X_SCM_BASE
+#define OMAP443X_CTRL_BASE 0x4A100000
#define OMAP44XX_IC_BASE 0x48200000
#define OMAP44XX_IVA_INTC_BASE 0x40000000
#define IRQ_SIR_IRQ 0x0040
@@ -46,5 +48,7 @@
#define OMAP44XX_L2CACHE_BASE 0x48242000
#define OMAP44XX_VA_L2CACHE_BASE 0x48242000
+#define OMAP44xx_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
+
#endif /* __ASM_ARCH_OMAP44XX_H */
diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h
index 69c9e675d8ee..6e65266fe1ae 100644
--- a/arch/arm/plat-omap/include/mach/powerdomain.h
+++ b/arch/arm/plat-omap/include/mach/powerdomain.h
@@ -43,16 +43,16 @@
/*
- * Number of memory banks that are power-controllable. On OMAP3430, the
- * maximum is 4.
+ * Number of memory banks that are power-controllable. On OMAP4430, the
+ * maximum is 5.
*/
-#define PWRDM_MAX_MEM_BANKS 4
+#define PWRDM_MAX_MEM_BANKS 5
/*
* Maximum number of clockdomains that can be associated with a powerdomain.
- * CORE powerdomain on OMAP3 is the worst case
+ * CORE powerdomain on OMAP4 is the worst case
*/
-#define PWRDM_MAX_CLKDMS 4
+#define PWRDM_MAX_CLKDMS 9
/* XXX A completely arbitrary number. What is reasonable here? */
#define PWRDM_TRANSITION_BAILOUT 100000
diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
new file mode 100644
index 000000000000..8639e08c5efa
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/vram.h
@@ -0,0 +1,34 @@
+/*
+ * File: arch/arm/plat-omap/include/mach/vram.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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 __OMAPVRAM_H
+#define __OMAPVRAM_H
+
+#include <asm/types.h>
+
+extern int omap_vram_add_region(unsigned long paddr, size_t size);
+extern int omap_vram_free(unsigned long paddr, size_t size);
+extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+extern int omap_vram_reserve(unsigned long paddr, size_t size);
+extern void omap2_set_sdram_vram(u32 size, u32 start);
+extern void omap2_set_sram_vram(u32 size, u32 start);
+
+#endif
diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
new file mode 100644
index 000000000000..9647d82c1cdd
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/vrfb.h
@@ -0,0 +1,51 @@
+/*
+ * File: arch/arm/plat-omap/include/mach/vrfb.h
+ *
+ * VRFB
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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 __VRFB_H
+#define __VRFB_H
+
+#include <mach/display.h>
+#define OMAP_VRFB_LINE_LEN 2048
+
+struct vrfb
+{
+ u8 context;
+ void __iomem *vaddr[4];
+ unsigned long paddr[4];
+ u16 xoffset;
+ u16 yoffset;
+ u8 bytespp;
+};
+
+extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp);
+extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode);
+extern void omap_vrfb_restore_context(void);
+
+#endif /* __VRFB_H */
diff --git a/arch/arm/plat-omap/include/syslink/GlobalTypes.h b/arch/arm/plat-omap/include/syslink/GlobalTypes.h
new file mode 100755
index 000000000000..6cd959cde952
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/GlobalTypes.h
@@ -0,0 +1,154 @@
+/*
+ * GlobalTypes.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef __GLOBALTYPES_H
+#define __GLOBALTYPES_H
+
+#define REG volatile
+
+/*
+ * Definition: RET_CODE_BASE
+ *
+ * DESCRIPTION: Base value for return code offsets
+ *
+ *
+ */
+#define RET_CODE_BASE 0
+
+/*
+ * TYPE: ReturnCode_t
+ *
+ * DESCRIPTION: Return codes to be returned by all library functions
+ *
+ *
+ */
+enum ReturnCode_label {
+RET_OK = 0,
+RET_FAIL = -1,
+RET_BAD_NULL_PARAM = -2,
+RET_PARAM_OUT_OF_RANGE = -3,
+RET_INVALID_ID = -4,
+RET_EMPTY = -5,
+RET_FULL = -6,
+RET_TIMEOUT = -7,
+RET_INVALID_OPERATION = -8,
+/* Add new error codes at end of above list */
+RET_NUM_RET_CODES /* this should ALWAYS be LAST entry */
+};
+
+
+
+/*
+ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
+ *
+ * DESCRIPTION: 32 bit register access macros
+ *
+ *
+ */
+#define RD_MEM_32_VOLATILE(addr) \
+((unsigned long)(*((REG unsigned long *)(addr))))
+
+#define WR_MEM_32_VOLATILE(addr, data) \
+(*((REG unsigned long *)(addr)) = (unsigned long)(data))
+
+
+
+
+#ifdef CHECK_INPUT_PARAMS
+/*
+ * MACRO: CHECK_INPUT_PARAMS
+ *
+ * DESCRIPTION: Checks an input code and returns a specified value if code is
+ * invalid value, also writes spy value if error found.
+ *
+ * NOTE: Can be disabled to save HW cycles.
+ *
+ *
+ */
+#define CHECK_INPUT_PARAM(actualValue, invalidValue, \
+returnCodeIfMismatch, spyCodeIfMisMatch) do {\
+ if ((invalidValue) == (actualValue)) {\
+ RES_Set((spyCodeIfMisMatch));\
+ return returnCodeIfMismatch; \
+ } \
+} while (0)
+
+/*
+ * MACRO: CHECK_INPUT_RANGE
+ *
+ * DESCRIPTION: Checks an input value and returns a specified value if not in
+ * specified range, also writes spy value if error found.
+ *
+* NOTE: Can be disabled to save HW cycles.
+ *
+ *
+ */
+#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue, \
+returnCodeIfMismatch, spyCodeIfMisMatch) do {\
+ if (((actualValue) < (minValidValue)) || \
+ ((actualValue) > (maxValidValue))) {\
+ RES_Set((spyCodeIfMisMatch));\
+ return returnCodeIfMismatch; \
+ } \
+} while (0)
+
+/*
+ * MACRO: CHECK_INPUT_RANGE_MIN0
+ *
+ * DESCRIPTION: Checks an input value and returns a
+ * specified value if not in
+ * specified range, also writes spy value if error found.
+ * The minimum
+ * value is 0.
+ *
+ * NOTE: Can be disabled to save HW cycles.
+ *
+ *
+ */
+#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue, \
+returnCodeIfMismatch, spyCodeIfMisMatch) do {\
+ if ((actualValue) > (maxValidValue)) {\
+ RES_Set((spyCodeIfMisMatch));\
+ return returnCodeIfMismatch; \
+ } \
+} while (0)
+
+#else
+
+#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
+spyCodeIfMisMatch)
+
+#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue, \
+returnCodeIfMismatch)
+
+#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue, \
+returnCodeIfMismatch, spyCodeIfMisMatch)
+
+#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue , \
+maxValidValue, returnCodeIfMismatch)
+
+#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue, \
+returnCodeIfMismatch, spyCodeIfMisMatch)
+
+#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, \
+maxValidValue, returnCodeIfMismatch)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __GLOBALTYPES_H */
diff --git a/arch/arm/plat-omap/include/syslink/MBXAccInt.h b/arch/arm/plat-omap/include/syslink/MBXAccInt.h
new file mode 100755
index 000000000000..84e333d0d5da
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MBXAccInt.h
@@ -0,0 +1,550 @@
+/*
+ * MBXAccInt.h
+ *
+ * Notify mailbox driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#ifndef _MLB_ACC_INT_H
+#define _MLB_ACC_INT_H
+
+
+/*
+ * EXPORTED DEFINITIONS
+ *
+ */
+
+
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (unsigned long)(0x0040)
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (unsigned long)(0x0004)
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_BANKS (unsigned long)(16)
+
+/* Register offset address definitions relative
+to register set MAILBOX_MESSAGE___REGSET_0_15 */
+
+#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (unsigned long)(0x0)
+
+
+/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15
+address offset, bank address increment and number of banks */
+
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (unsigned long)(0x0080)
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (unsigned long)(0x0004)
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_BANKS (unsigned long)(16)
+
+/* Register offset address definitions relative to
+register set MAILBOX_FIFOSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (unsigned long)(0x0)
+
+
+/* Register set MAILBOX_MSGSTATUS___REGSET_0_15
+address offset, bank address increment and number of banks */
+
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (unsigned long)(0x00c0)
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (unsigned long)(0x0004)
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_BANKS (unsigned long)(16)
+
+/* Register offset address definitions relative to
+register set MAILBOX_MSGSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (unsigned long)(0x0)
+
+
+/*Register set MAILBOX_IRQSTATUS___REGSET_0_3 address
+offset, bank address increment and number of banks */
+
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (unsigned long)(0x0100)
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (unsigned long)(0x0008)
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_BANKS (unsigned long)(4)
+
+#define MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_OFFSET (unsigned long)(0x0104)
+#define MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_STEP (unsigned long)(0x0010)
+#define MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_BANKS (unsigned long)(4)
+
+/* Register offset address definitions relative to
+register set MAILBOX_IRQSTATUS___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (unsigned long)(0x0)
+
+
+/* Register set MAILBOX_IRQENABLE___REGSET_0_3
+address offset, bank address increment and number of banks */
+
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (unsigned long)(0x0104)
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (unsigned long)(0x0008)
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_BANKS (unsigned long)(4)
+
+#define MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_OFFSET (unsigned long)(0x0108)
+#define MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_STEP (unsigned long)(0x0010)
+#define MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_BANKS (unsigned long)(4)
+
+#define MLB_MAILBOX_IRQENABLE_CLR___REGSET_0_3_OFFSET (unsigned long)(0x010C)
+#define MLB_MAILBOX_IRQENABLE_CLR___REGSET_0_3_STEP (unsigned long)(0x0010)
+#define MLB_MAILBOX_IRQENABLE_CLR___REGSET_0_3_BANKS (unsigned long)(4)
+
+/* Register offset address definitions relative to register
+set MAILBOX_IRQENABLE___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (unsigned long)(0x0)
+
+
+/* Register offset address definitions */
+
+#define MLB_MAILBOX_REVISION_OFFSET (unsigned long)(0x0)
+#define MLB_MAILBOX_SYSCONFIG_OFFSET (unsigned long)(0x10)
+#define MLB_MAILBOX_SYSSTATUS_OFFSET (unsigned long)(0x14)
+
+
+/* Bitfield mask and offset declarations */
+
+#define MLB_MAILBOX_REVISION_Rev_MASK (unsigned long)(0xff)
+#define MLB_MAILBOX_REVISION_Rev_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_SYSCONFIG_ClockActivity_MASK (unsigned long)(0x100)
+#define MLB_MAILBOX_SYSCONFIG_ClockActivity_OFFSET (unsigned long)(8)
+
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (unsigned long)(0x18)
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (unsigned long)(3)
+
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (unsigned long)(0x2)
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (unsigned long)(1)
+
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (unsigned long)(0x1)
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (unsigned long)(0x1)
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK \
+(unsigned long)(0xffffffff)
+
+#define MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (unsigned long)(0x1)
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (unsigned long)(0x7f)
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (unsigned long)(0)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK \
+(unsigned long)(0x80000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_OFFSET \
+(unsigned long)(31)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK \
+(unsigned long)(0x40000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_OFFSET \
+(unsigned long)(30)
+
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK \
+(unsigned long)(0x20000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_OFFSET \
+(unsigned long)(29)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK \
+(unsigned long)(0x10000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_OFFSET \
+(unsigned long)(28)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK \
+(unsigned long)(0x8000000)
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_OFFSET \
+(unsigned long)(27)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK \
+(unsigned long)(0x4000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_OFFSET \
+(unsigned long)(26)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK \
+(unsigned long)(0x2000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_OFFSET \
+(unsigned long)(25)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK \
+(unsigned long)(0x1000000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_OFFSET \
+(unsigned long)(24)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK \
+(unsigned long)(0x800000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_OFFSET \
+(unsigned long)(23)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK \
+(unsigned long)(0x400000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_OFFSET \
+(unsigned long)(22)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK \
+(unsigned long)(0x200000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_OFFSET \
+(unsigned long)(21)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK \
+(unsigned long)(0x100000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_OFFSET \
+(unsigned long)(20)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK \
+(unsigned long)(0x80000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_OFFSET \
+(unsigned long)(19)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK \
+(unsigned long)(0x40000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_OFFSET \
+(unsigned long)(18)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK \
+(unsigned long)(0x20000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_OFFSET \
+(unsigned long)(17)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK \
+(unsigned long)(0x10000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_OFFSET \
+(unsigned long)(16)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK \
+(unsigned long)(0x8000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_OFFSET \
+(unsigned long)(15)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK \
+(unsigned long)(0x4000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_OFFSET \
+(unsigned long)(14)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK \
+(unsigned long)(0x2000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_OFFSET \
+(unsigned long)(13)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK \
+(unsigned long)(0x1000)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_OFFSET \
+(unsigned long)(12)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK \
+(unsigned long)(0x800)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_OFFSET \
+(unsigned long)(11)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK \
+(unsigned long)(0x400)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_OFFSET \
+(unsigned long)(10)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK \
+(unsigned long)(0x200)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_OFFSET \
+(unsigned long)(9)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK \
+(unsigned long)(0x100)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_OFFSET \
+(unsigned long)(8)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK \
+(unsigned long)(0x80)
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_OFFSET \
+(unsigned long)(7)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK \
+(unsigned long)(0x40)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_OFFSET \
+(unsigned long)(6)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK \
+(unsigned long)(0x20)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_OFFSET \
+(unsigned long)(5)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK \
+(unsigned long)(0x10)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_OFFSET \
+(unsigned long)(4)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK \
+(unsigned long)(0x8)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_OFFSET \
+(unsigned long)(3)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK \
+(unsigned long)(0x4)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_OFFSET \
+(unsigned long)(2)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK \
+(unsigned long)(0x2)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_OFFSET \
+(unsigned long)(1)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK \
+(unsigned long)(0x1)
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_OFFSET \
+(unsigned long)(0)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK \
+(unsigned long)(0x80000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_OFFSET \
+(unsigned long)(31)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK \
+(unsigned long)(0x40000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_OFFSET \
+(unsigned long)(30)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK \
+(unsigned long)(0x20000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_OFFSET \
+(unsigned long)(29)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK \
+(unsigned long)(0x10000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_OFFSET \
+(unsigned long)(28)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK \
+(unsigned long)(0x8000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_OFFSET \
+(unsigned long)(27)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK \
+(unsigned long)(0x4000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_OFFSET \
+(unsigned long)(26)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK \
+(unsigned long)(0x2000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_OFFSET \
+(unsigned long)(25)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK \
+(unsigned long)(0x1000000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_OFFSET \
+(unsigned long)(24)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK \
+(unsigned long)(0x800000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_OFFSET \
+(unsigned long)(23)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK \
+(unsigned long)(0x400000)
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_OFFSET \
+(unsigned long)(22)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK \
+(unsigned long)(0x200000)
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_OFFSET \
+(unsigned long)(21)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK \
+(unsigned long)(0x100000)
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_OFFSET \
+(unsigned long)(20)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK \
+(unsigned long)(0x80000)
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_OFFSET \
+(unsigned long)(19)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK \
+(unsigned long)(0x40000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_OFFSET \
+(unsigned long)(18)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK \
+(unsigned long)(0x20000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_OFFSET \
+(unsigned long)(17)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK \
+(unsigned long)(0x10000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_OFFSET \
+(unsigned long)(16)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK \
+(unsigned long)(0x8000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_OFFSET \
+(unsigned long)(15)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK \
+(unsigned long)(0x4000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_OFFSET \
+(unsigned long)(14)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK \
+(unsigned long)(0x2000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_OFFSET \
+(unsigned long)(13)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK \
+(unsigned long)(0x1000)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_OFFSET \
+(unsigned long)(12)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK \
+(unsigned long)(0x800)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_OFFSET \
+(unsigned long)(11)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK \
+(unsigned long)(0x400)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_OFFSET \
+(unsigned long)(10)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK \
+(unsigned long)(0x200)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_OFFSET \
+(unsigned long)(9)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK \
+(unsigned long)(0x100)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_OFFSET \
+(unsigned long)(8)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK \
+(unsigned long)(0x80)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_OFFSET \
+(unsigned long)(7)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK \
+(unsigned long)(0x40)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_OFFSET \
+(unsigned long)(6)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK \
+(unsigned long)(0x20)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_OFFSET \
+(unsigned long)(5)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK \
+(unsigned long)(0x10)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_OFFSET \
+(unsigned long)(4)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK \
+(unsigned long)(0x8)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_OFFSET \
+(unsigned long)(3)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK \
+(unsigned long)(0x4)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_OFFSET \
+(unsigned long)(2)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK \
+(unsigned long)(0x2)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_OFFSET \
+(unsigned long)(1)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK \
+(unsigned long)(0x1)
+
+#define MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_OFFSET \
+(unsigned long)(0)
+
+
+/*
+ * EXPORTED TYPES
+ *
+ */
+
+/* The following type definitions
+represent the enumerated values for each bitfield */
+
+enum MLBMAILBOX_SYSCONFIGSIdleModeE {
+ MLBMAILBOX_SYSCONFIGSIdleModeb00 = 0x0000,
+ MLBMAILBOX_SYSCONFIGSIdleModeb01 = 0x0001,
+ MLBMAILBOX_SYSCONFIGSIdleModeb10 = 0x0002,
+ MLBMAILBOX_SYSCONFIGSIdleModeb11 = 0x0003
+};
+
+enum MLBMAILBOX_SYSCONFIGSoftResetE {
+ MLBMAILBOX_SYSCONFIGSoftResetb0 = 0x0000,
+ MLBMAILBOX_SYSCONFIGSoftResetb1 = 0x0001
+};
+
+enum MLBMAILBOX_SYSCONFIGAutoIdleE {
+ MLBMAILBOX_SYSCONFIGAutoIdleb0 = 0x0000,
+ MLBMAILBOX_SYSCONFIGAutoIdleb1 = 0x0001
+};
+
+enum MLBMAILBOX_SYSSTATUSResetDoneE {
+ MLBMAILBOX_SYSSTATUSResetDonerstongoing = 0x0000,
+ MLBMAILBOX_SYSSTATUSResetDonerstcomp = 0x0001
+};
+
+#endif /* _MLB_ACC_INT_H */
diff --git a/arch/arm/plat-omap/include/syslink/MBXRegAcM.h b/arch/arm/plat-omap/include/syslink/MBXRegAcM.h
new file mode 100755
index 000000000000..1c6732ecc9a2
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MBXRegAcM.h
@@ -0,0 +1,3027 @@
+/*
+ * MBXRegAcM.h
+ *
+ * Notify mailbox driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MBX_REG_ACM_H
+#define _MBX_REG_ACM_H
+
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/MBXAccInt.h>
+
+
+/*
+ * EXPORTED DEFINITIONS
+ *
+ */
+
+#if defined(USE_LEVEL_1_MACROS)
+
+#define MLBMAILBOX_REVISIONReadRegister32(base_address)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+MLB_MAILBOX_REVISION_OFFSET))
+
+
+
+#define MLBMAILBOX_REVISIONRevRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+ \
+(MLB_MAILBOX_REVISION_OFFSET)))) &\
+MLB_MAILBOX_REVISION_Rev_MASK) >>\
+MLB_MAILBOX_REVISION_Rev_OFFSET))
+
+
+
+#define MLBMAILBOX_REVISIONRevGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_REVISION_Rev_MASK) \
+>> MLB_MAILBOX_REVISION_Rev_OFFSET))
+
+
+
+#define MLBMAILBOX_SYSCONFIGReadRegister32(base_address)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+MLB_MAILBOX_SYSCONFIG_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGWriteRegister32(base_address, value)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+ \
+ offset, newValue);\
+} while (0)
+
+
+#define MLBMAILBOX_SYSCONFIGClockActivityRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_ClockActivity_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_ClockActivity_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGClockActivityGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_SYSCONFIG_ClockActivity_MASK) \
+>> MLB_MAILBOX_SYSCONFIG_ClockActivity_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeReadIsb0032(base_address)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb00 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeReadIsb0132(base_address)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb01 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeReadIsb1032(base_address)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb10 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeReadIsb1132(base_address)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb11 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >> \
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeIsb0032(var)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb00 == \
+(MLBMAILBOX_SYSCONFIGSIdleModeE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeIsb0132(var)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb01 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeIsb1032(var)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb10 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeIsb1132(var)\
+((MLBMAILBOX_SYSCONFIGSIdleModeb11 == (MLBMAILBOX_SYSCONFIGSIdleModeE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(base_address, value)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+ \
+ offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWriteb0032(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSIdleModeb00 <<\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWriteb0132(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSIdleModeb01 <<\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWriteb1032(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSIdleModeb10 <<\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWriteb1132(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSIdleModeb11 <<\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeSet32(var, value)\
+(((((unsigned long)(var)) & ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK)) |\
+((((unsigned long)(value)) << MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK)))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetReadIsb032(base_address)\
+((MLBMAILBOX_SYSCONFIGSoftResetb0 == (MLBMAILBOX_SYSCONFIGSoftResetE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetReadIsb132(base_address)\
+((MLBMAILBOX_SYSCONFIGSoftResetb1 == (MLBMAILBOX_SYSCONFIGSoftResetE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >> \
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetIsb032(var)\
+((MLBMAILBOX_SYSCONFIGSoftResetb0 == (MLBMAILBOX_SYSCONFIGSoftResetE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetIsb132(var)\
+((MLBMAILBOX_SYSCONFIGSoftResetb1 == (MLBMAILBOX_SYSCONFIGSoftResetE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_SoftReset_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(base_address, value)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSoftResetWriteb032(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSoftResetb0 <<\
+ MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSoftResetWriteb132(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGSoftResetb1 <<\
+ MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGSoftResetSet32(var, value)\
+(((((unsigned long)(var)) & ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK)) |\
+((((unsigned long)(value)) << MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET) &\
+MLB_MAILBOX_SYSCONFIG_SoftReset_MASK)))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleReadIsb032(base_address)\
+((MLBMAILBOX_SYSCONFIGAutoIdleb0 == (MLBMAILBOX_SYSCONFIGAutoIdleE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleReadIsb132(base_address)\
+((MLBMAILBOX_SYSCONFIGAutoIdleb1 == (MLBMAILBOX_SYSCONFIGAutoIdleE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >> MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleIsb032(var)\
+((MLBMAILBOX_SYSCONFIGAutoIdleb0 == (MLBMAILBOX_SYSCONFIGAutoIdleE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleIsb132(var)\
+((MLBMAILBOX_SYSCONFIGAutoIdleb1 == (MLBMAILBOX_SYSCONFIGAutoIdleE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET)))
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(base_address, value)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleWriteb032(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGAutoIdleb0 <<\
+ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleWriteb132(base_address)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ const unsigned long newValue = \
+ (unsigned long)MLBMAILBOX_SYSCONFIGAutoIdleb1 <<\
+ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE((unsigned long)(base_address)+offset);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, data);\
+} while (0)
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleSet32(var, value)\
+(((((unsigned long)(var)) & ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK)) |\
+((((unsigned long)(value)) << MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET) &\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK)))
+
+#define MLBMAILBOX_SYSSTATUSReadRegister32(base_address)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+MLB_MAILBOX_SYSSTATUS_OFFSET))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneRead32(base_address)\
+((((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
+MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneReadisrstongoing32(base_address)\
+((MLBMAILBOX_SYSSTATUSResetDonerstongoing == (MLBMAILBOX_SYSSTATUSResetDoneE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
+MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET)))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneReadisrstcomp32(base_address)\
+((MLBMAILBOX_SYSSTATUSResetDonerstcomp == (MLBMAILBOX_SYSSTATUSResetDoneE)\
+(((RD_MEM_32_VOLATILE((((unsigned long)(base_address))+\
+(MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
+MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET)))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >> \
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneisrstongoing32(var)\
+((MLBMAILBOX_SYSSTATUSResetDonerstongoing == (MLBMAILBOX_SYSSTATUSResetDoneE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET)))
+
+#define MLBMAILBOX_SYSSTATUSResetDoneisrstcomp32(var)\
+((MLBMAILBOX_SYSSTATUSResetDonerstcomp == (MLBMAILBOX_SYSSTATUSResetDoneE)\
+((((unsigned long)(var)) & MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET)))
+
+#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MESSAGE___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
+
+#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(base_address, bank, value)\
+do {\
+ const unsigned long offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
+ ((bank) * MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_MESSAGE___0_15MessageValueMBmRead32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MESSAGE___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP)))) &\
+MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK) >>\
+MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_OFFSET))
+
+#define MLBMAILBOX_MESSAGE___0_15MessageValueMBmGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK) >> \
+MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_OFFSET))
+
+#define MLBMAILBOX_MESSAGE___0_15MessageValueMBmWrite32\
+(base_address, bank, value) do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
+ ((bank) * MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK);\
+ newValue <<= MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_OFFSET;\
+ newValue &= MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_MESSAGE___0_15MessageValueMBmSet32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_OFFSET) &\
+MLB_MAILBOX_MESSAGE___0_15_MessageValueMBm_MASK)))
+
+#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
+
+#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
+
+#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >> \
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
+
+#define MLBMAILBOX_MSGSTATUS___0_15ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP))))
+
+#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+((bank)*\
+MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
+MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
+MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
+
+#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmGet32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) \
+>> MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+
+#define MLBMAILBOX_IRQSTATUS_CLR___0_3ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_STEP))))
+
+#else
+
+#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
+
+#endif
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+
+#define MLBMAILBOX_IRQSTATUS_CLR___0_3WriteRegister32\
+(base_address, bank, value) do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * \
+ MLB_MAILBOX_IRQSTATUS_CLR___REGSET_0_3_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+ \
+ offset, newValue);\
+} while (0)
+
+#else
+
+#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+offset, newValue);\
+} while (0)
+
+#endif
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB15Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB15Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB15Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB15Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB15_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB15Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB15Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB15Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB15Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB15_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB14Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB14Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB14Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB14Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB14_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB14Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB14Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB14Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB14Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB14_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB13Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB13Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB13Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB13Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB13_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB13Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB13Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB13Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB13Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB13_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB12Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB12Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB12Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB12Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB12_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB12Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB12Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB12Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB12Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB12_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB11Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB11Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB11Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB11Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB11_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB11Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB11Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB11Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB11Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB11_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB10Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB10Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB10Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB10Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB10_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB10Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB10Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB10Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB10Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB10_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB9Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB9Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB9Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB9Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB9_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB9Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB9Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB9Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB9Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB9_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB8Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB8Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB8Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB8Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB8_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB8Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB8Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB8Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB8Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB8_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB7Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB7Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB7Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB7Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB7_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB7Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB7Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB7Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB7Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB7_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB6Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB6Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB6Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB6Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB6_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB6Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB6Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB6Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB6Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB6_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB5Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB5Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB5Write32\
+(base_address, bank, value)\
+do {\
+ onst unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB5Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB5_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB5Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB5Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB5Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB5Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB5_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB4Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB4Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB4Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB4Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB4_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB4Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB4Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB4Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB4Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB4_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB3Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)\
+*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB3Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB3Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB3Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB3_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB3Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB3Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB3Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB3Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB3_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB2Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB2Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB2Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB2Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB2_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB2Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB2Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK) \
+>> MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB2Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB2Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB2_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB1Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB1Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB1Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = RD_\
+ MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB1Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB1_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB1Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB1Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB1Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB1Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB1_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB0Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB0Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB0Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NotFullStatusUuMB0Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NotFullStatusUuMB0_MASK)))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB0Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK) >>\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB0Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK) >> \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB0Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK);\
+ newValue <<= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQSTATUS___0_3NewMsgStatusUuMB0Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_OFFSET) &\
+MLB_MAILBOX_IRQSTATUS___0_3_NewMsgStatusUuMB0_MASK)))
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+
+#define MLBMAILBOX_IRQENABLE_SET___0_3ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_STEP))))
+
+#else
+
+#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(base_address, bank)\
+(RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
+
+#endif
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+
+#define MLBMAILBOX_IRQENABLE_SET___0_3WriteRegister32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * \
+ MLB_MAILBOX_IRQENABLE_SET___REGSET_0_3_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE_CLR___0_3WriteRegister32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE_CLR___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * \
+ MLB_MAILBOX_IRQENABLE_CLR___REGSET_0_3_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+offset, newValue);\
+} while (0)
+
+#else
+
+#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ WR_MEM_32_VOLATILE(((unsigned long)(base_address))+offset, newValue);\
+} while (0)
+
+#endif
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB15Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB15Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB15Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB15Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB15_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB15Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB15Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB15Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB15Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB15_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB14Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB14Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB14Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB14Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB14_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB14Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB14Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB14Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB14Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB14_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB13Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB13Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB13Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB13Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB13_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB13Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB13Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB13Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB13Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB13_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB12Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB12Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB12Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB12Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB12_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB12Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB12Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB12Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB12Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB12_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB11Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB11Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB11Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB11Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB11_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB11Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB11Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB11Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB11Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB11_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB10Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB10Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB10Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = \
+ ((unsigned long)(value));\
+ data &= \
+ ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK);\
+ newValue <<= \
+ MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_OFFSET;\
+ newValue \
+ &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB10Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB10_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB10Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB10Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB10Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = \
+ ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB10Set32\
+(var, value)\
+(((((unsigned long)(var)) &\
+~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB10_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB9Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB9Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB9Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB9Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB9_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB9Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB9Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB9Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB9Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB9_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB8Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB8Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB8Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB8Set32(var, value)\
+(((((unsigned long)(var)) & \
+~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB8_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB8Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB8Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB8Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB8Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB8_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB7Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB7Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB7Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB7Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB7_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB7Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB7Get32(var)\
+((unsigned long)((((unsigned long)(var)) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB7Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB7Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB7_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB6Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB6Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB6Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB6Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB6_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB6Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB6Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB6Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB6Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB6_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB5Read32(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB5Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB5Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB5Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB5_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB5Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB5Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB5Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB5Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB5_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB4Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB4Get32\
+(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB4Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB4Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB4_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB4Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB4Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB4Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB4Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB4_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB3Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)\
+*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB3Get32\
+(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB3Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB3Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB3_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB3Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB3Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB3Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB3Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB3_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB2Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB2Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB2Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB2Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB2_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB2Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB2Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB2Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB2Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB2_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB1Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))\
++(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)\
+*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB1Get32(var)\
+((unsigned long)((((unsigned long)(var)) \
+& MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB1Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB1Set32\
+(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK)) |\
+((((unsigned long)(value)) << \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB1_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB1Read32\
+(base_address, bank) do {\
+ ((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+ (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+ MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK) >>\
+ MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_OFFSET))\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB1Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK) >> \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB1Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB1Set32(var, value)\
+(((((unsigned long)(var)) &\
+~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB1_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB0Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB0Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB0Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NotFullEnableUuMB0Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NotFullEnableUuMB0_MASK)))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB0Read32\
+(base_address, bank)\
+((((RD_MEM_32_VOLATILE(((unsigned long)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+((bank)*\
+MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP)))) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK) >>\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB0Get32(var)\
+((unsigned long)((((unsigned long)(var)) & \
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK) \
+>> MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_OFFSET))
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB0Write32\
+(base_address, bank, value)\
+do {\
+ const unsigned long offset = \
+ MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank) * MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register unsigned long data = \
+ RD_MEM_32_VOLATILE(((unsigned long)(base_address))+offset);\
+ register unsigned long newValue = ((unsigned long)(value));\
+ data &= ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK);\
+ newValue <<= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_OFFSET;\
+ newValue &= MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((unsigned long)(base_address)+offset, newValue);\
+} while (0)
+
+#define MLBMAILBOX_IRQENABLE___0_3NewMsgEnableUuMB0Set32(var, value)\
+(((((unsigned long)(var)) \
+& ~(MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK)) |\
+((((unsigned long)(value)) \
+<< MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_OFFSET) &\
+MLB_MAILBOX_IRQENABLE___0_3_NewMsgEnableUuMB0_MASK)))
+
+#endif /* USE_LEVEL_1_MACROS */
+
+
+#endif /* _MBX_REG_ACM_H */
diff --git a/arch/arm/plat-omap/include/syslink/MLBAccInt.h b/arch/arm/plat-omap/include/syslink/MLBAccInt.h
new file mode 100755
index 000000000000..6cd469709005
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MLBAccInt.h
@@ -0,0 +1,132 @@
+/*
+ * MLBAccInt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#ifndef _MLB_ACC_INT_H
+#define _MLB_ACC_INT_H
+
+/* Mappings of level 1 EASI function numbers to function names */
+
+#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32 (MLB_BASE_EASIL1 + 3)
+#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32 (MLB_BASE_EASIL1 + 4)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32 (MLB_BASE_EASIL1 + 7)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32 (MLB_BASE_EASIL1 + 17)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
+#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
+ (MLB_BASE_EASIL1 + 33)
+#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32 (MLB_BASE_EASIL1 + 39)
+#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32 (MLB_BASE_EASIL1 + 44)
+#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
+ (MLB_BASE_EASIL1 + 50)
+#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32 \
+ (MLB_BASE_EASIL1 + 51)
+#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32 \
+ (MLB_BASE_EASIL1 + 56)
+#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
+ (MLB_BASE_EASIL1 + 57)
+#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32 \
+ (MLB_BASE_EASIL1 + 60)
+#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32 \
+ (MLB_BASE_EASIL1 + 62)
+#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
+ (MLB_BASE_EASIL1 + 63)
+#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32 \
+ (MLB_BASE_EASIL1 + 192)
+#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32 \
+ (MLB_BASE_EASIL1 + 193)
+
+/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (u32)(0x0040)
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_MESSAGE___REGSET_0_15 */
+
+#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (u32)(0x0080)
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (u32)(0x00c0)
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_MSGSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (u32)(0x0100)
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (u32)(0x0008)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_IRQSTATUS___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (u32)(0x0104)
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (u32)(0x0008)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_IRQENABLE___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (u32)(0x0)
+
+
+/* Register offset address definitions */
+
+#define MLB_MAILBOX_SYSCONFIG_OFFSET (u32)(0x10)
+#define MLB_MAILBOX_SYSSTATUS_OFFSET (u32)(0x14)
+
+
+/* Bitfield mask and offset declarations */
+
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (u32)(0x18)
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (u32)(3)
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (u32)(0x2)
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (u32)(1)
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (u32)(0x1)
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (u32)(0)
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (u32)(0x1)
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (u32)(0)
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (u32)(0x1)
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (u32)(0)
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (u32)(0x7f)
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (u32)(0)
+
+#endif /* _MLB_ACC_INT_H */
diff --git a/arch/arm/plat-omap/include/syslink/MLBRegAcM.h b/arch/arm/plat-omap/include/syslink/MLBRegAcM.h
new file mode 100755
index 000000000000..5ef9cf32aef2
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MLBRegAcM.h
@@ -0,0 +1,206 @@
+/*
+ * MLBRegAcM.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _MLB_REG_ACM_H
+#define _MLB_REG_ACM_H
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/EasiGlobal.h>
+#include <syslink/MLBAccInt.h>
+
+#if defined(USE_LEVEL_1_MACROS)
+
+#define MLBMAILBOX_SYSCONFIGReadRegister32(base_address)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
+RD_MEM_32_VOLATILE(((u32)(base_address))+ \
+MLB_MAILBOX_SYSCONFIG_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGWriteRegister32(base_address, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
+ WR_MEM_32_VOLATILE(((u32)(base_address))+offset, newValue);\
+} while (0)
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(base_address)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
+(((RD_MEM_32_VOLATILE((((u32)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(base_address, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(base_address)) +\
+ offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(base_address)+offset, newValue);\
+} while (0)
+
+
+#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(base_address, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data =\
+ RD_MEM_32_VOLATILE(((u32)(base_address))+offset);\
+ register u32 newValue = ((u32)(value));\
+ printk(KERN_ALERT "In SYSCONFIG MACOR line %i file %s", \
+ __LINE__, __FILE__);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
+ printk(KERN_ALERT "******************BEFORE DATA WRITE");\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
+ printk(KERN_ALERT "line %i file %s", __LINE__, __FILE__);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
+ newValue |= data;\
+ printk(KERN_ALERT "line %i file %s", __LINE__, __FILE__);\
+ WR_MEM_32_VOLATILE((u32)(base_address)+offset, newValue);\
+ printk(KERN_ALERT "line %i file %s", __LINE__, __FILE__);\
+} while (0)
+
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(base_address)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
+(((RD_MEM_32_VOLATILE((((u32)(base_address))+\
+(MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(base_address, value)\
+{\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data =\
+ RD_MEM_32_VOLATILE(((u32)(base_address))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(base_address)+offset, newValue);\
+}
+
+
+#define MLBMAILBOX_SYSSTATUSResetDoneRead32(base_address)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
+(((RD_MEM_32_VOLATILE((((u32)(base_address))+\
+(MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
+MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
+
+
+#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
+RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
+(bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
+
+
+#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(base_address, bank, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
+ ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
+ WR_MEM_32_VOLATILE(((u32)(base_address))+offset, newValue);\
+} while (0)
+
+
+#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(\
+EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
+RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
+((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
+
+
+#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(\
+EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
+(((RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
+((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
+MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
+
+
+#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(\
+EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
+(((RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
+MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
+((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
+MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
+MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
+
+
+#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
+RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
+
+
+#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(base_address, bank, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
+ WR_MEM_32_VOLATILE(((u32)(base_address))+offset, newValue);\
+} while (0)
+
+
+#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(base_address, bank)\
+(_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
+RD_MEM_32_VOLATILE(((u32)(base_address))+\
+(MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
+((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
+
+
+#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(base_address, bank, value)\
+do {\
+ const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
+ WR_MEM_32_VOLATILE(((u32)(base_address))+offset, newValue);\
+} while (0)
+
+
+#endif /* USE_LEVEL_1_MACROS */
+
+#endif /* _MLB_REG_ACM_H */
diff --git a/arch/arm/plat-omap/include/syslink/MMUAccInt.h b/arch/arm/plat-omap/include/syslink/MMUAccInt.h
new file mode 100755
index 000000000000..827e1bc16b62
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MMUAccInt.h
@@ -0,0 +1,179 @@
+/*
+ * MMUAccInt.h
+ *
+ * Syslink ducati driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MMU_ACC_INT_H
+#define _MMU_ACC_INT_H
+
+
+/* Register offset address definitions */
+
+#define MMU_MMU_REVISION_OFFSET 0x0
+#define MMU_MMU_SYSCONFIG_OFFSET 0x10
+#define MMU_MMU_SYSSTATUS_OFFSET 014
+#define MMU_MMU_IRQSTATUS_OFFSET 0x18
+#define MMU_MMU_IRQENABLE_OFFSET 0x1c
+#define MMU_MMU_WALKING_ST_OFFSET 0x40
+#define MMU_MMU_CNTL_OFFSET 0x44
+#define MMU_MMU_FAULT_AD_OFFSET 0x48
+#define MMU_MMU_TTB_OFFSET 0x4c
+#define MMU_MMU_LOCK_OFFSET 0x50
+#define MMU_MMU_LD_TLB_OFFSET 0x54
+#define MMU_MMU_CAM_OFFSET 0x58
+#define MMU_MMU_RAM_OFFSET 0x5c
+#define MMU_MMU_GFLUSH_OFFSET 0x60
+#define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64
+#define MMU_MMU_READ_CAM_OFFSET 0x68
+#define MMU_MMU_READ_RAM_OFFSET 0x6c
+#define MMU_MMU_EMU_FAULT_AD_OFFSET 0x70
+
+
+/* Bitfield mask and offset declarations */
+
+#define MMU_MMU_REVISION_Rev_MASK 0xff
+#define MMU_MMU_REVISION_Rev_OFFSET 0
+
+#define MMU_MMU_SYSCONFIG_ClockActivity_MASK 0x300
+#define MMU_MMU_SYSCONFIG_ClockActivity_OFFSET 8
+
+#define MMU_MMU_SYSCONFIG_IdleMode_MASK 0x18
+#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET 3
+
+#define MMU_MMU_SYSCONFIG_SoftReset_MASK 0x2
+#define MMU_MMU_SYSCONFIG_SoftReset_OFFSET 1
+
+#define MMU_MMU_SYSCONFIG_AutoIdle_MASK 0x1
+#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET 0
+
+#define MMU_MMU_SYSSTATUS_ResetDone_MASK 0x1
+#define MMU_MMU_SYSSTATUS_ResetDone_OFFSET 0
+
+#define MMU_MMU_IRQSTATUS_MultiHitFault_MASK 0x10
+#define MMU_MMU_IRQSTATUS_MultiHitFault_OFFSET 4
+
+#define MMU_MMU_IRQSTATUS_TableWalkFault_MASK 0x8
+#define MMU_MMU_IRQSTATUS_TableWalkFault_OFFSET 3
+
+#define MMU_MMU_IRQSTATUS_EMUMiss_MASK 0x4
+#define MMU_MMU_IRQSTATUS_EMUMiss_OFFSET 2
+
+#define MMU_MMU_IRQSTATUS_TranslationFault_MASK 0x2
+#define MMU_MMU_IRQSTATUS_TranslationFault_OFFSET 1
+
+#define MMU_MMU_IRQSTATUS_TLBMiss_MASK 0x1
+#define MMU_MMU_IRQSTATUS_TLBMiss_OFFSET 0
+
+#define MMU_MMU_IRQENABLE_MultiHitFault_MASK 0x10
+#define MMU_MMU_IRQENABLE_MultiHitFault_OFFSET 4
+
+#define MMU_MMU_IRQENABLE_TableWalkFault_MASK 0x8
+#define MMU_MMU_IRQENABLE_TableWalkFault_OFFSET 3
+
+#define MMU_MMU_IRQENABLE_EMUMiss_MASK 0x4
+#define MMU_MMU_IRQENABLE_EMUMiss_OFFSET 2
+
+#define MMU_MMU_IRQENABLE_TranslationFault_MASK 0x2
+#define MMU_MMU_IRQENABLE_TranslationFault_OFFSET 1
+
+#define MMU_MMU_IRQENABLE_TLBMiss_MASK 0x1
+#define MMU_MMU_IRQENABLE_TLBMiss_OFFSET 0
+
+#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
+#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET 0
+
+#define MMU_MMU_CNTL_EmuTLBUpdate_MASK 0x8
+#define MMU_MMU_CNTL_EmuTLBUpdate_OFFSET 3
+
+#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
+#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
+
+#define MMU_MMU_CNTL_MMUEnable_MASK 0x2
+#define MMU_MMU_CNTL_MMUEnable_OFFSET 1
+
+#define MMU_MMU_FAULT_AD_FaultAddress_MASK 0xffffffff
+#define MMU_MMU_FAULT_AD_FaultAddress_OFFSET 0
+
+#define MMU_MMU_TTB_TTBAddress_MASK 0xffffff00
+#define MMU_MMU_TTB_TTBAddress_OFFSET 8
+
+#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
+#define MMU_MMU_LOCK_BaseValue_OFFSET 10
+
+#define MMU_MMU_LOCK_CurrentVictim_MASK 0x3f0
+#define MMU_MMU_LOCK_CurrentVictim_OFFSET 4
+
+#define MMU_MMU_LD_TLB_LdTLBItem_MASK 0x1
+#define MMU_MMU_LD_TLB_LdTLBItem_OFFSET 0
+
+#define MMU_MMU_CAM_VATag_MASK 0xfffff000
+#define MMU_MMU_CAM_VATag_OFFSET 12
+
+#define MMU_MMU_CAM_P_MASK 0x8
+#define MMU_MMU_CAM_P_OFFSET 3
+
+#define MMU_MMU_CAM_V_MASK 0x4
+#define MMU_MMU_CAM_V_OFFSET 2
+
+#define MMU_MMU_CAM_PageSize_MASK 0x3
+#define MMU_MMU_CAM_PageSize_OFFSET 0
+
+#define MMU_MMU_RAM_PhysicalAddress_MASK 0xfffff000
+#define MMU_MMU_RAM_PhysicalAddress_OFFSET 12
+
+#define MMU_MMU_RAM_Endianness_MASK 0x200
+#define MMU_MMU_RAM_Endianness_OFFSET 9
+
+#define MMU_MMU_RAM_ElementSize_MASK 0x180
+#define MMU_MMU_RAM_ElementSize_OFFSET 7
+
+#define MMU_MMU_RAM_Mixed_MASK 0x40
+#define MMU_MMU_RAM_Mixed_OFFSET 6
+
+#define MMU_MMU_GFLUSH_GlobalFlush_MASK 0x1
+#define MMU_MMU_GFLUSH_GlobalFlush_OFFSET 0
+
+#define MMU_MMU_FLUSH_ENTRY_FlushEntry_MASK 0x1
+#define MMU_MMU_FLUSH_ENTRY_FlushEntry_OFFSET 0
+
+#define MMU_MMU_READ_CAM_VATag_MASK 0xfffff000
+#define MMU_MMU_READ_CAM_VATag_OFFSET 12
+
+#define MMU_MMU_READ_CAM_P_MASK 0x8
+#define MMU_MMU_READ_CAM_P_OFFSET 3
+
+#define MMU_MMU_READ_CAM_V_MASK 0x4
+#define MMU_MMU_READ_CAM_V_OFFSET 2
+
+#define MMU_MMU_READ_CAM_PageSize_MASK 0x3
+#define MMU_MMU_READ_CAM_PageSize_OFFSET 0
+
+#define MMU_MMU_READ_RAM_PhysicalAddress_MASK 0xfffff000
+#define MMU_MMU_READ_RAM_PhysicalAddress_OFFSET 12
+
+#define MMU_MMU_READ_RAM_Endianness_MASK 0x200
+#define MMU_MMU_READ_RAM_Endianness_OFFSET 9
+
+#define MMU_MMU_READ_RAM_ElementSize_MASK 0x180
+#define MMU_MMU_READ_RAM_ElementSize_OFFSET 7
+
+#define MMU_MMU_READ_RAM_Mixed_MASK 0x40
+#define MMU_MMU_READ_RAM_Mixed_OFFSET 6
+
+#define MMU_MMU_EMU_FAULT_AD_EmuFaultAddress_MASK 0xffffffff
+#define MMU_MMU_EMU_FAULT_AD_EmuFaultAddress_OFFSET 0
+
+#endif /* _MMU_ACC_INT_H */
+/* EOF */
+
diff --git a/arch/arm/plat-omap/include/syslink/MMURegAcM.h b/arch/arm/plat-omap/include/syslink/MMURegAcM.h
new file mode 100755
index 000000000000..8088ca94f9c2
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/MMURegAcM.h
@@ -0,0 +1,427 @@
+/*
+ * MMURegAcM.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MMU_REG_ACM_H
+#define _MMU_REG_ACM_H
+
+
+
+#include "GlobalTypes.h"
+#include "MMUAccInt.h"
+
+
+/*
+* EXPORTED DEFINITIONS
+*
+*/
+
+#if defined(USE_LEVEL_1_MACROS)
+
+
+#define MMUMMU_SYSCONFIGReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_SYSCONFIG_OFFSET))
+
+
+#define MMUMMU_SYSCONFIGWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_SYSCONFIGClockActivityGet32(var)\
+ ((u32)(((var) & MMU_MMU_SYSCONFIG_ClockActivity_MASK)\
+ >> MMU_MMU_SYSCONFIG_ClockActivity_OFFSET))
+
+#define mmu_sisconf_auto_idle_set32(var, value)\
+ ((((var) & ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK)) |\
+ (((value) << MMU_MMU_SYSCONFIG_AutoIdle_OFFSET) &\
+ MMU_MMU_SYSCONFIG_AutoIdle_MASK)))
+
+#define MMUMMU_IRQSTATUSReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_IRQSTATUS_OFFSET))
+
+
+#define MMUMMU_IRQSTATUSWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+
+#define MMUMMU_IRQENABLEReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_IRQENABLE_OFFSET))
+
+
+#define MMUMMU_IRQENABLEWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_IRQENABLETableWalkFaultSet32(var, value)\
+ ((((var) & ~(MMU_MMU_IRQENABLE_TableWalkFault_MASK)) |\
+ (((value) << MMU_MMU_IRQENABLE_TableWalkFault_OFFSET) &\
+ MMU_MMU_IRQENABLE_TableWalkFault_MASK)))
+
+#define MMUMMU_IRQENABLETranslationFaultRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_IRQENABLE_OFFSET)))) &\
+ MMU_MMU_IRQENABLE_TranslationFault_MASK) >>\
+ MMU_MMU_IRQENABLE_TranslationFault_OFFSET))
+
+
+
+#define MMUMMU_IRQENABLETranslationFaultSet32(var, value)\
+ ((((var) & ~(MMU_MMU_IRQENABLE_TranslationFault_MASK)) |\
+ (((value) << MMU_MMU_IRQENABLE_TranslationFault_OFFSET) &\
+ MMU_MMU_IRQENABLE_TranslationFault_MASK)))
+
+
+#define MMUMMU_IRQENABLETLBMissRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_IRQENABLE_OFFSET)))) &\
+ MMU_MMU_IRQENABLE_TLBMiss_MASK) >>\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET))
+
+
+#define MMUMMU_IRQENABLETLBMissReadIsTrMissIntM32(base_address)\
+ ((MMUMMU_IRQENABLETLBMissTrMissIntM == (MMUMMU_IRQENABLETLBMissE)\
+ (((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_IRQENABLE_OFFSET)))) &\
+ MMU_MMU_IRQENABLE_TLBMiss_MASK) >>\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET)))
+
+
+#define MMUMMU_IRQENABLETLBMissReadIsTrMissGInt32(base_address)\
+ ((MMUMMU_IRQENABLETLBMissTrMissGInt == (MMUMMU_IRQENABLETLBMissE)\
+ (((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_IRQENABLE_OFFSET)))) &\
+ MMU_MMU_IRQENABLE_TLBMiss_MASK) >>\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET)))
+
+
+#define MMUMMU_IRQENABLETLBMissGet32(var)\
+ ((u32)(((var) & MMU_MMU_IRQENABLE_TLBMiss_MASK)\
+ >> MMU_MMU_IRQENABLE_TLBMiss_OFFSET))
+
+
+#define MMUMMU_IRQENABLETLBMissIsTrMissIntM32(var)\
+ ((MMUMMU_IRQENABLETLBMissTrMissIntM == \
+ (MMUMMU_IRQENABLETLBMissE)(((var) & MMU_MMU_IRQENABLE_TLBMiss_MASK) >>\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET)))
+
+#define MMUMMU_IRQENABLETLBMissIsTrMissGInt32(var)\
+ ((MMUMMU_IRQENABLETLBMissTrMissGInt ==\
+ (MMUMMU_IRQENABLETLBMissE)(((var) & MMU_MMU_IRQENABLE_TLBMiss_MASK) >>\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET)))
+
+#define MMUMMU_IRQENABLETLBMissWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_IRQENABLE_TLBMiss_MASK);\
+ newValue <<= MMU_MMU_IRQENABLE_TLBMiss_OFFSET;\
+ newValue &= MMU_MMU_IRQENABLE_TLBMiss_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+
+#define MMUMMU_IRQENABLETLBMissWriteTrMissIntM32(base_address)\
+{\
+ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
+ const u32 newValue = (u32)MMUMMU_IRQENABLETLBMissTrMissIntM <<\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(base_address+offset);\
+ data &= ~(MMU_MMU_IRQENABLE_TLBMiss_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE(base_address+offset, data);\
+}
+
+
+#define MMUMMU_IRQENABLETLBMissWriteTrMissGInt32(base_address)\
+{\
+ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
+ const u32 newValue = (u32)MMUMMU_IRQENABLETLBMissTrMissGInt <<\
+ MMU_MMU_IRQENABLE_TLBMiss_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(base_address+offset);\
+ data &= ~(MMU_MMU_IRQENABLE_TLBMiss_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE(base_address+offset, data);\
+}
+
+
+#define MMUMMU_IRQENABLETLBMissSet32(var, value)\
+ ((((var) & ~(MMU_MMU_IRQENABLE_TLBMiss_MASK)) |\
+ (((value) << MMU_MMU_IRQENABLE_TLBMiss_OFFSET) &\
+ MMU_MMU_IRQENABLE_TLBMiss_MASK)))
+
+
+#define MMUMMU_WALKING_STTWLRunningRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_WALKING_ST_OFFSET)))) &\
+ MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
+ MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
+
+
+
+#define MMUMMU_CNTLTWLEnableRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_CNTL_OFFSET)))) &\
+ MMU_MMU_CNTL_TWLEnable_MASK) >>\
+ MMU_MMU_CNTL_TWLEnable_OFFSET))
+
+
+#define MMUMMU_CNTLTWLEnableWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_CNTL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
+ newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
+ newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+
+#define MMUMMU_CNTLMMUEnableWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_CNTL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
+ newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
+ newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+
+#define MMUMMU_FAULT_ADReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_FAULT_AD_OFFSET))
+
+
+#define MMUMMU_FAULT_ADFaultAddressRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_FAULT_AD_OFFSET)))) &\
+ MMU_MMU_FAULT_AD_FaultAddress_MASK) >>\
+ MMU_MMU_FAULT_AD_FaultAddress_OFFSET))
+
+#define MMUMMU_FAULT_ADFaultAddressGet32(var)\
+ ((u32)(((var) & MMU_MMU_FAULT_AD_FaultAddress_MASK)\
+ >> MMU_MMU_FAULT_AD_FaultAddress_OFFSET))
+
+
+#define MMUMMU_TTBReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_TTB_OFFSET))
+
+#define MMUMMU_TTBWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_TTB_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_TTBTTBAddressRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_TTB_OFFSET)))) &\
+ MMU_MMU_TTB_TTBAddress_MASK) >>\
+ MMU_MMU_TTB_TTBAddress_OFFSET))
+
+#define MMUMMU_TTBTTBAddressGet32(var)\
+ ((u32)(((var) & MMU_MMU_TTB_TTBAddress_MASK)\
+ >> MMU_MMU_TTB_TTBAddress_OFFSET))
+
+
+#define MMUMMU_TTBTTBAddressWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_TTB_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_TTB_TTBAddress_MASK);\
+ newValue <<= MMU_MMU_TTB_TTBAddress_OFFSET;\
+ newValue &= MMU_MMU_TTB_TTBAddress_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+#define MMUMMU_TTBTTBAddressSet32(var, value)\
+ ((((var) & ~(MMU_MMU_TTB_TTBAddress_MASK)) |\
+ (((value) << MMU_MMU_TTB_TTBAddress_OFFSET) &\
+ MMU_MMU_TTB_TTBAddress_MASK)))
+
+
+#define mmu_lckread_reg_32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_LOCK_OFFSET))
+
+#define mmu_lck_write_reg32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+
+#define MMUMMU_LOCKBaseValueRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_LOCK_OFFSET)))) &\
+ MMU_MMU_LOCK_BaseValue_MASK) >>\
+ MMU_MMU_LOCK_BaseValue_OFFSET))
+#define MMUMMU_LOCKBaseValueGet32(var)\
+ ((u32)(((var) & MMU_MMU_LOCK_BaseValue_MASK)\
+ >> MMU_MMU_LOCK_BaseValue_OFFSET))
+
+
+#define MMUMMU_LOCKBaseValueWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
+ newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
+ newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+
+#define MMUMMU_LOCKBaseValueSet32(var, value)\
+ ((((var) & ~(MMU_MMU_LOCK_BaseValue_MASK)) |\
+ (((value) << MMU_MMU_LOCK_BaseValue_OFFSET) &\
+ MMU_MMU_LOCK_BaseValue_MASK)))
+
+#define MMUMMU_LOCKCurrentVictimRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_LOCK_OFFSET)))) &\
+ MMU_MMU_LOCK_CurrentVictim_MASK) >>\
+ MMU_MMU_LOCK_CurrentVictim_OFFSET))
+
+
+#define MMUMMU_LOCKCurrentVictimGet32(var)\
+ ((u32)(((var) & MMU_MMU_LOCK_CurrentVictim_MASK)\
+ >> MMU_MMU_LOCK_CurrentVictim_OFFSET))
+
+
+#define mmu_lck_crnt_vctmwite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
+ newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
+ newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+
+#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
+ ((((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
+ (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
+ MMU_MMU_LOCK_CurrentVictim_MASK)))
+
+
+#define MMUMMU_LD_TLBReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_LD_TLB_OFFSET))
+
+#define mmu_ld_tlbwrt_reg32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_LD_TLBLdTLBItemRead32(base_address)\
+ ((((RD_MEM_32_VOLATILE(((base_address)+(MMU_MMU_LD_TLB_OFFSET)))) &\
+ MMU_MMU_LD_TLB_LdTLBItem_MASK) >>\
+ MMU_MMU_LD_TLB_LdTLBItem_OFFSET))
+
+
+#define MMUMMU_CAMReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_READ_CAM_OFFSET))
+
+
+#define MMUMMU_CAMWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_CAM_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_RAMReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_READ_RAM_OFFSET))
+
+
+#define MMUMMU_RAMWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_RAM_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+#define MMUMMU_GFLUSHGlobalFlushWrite32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_GFLUSH_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((base_address)+offset);\
+ register u32 newValue = (value);\
+ data &= ~(MMU_MMU_GFLUSH_GlobalFlush_MASK);\
+ newValue <<= MMU_MMU_GFLUSH_GlobalFlush_OFFSET;\
+ newValue &= MMU_MMU_GFLUSH_GlobalFlush_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE(base_address+offset, newValue);\
+}
+
+#define MMUMMU_GFLUSHGlobalFlushWritenft_w32(base_address)\
+{\
+ const u32 offset = MMU_MMU_GFLUSH_OFFSET;\
+ const u32 newValue = (u32)MMUMMU_GFLUSHGlobalFlushnft_w <<\
+ MMU_MMU_GFLUSH_GlobalFlush_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(base_address+offset);\
+ data &= ~(MMU_MMU_GFLUSH_GlobalFlush_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE(base_address+offset, data);\
+}
+
+#define MMUMMU_GFLUSHGlobalFlushWriteflush_w32(base_address)\
+{\
+ const u32 offset = MMU_MMU_GFLUSH_OFFSET;\
+ const u32 newValue = (u32)MMUMMU_GFLUSHGlobalFlushflush_w <<\
+ MMU_MMU_GFLUSH_GlobalFlush_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(base_address+offset);\
+ data &= ~(MMU_MMU_GFLUSH_GlobalFlush_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE(base_address+offset, data);\
+}
+
+
+#define MMUMMU_GFLUSHGlobalFlushSet32(var, value)\
+ ((((var) & ~(MMU_MMU_GFLUSH_GlobalFlush_MASK)) |\
+ (((value) << MMU_MMU_GFLUSH_GlobalFlush_OFFSET) &\
+ MMU_MMU_GFLUSH_GlobalFlush_MASK)))
+
+#define MMUMMU_FLUSH_ENTRYReadRegister32(base_address)\
+ (RD_MEM_32_VOLATILE((base_address)+MMU_MMU_FLUSH_ENTRY_OFFSET))
+
+
+#define MMUMMU_FLUSH_ENTRYWriteRegister32(base_address, value)\
+{\
+ const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
+ register u32 newValue = (value);\
+ WR_MEM_32_VOLATILE((base_address)+offset, newValue);\
+}
+
+
+
+#endif /* USE_LEVEL_1_MACROS */
+
+#endif /* _MMU_REG_ACM_H */
+/* EOF */
+
diff --git a/arch/arm/plat-omap/include/syslink/_sysmgr.h b/arch/arm/plat-omap/include/syslink/_sysmgr.h
new file mode 100644
index 000000000000..58fbdd378155
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/_sysmgr.h
@@ -0,0 +1,50 @@
+/*
+ * _sysmgr.h
+ *
+ * Defines for system manager functions
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef __SYSMGR_H_
+#define __SYSMGR_H_
+
+/* Structure to retrieve the scalability proc info from the slave */
+struct sysmgr_proc_config {
+ u32 proc_id;
+ u32 use_notify;
+ u32 use_messageq;
+ u32 use_heapbuf;
+ u32 use_frameq;
+ u32 use_ringio;
+ u32 use_listmp;
+ u32 use_nameserver;
+ u32 boot_mode;
+};
+
+/* Function to set the boot load page address for a slave */
+void sysmgr_set_boot_load_page(u16 proc_id, u32 boot_load_page);
+
+/* Function to get configuration values for a host object(component/instance) */
+u32 sysmgr_get_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size);
+
+/* Function to put configuration values for a slave object(component/instance)*/
+u32 sysmgr_put_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size);
+
+/* Function to wait for scalability handshake value. */
+void sysmgr_wait_for_scalability_info(u16 proc_id);
+
+/* Function to wait for slave to complete setup */
+void sysmgr_wait_for_slave_setup(u16 proc_id);
+
+
+#endif /* ifndef __SYSMGR_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/atomic_linux.h b/arch/arm/plat-omap/include/syslink/atomic_linux.h
new file mode 100755
index 000000000000..e36cb8ba2abc
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/atomic_linux.h
@@ -0,0 +1,105 @@
+/*
+* atomic_linux.h
+*
+* Atomic operations functions
+*
+* Copyright (C) 2008-2009 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.
+*/
+
+#ifndef _ATOMIC_LINUX_H
+#define _ATOMIC_LINUX_H
+
+#include <linux/types.h>
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/atomic.h>
+
+/*
+ * ======== atomic_cmpmask_and_set ========
+ * Purpose:
+ * This will compare a mask and set if not equal
+ */
+static inline void atomic_cmpmask_and_set(atomic_t *v, u32 mask, u32 val)
+{
+ s32 ret;
+ unsigned long flags;
+ atomic_t *atm = v;
+
+ raw_local_irq_save(flags);
+ ret = atm->counter;
+ if (likely(((ret & mask) != mask)))
+ atm->counter = val;
+ raw_local_irq_restore(flags);
+}
+
+/*
+ * ======== atomic_cmpmask_and_set ========
+ * Purpose:
+ * This will compare a mask and then check current value less than
+ * provided value.
+ */
+static inline bool atomic_cmpmask_and_lt(atomic_t *v, u32 mask, u32 val)
+{
+ bool ret = true;
+ atomic_t *atm = v;
+ s32 cur;
+ unsigned long flags;
+
+ raw_local_irq_save(flags);
+ cur = atm->counter;
+ /* Compare mask, if matches then compare val */
+ if (likely(((cur & mask) == mask))) {
+ if (likely(cur >= val))
+ ret = false;
+ }
+ raw_local_irq_restore(flags);
+
+ /* retval = true if mask matches and current value is less than given
+ * value */
+ /* retval = false either mask doesnot matches or current value is not
+ * less than given value */
+ return ret;
+}
+
+
+/*
+ * ======== atomic_cmpmask_and_set ========
+ * Purpose:
+ * This will compare a mask and then check current value greater than
+ * provided value.
+ */
+static inline bool atomic_cmpmask_and_gt(atomic_t *v, u32 mask, u32 val)
+{
+ bool ret = false;
+ atomic_t *atm = v;
+ s32 cur;
+ unsigned long flags;
+
+ raw_local_irq_save(flags);
+ cur = atm->counter;
+ /* Compare mask, if matches then compare val */
+ if (likely(((cur & mask) == mask))) {
+ if (likely(cur > val))
+ ret = true;
+ }
+
+ raw_local_irq_restore(flags);
+ /* retval = true if mask matches and current value is less than given
+ * value */
+ /* etval =false either mask doesnot matches or current value is not
+ * greater than given value */
+ return ret;
+}
+
+#endif /* if !defined(_ATOMIC_LINUX_H) */
+
diff --git a/arch/arm/plat-omap/include/syslink/ducatienabler.h b/arch/arm/plat-omap/include/syslink/ducatienabler.h
new file mode 100644
index 000000000000..6674b8f2d439
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/ducatienabler.h
@@ -0,0 +1,291 @@
+/*
+ * ducatienabler.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+#ifndef _DDUCATIMMU_ENABLER_H_
+#define _DDUCATIMMU_ENABLER_H_
+
+#include <linux/types.h>
+#include <linux/mm.h>
+
+#include <syslink/hw_defs.h>
+#include <syslink/hw_mmu.h>
+
+
+#define PAGE_SIZE_4KB 0x1000
+#define PAGE_SIZE_64KB 0x10000
+#define PAGE_SIZE_1MB 0x100000
+#define PAGE_SIZE_16MB 0x1000000
+
+/* Define the Peripheral PAs and their Ducati VAs. */
+#define L4_PERIPHERAL_MBOX 0x4A0F4000
+#define DUCATI_PERIPHERAL_MBOX 0xAA0F4000
+
+#define L4_PERIPHERAL_I2C1 0x48070000
+#define DUCATI_PERIPHERAL_I2C1 0xA8070000
+#define L4_PERIPHERAL_I2C2 0x48072000
+#define DUCATI_PERIPHERAL_I2C2 0xA8072000
+#define L4_PERIPHERAL_I2C3 0x48060000
+#define DUCATI_PERIPHERAL_I2C3 0xA8060000
+
+#define L4_PERIPHERAL_DMA 0x4A056000
+#define DUCATI_PERIPHERAL_DMA 0xAA056000
+
+#define L4_PERIPHERAL_GPIO1 0x4A310000
+#define DUCATI_PERIPHERAL_GPIO1 0xAA310000
+#define L4_PERIPHERAL_GPIO2 0x48055000
+#define DUCATI_PERIPHERAL_GPIO2 0xA8055000
+#define L4_PERIPHERAL_GPIO3 0x48057000
+#define DUCATI_PERIPHERAL_GPIO3 0xA8057000
+
+#define L4_PERIPHERAL_GPTIMER3 0x48034000
+#define DUCATI_PERIPHERAL_GPTIMER3 0xA8034000
+#define L4_PERIPHERAL_GPTIMER4 0x48036000
+#define DUCATI_PERIPHERAL_GPTIMER4 0xA8036000
+#define L4_PERIPHERAL_GPTIMER9 0x48040000
+#define DUCATI_PERIPHERAL_GPTIMER9 0xA8040000
+#define L4_PERIPHERAL_GPTIMER11 0x48088000
+#define DUCATI_PERIPHERAL_GPTIMER11 0xA8088000
+
+#define L4_PERIPHERAL_UART1 0x4806A000
+#define DUCATI_PERIPHERAL_UART1 0xA806A000
+#define L4_PERIPHERAL_UART2 0x4806C000
+#define DUCATI_PERIPHERAL_UART2 0xA806C000
+#define L4_PERIPHERAL_UART3 0x48020000
+#define DUCATI_PERIPHERAL_UART3 0xA8020000
+#define L4_PERIPHERAL_UART4 0x4806E000
+#define DUCATI_PERIPHERAL_UART4 0xA806E000
+
+
+#define L3_TILER_VIEW0_ADDR 0x60000000
+#define DUCATIVA_TILER_VIEW0_ADDR 0x60000000
+#define DUCATIVA_TILER_VIEW0_LEN 0x20000000
+
+
+
+#if 0 /* Original definitions for OMAP4430. */
+/* Define the various Ducati Memory Regions. */
+/* The first 4K page of BOOTVECS is programmed as a TLB entry. The remaining */
+/* three pages are not used and are mapped to minimize number of PTEs */
+#define DUCATI_BOOTVECS_ADDR 0x1000
+#define DUCATI_BOOTVECS_LEN 0x3000
+
+#define DUCATI_EXTMEM_SYSM3_ADDR 0x4000
+#define DUCATI_EXTMEM_SYSM3_LEN 0x1FC000
+
+#define DUCATI_EXTMEM_APPM3_ADDR 0x10000000
+#define DUCATI_EXTMEM_APPM3_LEN 0x200000
+
+#define DUCATI_PRIVATE_SYSM3_DATA_ADDR 0x84000000
+#define DUCATI_PRIVATE_SYSM3_DATA_LEN 0x200000
+
+#define DUCATI_PRIVATE_APPM3_DATA_ADDR 0x8A000000
+#define DUCATI_PRIVATE_APPM3_DATA_LEN 0x200000
+
+#define DUCATI_SHARED_M3_DATA_ADDR 0x90000000
+#define DUCATI_SHARED_M3_DATA_LEN 0x100000
+
+#define DUCATI_SHARED_IPC_ADDR 0x98000000
+#define DUCATI_SHARED_IPC_LEN 0x100000
+
+#define DUCATI_SW_DMM_ADDR 0x80000000
+#define DUCATI_SW_DMM_LEN 0x400000
+#endif
+
+/* OMAP4430 SDC definitions */
+#define L4_PERIPHERAL_L4CFG 0x4A000000
+#define DUCATI_PERIPHERAL_L4CFG 0xAA000000
+
+#define L4_PERIPHERAL_L4PER 0x48000000
+#define DUCATI_PERIPHERAL_L4PER 0xA8000000
+
+#define L3_IVAHD_CONFIG 0x5A000000
+#define DUCATI_IVAHD_CONFIG 0xBA000000
+
+#define L3_IVAHD_SL2 0x5B000000
+#define DUCATI_IVAHD_SL2 0xBB000000
+
+#define L3_TILER_MODE0_1_ADDR 0x60000000
+#define DUCATI_TILER_MODE0_1_ADDR 0x60000000
+#define DUCATI_TILER_MODE0_1_LEN 0x10000000
+
+#define L3_TILER_MODE3_ADDR 0x78000000
+#define DUCATI_TILER_MODE3_ADDR 0x78000000
+#define DUCATI_TILER_MODE3_LEN 0x8000000
+
+#define DUCATI_BOOTVECS_UNUSED_ADDR 0x1000
+#define DUCATI_BOOTVECS_UNUSED_LEN 0x3000
+
+#define DUCATI_MEM_CODE_SYSM3_ADDR 0x4000
+#define DUCATI_MEM_CODE_SYSM3_LEN 0x1FC000
+
+#define DUCATI_MEM_CODE_APPM3_ADDR 0x800000
+#define DUCATI_MEM_CODE_APPM3_LEN 0x200000
+
+#define DUCATI_MEM_CONST_SYSM3_ADDR 0x80000000
+#define DUCATI_MEM_CONST_SYSM3_LEN 0x100000
+
+#define DUCATI_MEM_CONST_APPM3_ADDR 0x80100000
+#define DUCATI_MEM_CONST_APPM3_LEN 0x100000
+
+#define DUCATI_MEM_HEAP_SYSM3_ADDR 0x80200000
+#define DUCATI_MEM_HEAP_SYSM3_LEN 0x100000
+
+#define DUCATI_MEM_HEAP_APPM3_ADDR 0x80300000
+#define DUCATI_MEM_HEAP_APPM3_LEN 0x1000000
+
+#define DUCATI_MEM_MPU_DUCATI_SHMEM_ADDR 0x81300000
+#define DUCATI_MEM_MPU_DUCATI_SHMEM_LEN 0xC00000
+
+#define DUCATI_MEM_IPC_SHMEM_ADDR 0x81F00000
+#define DUCATI_MEM_IPC_SHMEM_LEN 0x100000
+
+#define DUCATI_MEM_IPC_HEAP0_ADDR 0xA0000000
+#define DUCATI_MEM_IPC_HEAP0_LEN 0x55000
+
+#define DUCATI_MEM_IPC_HEAP1_ADDR 0xA0055000
+#define DUCATI_MEM_IPC_HEAP1_LEN 0x55000
+
+#define DUCATI_MEM_IPC_HEAP2_ADDR 0xA00AA000
+#define DUCATI_MEM_IPC_HEAP2_LEN 0x56000
+
+
+/* Types of mapping attributes */
+
+/* MPU address is virtual and needs to be translated to physical addr */
+#define DSP_MAPVIRTUALADDR 0x00000000
+#define DSP_MAPPHYSICALADDR 0x00000001
+
+/* Mapped data is big endian */
+#define DSP_MAPBIGENDIAN 0x00000002
+#define DSP_MAPLITTLEENDIAN 0x00000000
+
+/* Element size is based on DSP r/w access size */
+#define DSP_MAPMIXEDELEMSIZE 0x00000004
+
+/*
+ * Element size for MMU mapping (8, 16, 32, or 64 bit)
+ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
+ */
+#define DSP_MAPELEMSIZE8 0x00000008
+#define DSP_MAPELEMSIZE16 0x00000010
+#define DSP_MAPELEMSIZE32 0x00000020
+#define DSP_MAPELEMSIZE64 0x00000040
+
+#define DSP_MAPVMALLOCADDR 0x00000080
+#define DSP_MAPTILERADDR 0x00000100
+
+
+#define PG_MASK(pg_size) (~((pg_size)-1))
+#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
+#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
+
+
+struct mmu_entry {
+ u32 ul_phy_addr ;
+ u32 ul_virt_addr ;
+ u32 ul_size ;
+};
+
+struct memory_entry {
+ u32 ul_virt_addr;
+ u32 ul_size;
+};
+
+#if 0 /* Original definitions for OMAP4430. */
+static const struct mmu_entry l4_map[] = {
+ /* Mailbox 4KB*/
+ {L4_PERIPHERAL_MBOX, DUCATI_PERIPHERAL_MBOX, HW_PAGE_SIZE_4KB},
+ /* I2C 4KB each */
+ {L4_PERIPHERAL_I2C1, DUCATI_PERIPHERAL_I2C1, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_I2C2, DUCATI_PERIPHERAL_I2C2, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_I2C3, DUCATI_PERIPHERAL_I2C3, HW_PAGE_SIZE_4KB},
+ /* DMA 4KB */
+ {L4_PERIPHERAL_DMA, DUCATI_PERIPHERAL_DMA, HW_PAGE_SIZE_4KB},
+ /* GPIO Banks 4KB each */
+ {L4_PERIPHERAL_GPIO1, DUCATI_PERIPHERAL_GPIO1, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_GPIO2, DUCATI_PERIPHERAL_GPIO2, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_GPIO3, DUCATI_PERIPHERAL_GPIO3, HW_PAGE_SIZE_4KB},
+ /* GPTimers 4KB each */
+ {L4_PERIPHERAL_GPTIMER3, DUCATI_PERIPHERAL_GPTIMER3, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_GPTIMER4, DUCATI_PERIPHERAL_GPTIMER4, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_GPTIMER9, DUCATI_PERIPHERAL_GPTIMER9, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_GPTIMER11, DUCATI_PERIPHERAL_GPTIMER11,
+ HW_PAGE_SIZE_4KB},
+ /* UARTs 4KB each */
+ {L4_PERIPHERAL_UART1, DUCATI_PERIPHERAL_UART1, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_UART2, DUCATI_PERIPHERAL_UART2, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_UART3, DUCATI_PERIPHERAL_UART3, HW_PAGE_SIZE_4KB},
+ {L4_PERIPHERAL_UART4, DUCATI_PERIPHERAL_UART4,
+ HW_PAGE_SIZE_4KB},
+};
+
+static const struct memory_entry l3_memory_regions[] = {
+ /* BootVecs regions */
+ {0, (PAGE_SIZE_1MB * 2)},
+ /* EXTMEM_CORE1: 0x10000000 to 0x100FFFFF */
+ {DUCATI_EXTMEM_APPM3_ADDR, DUCATI_EXTMEM_APPM3_LEN},
+ /* PRIVATE_SYSM3_DATA*/
+ {DUCATI_PRIVATE_SYSM3_DATA_ADDR, DUCATI_PRIVATE_SYSM3_DATA_LEN},
+ /* PRIVATE_APPM3_DATA*/
+ {DUCATI_PRIVATE_APPM3_DATA_ADDR, DUCATI_PRIVATE_APPM3_DATA_LEN},
+ /* SHARED_M3_DATA*/
+ {DUCATI_SHARED_M3_DATA_ADDR, DUCATI_SHARED_M3_DATA_LEN},
+ /* IPC*/
+ {DUCATI_SHARED_IPC_ADDR, DUCATI_SHARED_IPC_LEN},
+ /* DMM*/
+ {DUCATI_SW_DMM_ADDR, DUCATI_SW_DMM_LEN},
+};
+#endif
+
+/* OMAP4430 SDC definitions */
+static const struct mmu_entry l4_map[] = {
+ /* TILER 8-bit and 16-bit modes */
+ {L3_TILER_MODE0_1_ADDR, DUCATI_TILER_MODE0_1_ADDR,
+ (HW_PAGE_SIZE_16MB * 16)},
+ /* TILER: Pages-mode */
+ {L3_TILER_MODE3_ADDR, DUCATI_TILER_MODE3_ADDR,
+ (HW_PAGE_SIZE_16MB * 8)},
+ /* L4_CFG: Covers all modules in L4_CFG 16MB*/
+ {L4_PERIPHERAL_L4CFG, DUCATI_PERIPHERAL_L4CFG, HW_PAGE_SIZE_16MB},
+ /* L4_PER: Covers all modules in L4_PER 16MB*/
+ {L4_PERIPHERAL_L4PER, DUCATI_PERIPHERAL_L4PER, HW_PAGE_SIZE_16MB},
+ /* IVA_HD Config: Covers all modules in IVA_HD Config space 16MB */
+ {L3_IVAHD_CONFIG, DUCATI_IVAHD_CONFIG, HW_PAGE_SIZE_16MB},
+ /* IVA_HD SL2: Covers all memory in IVA_HD SL2 space 16MB */
+ {L3_IVAHD_SL2, DUCATI_IVAHD_SL2, HW_PAGE_SIZE_16MB},
+};
+
+static const struct memory_entry l3_memory_regions[] = {
+ /* MEM_INTVECS_SYSM3, MEM_INTVECS_APPM3, MEM_CODE_SYSM3,
+ MEM_CODE_APPM3 */
+ {0, PAGE_SIZE_16MB},
+ /* MEM_CONST_SYSM3, MEM_CONST_APPM3, MEM_HEAP_SYSM3, MEM_HEAP_APPM3,
+ MEM_MPU_DUCATI_SHMEM, MEM_IPC_SHMEM */
+ {DUCATI_MEM_CONST_SYSM3_ADDR, (PAGE_SIZE_16MB * 2)},
+ /* MEM_IPC_HEAP0, MEM_IPC_HEAP1, MEM_IPC_HEAP2 */
+ {DUCATI_MEM_IPC_HEAP0_ADDR, PAGE_SIZE_1MB},
+};
+
+
+void dbg_print_ptes(bool ashow_inv_entries, bool ashow_repeat_entries);
+int ducati_setup(void);
+void ducati_destroy(void);
+u32 get_ducati_virt_mem();
+void unmap_ducati_virt_mem(u32 shm_virt_addr);
+int ducati_mem_map(u32 va, u32 da, u32 num_bytes, u32 map_attr);
+int ducati_mem_unmap(u32 da, u32 num_bytes);
+u32 user_va2pa(struct mm_struct *mm, u32 address);
+inline u32 ducati_mem_virtToPhys(u32 da);
+#endif /* _DDUCATIMMU_ENABLER_H_*/
diff --git a/arch/arm/plat-omap/include/syslink/gate_remote.h b/arch/arm/plat-omap/include/syslink/gate_remote.h
new file mode 100644
index 000000000000..e8115d59535a
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/gate_remote.h
@@ -0,0 +1,34 @@
+/*
+ * gate_remote.h
+ *
+ * This includes the functions to handle remote gates
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _NAMESERVER_REMOTE_H_
+#define _GATE_REMOTE_H_
+
+#include <linux/types.h>
+
+/*
+ * This function is used to enter in to a remote gate
+ */
+int gate_remote_enter(void *ghandle, u32 key);
+
+/*
+ * This function is used to leave from a remote gate
+ */
+int gate_remote_leave(void *ghandle, u32 key);
+
+#endif /* _GATE_REMOTE_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/gatepeterson.h b/arch/arm/plat-omap/include/syslink/gatepeterson.h
new file mode 100755
index 000000000000..f2e3f78bf146
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/gatepeterson.h
@@ -0,0 +1,167 @@
+/*
+ * gatepeterson.h
+ *
+ * The Gate Peterson Algorithm for mutual exclusion of shared memory.
+ * Current implementation works for 2 processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _GATEPETERSON_H_
+#define _GATEPETERSON_H_
+
+#include <linux/types.h>
+
+/*
+ * GATEPETERSON_MODULEID
+ * Unique module ID
+ */
+#define GATEPETERSON_MODULEID (0xF415)
+
+/*
+ * A set of context protection levels that each correspond to
+ * single processor gates used for local protection
+ */
+enum gatepeterson_protect {
+ GATEPETERSON_PROTECT_DEFAULT = 0,
+ GATEPETERSON_PROTECT_NONE = 1,
+ GATEPETERSON_PROTECT_INTERRUPT = 2,
+ GATEPETERSON_PROTECT_TASKLET = 3,
+ GATEPETERSON_PROTECT_THREAD = 4,
+ GATEPETERSON_PROTECT_PROCESS = 5,
+ GATEPETERSON_PROTECT_END_VALUE = 6
+};
+
+/*
+ * Structure defining config parameters for the Gate Peterson
+ * module
+ */
+struct gatepeterson_config {
+ enum gatepeterson_protect default_protection;
+ /*!< Default module-wide local context protection level. The level of
+ * protection specified here determines which local gate is created per
+ * GatePeterson instance for local protection during create. The instance
+ * configuration parameter may be usedto override this module setting per
+ * instance. The configuration used here should reflect both the context
+ * in which enter and leave are to be called,as well as the maximum level
+ * of protection needed locally.
+ */
+ u32 max_name_len; /* GP name len */
+ bool use_nameserver;
+ /*!< Whether to have this module use the NameServer or not. If the
+ * NameServer is not needed, set this configuration parameter to false.
+ * This informs GatePeterson not to pull in the NameServer module.
+ * In this case, all names passed into create and open are ignored.
+ */
+};
+
+/*
+ * Structure defining config parameters for the Gate Peterson
+ * instances
+ */
+struct gatepeterson_params {
+ void *shared_addr;
+ /* Address of the shared memory. The creator must supply a cache-aligned
+ * address in shared memory that will be used to store shared state
+ * information.
+ */
+
+ u32 shared_addr_size;
+ /* Size of the shared memory region. Can use gatepeterson_shared_memreq
+ * call to determine the required size.
+ */
+
+ char *name;
+ /* If using nameserver, name of this instance. The name (if not NULL) must
+ * be unique among all gatepeterson instances in the entire system.
+ */
+
+ enum gatepeterson_protect local_protection;
+ /* Local gate protection level. The default value, (Protect_DEFAULT)
+ * results in inheritance from module-level defaultProtection. This
+ * instance setting should be set to an alternative only if a different
+ * local protection level is needed for the instance.
+ */
+ bool use_nameserver;
+ /* Whether to have this module use the nameserver or not. If the
+ * nameserver is not needed, set this configuration parameter to
+ * false.This informs gatepeterson not to pull in the nameaerver
+ * module. In this case, all names passed into create and open are
+ * ignored.
+ */
+};
+
+/*
+ * Function to initialize the parameter structure
+ */
+void gatepeterson_get_config(struct gatepeterson_config *config);
+
+/*
+ * Function to initialize GP module
+ */
+int gatepeterson_setup(const struct gatepeterson_config *config);
+
+/*
+ * Function to destroy the GP module
+ */
+int gatepeterson_destroy(void);
+
+/*
+ * Function to initialize the parameter structure
+ */
+void gatepeterson_params_init(void *handle,
+ struct gatepeterson_params *params);
+
+/*
+ * Function to create an instance of GatePeterson
+ */
+void *gatepeterson_create(const struct gatepeterson_params *params);
+
+/*
+ * Function to delete an instance of GatePeterson
+ */
+int gatepeterson_delete(void **gphandle);
+
+/*
+ * Function to open a previously created instance
+ */
+int gatepeterson_open(void **gphandle,
+ struct gatepeterson_params *params);
+
+/*
+ * Function to close a previously opened instance
+ */
+int gatepeterson_close(void **gphandle);
+
+/*
+ * Function to enter the gate peterson
+ */
+u32 gatepeterson_enter(void *gphandle);
+
+/*
+ *Function to leave the gate peterson
+ */
+void gatepeterson_leave(void *gphandle, u32 flag);
+
+
+/*
+ * Returns the gatepeterson kernel object pointer
+ */
+void *gatepeterson_get_knl_handle(void **gpHandle);
+
+/*
+ * Function to return the shared memory requirement
+ */
+u32 gatepeterson_shared_memreq(const struct gatepeterson_params *params);
+
+#endif /* _GATEPETERSON_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/gatepeterson_ioctl.h b/arch/arm/plat-omap/include/syslink/gatepeterson_ioctl.h
new file mode 100755
index 000000000000..ed7ab86b75bc
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/gatepeterson_ioctl.h
@@ -0,0 +1,193 @@
+/*
+ * gatepeterson_ioctl.h
+ *
+ * The Gate Peterson Algorithm for mutual exclusion of shared memory.
+ * Current implementation works for 2 processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _GATEPETERSON_IOCTL_
+#define _GATEPETERSON_IOCTL_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <gatepeterson.h>
+
+enum CMD_GATEPETERSON {
+ GATEPETERSON_GETCONFIG = GATEPETERSON_BASE_CMD,
+ GATEPETERSON_SETUP,
+ GATEPETERSON_DESTROY,
+ GATEPETERSON_PARAMS_INIT,
+ GATEPETERSON_CREATE,
+ GATEPETERSON_DELETE,
+ GATEPETERSON_OPEN,
+ GATEPETERSON_CLOSE,
+ GATEPETERSON_ENTER,
+ GATEPETERSON_LEAVE,
+ GATEPETERSON_SHAREDMEMREQ
+};
+
+/*
+ * IOCTL command IDs for gatepeterson
+ */
+
+/*
+ * Command for gatepeterson_get_config
+ */
+#define CMD_GATEPETERSON_GETCONFIG _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_GETCONFIG, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_setup
+ */
+#define CMD_GATEPETERSON_SETUP _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_SETUP, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_setup
+ */
+#define CMD_GATEPETERSON_DESTROY _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_DESTROY, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_destroy
+ */
+#define CMD_GATEPETERSON_PARAMS_INIT _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_PARAMS_INIT, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_create
+ */
+#define CMD_GATEPETERSON_CREATE _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_CREATE, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_delete
+ */
+#define CMD_GATEPETERSON_DELETE _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_DELETE, \
+ struct gatepeterson_cmd_args)
+/*
+ * Command for gatepeterson_open
+ */
+#define CMD_GATEPETERSON_OPEN _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_OPEN, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_close
+ */
+#define CMD_GATEPETERSON_CLOSE _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_CLOSE, \
+ struct gatepeterson_cmd_args)
+/*
+ * Command for gatepeterson_enter
+ */
+#define CMD_GATEPETERSON_ENTER _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_ENTER, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_leave
+ */
+#define CMD_GATEPETERSON_LEAVE _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_LEAVE, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command for gatepeterson_shared_memreq
+ */
+#define CMD_GATEPETERSON_SHAREDMEMREQ _IOWR(IPC_IOC_MAGIC, \
+ GATEPETERSON_SHAREDMEMREQ, \
+ struct gatepeterson_cmd_args)
+
+/*
+ * Command arguments for gatepeterson
+ */
+union gatepeterson_arg {
+ struct {
+ void *handle;
+ struct gatepeterson_params *params;
+ } params_init;
+
+ struct {
+ struct gatepeterson_config *config;
+ } get_config;
+
+ struct {
+ struct gatepeterson_config *config;
+ } setup;
+
+ struct {
+ void *handle;
+ struct gatepeterson_params *params;
+ u32 name_len;
+ u32 shared_addr_srptr;
+ } create;
+
+ struct {
+ void *handle;
+ } delete;
+
+ struct {
+ void *handle;
+ struct gatepeterson_params *params;
+ u32 name_len;
+ u32 shared_addr_srptr;
+ } open;
+
+ struct {
+ void *handle;
+ } close;
+
+ struct {
+ void *handle;
+ u32 flags;
+ } enter;
+
+ struct {
+ void *handle;
+ u32 flags;
+ } leave;
+
+ struct {
+ void *handle;
+ struct gatepeterson_params *params;
+ u32 bytes;
+ } shared_memreq;
+
+};
+
+/*
+ * Command arguments for gatepeterson
+ */
+struct gatepeterson_cmd_args {
+ union gatepeterson_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for gatepeterson module
+ */
+int gatepeterson_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _GATEPETERSON_IOCTL_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/gt.h b/arch/arm/plat-omap/include/syslink/gt.h
new file mode 100644
index 000000000000..95e3feb18e7b
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/gt.h
@@ -0,0 +1,320 @@
+
+/*
+ * gt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== gt.h ========
+ * Purpose:
+ * There are two definitions that affect which portions of trace
+ * are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
+ * GT_TRACE is set to 0 then all trace statements (except for assertions)
+ * will be compiled out of the client. If GT_ASSERT is set to 0 then
+ * assertions will be compiled out of the client. GT_ASSERT can not be
+ * set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
+ * GT_ASSERT == 1).
+ *
+ *! Revision History
+ *! ================
+ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace
+ *! definitions are WinCE Specific.
+ *! 03-Jan-1997 ge Replaced "GT_" prefix to GT_Config structure members
+ *! to eliminate preprocessor confusion with other macros.
+ */
+#include <linux/types.h>
+#ifndef GT_
+#define GT_
+
+#ifndef GT_TRACE
+#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
+#endif
+
+/* #include <syslink/host_os.h> */
+
+typedef s32(*Fxn)(); /* generic function type */
+
+
+#if !defined(GT_ASSERT) || GT_TRACE
+#define GT_ASSERT 1
+#endif
+
+struct GT_Config {
+ Fxn PRINTFXN;
+ Fxn PIDFXN;
+ Fxn TIDFXN;
+ Fxn ERRORFXN;
+};
+
+extern struct GT_Config *GT;
+
+struct gt_mask {
+ char *modName;
+ u8 *flags;
+} ;
+
+/*
+ * New GT Class defenitions.
+ *
+ * The following are the explanations and how it could be used in the code
+ *
+ * - GT_ENTER On Entry to Functions
+ *
+ * - GT_1CLASS Display level of debugging status- Object/Automatic
+ * variables
+ * - GT_2CLASS ---- do ----
+ *
+ * - GT_3CLASS ---- do ---- + It can be used(recommended) for debug
+ * status in the ISR, IST
+ * - GT_4CLASS ---- do ----
+ *
+ * - GT_5CLASS Display entry for module init/exit functions
+ *
+ * - GT_6CLASS Warn whenever SERVICES function fails
+ *
+ * - GT_7CLASS Warn failure of Critical failures
+ *
+ */
+
+#define GT_ENTER ((u8)0x01)
+#define GT_1CLASS ((u8)0x02)
+#define GT_2CLASS ((u8)0x04)
+#define GT_3CLASS ((u8)0x08)
+#define GT_4CLASS ((u8)0x10)
+#define GT_5CLASS ((u8)0x20)
+#define GT_6CLASS ((u8)0x40)
+#define GT_7CLASS ((u8)0x80)
+#define GT_LEAVE ((u8)0x02)
+
+#ifdef _LINT_
+
+/* LINTLIBRARY */
+
+/*
+ * ======== GT_assert ========
+ */
+/* ARGSUSED */
+void GT_assert(struct gt_mask mask, s32 expr)
+{
+}
+
+/*
+ * ======== GT_config ========
+ */
+/* ARGSUSED */
+void GT_config(struct GT_Config config)
+{
+}
+
+/*
+ * ======== GT_create ========
+ */
+/* ARGSUSED */
+void GT_create(struct gt_mask *mask, char *modName)
+{
+}
+
+/*
+ * ======== GT_curline ========
+ * Purpose:
+ * Returns the current source code line number. Is useful for performing
+ * branch testing using trace. For example,
+ *
+ * gt_1trace(curTrace, GT_1CLASS,
+ * "in module XX_mod, executing line %u\n", GT_curline());
+ */
+/* ARGSUSED */
+u16 GT_curline(void)
+{
+ return (u16)NULL;
+}
+
+/*
+ * ======== GT_exit ========
+ */
+/* ARGSUSED */
+void GT_exit(void)
+{
+}
+
+/*
+ * ======== GT_init ========
+ */
+/* ARGSUSED */
+void GT_init(void)
+{
+}
+
+/*
+ * ======== GT_query ========
+ */
+/* ARGSUSED */
+bool GT_query(struct gt_mask mask, u8 class)
+{
+ return false;
+}
+
+/*
+ * ======== GT_set ========
+ * sets trace mask according to settings
+ */
+
+/* ARGSUSED */
+void GT_set(char *settings)
+{
+}
+
+/*
+ * ======== GT_setprintf ========
+ * sets printf function
+ */
+
+/* ARGSUSED */
+void GT_setprintf(Fxn fxn)
+{
+}
+
+/* ARGSUSED */
+void gt_0trace(struct gt_mask mask, u8 class, char *format)
+{
+}
+
+/* ARGSUSED */
+void gt_1trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void gt_2trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void gt_3trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void gt_4trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void gt_5trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+/* ARGSUSED */
+void GT_6trace(struct gt_mask mask, u8 class, char *format, ...)
+{
+}
+
+#else
+
+#define GT_BOUND 26 /* 26 letters in alphabet */
+
+extern void _GT_create(struct gt_mask *mask, char *modName);
+
+#define GT_exit()
+
+extern void GT_init(void);
+extern void _GT_set(char *str);
+extern s32 _GT_trace(struct gt_mask *mask, char *format, ...);
+
+#if GT_ASSERT == 0
+
+#define GT_assert(mask, expr)
+#define GT_config(config)
+#define GT_configInit(config)
+#define GT_seterror(fxn)
+
+#else
+
+extern struct GT_Config _GT_params;
+
+#define GT_assert(mask, expr) \
+ (!(expr) ? \
+ printk(KERN_ALERT "assertion violation: %s, line %d\n", \
+ __FILE__, __LINE__), NULL : NULL)
+
+#define GT_config(config) (_GT_params = *(config))
+#define GT_configInit(config) (*(config) = _GT_params)
+#define GT_seterror(fxn) (_GT_params.ERRORFXN = (Fxn)(fxn))
+
+#endif
+
+#if GT_TRACE == 0
+
+#define GT_curline() ((u16)__LINE__)
+#define GT_create(mask, modName)
+#define GT_exit()
+#define GT_init()
+#define GT_set(settings)
+#define GT_setprintf(fxn)
+
+#define GT_query(mask, class) false
+
+#define gt_0trace(mask, class, format)
+#define gt_1trace(mask, class, format, arg1)
+#define gt_2trace(mask, class, format, arg1, arg2)
+#define gt_3trace(mask, class, format, arg1, arg2, arg3)
+#define gt_4trace(mask, class, format, arg1, arg2, arg3, arg4)
+#define gt_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
+#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
+
+#else /* GT_TRACE == 1 */
+
+#define GT_create(mask, modName) _GT_create((mask), (modName))
+#define GT_curline() ((u16)__LINE__)
+#define GT_set(settings) _GT_set(settings)
+#define GT_setprintf(fxn) (_GT_params.PRINTFXN = (Fxn)(fxn))
+
+#define GT_query(mask, class) ((*(mask).flags & (class)))
+
+#define gt_0trace(mask, class, format) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format)) : 0)
+
+#define gt_1trace(mask, class, format, arg1) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1)) : 0)
+
+#define gt_2trace(mask, class, format, arg1, arg2) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
+
+#define gt_3trace(mask, class, format, arg1, arg2, arg3) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
+
+#define gt_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
+
+#define gt_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) \
+ : 0)
+
+#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
+ ((*(mask).flags & (class)) ? \
+ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
+ (arg6)) : 0)
+
+#endif /* GT_TRACE */
+
+#endif /* _LINT_ */
+
+#endif /* GTCE_ */
diff --git a/arch/arm/plat-omap/include/syslink/heap.h b/arch/arm/plat-omap/include/syslink/heap.h
new file mode 100755
index 000000000000..f03a692a71ab
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/heap.h
@@ -0,0 +1,91 @@
+/*
+ * heap.h
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+#include <linux/types.h>
+
+/*
+ * Structure defining memory related statistics
+ */
+struct memory_stats{
+ u32 *total_size; /* Total memory size */
+ u32 *total_free_size; /* Total free memory size */
+ u32 *largest_free_size; /* Largest free memory size */
+};
+
+/*!
+ * ======== extendedstats ========
+ * Stats structure for the get_extended_stats API.
+ *
+ * max_allocated_blocks: The maximum number of blocks allocated
+ * from this heap at any single point in time during the lifetime of this
+ * heap instance.
+ *
+ * num_allocated_blocks: The total number of blocks currently
+ * allocated in this Heap instance.
+ */
+struct heap_extended_stats {
+ u32 max_allocated_blocks;
+ u32 num_allocated_blocks;
+};
+
+/*
+ * Structure defining config parameters for the heapbuf module
+ */
+struct heap_config {
+ u32 max_name_len; /* Maximum length of name */
+ bool track_max_allocs; /* Track the max number of allocated blocks */
+};
+
+/*
+ * Structure for the handle for the heap
+ */
+struct heap_object {
+ void* (*alloc) (void *handle, u32 size, u32 align);
+ int (*free) (void *handle, void *block, u32 size);
+ int (*get_stats) (void *handle, struct memory_stats *stats);
+ int (*get_extended_stats) (void *handle,
+ struct heap_extended_stats *stats);
+ void *obj;
+};
+
+/*
+ * Allocate a block
+ */
+void *heap_alloc(void *handle, u32 size, u32 align);
+
+/*
+ * Frees the block to this Heap
+ */
+int heap_free(void *handle, void *block, u32 size);
+
+/*
+ * Get heap statistics
+ */
+int heap_get_stats(void *handle, struct memory_stats *stats);
+
+/*
+ * Get heap extended statistics
+ */
+int heap_get_extended_stats(void *hphandle,
+ struct heap_extended_stats *stats);
+
+#endif /* _HEAP_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/heapbuf.h b/arch/arm/plat-omap/include/syslink/heapbuf.h
new file mode 100755
index 000000000000..3667c4675d49
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/heapbuf.h
@@ -0,0 +1,152 @@
+/*
+ * heapbuf.h
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _HEAPBUF_H_
+#define _HEAPBUF_H_
+
+#include <linux/types.h>
+#include <heap.h>
+#include <listmp.h>
+
+/*!
+ * @def LISTMP_MODULEID
+ * @brief Unique module ID.
+ */
+#define HEAPBUF_MODULEID (0x4cd5)
+
+/*
+ * Creation of Heap Buf succesful.
+*/
+#define HEAPBUF_CREATED (0x05251995)
+
+/*
+ * Version.
+ */
+#define HEAPBUF_VERSION (1)
+
+/*
+ * Structure defining config parameters for the HeapBuf module.
+ */
+struct heapbuf_config {
+ u32 max_name_len; /* Maximum length of name */
+ bool use_nameserver; /* To have this module use the NameServer or not */
+ bool track_max_allocs; /* Track the maximum number of allocated blocks */
+};
+
+/*
+ * Structure defining parameters for the HeapBuf module
+ */
+struct heapbuf_params {
+ void *gate;
+ bool exact; /* Only allocate on exact match of rquested size */
+ char *name; /* Name when using nameserver */
+ int resource_id; /* Resource id of the hardware linked list */
+ bool cache_flag; /* Whether to perform cache coherency calls */
+ u32 align; /* Alignment (in MAUs, power of 2) of each block */
+ u32 num_blocks; /* Number of fixed-size blocks */
+ u32 block_size; /* Size (in MAUs) of each block*/
+ void *shared_addr; /* Physical address of the shared memory */
+ u32 shared_addr_size; /* Size of shareAddr */
+ void *shared_buf; /* Physical address of the shared buffers */
+ u32 shared_buf_size; /* Size of sharedBuf */
+};
+
+/*
+ * Stats structure for the getExtendedStats API.
+ */
+struct heapbuf_extended_stats {
+ u32 max_allocated_blocks;
+ /* maximum number of blocks allocated from this heap instance */
+ u32 num_allocated_blocks;
+ /* total number of blocks currently allocated from this heap instance*/
+};
+
+
+/*
+ * Function to get default configuration for the heapbuf module
+ */
+int heapbuf_get_config(struct heapbuf_config *cfgparams);
+
+/*
+ * Function to setup the heapbuf module
+ */
+int heapbuf_setup(const struct heapbuf_config *cfg);
+
+/*
+ * Function to destroy the heapbuf module
+ */
+int heapbuf_destroy(void);
+
+/* Initialize this config-params structure with supplier-specified
+ * defaults before instance creation
+ */
+void heapbuf_params_init(void *handle, struct heapbuf_params *params);
+
+/*
+ * Creates a new instance of heapbuf module
+ */
+void *heapbuf_create(const struct heapbuf_params *params);
+
+/*
+ * Deletes a instance of heapbuf module
+ */
+int heapbuf_delete(void **handle_ptr);
+
+/*
+ * Opens a created instance of heapbuf module
+ */
+int heapbuf_open(void **handle_ptr, struct heapbuf_params *params);
+
+/*
+ * Closes previously opened/created instance of heapbuf module
+ */
+int heapbuf_close(void *handle_ptr);
+
+/*
+ * Returns the amount of shared memory required for creation
+ * of each instance
+ */
+int heapbuf_shared_memreq(const struct heapbuf_params *params, u32 *buf_size);
+
+/*
+ * Allocate a block
+ */
+void *heapbuf_alloc(void *hphandle, u32 size, u32 align);
+
+/*
+ * Frees the block to this heapbuf
+ */
+int heapbuf_free(void *hphandle, void *block, u32 size);
+
+/*
+ * Get memory statistics
+ */
+int heapbuf_get_stats(void *hphandle, struct memory_stats *stats);
+
+/*
+ * Indicate whether the heap may block during an alloc or free call
+ */
+bool heapbuf_isblocking(void *handle);
+
+/*
+ * Get extended statistics
+ */
+int heapbuf_get_extended_stats(void *hphandle,
+ struct heapbuf_extended_stats *stats);
+
+#endif /* _HEAPBUF_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/heapbuf_ioctl.h b/arch/arm/plat-omap/include/syslink/heapbuf_ioctl.h
new file mode 100755
index 000000000000..80165dcfc436
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/heapbuf_ioctl.h
@@ -0,0 +1,215 @@
+/*
+ * heapbuf_ioctl.h
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _HEAPBUF_IOCTL_
+#define _HEAPBUF_IOCTL_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <heap.h>
+#include <heapbuf.h>
+
+
+enum CMD_HEAPBUF {
+ HEAPBUF_GETCONFIG = HEAPBUF_BASE_CMD,
+ HEAPBUF_SETUP,
+ HEAPBUF_DESTROY,
+ HEAPBUF_PARAMS_INIT,
+ HEAPBUF_CREATE,
+ HEAPBUF_DELETE,
+ HEAPBUF_OPEN,
+ HEAPBUF_CLOSE,
+ HEAPBUF_ALLOC,
+ HEAPBUF_FREE,
+ HEAPBUF_SHAREDMEMREQ,
+ HEAPBUF_GETSTATS,
+ HEAPBUF_GETEXTENDEDSTATS
+};
+
+/*
+ * Command for heapbuf_get_config
+ */
+#define CMD_HEAPBUF_GETCONFIG _IOWR(IPC_IOC_MAGIC, HEAPBUF_GETCONFIG,\
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_setup
+ */
+#define CMD_HEAPBUF_SETUP _IOWR(IPC_IOC_MAGIC, HEAPBUF_SETUP, \
+ struct heapbuf_cmd_args)
+/*
+ * Command for heapbuf_destroy
+ */
+#define CMD_HEAPBUF_DESTROY _IOWR(IPC_IOC_MAGIC, HEAPBUF_DESTROY, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_prams_init
+ */
+#define CMD_HEAPBUF_PARAMS_INIT _IOWR(IPC_IOC_MAGIC, \
+ HEAPBUF_PARAMS_INIT, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_create
+ */
+#define CMD_HEAPBUF_CREATE _IOWR(IPC_IOC_MAGIC, HEAPBUF_CREATE, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_delete
+ */
+#define CMD_HEAPBUF_DELETE _IOWR(IPC_IOC_MAGIC, HEAPBUF_DELETE, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_open
+ */
+#define CMD_HEAPBUF_OPEN _IOWR(IPC_IOC_MAGIC, HEAPBUF_OPEN, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_close
+ */
+#define CMD_HEAPBUF_CLOSE _IOWR(IPC_IOC_MAGIC, HEAPBUF_CLOSE, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_alloc
+ */
+#define CMD_HEAPBUF_ALLOC _IOWR(IPC_IOC_MAGIC, HEAPBUF_ALLOC, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_free
+ */
+#define CMD_HEAPBUF_FREE _IOWR(IPC_IOC_MAGIC, HEAPBUF_FREE, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_shared_memreq
+ */
+#define CMD_HEAPBUF_SHAREDMEMREQ _IOWR(IPC_IOC_MAGIC, \
+ HEAPBUF_SHAREDMEMREQ, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_get_stats
+ */
+#define CMD_HEAPBUF_GETSTATS _IOWR(IPC_IOC_MAGIC, \
+ HEAPBUF_GETSTATS, \
+ struct heapbuf_cmd_args)
+
+/*
+ * Command for heapbuf_get_extended_stats
+ */
+#define CMD_HEAPBUF_GETEXTENDEDSTATS _IOWR(IPC_IOC_MAGIC, \
+ HEAPBUF_GETEXTENDEDSTATS, \
+ struct heapbuf_cmd_args)
+
+
+/*
+ * Command arguments for heapbuf
+ */
+union heapbuf_arg {
+ struct {
+ void *handle;
+ struct heapbuf_params *params;
+ } params_init;
+
+ struct {
+ struct heapbuf_config *config;
+ } get_config;
+
+ struct {
+ struct heapbuf_config *config;
+ } setup;
+
+ struct {
+ void *handle;
+ struct heapbuf_params *params;
+ u32 name_len;
+ u32 *shared_addr_srptr;
+ u32 *shared_buf_srptr;
+ void *knl_gate;
+ } create;
+
+ struct {
+ void *handle;
+ } delete;
+
+ struct {
+ void *handle;
+ struct heapbuf_params *params;
+ u32 name_len;
+ u32 *shared_addr_srptr;
+ void *knl_gate;
+ } open;
+
+ struct {
+ void *handle;
+ } close;
+
+ struct {
+ void *handle;
+ u32 size;
+ u32 align;
+ u32 *block_srptr;
+ } alloc;
+
+ struct {
+ void *handle;
+ u32 *block_srptr;
+ u32 size;
+ } free;
+
+ struct {
+ void *handle;
+ struct memory_stats *stats;
+ } get_stats;
+
+ struct {
+ void *handle;
+ struct heapbuf_extended_stats *stats;
+ } get_extended_stats;
+
+ struct {
+ void *handle;
+ struct heapbuf_params *params;
+ u32 buf_size;
+ u32 bytes;
+ } shared_memreq;
+};
+
+/*
+ * Command arguments for heapbuf
+ */
+struct heapbuf_cmd_args{
+ union heapbuf_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for heapbuf module
+ */
+int heapbuf_ioctl(struct inode *pinode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _HEAPBUF_IOCTL_ */
diff --git a/arch/arm/plat-omap/include/syslink/host_os.h b/arch/arm/plat-omap/include/syslink/host_os.h
new file mode 100755
index 000000000000..e0f02c3cfe88
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/host_os.h
@@ -0,0 +1,72 @@
+
+/*
+ * host_os.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * ======== windows.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
+ *! 16-Feb-2004 sb Added headers required for consistent_alloc
+ */
+
+#ifndef _HOST_OS_H_
+#define _HOST_OS_H_
+
+#include <linux/autoconf.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/syscalls.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+
+/* ----------------------------------- Macros */
+
+#define SEEK_SET 0 /* Seek from beginning of file. */
+#define SEEK_CUR 1 /* Seek from current position. */
+#define SEEK_END 2 /* Seek from end of file. */
+
+/* TODO -- Remove, once BP defines them */
+#define INT_MAIL_MPU_IRQ 26
+#define INT_DSP_MMU_IRQ 28
+
+#endif
diff --git a/arch/arm/plat-omap/include/syslink/hw_defs.h b/arch/arm/plat-omap/include/syslink/hw_defs.h
new file mode 100755
index 000000000000..440dbb14445e
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/hw_defs.h
@@ -0,0 +1,63 @@
+/*
+ * hw_defs.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef __HW_DEFS_H
+#define __HW_DEFS_H
+
+#include <syslink/GlobalTypes.h>
+
+/* Page size */
+#define HW_PAGE_SIZE_4KB 0x1000
+#define HW_PAGE_SIZE_64KB 0x10000
+#define HW_PAGE_SIZE_1MB 0x100000
+#define HW_PAGE_SIZE_16MB 0x1000000
+
+/* hw_status: return type for HW API */
+typedef long hw_status;
+
+/* hw_set_clear_t: Enumerated Type used to set and clear any bit */
+enum hw_set_clear_t {
+ HW_CLEAR,
+ HW_SET
+} ;
+
+/* hw_endianism_t: Enumerated Type used to specify the endianism
+ * Do NOT change these values. They are used as bit fields. */
+enum hw_endianism_t {
+ HW_LITTLE_ENDIAN,
+ HW_BIG_ENDIAN
+
+} ;
+
+/* hw_elemnt_siz_t: Enumerated Type used to specify the element size
+ * Do NOT change these values. They are used as bit fields. */
+enum hw_elemnt_siz_t {
+ HW_ELEM_SIZE_8BIT,
+ HW_ELEM_SIZE_16BIT,
+ HW_ELEM_SIZE_32BIT,
+ HW_ELEM_SIZE_64BIT
+
+} ;
+
+/* HW_IdleMode_t: Enumerated Type used to specify Idle modes */
+enum HW_IdleMode_t {
+ HW_FORCE_IDLE,
+ HW_NO_IDLE,
+ HW_SMART_IDLE
+} ;
+
+#endif /* __HW_DEFS_H */
diff --git a/arch/arm/plat-omap/include/syslink/hw_mbox.h b/arch/arm/plat-omap/include/syslink/hw_mbox.h
new file mode 100755
index 000000000000..f50ef782e66f
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/hw_mbox.h
@@ -0,0 +1,447 @@
+/*
+ * hw_mbox.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef __MBOX_H
+#define __MBOX_H
+
+#include <syslink/hw_defs.h>
+
+
+#define HW_MBOX_INT_NEW_MSG 0x1
+#define HW_MBOX_INT_NOT_FULL 0x2
+#define HW_MBOX_INT_ALL 0x3
+
+/*
+ * DEFINITION: HW_MBOX_MAX_NUM_MESSAGES
+ *
+ * DESCRIPTION: Maximum number of messages that mailbox can hald at a time.
+ *
+ *
+ */
+
+#define HW_MBOX_MAX_NUM_MESSAGES 4
+
+
+ /* width in bits of MBOX Id */
+#define HW_MBOX_ID_WIDTH 2
+
+
+/*
+ * TYPE: enum hw_mbox_id_t
+ *
+ * DESCRIPTION: Enumerated Type used to specify Mail Box Sub Module Id Number
+ *
+ *
+ */
+ enum hw_mbox_id_t {
+ HW_MBOX_ID_0,
+ HW_MBOX_ID_1,
+ HW_MBOX_ID_2,
+ HW_MBOX_ID_3,
+ HW_MBOX_ID_4,
+ HW_MBOX_ID_5
+ };
+
+/*
+ * TYPE: enum hw_mbox_userid_t
+ *
+ * DESCRIPTION: Enumerated Type used to specify Mail box User Id
+ *
+ *
+ */
+ enum hw_mbox_userid_t {
+ HW_MBOX_U0_ARM11,
+ HW_MBOX_U1_UMA,
+ HW_MBOX_U2_IVA,
+ HW_MBOX_U3_ARM11
+ };
+
+#if defined(OMAP3430)
+/*
+* TYPE: mailbox_context
+*
+* DESCRIPTION: Mailbox context settings
+*
+*
+*/
+struct mailbox_context {
+ unsigned long sysconfig;
+ unsigned long irqEnable0;
+ unsigned long irqEnable1;
+};
+#endif/* defined(OMAP3430)*/
+
+/*
+* FUNCTION : hw_mbox_msg_read
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to read
+*
+* OUTPUTS:
+*
+* Identifier : p_read_value
+* Type : unsigned long *const
+* Description : Value read from MailBox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE:
+* : this function reads a unsigned long from the sub module message
+* box Specified. if there are no messages in the mailbox
+* then and error is returned.
+*
+*/
+extern long hw_mbox_msg_read(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_read_value
+ );
+
+/*
+* FUNCTION : hw_mbox_msg_write
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to write
+*
+* Identifier : write_value
+* Type : const unsigned long
+* Description : Value to write to MailBox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE:: this function writes a unsigned long from the sub module message
+* box Specified.
+*
+*
+*/
+extern long hw_mbox_msg_write(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const unsigned long write_value
+ );
+
+/*
+* FUNCTION : hw_mbox_is_full
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to check
+*
+* OUTPUTS:
+*
+* Identifier : p_is_full
+* Type : unsigned long *const
+* Description : false means mail box not Full
+* true means mailbox full.
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function reads the full status register for mailbox.
+*
+*
+*/
+extern long hw_mbox_is_full(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_is_full
+ );
+
+/* -----------------------------------------------------------------
+* FUNCTION : hw_mbox_nomsg_get
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to get num messages
+*
+* OUTPUTS:
+*
+* Identifier : p_num_msg
+* Type : unsigned long *const
+* Description : Number of messages in mailbox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Inavlid ID input at parameter
+*
+* PURPOSE:
+* : this function gets number of messages in a specified mailbox.
+*
+*
+*/
+extern long hw_mbox_nomsg_get(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_num_msg
+ );
+
+/*
+* FUNCTION : hw_mbox_event_enable
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to enable
+*
+* Identifier : user_id
+* Type : const enum hw_mbox_userid_t
+* Description : Mail box User Id to enable
+*
+* Identifier : enableIrq
+* Type : const unsigned long
+* Description : Irq value to enable
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function enables the specified IRQ.
+*
+*
+*/
+extern long hw_mbox_event_enable(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long events
+ );
+
+/*
+* FUNCTION : hw_mbox_event_disable
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to disable
+*
+* Identifier : user_id
+* Type : const enum hw_mbox_userid_t
+* Description : Mail box User Id to disable
+*
+* Identifier : enableIrq
+* Type : const unsigned long
+* Description : Irq value to disable
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function disables the specified IRQ.
+*
+*
+*/
+extern long hw_mbox_event_disable(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long events
+ );
+
+/*
+* FUNCTION : hw_mbox_event_status
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to clear
+*
+* Identifier : user_id
+* Type : const enum hw_mbox_userid_t
+* Description : Mail box User Id to clear
+*
+* OUTPUTS:
+*
+* Identifier : pIrqStatus
+* Type : pMBOX_Int_t *const
+* Description : The value in IRQ status register
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function gets the status of the specified IRQ.
+*
+*
+*/
+extern long hw_mbox_event_status(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ unsigned long *const p_eventStatus
+ );
+
+/*
+* FUNCTION : hw_mbox_event_ack
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mail_box_id
+* Type : const enum hw_mbox_id_t
+* Description : Mail Box Sub module Id to set
+*
+* Identifier : user_id
+* Type : const enum hw_mbox_userid_t
+* Description : Mail box User Id to set
+*
+* Identifier : irqStatus
+* Type : const unsigned long
+* Description : The value to write IRQ status
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address Paramater was set to 0
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function sets the status of the specified IRQ.
+*
+*
+*/
+extern long hw_mbox_event_ack(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long event
+ );
+
+#if defined(OMAP3430)
+/* ---------------------------------------------------------------
+* FUNCTION : hw_mbox_save_settings
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE: : this function saves the context of mailbox
+*
+* ----------------------------------------------------------------
+*/
+extern long hw_mbox_save_settings(unsigned long baseAddres);
+
+/*
+* FUNCTION : hw_mbox_restore_settings
+*
+* INPUTS:
+*
+* Identifier : base_address
+* Type : const unsigned long
+* Description : Base Address of instance of Mailbox module
+*
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE: : this function restores the context of mailbox
+*
+*
+*/
+extern long hw_mbox_restore_settings(unsigned long baseAddres);
+#endif/* defined(OMAP3430)*/
+
+#endif /* __MBOX_H */
+
diff --git a/arch/arm/plat-omap/include/syslink/hw_mmu.h b/arch/arm/plat-omap/include/syslink/hw_mmu.h
new file mode 100755
index 000000000000..a85b2f9ca024
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/hw_mmu.h
@@ -0,0 +1,169 @@
+/*
+ * hw_mbox.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef __HW_MMU_H
+#define __HW_MMU_H
+
+#include <linux/types.h>
+
+/* Bitmasks for interrupt sources */
+#define HW_MMU_TRANSLATION_FAULT 0x2
+#define HW_MMU_ALL_INTERRUPTS 0x1F
+
+#define HW_MMU_COARSE_PAGE_SIZE 0x400
+
+/* hw_mmu_mixed_size_t: Enumerated Type used to specify whether to follow
+ CPU/TLB Element size */
+enum hw_mmu_mixed_size_t {
+ HW_MMU_TLBES,
+ HW_MMU_CPUES
+
+} ;
+
+/* hw_mmu_map_attrs_t: Struct containing MMU mapping attributes */
+struct hw_mmu_map_attrs_t {
+ enum hw_endianism_t endianism;
+ enum hw_elemnt_siz_t element_size;
+ enum hw_mmu_mixed_size_t mixedSize;
+} ;
+
+extern hw_status hw_mmu_enable(const u32 base_address);
+
+extern hw_status hw_mmu_disable(const u32 base_address);
+
+extern hw_status hw_mmu_numlocked_set(const u32 base_address,
+ u32 num_lcked_entries);
+
+extern hw_status hw_mmu_victim_numset(const u32 base_address,
+ u32 vctm_entry_num);
+
+/* For MMU faults */
+extern hw_status hw_mmu_eventack(const u32 base_address,
+ u32 irq_mask);
+
+extern hw_status hw_mmu_event_disable(const u32 base_address,
+ u32 irq_mask);
+
+extern hw_status hw_mmu_event_enable(const u32 base_address,
+ u32 irq_mask);
+
+extern hw_status hw_mmu_event_status(const u32 base_address,
+ u32 *irq_mask);
+
+extern hw_status hw_mmu_flt_adr_rd(const u32 base_address,
+ u32 *addr);
+
+/* Set the TT base address */
+extern hw_status hw_mmu_ttbset(const u32 base_address,
+ u32 ttb_phys_addr);
+
+extern hw_status hw_mmu_twl_enable(const u32 base_address);
+
+extern hw_status hw_mmu_twl_disable(const u32 base_address);
+
+extern hw_status hw_mmu_tlb_flush(const u32 base_address,
+ u32 virtual_addr,
+ u32 page_size);
+
+extern hw_status hw_mmu_tlb_flushAll(const u32 base_address);
+
+extern hw_status hw_mmu_tlb_add(const u32 base_address,
+ u32 physical_addr,
+ u32 virtual_addr,
+ u32 page_size,
+ u32 entryNum,
+ struct hw_mmu_map_attrs_t *map_attrs,
+ enum hw_set_clear_t preserve_bit,
+ enum hw_set_clear_t valid_bit);
+
+
+/* For PTEs */
+extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
+ u32 physical_addr,
+ u32 virtual_addr,
+ u32 page_size,
+ struct hw_mmu_map_attrs_t *map_attrs);
+
+extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
+ u32 pg_size,
+ u32 virtual_addr);
+
+static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)
+{
+ u32 pte_addr;
+ u32 VA_31_to_20;
+
+ VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
+ VA_31_to_20 &= 0xFFFFFFFCUL;
+ pte_addr = l1_base + VA_31_to_20;
+
+ return pte_addr;
+}
+
+static inline u32 hw_mmu_pte_addr_l2(u32 l2_base, u32 va)
+{
+ u32 pte_addr;
+
+ pte_addr = (l2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
+
+ return pte_addr;
+}
+
+static inline u32 hw_mmu_pte_coarsel1(u32 pte_val)
+{
+ u32 pteCoarse;
+
+ pteCoarse = pte_val & 0xFFFFFC00;
+
+ return pteCoarse;
+}
+
+static inline u32 hw_mmu_pte_sizel1(u32 pte_val)
+{
+ u32 pte_size = 0;
+
+ if ((pte_val & 0x3) == 0x1) {
+ /* Points to L2 PT */
+ pte_size = HW_MMU_COARSE_PAGE_SIZE;
+ }
+
+ if ((pte_val & 0x3) == 0x2) {
+ if (pte_val & (1 << 18))
+ pte_size = HW_PAGE_SIZE_16MB;
+ else
+ pte_size = HW_PAGE_SIZE_1MB;
+ }
+
+ return pte_size;
+}
+
+static inline u32 hw_mmu_pte_sizel2(u32 pte_val)
+{
+ u32 pte_size = 0;
+
+ if (pte_val & 0x2)
+ pte_size = HW_PAGE_SIZE_4KB;
+ else if (pte_val & 0x1)
+ pte_size = HW_PAGE_SIZE_64KB;
+
+ return pte_size;
+}
+extern hw_status hw_mmu_tlb_dump(u32 base_address, bool shw_inv_entries);
+
+extern u32 hw_mmu_pte_phyaddr(u32 pte_val, u32 pte_size);
+
+#endif /* __HW_MMU_H */
diff --git a/arch/arm/plat-omap/include/syslink/hw_ocp.h b/arch/arm/plat-omap/include/syslink/hw_ocp.h
new file mode 100755
index 000000000000..7277bbfcde33
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/hw_ocp.h
@@ -0,0 +1,60 @@
+/*
+ * hw_ocp.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#ifndef __HW_OCP_H
+#define __HW_OCP_H
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/hw_ocp.h>
+#include <syslink/hw_defs.h>
+#include <syslink/MBXRegAcM.h>
+#include <syslink/MBXAccInt.h>
+
+
+/*
+* TYPE: HW_IdleMode_t
+*
+* DESCRIPTION: Enumerated Type for idle modes in OCP SYSCONFIG register
+*
+*
+*/
+enum hal_ocp_idlemode_t {
+ HW_OCP_FORCE_IDLE,
+ HW_OCP_NO_IDLE,
+ HW_OCP_SMART_IDLE
+};
+
+extern long hw_ocp_soft_reset(const unsigned long base_address);
+
+extern long hw_ocp_soft_reset_isdone(const unsigned long base_address,
+ unsigned long *reset_is_done);
+
+extern long hw_ocp_idle_modeset(const unsigned long base_address,
+ enum hal_ocp_idlemode_t idle_mode);
+
+extern long hw_ocp_idlemode_get(const unsigned long base_address,
+ enum hal_ocp_idlemode_t *idle_mode);
+
+extern long hw_ocp_autoidle_set(const unsigned long base_address,
+ enum hw_set_clear_t auto_idle);
+
+extern long hw_ocp_autoidle_get(const unsigned long base_address,
+ enum hw_set_clear_t *auto_idle);
+
+#endif /* __HW_OCP_H */
+
diff --git a/arch/arm/plat-omap/include/syslink/ipc_ioctl.h b/arch/arm/plat-omap/include/syslink/ipc_ioctl.h
new file mode 100755
index 000000000000..5a5078fcf3bd
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/ipc_ioctl.h
@@ -0,0 +1,92 @@
+/*
+ * ipc_ioctl.h
+ *
+ * Base file for all TI OMAP IPC ioctl's.
+ * Linux-OMAP IPC has allocated base 0xEE with a range of 0x00-0xFF.
+ * (need to get the real one from open source maintainers)
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _IPC_IOCTL_H
+#define _IPC_IOCTL_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+
+#define IPC_IOC_MAGIC 0xE0
+#define IPC_IOC_BASE 2
+
+enum ipc_command_count {
+ MULTIPROC_CMD_NOS = 4,
+ NAMESERVER_CMD_NOS = 13,
+ HEAPBUF_CMD_NOS = 13,
+ SHAREDREGION_CMD_NOS = 10,
+ GATEPETERSON_CMD_NOS = 11,
+ LISTMP_SHAREDMEMORY_CMD_NOS = 18,
+ MESSAGEQ_CMD_NOS = 17,
+ MESSAGEQ_TRANSPORTSHM_CMD_NOS = 9,
+ NAMESERVERREMOTENOTIFY_CMD_NOS = 8,
+ SYSMGR_CMD_NOS = 5,
+ SYSMEMMGR_CMD_NOS = 6
+};
+
+enum ipc_command_ranges {
+ MULTIPROC_BASE_CMD = IPC_IOC_BASE,
+ MULTIPROC_END_CMD = (MULTIPROC_BASE_CMD + \
+ MULTIPROC_CMD_NOS - 1),
+
+ NAMESERVER_BASE_CMD = 10,
+ NAMESERVER_END_CMD = (NAMESERVER_BASE_CMD + \
+ NAMESERVER_CMD_NOS - 1),
+
+ HEAPBUF_BASE_CMD = 30,
+ HEAPBUF_END_CMD = (HEAPBUF_BASE_CMD + \
+ HEAPBUF_CMD_NOS - 1),
+
+ SHAREDREGION_BASE_CMD = 50,
+ SHAREDREGION_END_CMD = (SHAREDREGION_BASE_CMD + \
+ SHAREDREGION_CMD_NOS - 1),
+
+ GATEPETERSON_BASE_CMD = 70,
+ GATEPETERSON_END_CMD = (GATEPETERSON_BASE_CMD + \
+ GATEPETERSON_CMD_NOS - 1),
+
+ LISTMP_SHAREDMEMORY_BASE_CMD = 90,
+ LISTMP_SHAREDMEMORY_END_CMD = (LISTMP_SHAREDMEMORY_BASE_CMD + \
+ LISTMP_SHAREDMEMORY_CMD_NOS - 1),
+
+ MESSAGEQ_BASE_CMD = 110,
+ MESSAGEQ_END_CMD = (MESSAGEQ_BASE_CMD + \
+ MESSAGEQ_CMD_NOS - 1),
+
+ MESSAGEQ_TRANSPORTSHM_BASE_CMD = 130,
+ MESSAGEQ_TRANSPORTSHM_END_CMD = (MESSAGEQ_TRANSPORTSHM_BASE_CMD + \
+ MESSAGEQ_TRANSPORTSHM_CMD_NOS - 1),
+
+ NAMESERVERREMOTENOTIFY_BASE_CMD = 160,
+ NAMESERVERREMOTENOTIFY_END_CMD = (NAMESERVERREMOTENOTIFY_BASE_CMD + \
+ NAMESERVERREMOTENOTIFY_CMD_NOS - 1),
+
+ SYSMGR_BASE_CMD = 170,
+ SYSMGR_END_CMD = (SYSMGR_BASE_CMD + \
+ SYSMGR_CMD_NOS - 1),
+
+ SYSMEMMGR_BASE_CMD = 180,
+ SYSMEMMGR_END_CMD = (SYSMEMMGR_BASE_CMD + \
+ SYSMEMMGR_CMD_NOS - 1)
+};
+
+int ipc_ioc_router(u32 cmd, ulong arg);
+
+#endif /* _IPC_IOCTL_H */
diff --git a/arch/arm/plat-omap/include/syslink/listmp.h b/arch/arm/plat-omap/include/syslink/listmp.h
new file mode 100644
index 000000000000..536f1804da91
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/listmp.h
@@ -0,0 +1,267 @@
+/*
+ * listmp.h
+ *
+ * The listmp module defines the shared memory doubly linked list.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _LISTMP_H_
+#define _LISTMP_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+#include <linux/list.h>
+/*#include <heap.h>*/
+
+/* =============================================================================
+ * All success and failure codes for the module
+ * =============================================================================
+ */
+/*!
+ * @def LISTMP_MODULEID
+ * @brief Unique module ID.
+ */
+#define LISTMP_MODULEID (0xa413)
+
+/*!
+ * @def LISTMP_ERRORCODEBASE
+ * @brief Error code base for ListMP.
+ */
+#define LISTMP_ERRORCODEBASE (LISTMP_MODULEID << 12)
+
+/*!
+ * @def LISTMP_MAKE_FAILURE
+ * @brief Macro to make error code.
+ */
+#define LISTMP_MAKE_FAILURE(x) ((int)(0x80000000 \
+ + (LISTMP_ERRORCODEBASE + (x))))
+
+/*!
+ * @def LISTMP_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define LISTMP_MAKE_SUCCESS(x) (LISTMP_ERRORCODEBASE + (x))
+
+/*!
+ * @def LISTMP_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define LISTMP_E_INVALIDARG LISTMP_MAKE_FAILURE(1)
+
+/*!
+ * @def LISTMP_E_MEMORY
+ * @brief Memory allocation failed.
+ */
+#define LISTMP_E_MEMORY LISTMP_MAKE_FAILURE(2)
+
+/*!
+ * @def LISTMP_E_BUSY
+ * @brief The name is already registered or not.
+ */
+#define LISTMP_E_BUSY LISTMP_MAKE_FAILURE(3)
+
+/*!
+ * @def LISTMP_E_FAIL
+ * @brief Generic failure.
+ */
+#define LISTMP_E_FAIL LISTMP_MAKE_FAILURE(4)
+
+/*!
+ * @def LISTMP_E_NOTFOUND
+ * @brief Name not found in the nameserver.
+ */
+#define LISTMP_E_NOTFOUND LISTMP_MAKE_FAILURE(5)
+
+/*!
+ * @def LISTMP_E_INVALIDSTATE
+ * @brief Module is not initialized.
+ */
+#define LISTMP_E_INVALIDSTATE LISTMP_MAKE_FAILURE(6)
+
+/*!
+ * @def LISTMP_E_OSFAILURE
+ * @brief Failure in OS call.
+ */
+#define LISTMP_E_OSFAILURE LISTMP_MAKE_FAILURE(7)
+
+/*!
+ * @def LISTMP_SUCCESS
+ * @brief Operation successful.
+ */
+#define LISTMP_SUCCESS LISTMP_MAKE_SUCCESS(0)
+
+/*!
+ * @def LISTMP_S_ALREADYSETUP
+ * @brief The LISTMP module has already been setup in this process.
+ */
+#define LISTMP_S_ALREADYSETUP LISTMP_MAKE_SUCCESS(1)
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/*!
+ * @brief Enum defining types of list for the ListMP module.
+ */
+enum listmp_type {
+ listmp_type_SHARED = 0,
+ /*!< List in shared memory */
+ listmp_type_FAST = 1
+ /*!< Hardware Queue */
+};
+
+/*!
+ * @brief Structure defining config parameters for the ListMP module.
+ */
+struct listmp_config {
+ u32 max_name_len;
+ /*!< Maximum length of name */
+ bool use_name_server;
+ /*!< Whether to have this module use the NameServer or not. If the
+ * NameServer is not needed, set this configuration parameter to false.
+ * This informs ListMPSharedMemory not to pull in the NameServer module
+ * In this case, all names passed into create and open are ignored.
+ */
+};
+
+/*!
+ * @brief Structure defining list element for the ListMP.
+ */
+struct listmp_elem {
+ volatile struct listmp_elem *next;
+ volatile struct listmp_elem *prev;
+};
+
+/*!
+ * @brief Structure defining config parameters for the ListMP instances.
+ */
+struct listmp_params {
+ bool cache_flag;
+ /*!< Set to 1 by the open() call. No one else should touch this! */
+ struct mutex *gate;
+ /*!< Lock used for critical region management of the list */
+ void *shared_addr;
+ /*!< shared memory address */
+ u32 shared_addr_size;
+ /*!< shared memory size */
+ char *name;
+ /*!< Name of the object */
+ int resource_id;
+ /*!<
+ * resourceId Specifies the resource id number.
+ * Parameter is used only when type is set to Fast List
+ */
+ enum listmp_type list_type ;
+ /*!< Type of list */
+};
+
+
+/* =============================================================================
+ * Forward declarations
+ * =============================================================================
+ */
+/*!
+ * @brief Structure defining config parameters for the ListMPSharedMemory.
+ */
+struct listmp_object {
+ bool (*empty)(void *listmp_handle);
+ /* Function to check if list is empty */
+ void *(*get_head)(void *listmp_handle);
+ /* Function to get head element from list */
+ void *(*get_tail)(void *listmp_handle);
+ /* Function to get tail element from list */
+ int (*put_head)(void *listmp_handle, struct listmp_elem *elem);
+ /* Function to put head element into list */
+ int (*put_tail)(void *listmp_handle, struct listmp_elem *elem);
+ /* Function to put tail element into list */
+ int (*insert)(void *listmp_handle, struct listmp_elem *elem,
+ struct listmp_elem *curElem);
+ /* Function to insert element into list */
+ int (*remove)(void *listmp_handle, struct listmp_elem *elem);
+ /* Function to remove element from list */
+ void *(*next)(void *listmp_handle, struct listmp_elem *elem);
+ /* Function to traverse to next element in list */
+ void *(*prev)(void *listmp_handle, struct listmp_elem *elem);
+ /* Function to traverse to prev element in list */
+ void *obj;
+ /*!< Handle to ListMP */
+ enum listmp_type list_type;
+ /* Type of list */
+};
+
+/*
+ * Function initializes listmp parameters
+ */
+void listmp_params_init(void *listmp_handle,
+ struct listmp_params *params);
+
+/*
+ * Function to get shared memory requirement for the module
+ */
+int listmp_shared_memreq(struct listmp_params *params);
+
+/* =============================================================================
+ * Functions to create instance of a list
+ * =============================================================================
+ */
+/* Function to create an instance of ListMP */
+void *listmp_create(struct listmp_params *params);
+
+/* Function to delete an instance of ListMP */
+int listmp_delete(void **listmp_handle_ptr);
+
+/* =============================================================================
+ * Functions to open/close handle to list instance
+ * =============================================================================
+ */
+/* Function to open a previously created instance */
+int listmp_open(void **listmp_handle_ptr, struct listmp_params *params);
+
+/* Function to close a previously opened instance */
+int listmp_close(void *listmp_handle);
+
+/* =============================================================================
+ * Function pointer types for list operations
+ * =============================================================================
+ */
+/* Function to check if list is empty */
+bool listmp_empty(void *listmp_handle);
+
+/* Function to get head element from list */
+void *listmp_get_head(void *listmp_handle);
+
+/* Function to get tail element from list */
+void *listmp_get_tail(void *listmp_handle);
+
+/* Function to put head element into list */
+int listmp_put_head(void *listmp_handle, struct listmp_elem *elem);
+
+/* Function to put tail element into list */
+int listmp_put_tail(void *listmp_handle, struct listmp_elem *elem);
+
+/* Function to insert element into list */
+int listmp_insert(void *listmp_handle, struct listmp_elem *elem,
+ struct listmp_elem *curElem);
+
+/* Function to traverse to remove element from list */
+int listmp_remove(void *listmp_handle, struct listmp_elem *elem);
+
+/* Function to traverse to next element in list */
+void *listmp_next(void *listmp_handle, struct listmp_elem *elem);
+
+/* Function to traverse to prev element in list */
+void *listmp_prev(void *listmp_handle, struct listmp_elem *elem);
+
+#endif /* _LISTMP_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/listmp_sharedmemory.h b/arch/arm/plat-omap/include/syslink/listmp_sharedmemory.h
new file mode 100644
index 000000000000..c6fd1629728e
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/listmp_sharedmemory.h
@@ -0,0 +1,289 @@
+/*
+ * listmp_sharedmemory.c
+ *
+ * The listmp_sharedmemory is a double linked-list based module designed to be
+ * used in a multi-processor environment. It is designed to provide a means
+ * of communication between different processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _LISTMP_SHAREDMEMORY_H_
+#define _LISTMP_SHAREDMEMORY_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+
+/* Other headers */
+#include <listmp.h>
+
+/* =============================================================================
+ * All success and failure codes for the module
+ * =============================================================================
+ */
+/*!
+ * @def LISTMPSHAREDMEMORY_MODULEID
+ * @brief Unique module ID.
+ */
+#define LISTMPSHAREDMEMORY_MODULEID (0xDD3C)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_ERRORCODEBASE
+ * @brief Error code base for ListMPSharedMemory.
+ */
+#define LISTMPSHAREDMEMORY_ERRORCODEBASE \
+ (LISTMPSHAREDMEMORY_MODULEID << 12)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_MAKE_FAILURE
+ * @brief Macro to make error code.
+ */
+#define LISTMPSHAREDMEMORY_MAKE_FAILURE(x) \
+ ((int) (0x80000000 \
+ + (LISTMPSHAREDMEMORY_ERRORCODEBASE \
+ + (x))))
+
+/*!
+ * @def LISTMPSHAREDMEMORY_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define LISTMPSHAREDMEMORY_MAKE_SUCCESS(x) \
+ (LISTMPSHAREDMEMORY_ERRORCODEBASE + (x))
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define LISTMPSHAREDMEMORY_E_INVALIDARG \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(1)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_MEMORY
+ * @brief Memory allocation failed.
+ */
+#define LISTMPSHAREDMEMORY_E_MEMORY \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(2)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_FAIL
+ * @brief Generic failure.
+ */
+#define LISTMPSHAREDMEMORY_E_FAIL \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(3)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_INVALIDSTATE
+ * @brief Module is not initialized.
+ */
+#define LISTMPSHAREDMEMORY_E_INVALIDSTATE \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(4)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_OSFAILURE
+ * @brief Failure in OS call.
+ */
+#define LISTMPSHAREDMEMORY_E_OSFAILURE \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(5)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_NOTONWER
+ * @brief Instance is not created on this processor.
+ */
+#define LISTMPSHAREDMEMORY_E_NOTOWNER \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(6)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_REMOTEACTIVE
+ * @brief Remote opener of the instance has not closed the instance.
+ */
+#define LISTMPSHAREDMEMORY_E_REMOTEACTIVE \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(7)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_INUSE
+ * @brief Indicates that the instance is in use..
+ */
+#define LISTMPSHAREDMEMORY_E_INUSE \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(8)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_NOTFOUND
+ * @brief name not found in the nameserver.
+ */
+#define LISTMPSHAREDMEMORY_E_NOTFOUND \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(9)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_NOTCREATED
+ * @brief Instance is not created yet
+ */
+#define LISTMPSHAREDMEMORY_E_NOTCREATED \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(10)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_VERSION
+ * @brief Version mismatch error.
+ */
+#define LISTMPSHAREDMEMORY_E_VERSION \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(11)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_E_BUSY
+ * @brief the name is already registered or not.
+ */
+#define LISTMPSHAREDMEMORY_E_BUSY \
+ LISTMPSHAREDMEMORY_MAKE_FAILURE(12)
+
+
+/*!
+ * @def LISTMPSHAREDMEMORY_SUCCESS
+ * @brief Operation successful.
+ */
+#define LISTMPSHAREDMEMORY_SUCCESS \
+ LISTMPSHAREDMEMORY_MAKE_SUCCESS(0)
+
+/*!
+ * @def LISTMPSHAREDMEMORY_S_ALREADYSETUP
+ * @brief The LISTMPSHAREDMEMORY module has already been setup in this
+ * process.
+ */
+#define LISTMPSHAREDMEMORY_S_ALREADYSETUP \
+ LISTMPSHAREDMEMORY_MAKE_SUCCESS(1)
+
+/*!
+ * @def listmp_sharedmemory_CREATED
+ * @brief Creation of list succesful.
+*/
+#define LISTMP_SHAREDMEMORY_CREATED (0x12181964)
+
+/*!
+ * @def LISTMP_SHAREDMEMORY_VERSION
+ * @brief Version.
+ */
+#define LISTMP_SHAREDMEMORY_VERSION (1)
+
+/* =============================================================================
+ * Structure definitions
+ * =============================================================================
+ */
+/*!
+ * @brief Structure defining config parameters for the ListMP instances.
+ */
+#define listmp_sharedmemory_params struct listmp_params
+
+
+/*! @brief Forward declaration of structure defining object for the
+ * ListMPSharedMemory.
+ */
+/*!
+ * @brief Object for the ListMPSharedMemory Handle
+ */
+#define listmp_sharedmemory_object struct listmp_object
+
+/*!
+ * @brief Handle for the ListMPSharedMemory
+ */
+#define listmp_sharedmemory_handle void *
+
+/* =============================================================================
+ * Functions to create the module
+ * =============================================================================
+ */
+/* Function to get configuration parameters to setup
+ * the ListMPSharedMemory module.
+ */
+int listmp_sharedmemory_get_config(struct listmp_config *cfgParams);
+
+/* Function to setup the ListMPSharedMemory module. */
+int listmp_sharedmemory_setup(struct listmp_config *config) ;
+
+/* Function to destroy the ListMPSharedMemory module. */
+int listmp_sharedmemory_destroy(void);
+
+/* =============================================================================
+ * Functions to create instance of a list
+ * =============================================================================
+ */
+/* Function to create an instance of ListMP */
+listmp_sharedmemory_handle listmp_sharedmemory_create
+ (listmp_sharedmemory_params *params);
+
+/* Function to delete an instance of ListMP */
+int listmp_sharedmemory_delete(listmp_sharedmemory_handle *listMPHandlePtr);
+
+/* =============================================================================
+ * Functions to open/close handle to list instance
+ * =============================================================================
+ */
+/*
+ * Initialize this config-params structure with supplier-specified
+ * defaults before instance creation.
+ */
+void listmp_sharedmemory_params_init(listmp_sharedmemory_handle handle,
+ listmp_sharedmemory_params *params);
+
+/* Function to open a previously created instance */
+int listmp_sharedmemory_open(listmp_sharedmemory_handle *listMpHandlePtr,
+ listmp_sharedmemory_params *params);
+
+/* Function to close a previously opened instance */
+int listmp_sharedmemory_close(listmp_sharedmemory_handle listMPHandle);
+
+/* =============================================================================
+ * Functions for list operations
+ * =============================================================================
+ */
+/* Function to check if list is empty */
+bool listmp_sharedmemory_empty(listmp_sharedmemory_handle listMPHandle);
+
+/* Function to get head element from list */
+void *listmp_sharedmemory_get_head(listmp_sharedmemory_handle listMPHandle);
+
+/* Function to get tail element from list */
+void *listmp_sharedmemory_get_tail(listmp_sharedmemory_handle listMPHandle);
+
+/* Function to put head element into list */
+int listmp_sharedmemory_put_head(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem);
+
+/* Function to put tail element into list */
+int listmp_sharedmemory_put_tail(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem);
+
+/* Function to insert element into list */
+int listmp_sharedmemory_insert(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem,
+ struct listmp_elem *curElem);
+
+/* Function to traverse to remove element from list */
+int listmp_sharedmemory_remove(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem);
+
+/* Function to traverse to next element in list */
+void *listmp_sharedmemory_next(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem);
+
+/* Function to traverse to prev element in list */
+void *listmp_sharedmemory_prev(listmp_sharedmemory_handle listMPHandle,
+ struct listmp_elem *elem);
+
+/* =============================================================================
+ * Functions for shared memory requirements
+ * =============================================================================
+ */
+/* Amount of shared memory required for creation of each instance. */
+int listmp_sharedmemory_shared_memreq(
+ listmp_sharedmemory_params *params);
+
+#endif /* _LISTMP_SHAREDMEMORY_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/listmp_sharedmemory_ioctl.h b/arch/arm/plat-omap/include/syslink/listmp_sharedmemory_ioctl.h
new file mode 100644
index 000000000000..42fc4d6edd24
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/listmp_sharedmemory_ioctl.h
@@ -0,0 +1,258 @@
+/*
+ * listmp_sharedmemory_ioctl.h
+ *
+ * Definitions of listmp_sharedmemory driver types and structures.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _LISTMP_SHAREDMEMORY_IOCTL_H_
+#define _LISTMP_SHAREDMEMORY_IOCTL_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Syslink headers */
+#include <ipc_ioctl.h>
+#include <listmp_sharedmemory.h>
+#include <sharedregion.h>
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/* Base command ID for listmp_sharedmemory */
+#define LISTMP_SHAREDMEMORY_IOC_MAGIC IPC_IOC_MAGIC
+enum listmp_sharedmemory_drv_cmd {
+ LISTMP_SHAREDMEMORY_GETCONFIG = LISTMP_SHAREDMEMORY_BASE_CMD,
+ LISTMP_SHAREDMEMORY_SETUP,
+ LISTMP_SHAREDMEMORY_DESTROY,
+ LISTMP_SHAREDMEMORY_PARAMS_INIT,
+ LISTMP_SHAREDMEMORY_CREATE,
+ LISTMP_SHAREDMEMORY_DELETE,
+ LISTMP_SHAREDMEMORY_OPEN,
+ LISTMP_SHAREDMEMORY_CLOSE,
+ LISTMP_SHAREDMEMORY_ISEMPTY,
+ LISTMP_SHAREDMEMORY_GETHEAD,
+ LISTMP_SHAREDMEMORY_GETTAIL,
+ LISTMP_SHAREDMEMORY_PUTHEAD,
+ LISTMP_SHAREDMEMORY_PUTTAIL,
+ LISTMP_SHAREDMEMORY_INSERT,
+ LISTMP_SHAREDMEMORY_REMOVE,
+ LISTMP_SHAREDMEMORY_NEXT,
+ LISTMP_SHAREDMEMORY_PREV,
+ LISTMP_SHAREDMEMORY_SHAREDMEMREQ
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for listmp_sharedmemory
+ * ----------------------------------------------------------------------------
+ */
+/* Command for listmp_sharedmemory_get_config */
+#define CMD_LISTMP_SHAREDMEMORY_GETCONFIG \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_GETCONFIG, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_setup */
+#define CMD_LISTMP_SHAREDMEMORY_SETUP \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_SETUP, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_destroy */
+#define CMD_LISTMP_SHAREDMEMORY_DESTROY \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_DESTROY, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_params_init */
+#define CMD_LISTMP_SHAREDMEMORY_PARAMS_INIT \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_PARAMS_INIT, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_create */
+#define CMD_LISTMP_SHAREDMEMORY_CREATE \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_CREATE, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_delete */
+#define CMD_LISTMP_SHAREDMEMORY_DELETE \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_DELETE, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_open */
+#define CMD_LISTMP_SHAREDMEMORY_OPEN \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_OPEN, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_close */
+#define CMD_LISTMP_SHAREDMEMORY_CLOSE \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_CLOSE, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_is_empty */
+#define CMD_LISTMP_SHAREDMEMORY_ISEMPTY \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_ISEMPTY, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_get_head */
+#define CMD_LISTMP_SHAREDMEMORY_GETHEAD \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_GETHEAD, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_get_tail */
+#define CMD_LISTMP_SHAREDMEMORY_GETTAIL \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_GETTAIL, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_put_head */
+#define CMD_LISTMP_SHAREDMEMORY_PUTHEAD \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_PUTHEAD, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_put_tail */
+#define CMD_LISTMP_SHAREDMEMORY_PUTTAIL \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_PUTTAIL, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_insert */
+#define CMD_LISTMP_SHAREDMEMORY_INSERT \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_INSERT, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_remove */
+#define CMD_LISTMP_SHAREDMEMORY_REMOVE \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_REMOVE, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_next */
+#define CMD_LISTMP_SHAREDMEMORY_NEXT \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_NEXT, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_prev */
+#define CMD_LISTMP_SHAREDMEMORY_PREV \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_PREV, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command for listmp_sharedmemory_shared_memreq */
+#define CMD_LISTMP_SHAREDMEMORY_SHAREDMEMREQ \
+ _IOWR(LISTMP_SHAREDMEMORY_IOC_MAGIC, LISTMP_SHAREDMEMORY_SHAREDMEMREQ, \
+ struct listmp_sharedmemory_cmd_args)
+
+/* Command arguments for listmp_sharedmemory */
+struct listmp_sharedmemory_cmd_args {
+ union {
+ struct {
+ void *listmp_handle;
+ struct listmp_params *params;
+ } params_init;
+
+ struct {
+ struct listmp_config *config;
+ } get_config;
+
+ struct {
+ struct listmp_config *config;
+ } setup;
+
+ struct {
+ void *listmp_handle;
+ struct listmp_params *params;
+ u32 name_len;
+ u32 shared_addr_srptr;
+ void *knl_gate;
+ } create;
+
+ struct {
+ void *listmp_handle;
+ } delete_listmp;
+
+ struct {
+ void *listmp_handle;
+ struct listmp_params *params;
+ u32 name_len;
+ u32 shared_addr_srptr;
+ void *knl_gate;
+ } open;
+
+ struct {
+ void *listmp_handle;
+ } close;
+
+ struct {
+ void *listmp_handle;
+ bool is_empty;
+ } is_empty;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ } get_head;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ } get_tail;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ } put_head;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ } put_tail;
+
+ struct {
+ void *listmp_handle;
+ u32 *new_elem_srptr;
+ u32 *cur_elem_srptr;
+ } insert;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ } remove;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ u32 *next_elem_srptr ;
+ } next;
+
+ struct {
+ void *listmp_handle;
+ u32 *elem_srptr ;
+ u32 *prev_elem_srptr ;
+ } prev;
+
+ struct {
+ void *listmp_handle;
+ struct listmp_params *params;
+ u32 bytes;
+ } shared_memreq;
+ } args;
+
+ int api_status;
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL functions for listmp_sharedmemory module
+ * ----------------------------------------------------------------------------
+ */
+/*
+ * ioctl interface function for listmp_sharedmemory
+ */
+int listmp_sharedmemory_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _LISTMP_SHAREDMEMORY_IOCTL_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/messageq.h b/arch/arm/plat-omap/include/syslink/messageq.h
new file mode 100644
index 000000000000..90ba6f070048
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/messageq.h
@@ -0,0 +1,464 @@
+/*
+ * messageq.h
+ *
+ * The MessageQ module supports the structured sending and receiving of
+ * variable length messages. This module can be used for homogeneous or
+ * heterogeneous multi-processor messaging.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _MESSAGEQ_H_
+#define _MESSAGEQ_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+#include <linux/list.h>
+
+/* Syslink headers */
+#include <listmp.h>
+#include <messageq_transportshm.h>
+
+
+/*!
+ * @def MESSAGEQ_MODULEID
+ * @brief Unique module ID.
+ */
+#define MESSAGEQ_MODULEID (0xded2)
+
+/* =============================================================================
+ * All success and failure codes for the module
+ * =============================================================================
+ */
+
+/*!
+ * @def MESSAGEQ_STATUSCODEBASE
+ * @brief Error code base for MessageQ.
+ */
+#define MESSAGEQ_STATUSCODEBASE (MESSAGEQ_MODULEID << 12)
+
+/*!
+ * @def MESSAGEQ_MAKE_FAILURE
+ * @brief Macro to make error code.
+ */
+#define MESSAGEQ_MAKE_FAILURE(x) ((int) (0x80000000 + \
+ (MESSAGEQ_STATUSCODEBASE + \
+ (x))))
+
+/*!
+ * @def MESSAGEQ_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define MESSAGEQ_MAKE_SUCCESS(x) (MESSAGEQ_STATUSCODEBASE + (x))
+
+/*!
+ * @def MESSAGEQ_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define MESSAGEQ_E_INVALIDARG MESSAGEQ_MAKE_FAILURE(1)
+
+/*!
+ * @def MESSAGEQ_E_MEMORY
+ * @brief Memory allocation failed.
+ */
+#define MESSAGEQ_E_MEMORY MESSAGEQ_MAKE_FAILURE(2)
+
+/*!
+ * @def MESSAGEQ_E_BUSY
+ * @brief the name is already registered or not.
+ */
+#define MESSAGEQ_E_BUSY MESSAGEQ_MAKE_FAILURE(3)
+
+/*!
+ * @def MESSAGEQ_E_FAIL
+ * @brief Generic failure.
+ */
+#define MESSAGEQ_E_FAIL MESSAGEQ_MAKE_FAILURE(4)
+
+/*!
+ * @def MESSAGEQ_E_NOTFOUND
+ * @brief name not found in the nameserver.
+ */
+#define MESSAGEQ_E_NOTFOUND MESSAGEQ_MAKE_FAILURE(5)
+
+/*!
+ * @def MESSAGEQ_E_INVALIDSTATE
+ * @brief Module is not initialized.
+ */
+#define MESSAGEQ_E_INVALIDSTATE MESSAGEQ_MAKE_FAILURE(6)
+
+/*!
+ * @def MESSAGEQ_E_NOTONWER
+ * @brief Instance is not created on this processor.
+ */
+#define MESSAGEQ_E_NOTONWER MESSAGEQ_MAKE_FAILURE(7)
+
+/*!
+ * @def MESSAGEQ_E_REMOTEACTIVE
+ * @brief Remote opener of the instance has not closed the instance.
+ */
+#define MESSAGEQ_E_REMOTEACTIVE MESSAGEQ_MAKE_FAILURE(8)
+
+/*!
+ * @def MESSAGEQ_E_INUSE
+ * @brief Indicates that the instance is in use..
+ */
+#define MESSAGEQ_E_INUSE MESSAGEQ_MAKE_FAILURE(9)
+
+/*!
+ * @def MESSAGEQ_E_INVALIDCONTEXT
+ * @brief Indicates that the api is called with wrong handle
+ */
+#define MESSAGEQ_E_INVALIDCONTEXT MESSAGEQ_MAKE_FAILURE(10)
+
+/*!
+ * @def MESSAGEQ_E_INVALIDMSG
+ * @brief Indicates that an invalid msg has been specified
+ *
+ */
+#define MESSAGEQ_E_INVALIDMSG MESSAGEQ_MAKE_FAILURE(11)
+
+/*!
+ * @def MESSAGEQ_E_INVALIDHEAPID
+ * @brief Indicates that an invalid heap has been specified
+ */
+#define MESSAGEQ_E_INVALIDHEAPID MESSAGEQ_MAKE_FAILURE(12)
+
+/*!
+ * @def MESSAGEQ_E_INVALIDPROCID
+ * @brief Indicates that an invalid proc id has been specified
+ */
+#define MESSAGEQ_E_INVALIDPROCID MESSAGEQ_MAKE_FAILURE(13)
+
+/*!
+ * @def MESSAGEQ_E_MAXREACHED
+ * @brief Indicates that all message queues are taken
+ */
+#define MESSAGEQ_E_MAXREACHED MESSAGEQ_MAKE_FAILURE(14)
+
+/*!
+ * @def MESSAGEQ_E_UNREGISTERHEAPID
+ * @brief Indicates that heap id has not been registered
+ */
+#define MESSAGEQ_E_UNREGISTERHEAPID MESSAGEQ_MAKE_FAILURE(15)
+
+/*!
+ * @def MESSAGEQ_E_CANNOTFREESTATICMSG
+ * @brief Indicates that static msg cannot be freed
+ */
+#define MESSAGEQ_E_CANNOTFREESTATICMSG MESSAGEQ_MAKE_FAILURE(16)
+
+/*!
+ * @def MESSAGEQ_E_HEAPIDINVALID
+ * @brief Indicates that the heap id is invalid
+ */
+#define MESSAGEQ_E_HEAPIDINVALID MESSAGEQ_MAKE_FAILURE(17)
+
+/*!
+ * @def MESSAGEQ_E_PROCIDINVALID
+ * @brief Indicates that the proc id is invalid
+ */
+#define MESSAGEQ_E_PROCIDINVALID MESSAGEQ_MAKE_FAILURE(18)
+
+/*!
+ * @def MESSAGEQ_E_OSFAILURE
+ * @brief Failure in OS call.
+ */
+#define MESSAGEQ_E_OSFAILURE MESSAGEQ_MAKE_FAILURE(19)
+
+/*!
+ * @def MESSAGEQ_E_ALREADYEXISTS
+ * @brief Specified entity already exists
+ */
+#define MESSAGEQ_E_ALREADYEXISTS MESSAGEQ_MAKE_FAILURE(20)
+
+/*!
+ * @def MESSAGEQ_E_TIMEOUT
+ * @brief Timeout while attempting to get a message
+ */
+#define MESSAGEQ_E_TIMEOUT MESSAGEQ_MAKE_FAILURE(21)
+
+/*!
+ * @def MESSAGEQ_SUCCESS
+ * @brief Operation successful.
+ */
+#define MESSAGEQ_SUCCESS MESSAGEQ_MAKE_SUCCESS(0)
+
+/*!
+ * @def MESSAGEQ_S_ALREADYSETUP
+ * @brief The MESSAGEQ module has already been setup in this process.
+ */
+#define MESSAGEQ_S_ALREADYSETUP MESSAGEQ_MAKE_SUCCESS(1)
+
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/*!
+ * @brief Mask to extract version setting
+ */
+#define MESSAGEQ_HEADERVERSION 0x2000u
+
+/*!
+ * @brief Mask to extract priority setting
+ */
+#define MESSAGEQ_PRIORITYMASK 0x3u
+
+/*!
+ * @brief Mask to extract priority setting
+ */
+#define MESSAGEQ_TRANSPORTPRIORITYMASK 0x01u
+
+/*!
+ * Mask to extract version setting
+ */
+#define MESSAGEQ_VERSIONMASK 0xE000;
+
+/*!
+ * Used as the timeout value to specify wait forever
+ */
+#define MESSAGEQ_FOREVER (~((u32) 0))
+
+/*!
+ * Invalid message id
+ */
+#define MESSAGEQ_INVALIDMSGID 0xFFFF
+
+/*!
+ * Invalid message queue
+ */
+#define MESSAGEQ_INVALIDMESSAGEQ 0xFFFF
+
+/*!
+ * Indicates that if maximum number of message queues are already created,
+ * should allow growth to create additional Message Queue.
+ */
+#define MESSAGEQ_ALLOWGROWTH (~((u32) 0))
+
+/*!
+ * Number of types of priority queues for each transport
+ */
+#define MESSAGEQ_NUM_PRIORITY_QUEUES 2
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/*!
+ * Message priority
+ */
+enum messageq_priority {
+ MESSAGEQ_NORMALPRI = 0,
+ /*!< Normal priority message */
+ MESSAGEQ_HIGHPRI = 1,
+ /*!< High priority message */
+ MESSAGEQ_RESERVEDPRI = 2,
+ /*!< Reserved value for message priority */
+ MESSAGEQ_URGENTPRI = 3
+ /*!< Urgent priority message */
+};
+
+/*! Structure which defines the first field in every message */
+struct msgheader {
+ u32 reserved0;
+ /*!< Reserved field */
+ u32 reserved1;
+ /*!< Reserved field */
+ u32 msg_size;
+ /*!< Size of the message (including header) */
+ u16 flags;
+ /*!< Flags */
+ u16 msg_id;
+ /*!< Maximum length for Message queue names */
+ u16 dst_id;
+ /*!< Maximum length for Message queue names */
+ u16 dst_proc;
+ /*!< Maximum length for Message queue names */
+ u16 reply_id;
+ /*!< Maximum length for Message queue names */
+ u16 reply_proc;
+ /*!< Maximum length for Message queue names */
+ u16 src_proc;
+ /*!< Maximum length for Message queue names */
+ u16 heap_id;
+ /*!< Maximum length for Message queue names */
+ u32 reserved;
+ /*!< Reserved field */
+};
+/*! Structure which defines the first field in every message */
+#define messageq_msg struct msgheader *
+/*typedef struct msgheader *messageq_msg;*/
+
+
+/*!
+ * @brief Structure defining config parameters for the MessageQ Buf module.
+ */
+struct messageq_config {
+ u16 num_heaps;
+ /*!
+ * Number of heapIds in the system
+ *
+ * This allows MessageQ to pre-allocate the heaps table.
+ * The heaps table is used when registering heaps.
+ *
+ * The default is 1 since generally all systems need at least
+ * one heap.
+ *
+ * There is no default heap, so unless the system is only using
+ * staticMsgInit, the application must register a heap.
+ */
+
+ u32 max_runtime_entries;
+ /*!
+ * Maximum number of MessageQs that can be dynamically created
+ */
+
+ struct mutex *name_table_gate;
+ /*!
+ * Gate used to make the name table thread safe. If NULL is passed, gate
+ * will be created internally.
+ */
+
+ u32 max_name_len;
+ /*!
+ * Maximum length for Message queue names
+ */
+};
+
+struct messageq_params {
+ u32 reserved;
+ /*!< No parameters required currently. Reserved field. */
+ u32 max_name_len;
+ /*!< Maximum length for Message queue names */
+};
+
+/* =============================================================================
+ * APIs
+ * =============================================================================
+ */
+/* Functions to get the configuration for messageq setup */
+void messageq_get_config(struct messageq_config *cfg);
+
+/* Function to setup the MessageQ module. */
+int messageq_setup(const struct messageq_config *cfg);
+
+/* Function to destroy the MessageQ module. */
+int messageq_destroy(void);
+
+/* Initialize this config-params structure with supplier-specified
+ * defaults before instance creation.
+ */
+void messageq_params_init(void *messageq_handle,
+ struct messageq_params *params);
+
+/* Create a message queue */
+void *messageq_create(char *name, const struct messageq_params *params);
+
+/* Deletes a instance of MessageQ module. */
+int messageq_delete(void **messageq_handleptr);
+
+/* Allocates a message from the heap */
+messageq_msg messageq_alloc(u16 heapId, u32 size);
+
+/* Frees a message back to the heap */
+int messageq_free(messageq_msg msg);
+
+/* Open a message queue */
+int messageq_open(char *name, u32 *queue_id);
+
+/* Close an opened message queue handle */
+void messageq_close(u32 *queue_id);
+
+/* Initializes a message not obtained from MessageQ_alloc */
+void messageq_static_msg_init(messageq_msg msg, u32 size);
+
+/* Place a message onto a message queue */
+int messageq_put(u32 queueId, messageq_msg msg);
+
+/* Gets a message for a message queue and blocks if the queue is empty */
+int messageq_get(void *messageq_handle, messageq_msg *msg,
+ u32 timeout);
+
+/* Register a heap with MessageQ */
+int messageq_register_heap(void *heap_handle, u16 heap_id);
+
+/* Unregister a heap with MessageQ */
+int messageq_unregister_heap(u16 heapId);
+
+/* Returns the number of messages in a message queue */
+int messageq_count(void *messageq_handle);
+
+/* Set the destination queue of the message. */
+void messageq_set_reply_queue(void *messageq_handle, messageq_msg msg);
+
+/* Get the queue Id of the message. */
+u32 messageq_get_queue_id(void *messageq_handle);
+
+/* Get the proc Id of the message. */
+u16 messageq_get_proc_id(void *messageq_handle);
+
+/*
+ * Functions to set Message properties
+ */
+/*!
+ * @brief Returns the MessageQ_Queue handle of the destination
+ * message queue for the specified message.
+ */
+u32 messageq_get_dst_queue(messageq_msg msg);
+
+/*!
+ * @brief Returns the message ID of the specified message.
+ */
+u16 messageq_get_msg_id(messageq_msg msg);
+
+/*!
+ * @brief Returns the size of the specified message.
+ */
+u32 messageq_get_msg_size(messageq_msg msg);
+
+/*!
+ * @brief Gets the message priority of a message
+ */
+u32 messageq_get_msg_pri(messageq_msg msg);
+
+/*!
+ * @brief Returns the MessageQ_Queue handle of the destination
+ * message queue for the specified message.
+ */
+u32 messageq_get_reply_queue(messageq_msg msg);
+
+/*!
+ * @brief Sets the message ID in the specified message.
+ */
+void messageq_set_msg_id(messageq_msg msg, u16 msg_id);
+/*!
+ * @brief Sets the message priority in the specified message.
+ */
+void messageq_set_msg_pri(messageq_msg msg, u32 priority);
+
+/* =============================================================================
+ * APIs called internally by MessageQ transports
+ * =============================================================================
+ */
+/* Register a transport with MessageQ */
+int messageq_register_transport(void *messageq_transportshm_handle,
+ u16 proc_id, u32 priority);
+
+/* Unregister a transport with MessageQ */
+int messageq_unregister_transport(u16 proc_id, u32 priority);
+
+
+#endif /* _MESSAGEQ_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/messageq_ioctl.h b/arch/arm/plat-omap/include/syslink/messageq_ioctl.h
new file mode 100644
index 000000000000..2f8424c21d7e
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/messageq_ioctl.h
@@ -0,0 +1,237 @@
+/*
+ * messageq_ioctl.h
+ *
+ * Definitions of messageq driver types and structures.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MESSAGEQ_IOCTL_H_
+#define _MESSAGEQ_IOCTL_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Syslink headers */
+#include <ipc_ioctl.h>
+#include <messageq.h>
+#include <heap.h>
+#include <sharedregion.h>
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+#define MESSAGEQ_IOC_MAGIC IPC_IOC_MAGIC
+enum messageq_drv_cmd {
+ MESSAGEQ_GETCONFIG = MESSAGEQ_BASE_CMD,
+ MESSAGEQ_SETUP,
+ MESSAGEQ_DESTROY,
+ MESSAGEQ_PARAMS_INIT,
+ MESSAGEQ_CREATE,
+ MESSAGEQ_DELETE,
+ MESSAGEQ_OPEN,
+ MESSAGEQ_CLOSE,
+ MESSAGEQ_COUNT,
+ MESSAGEQ_ALLOC,
+ MESSAGEQ_FREE,
+ MESSAGEQ_PUT,
+ MESSAGEQ_REGISTERHEAP,
+ MESSAGEQ_UNREGISTERHEAP,
+ MESSAGEQ_REGISTERTRANSPORT,
+ MESSAGEQ_UNREGISTERTRANSPORT,
+ MESSAGEQ_GET
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for messageq
+ * ----------------------------------------------------------------------------
+ */
+/* Base command ID for messageq */
+#define MESSAGEQ_BASE_CMD 0x0
+
+/* Command for messageq_get_config */
+#define CMD_MESSAGEQ_GETCONFIG \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_GETCONFIG, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_setup */
+#define CMD_MESSAGEQ_SETUP \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_SETUP, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_destroy */
+#define CMD_MESSAGEQ_DESTROY \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_DESTROY, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_params_init */
+#define CMD_MESSAGEQ_PARAMS_INIT \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_PARAMS_INIT, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_create */
+#define CMD_MESSAGEQ_CREATE \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_CREATE, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_delete */
+#define CMD_MESSAGEQ_DELETE \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_DELETE, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_open */
+#define CMD_MESSAGEQ_OPEN \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_OPEN, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_close */
+#define CMD_MESSAGEQ_CLOSE \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_CLOSE, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_count */
+#define CMD_MESSAGEQ_COUNT \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_COUNT, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_alloc */
+#define CMD_MESSAGEQ_ALLOC \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_ALLOC, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_free */
+#define CMD_MESSAGEQ_FREE \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_FREE, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_put */
+#define CMD_MESSAGEQ_PUT \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_PUT, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_register_heap */
+#define CMD_MESSAGEQ_REGISTERHEAP \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_REGISTERHEAP, \
+ struct messageq_cmd_args)
+
+/* Command for messageq_unregister_heap */
+#define CMD_MESSAGEQ_UNREGISTERHEAP \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_UNREGISTERHEAP, \
+ struct messageq_cmd_args)
+
+
+/* Command for messageq_register_transport */
+#define CMD_MESSAGEQ_REGISTERTRANSPORT \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_REGISTERTRANSPORT, \
+ struct messageq_cmd_args)
+
+
+/* Command for messageq_unregister_transport */
+#define CMD_MESSAGEQ_UNREGISTERTRANSPORT \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_UNREGISTERTRANSPORT, \
+ struct messageq_cmd_args)
+
+
+/* Command for messageq_get */
+#define CMD_MESSAGEQ_GET \
+ _IOWR(MESSAGEQ_IOC_MAGIC, MESSAGEQ_GET, \
+ struct messageq_cmd_args)
+
+/* Command arguments for messageq */
+struct messageq_cmd_args {
+ union {
+ struct {
+ void *messageq_handle;
+ struct messageq_params *params;
+ } params_init;
+
+ struct {
+ struct messageq_config *config;
+ } get_config;
+
+ struct {
+ struct messageq_config *config;
+ } setup;
+
+ struct {
+ void *messageq_handle;
+ char *name;
+ struct messageq_params *params;
+ u32 name_len;
+ u32 queue_id;
+ } create;
+
+ struct {
+ void *messageq_handle;
+ } delete_messageq;
+
+ struct {
+ char *name;
+ u32 queue_id;
+ u32 name_len;
+ } open;
+
+ struct {
+ u32 queue_id;
+ } close;
+
+ struct {
+ void *messageq_handle;
+ u32 timeout;
+ u32 *msg_srptr;
+ } get;
+
+ struct {
+ void *messageq_handle;
+ int count;
+ } count;
+
+ struct {
+ u16 heap_id;
+ u32 size;
+ u32 *msg_srptr;
+ } alloc;
+
+ struct {
+ u32 *msg_srptr;
+ } free;
+
+ struct {
+ u32 queue_id;
+ u32 *msg_srptr;
+ } put;
+
+ struct {
+ void *heap_handle;
+ u16 heap_id;
+ } register_heap;
+
+ struct {
+ u16 heap_id;
+ } unregister_heap;
+ } args;
+
+ int api_status;
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL functions for messageq module
+ * ----------------------------------------------------------------------------
+ */
+/*
+ * ioctl interface function for messageq
+ */
+int messageq_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _MESSAGEQ_IOCTL_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/messageq_transportshm.h b/arch/arm/plat-omap/include/syslink/messageq_transportshm.h
new file mode 100644
index 000000000000..e2b55f6b0b4d
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/messageq_transportshm.h
@@ -0,0 +1,283 @@
+/*
+ * messageq_transportshm.h
+ *
+ * MessageQ shared memory based physical transport for
+ * communication with the remote processor.
+ *
+ * This file contains the declarations of types and APIs as part
+ * of interface of the MessageQ shared memory transport.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MESSAGEQ_TRANSPORTSHM_H_
+#define _MESSAGEQ_TRANSPORTSHM_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+#include <linux/list.h>
+
+/* =============================================================================
+ * All success and failure codes for the module
+ * =============================================================================
+ */
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_MODULEID
+ * @brief Unique module ID.
+ */
+#define MESSAGEQ_TRANSPORTSHM_MODULEID (0x0a7a)
+
+/* =============================================================================
+ * All success and failure codes for the module
+ * =============================================================================
+ */
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_STATUSCODEBASE
+ * @brief Error code base for MessageQ.
+ */
+#define MESSAGEQ_TRANSPORTSHM_STATUSCODEBASE \
+ (MESSAGEQ_TRANSPORTSHM_MODULEID << 12)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE
+ * @brief Macro to make error code.
+ */
+#define MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(x) ((int) (0x80000000 \
+ + (MESSAGEQ_TRANSPORTSHM_STATUSCODEBASE \
+ + (x))))
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define MESSAGEQ_TRANSPORTSHM_MAKE_SUCCESS(x) \
+ (MESSAGEQ_TRANSPORTSHM_STATUSCODEBASE + (x))
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_INVALIDARG \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(1)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_INVALIDSIZE
+ * @brief Invalid shared address size
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_INVALIDSIZE \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(2)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_INVALIDSTATE
+ * @brief Module is not initialized.
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_INVALIDSTATE \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(3)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_BADVERSION
+ * @brief Versions don't match
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_BADVERSION \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(4)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_FAIL
+ * @brief General Failure
+*/
+#define MESSAGEQ_TRANSPORTSHM_E_FAIL \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(5)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_MEMORY
+ * @brief Memory allocation failed
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_MEMORY \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(6)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_OSFAILURE
+ * @brief Failure in OS call.
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_OSFAILURE \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(7)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_E_HANDLE
+ * @brief Invalid handle specified.
+ */
+#define MESSAGEQ_TRANSPORTSHM_E_HANDLE \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(8)
+
+/*!
+ * @def MESSAGEQTRANSPORTSHM_E_NOTSUPPORTED
+ * @brief The specified operation is not supported.
+ */
+#define MESSAGEQTRANSPORTSHM_E_NOTSUPPORTED \
+ MESSAGEQ_TRANSPORTSHM_MAKE_FAILURE(9)
+
+/*!
+ * @def MESSAGEQ_TRANSPORTSHM_SUCCESS
+ * @brief Operation successful.
+ */
+#define MESSAGEQ_TRANSPORTSHM_SUCCESS \
+ MESSAGEQ_TRANSPORTSHM_MAKE_SUCCESS(0)
+
+/*!
+ * @def MESSAGETRANSPORTSHM_S_ALREADYSETUP
+ * @brief The MESSAGETRANSPORTSHM module has
+ * already been setup in this process.
+ */
+#define MESSAGEQ_TRANSPORTSHM_S_ALREADYSETUP \
+ MESSAGEQ_TRANSPORTSHM_MAKE_SUCCESS(1)
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+
+/*!
+ * @brief Structure defining the reason for error function being called
+ */
+enum MessageQTransportShm_Reason {
+ MessageQTransportShm_Reason_FAILEDPUT,
+ /*!< Failed to send the message. */
+ MessageQTransportShm_Reason_INTERNALERR,
+ /*!< An internal error occurred in the transport */
+ MessageQTransportShm_Reason_PHYSICALERR,
+ /*!< An error occurred in the physical link in the transport */
+ MessageQTransportShm_Reason_FAILEDALLOC
+ /*!< Failed to allocate a message. */
+};
+
+/*!
+ * @brief transport error callback function.
+ *
+ * First parameter: Why the error function is being called.
+ *
+ * Second parameter: Handle of transport that had the error. NULL denotes
+ * that it is a system error, not a specific transport.
+ *
+ * Third parameter: Pointer to the message. This is only valid for
+ * #MessageQTransportShm_Reason_FAILEDPUT.
+ *
+ * Fourth parameter: Transport specific information. Refer to individual
+ * transports for more details.
+ */
+
+/*!
+ * @brief Module configuration structure.
+ */
+struct messageq_transportshm_config {
+ void (*err_fxn)(enum MessageQTransportShm_Reason reason,
+ void *handle,
+ void *msg,
+ u32 info);
+ /*!< Asynchronous error function for the transport module */
+};
+
+/*!
+ * @brief Structure defining config parameters for the MessageQ transport
+ * instances.
+ */
+struct messageq_transportshm_params {
+ u32 priority;
+ /*!< Priority of messages supported by this transport */
+ void *gate;
+ /*!< Gate used for critical region management of the shared memory */
+ void *shared_addr;
+ /*!< Address of the shared memory. The creator must supply the shared
+ * memory that this will use for maintain shared state information.
+ */
+ u32 shared_addr_size;
+ /*!< Size of shared region provided. */
+ u32 notify_event_no;
+ /*!< Notify event number to be used by the transport */
+ void *notify_driver;
+ /*!< Notify driver to be used by the transport */
+};
+
+/*!
+ * @brief Structure defining Transport status values
+ */
+enum messageq_transportshm_status {
+ messageq_transportshm_status_INIT,
+ /*!< MessageQ transport Shm instance has not not completed
+ * initialization. */
+ messageq_transportshm_status_UP,
+ /*!< MessageQ transport Shm instance is up and functional. */
+ messageq_transportshm_status_DOWN,
+ /*!< MessageQ transport Shm instance is down and not functional. */
+ messageq_transportshm_status_RESETTING
+ /*!< MessageQ transport Shm instance was up at one point and is in
+ * process of resetting.
+ */
+};
+
+
+/* =============================================================================
+ * APIs called by applications
+ * =============================================================================
+ */
+/* Function to get the default configuration for the MessageQTransportShm
+ * module. */
+void messageq_transportshm_get_config(struct messageq_transportshm_config *cfg);
+
+/* Function to setup the MessageQTransportShm module. */
+int messageq_transportshm_setup(const struct messageq_transportshm_config *cfg);
+
+/* Function to destroy the MessageQTransportShm module. */
+int messageq_transportshm_destroy(void);
+
+/* Get the default parameters for the NotifyShmDriver. */
+void messageq_transportshm_params_init(void *mqtshm_handle,
+ struct messageq_transportshm_params *params);
+
+/* Create an instance of the MessageQTransportShm. */
+void *messageq_transportshm_create(u16 proc_id,
+ const struct messageq_transportshm_params *params);
+
+/* Delete an instance of the MessageQTransportShm. */
+int messageq_transportshm_delete(void **mqtshm_handleptr);
+
+/* Get the shared memory requirements for the MessageQTransportShm. */
+u32 messageq_transportshm_shared_mem_req(const
+ struct messageq_transportshm_params *params);
+
+/* Set the asynchronous error function for the transport module */
+void messageq_transportshm_set_err_fxn(
+ void (*err_fxn)(
+ enum MessageQTransportShm_Reason reason,
+ void *handle,
+ void *msg,
+ u32 info));
+
+
+/* =============================================================================
+ * APIs called internally by MessageQ module.
+ * =============================================================================
+ */
+/* Put msg to remote list */
+int messageq_transportshm_put(void *mqtshm_handle, void *msg);
+
+/* Control Function */
+int messageq_transportshm_control(void *mqtshm_handle, u32 cmd,
+ u32 *cmd_arg);
+
+/* Get current status of the MessageQTransportShm */
+enum messageq_transportshm_status messageq_transportshm_get_status(
+ void *mqtshm_handle);
+
+#endif /* _MESSAGEQ_TRANSPORTSHM_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/messageq_transportshm_ioctl.h b/arch/arm/plat-omap/include/syslink/messageq_transportshm_ioctl.h
new file mode 100644
index 000000000000..3790dc0d22e8
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/messageq_transportshm_ioctl.h
@@ -0,0 +1,160 @@
+/*
+ * messageq_transportshm_ioctl.h
+ *
+ * Definitions of messageq_transportshm driver types and structures.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _MESSAGEQ_TRANSPORTSHM_IOCTL_H_
+#define _MESSAGEQ_TRANSPORTSHM_IOCTL_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Syslink headers */
+#include <ipc_ioctl.h>
+#include <messageq_transportshm.h>
+#include <sharedregion.h>
+
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/* Base command ID for messageq_transportshm */
+#define MESSAGEQ_TRANSPORTSHM_IOC_MAGIC IPC_IOC_MAGIC
+enum messageq_transportshm_drv_cmd {
+ MESSAGEQ_TRANSPORTSHM_GETCONFIG = MESSAGEQ_TRANSPORTSHM_BASE_CMD,
+ MESSAGEQ_TRANSPORTSHM_SETUP,
+ MESSAGEQ_TRANSPORTSHM_DESTROY,
+ MESSAGEQ_TRANSPORTSHM_PARAMS_INIT,
+ MESSAGEQ_TRANSPORTSHM_CREATE,
+ MESSAGEQ_TRANSPORTSHM_DELETE,
+ MESSAGEQ_TRANSPORTSHM_PUT,
+ MESSAGEQ_TRANSPORTSHM_SHAREDMEMREQ,
+ MESSAGEQ_TRANSPORTSHM_GETSTATUS
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for messageq_transportshm
+ * ----------------------------------------------------------------------------
+ */
+/* Base command ID for messageq_transportshm */
+#define MESSAGEQ_TRANSPORTSHM_BASE_CMD 0x0
+
+/* Command for messageq_transportshm_get_config */
+#define CMD_MESSAGEQ_TRANSPORTSHM_GETCONFIG \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, \
+ MESSAGEQ_TRANSPORTSHM_GETCONFIG, struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_setup */
+#define CMD_MESSAGEQ_TRANSPORTSHM_SETUP \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, MESSAGEQ_TRANSPORTSHM_SETUP, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_setup */
+#define CMD_MESSAGEQ_TRANSPORTSHM_DESTROY \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, MESSAGEQ_TRANSPORTSHM_DESTROY, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_destroy */
+#define CMD_MESSAGEQ_TRANSPORTSHM_PARAMS_INIT \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, \
+ MESSAGEQ_TRANSPORTSHM_PARAMS_INIT, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_create */
+#define CMD_MESSAGEQ_TRANSPORTSHM_CREATE \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, MESSAGEQ_TRANSPORTSHM_CREATE, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_delete */
+#define CMD_MESSAGEQ_TRANSPORTSHM_DELETE \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, MESSAGEQ_TRANSPORTSHM_DELETE, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_put */
+#define CMD_MESSAGEQ_TRANSPORTSHM_PUT \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, MESSAGEQ_TRANSPORTSHM_PUT, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_shared_memreq */
+#define CMD_MESSAGEQ_TRANSPORTSHM_SHAREDMEMREQ \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, \
+ MESSAGEQ_TRANSPORTSHM_SHAREDMEMREQ, \
+ struct messageq_transportshm_cmd_args)
+
+/* Command for messageq_transportshm_get_status */
+#define CMD_MESSAGEQ_TRANSPORTSHM_GETSTATUS \
+ _IOWR(MESSAGEQ_TRANSPORTSHM_IOC_MAGIC, \
+ MESSAGEQ_TRANSPORTSHM_GETSTATUS, struct messageq_transportshm_cmd_args)
+
+/* Command arguments for messageq_transportshm */
+struct messageq_transportshm_cmd_args {
+ union {
+ struct {
+ struct messageq_transportshm_config *config;
+ } get_config;
+
+ struct {
+ struct messageq_transportshm_config *config;
+ } setup;
+
+ struct {
+ void *messageq_transportshm_handle;
+ struct messageq_transportshm_params *params;
+ } params_init;
+
+ struct {
+ void *messageq_transportshm_handle;
+ u16 proc_id;
+ struct messageq_transportshm_params *params;
+ u32 shared_addr_srptr;
+ void *knl_lock_handle;
+ void *knl_notify_driver;
+ } create;
+
+ struct {
+ void *messageq_transportshm_handle;
+ } delete_transport;
+
+ struct {
+ void *messageq_transportshm_handle;
+ u32 *msg_srptr;
+ } put;
+
+ struct {
+ void *messageq_transportshm_handle;
+ enum messageq_transportshm_status status;
+ } get_status;
+
+ struct {
+ struct messageq_transportshm_params *params;
+ u32 bytes;
+ } shared_memreq;
+ } args;
+
+ int api_status;
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL functions for messageq_transportshm module
+ * ----------------------------------------------------------------------------
+ */
+/*
+ * ioctl interface function for messageq_transportshm
+ */
+int messageq_transportshm_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _MESSAGEQ_TRANSPORTSHM_IOCTL_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/multiproc.h b/arch/arm/plat-omap/include/syslink/multiproc.h
new file mode 100755
index 000000000000..6361bae80d19
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/multiproc.h
@@ -0,0 +1,83 @@
+/*
+* multiproc.h
+*
+* Many multi-processor modules have the concept of processor id. multiproc
+* centeralizes the processor id management.
+*
+* Copyright (C) 2008-2009 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.
+*/
+
+#ifndef _MULTIPROC_H_
+#define _MULTIPROC_H_
+
+#include <linux/types.h>
+
+
+#define VOLATILE volatile
+
+/*
+ * Unique module ID
+ */
+#define MULTIPROC_MODULEID (u16)0xB522
+
+/* Macro to define invalid processor id */
+#define MULTIPROC_INVALIDID ((u16)0xFFFF)
+
+/*
+ * Maximum number of processors in the system
+ * OMAP4 has 4 processors in single core.
+ */
+#define MULTIPROC_MAXPROCESSORS 4
+
+/*
+ * Max name length for a processor name
+ */
+#define MULTIPROC_MAXNAMELENGTH 32
+
+/*
+ * Configuration structure for multiproc module
+ */
+struct multiproc_config {
+ s32 max_processors; /* Max number of procs for particular system */
+ char name_list[MULTIPROC_MAXPROCESSORS][MULTIPROC_MAXNAMELENGTH];
+ /* Name List for processors in the system */
+ u16 id; /* Local Proc ID. This needs to be set before calling any
+ other APIs */
+};
+
+/* =============================================================================
+ * APIs
+ * =============================================================================
+ */
+
+/* Function to get the default configuration for the multiproc module. */
+void multiproc_get_config(struct multiproc_config *cfg);
+
+/* Function to setup the multiproc Module */
+s32 multiproc_setup(struct multiproc_config *cfg);
+
+/* Function to destroy the multiproc module */
+s32 multiproc_destroy(void);
+
+/* Function to set local processor Id */
+int multiproc_set_local_id(u16 proc_id);
+
+/* Function to get processor id from processor name. */
+u16 multiproc_get_id(const char *proc_name);
+
+/* Function to get name from processor id. */
+char *multiproc_get_name(u16 proc_id);
+
+/* Function to get maximum proc Id in the system. */
+u16 multiproc_get_max_processors(void);
+
+#endif /* _MULTIPROC_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/multiproc_ioctl.h b/arch/arm/plat-omap/include/syslink/multiproc_ioctl.h
new file mode 100755
index 000000000000..0c9780136b02
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/multiproc_ioctl.h
@@ -0,0 +1,94 @@
+/*
+* multiproc_ioctl.h
+*
+* This provides the ioctl interface for multiproc module
+*
+* Copyright (C) 2008-2009 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.
+*/
+
+#ifndef _MULTIPROC_IOCTL_H_
+#define _MULTIPROC_IOCTL_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <multiproc.h>
+
+enum CMD_MULTIPROC {
+ MULTIPROC_SETUP = MULTIPROC_BASE_CMD,
+ MULTIPROC_DESTROY,
+ MULTIPROC_GETCONFIG,
+ MULTIPROC_SETLOCALID
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for MultiProc
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Command for multiproc_setup
+ */
+#define CMD_MULTIPROC_SETUP _IOWR(IPC_IOC_MAGIC, MULTIPROC_SETUP, \
+ struct multiproc_cmd_args)
+
+/*
+ * Command for multiproc_destroy
+ */
+#define CMD_MULTIPROC_DESTROY _IOWR(IPC_IOC_MAGIC, MULTIPROC_DESTROY, \
+ struct multiproc_cmd_args)
+
+/*
+ * Command for multiproc_get_config
+ */
+#define CMD_MULTIPROC_GETCONFIG _IOWR(IPC_IOC_MAGIC, MULTIPROC_GETCONFIG, \
+ struct multiproc_cmd_args)
+
+/*
+ * Command for multiproc_set_local_id
+ */
+#define CMD_MULTIPROC_SETLOCALID _IOWR(IPC_IOC_MAGIC, MULTIPROC_SETLOCALID, \
+ struct multiproc_cmd_args)
+
+/*
+ * Command arguments for multiproc
+ */
+union multiproc_arg {
+ struct {
+ struct multiproc_config *config;
+ } get_config;
+
+ struct {
+ struct multiproc_config *config;
+ } setup;
+
+ struct {
+ u16 id;
+ } set_local_id;
+};
+
+/*
+ * Command arguments for multiproc
+ */
+struct multiproc_cmd_args {
+ union multiproc_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for multiproc module
+ */
+int multiproc_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _MULTIPROC_IOCTL_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/nameserver.h b/arch/arm/plat-omap/include/syslink/nameserver.h
new file mode 100644
index 000000000000..87265d856d9b
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/nameserver.h
@@ -0,0 +1,131 @@
+/*
+ * nameserver.h
+ *
+ * The nameserver module manages local name/value pairs that
+ * enables an application and other modules to store and retrieve
+ * values based on a name.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _NAMESERVER_H_
+#define _NAMESERVER_H_
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+/*
+ * NAMESERVER_MODULEID
+ * Unique module ID
+ */
+#define NAMESERVER_MODULEID (0xF414)
+
+/*
+ * Instance config-params object.
+ */
+struct nameserver_params {
+ bool check_existing; /* Prevents duplicate entry add in to the table */
+ void *gate_handle; /* Lock used for critical region of the table */
+ u16 max_name_len; /* Length, in MAUs, of name field */
+ u32 max_runtime_entries;
+ u32 max_value_len; /* Length, in MAUs, of the value field */
+ void *table_heap; /* Table is placed into a section on dyn creates */
+};
+
+/*
+ * Function to setup the nameserver module
+ */
+int nameserver_setup(void);
+
+/*
+ * Function to destroy the nameserver module
+ */
+int nameserver_destroy(void);
+
+/*
+ * Function to initialize the parameter structure
+ */
+int nameserver_params_init(struct nameserver_params *params);
+
+/*
+ * Function to initialize the parameter structure
+ */
+int nameserver_get_params(void *handle,
+ struct nameserver_params *params);
+
+/*
+ * Function to create a name server
+ */
+void *nameserver_create(const char *name,
+ const struct nameserver_params *params);
+
+/*
+ * Function to delete a name server
+ */
+int nameserver_delete(void **handle);
+
+/*
+ * Function to add a variable length value into the local table
+ */
+void *nameserver_add(void *handle, const char *name,
+ void *buffer, u32 length);
+
+/*
+ * Function to add a 32 bit value into the local table
+ */
+void *nameserver_add_uint32(void *handle,
+ const char *name, u32 value);
+
+/*
+ * Function to Retrieve the value portion of a name/value pair
+ */
+int nameserver_get(void *handle, const char *name,
+ void *buffer, u32 length, u16 procId[]);
+
+/*
+ * Function to get the value portion of a name/value pair from local table
+ */
+int nameserver_get_local(void *handle, const char *name,
+ void *buffer, u32 length);
+
+/*
+ * Function to removes a value/pair
+ */
+int nameserver_remove(void *handle, const char *name);
+
+/*
+ * Function to Remove an entry from the table
+ */
+int nameserver_remove_entry(void *nshandle, void *nsentry);
+
+/*
+ * Function to handle for a name
+ */
+void *nameserver_get_handle(const char *name);
+
+/*
+ * Function to Match the name
+ */
+int nameserver_match(void *handle, const char *name, u32 *value);
+
+/*
+ * Function to register a remote driver
+ */
+int nameserver_register_remote_driver(void *handle, u16 proc_id);
+
+/*
+ * Function to unregister a remote driver
+ */
+int nameserver_unregister_remote_driver(u16 proc_id);
+
+#endif /* _NAMESERVER_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/nameserver_ioctl.h b/arch/arm/plat-omap/include/syslink/nameserver_ioctl.h
new file mode 100644
index 000000000000..defb71fae47b
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/nameserver_ioctl.h
@@ -0,0 +1,230 @@
+/*
+* nameserver_ioctl.h
+*
+* This provides the ioctl interface for nameserver module
+*
+* Copyright (C) 2008-2009 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.
+*/
+
+#ifndef _NAMESERVER_IOCTL_H_
+#define _NAMESERVER_IOCTL_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <nameserver.h>
+
+enum CMD_NAMESERVER {
+ NAMESERVER_SETUP = NAMESERVER_BASE_CMD,
+ NAMESERVER_DESTROY,
+ NAMESERVER_PARAMS_INIT,
+ NAMESERVER_CREATE,
+ NAMESERVER_DELETE,
+ NAMESERVER_ADD,
+ NAMESERVER_ADDUINT32,
+ NAMESERVER_GET,
+ NAMESERVER_GETLOCAL,
+ NAMESERVER_MATCH,
+ NAMESERVER_REMOVE,
+ NAMESERVER_REMOVEENTRY,
+ NAMESERVER_GETHANDLE,
+};
+
+/*
+ * IOCTL command IDs for nameserver
+ *
+ */
+/*
+ * Command for nameserver_setup
+ */
+#define CMD_NAMESERVER_SETUP _IOWR(IPC_IOC_MAGIC, NAMESERVER_SETUP, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_destroy
+ */
+#define CMD_NAMESERVER_DESTROY _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_DESTROY, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_params_init
+ */
+#define CMD_NAMESERVER_PARAMS_INIT _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_PARAMS_INIT, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_create
+ */
+#define CMD_NAMESERVER_CREATE _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_CREATE, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_delete
+ */
+#define CMD_NAMESERVER_DELETE _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_DELETE, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_add
+ */
+#define CMD_NAMESERVER_ADD _IOWR(IPC_IOC_MAGIC, NAMESERVER_ADD, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_addu32
+ */
+#define CMD_NAMESERVER_ADDUINT32 _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_ADDUINT32, \
+ struct nameserver_cmd_args)
+/*
+ * Command for nameserver_get
+ */
+#define CMD_NAMESERVER_GET _IOWR(IPC_IOC_MAGIC, NAMESERVER_GET, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_get_local
+ */
+#define CMD_NAMESERVER_GETLOCAL _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_GETLOCAL, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_match
+ */
+#define CMD_NAMESERVER_MATCH _IOWR(IPC_IOC_MAGIC, NAMESERVER_MATCH, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_remove
+ */
+#define CMD_NAMESERVER_REMOVE _IOWR(IPC_IOC_MAGIC, NAMESERVER_REMOVE,\
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_remove_entry
+ */
+#define CMD_NAMESERVER_REMOVEENTRY _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_REMOVEENTRY, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command for nameserver_get_handle
+ */
+#define CMD_NAMESERVER_GETHANDLE _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVER_GETHANDLE, \
+ struct nameserver_cmd_args)
+
+/*
+ * Command arguments for nameserver
+ */
+ union nameserver_arg {
+ struct {
+ struct nameserver_params *params;
+ } params_init;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ struct nameserver_params *params;
+ } create;
+
+ struct {
+ void *handle;
+ } delete_instance;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ void *buf;
+ s32 len;
+ void *entry;
+ struct nameserver_entry *node;
+ } add;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ u32 value;
+ void *entry;
+ } addu32;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ void *buf;
+ u32 len;
+ u16 *proc_id;
+ u32 proc_len;
+ u32 count;
+ } get;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ void *buf;
+ u32 len;
+ u32 count;
+ } get_local;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ u32 *value;
+ u32 count;
+ } match;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ } remove;
+
+ struct {
+ void *handle;
+ void *entry;
+ } remove_entry;
+
+ struct {
+ void *handle;
+ char *name;
+ u32 name_len;
+ } get_handle;
+};
+
+/*
+ * Command arguments for nameserver
+ */
+struct nameserver_cmd_args {
+ union nameserver_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for nameserver module
+ */
+int nameserver_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _NAMESERVER_IOCTL_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/nameserver_remote.h b/arch/arm/plat-omap/include/syslink/nameserver_remote.h
new file mode 100755
index 000000000000..dbdcedfc7ac3
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/nameserver_remote.h
@@ -0,0 +1,39 @@
+/*
+ * nameserver_remote.h
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _NAMESERVER_REMOTE_H_
+#define _NAMESERVER_REMOTE_H_
+
+#include <linux/types.h>
+
+/*
+ * Structure defining object for the nameserver remote driver
+ */
+struct nameserver_remote_object {
+ int (*get)(const struct nameserver_remote_object *obj,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len, void *reserved);
+ /* Function to get data from remote nameserver */
+ void *obj; /* Implementation specific object */
+};
+
+/*
+ * Function get data from remote name server
+ */
+int nameserver_remote_get(const struct nameserver_remote_object *handle,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len);
+
+#endif /* _NAMESERVER_REMOTE_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/nameserver_remotenotify.h b/arch/arm/plat-omap/include/syslink/nameserver_remotenotify.h
new file mode 100755
index 000000000000..852da8effcc6
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/nameserver_remotenotify.h
@@ -0,0 +1,100 @@
+/*
+ * nameserver_remotenotify.h
+ *
+ * The nameserver_remotenotify module provides functionality to get name
+ * value pair from a remote nameserver.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _NAMESERVER_REMOTENOTIFY_H_
+#define _NAMESERVER_REMOTENOTIFY_H_
+
+#include <linux/types.h>
+
+/*
+ * NAMESERVERREMOTENOTIFY_MODULEID
+ * Unique module ID
+ */
+#define NAMESERVERREMOTENOTIFY_MODULEID (0x08FD)
+
+/*
+ * Module configuration structure
+ */
+struct nameserver_remotenotify_config {
+ u32 reserved;
+ /* Reserved value (not currently used) */
+};
+
+/*
+ * Module configuration structure
+ */
+struct nameserver_remotenotify_params {
+ u32 notify_event_no; /* Notify event number */
+ void *notify_driver; /* Notify Driver handle */
+ void *shared_addr; /* Address of the shared memory */
+ u32 shared_addr_size; /* Size of the shared memory */
+ void *gate; /* Handle to the gate used for protecting
+ nameserver add and delete */
+};
+
+/*
+ * Function to get the default configuration for the nameserver_remotenotify
+ * module
+ */
+void nameserver_remotenotify_get_config(
+ struct nameserver_remotenotify_config *cfg);
+
+/*
+ * Function to setup the nameserver_remotenotify module
+ */
+int nameserver_remotenotify_setup(struct nameserver_remotenotify_config *cfg);
+
+/*
+ * Function to destroy the nameserver_remotenotify module
+ */
+int nameserver_remotenotify_destroy(void);
+
+/*
+ * Function to get the current configuration values
+ */
+void nameserver_remotenotify_params_init(void *handle,
+ struct nameserver_remotenotify_params *params);
+
+/*
+ * Function to setup the Name Server remote notify
+ */
+void *nameserver_remotenotify_create(u16 proc_id,
+ const struct nameserver_remotenotify_params *params);
+
+/*
+ * Function to destroy the Name Server remote notify
+ */
+int nameserver_remotenotify_delete(void **handle);
+
+
+/*
+ * Function to get a name/value from remote nameserver
+ */
+int nameserver_remotenotify_get(void *handle,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len, void *reserved);
+
+/*
+ * Get the shared memory requirements for the nameserver_remotenotify
+ */
+u32 nameserver_remotenotify_shared_memreq(
+ const struct nameserver_remotenotify_params *params);
+
+
+#endif /* _NAMESERVER_REMOTENOTIFY_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/nameserver_remotenotify_ioctl.h b/arch/arm/plat-omap/include/syslink/nameserver_remotenotify_ioctl.h
new file mode 100755
index 000000000000..e8a355456c09
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/nameserver_remotenotify_ioctl.h
@@ -0,0 +1,163 @@
+/*
+ * nameserver_remotenotify_ioctl.h
+ *
+ * The nameserver_remotenotify module provides functionality to get name
+ * value pair from a remote nameserver.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _NAMESERVERREMOTENOTIFY_DRVDEFS_H
+#define _NAMESERVERREMOTENOTIFY_DRVDEFS_H
+
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <nameserver_remotenotify.h>
+
+enum CMD_NAMESERVERREMOTENOTIFY {
+ NAMESERVERREMOTENOTIFY_GETCONFIG = NAMESERVERREMOTENOTIFY_BASE_CMD,
+ NAMESERVERREMOTENOTIFY_SETUP,
+ NAMESERVERREMOTENOTIFY_DESTROY,
+ NAMESERVERREMOTENOTIFY_PARAMS_INIT,
+ NAMESERVERREMOTENOTIFY_CREATE,
+ NAMESERVERREMOTENOTIFY_DELETE,
+ NAMESERVERREMOTENOTIFY_GET,
+ NAMESERVERREMOTENOTIFY_SHAREDMEMREQ
+};
+
+
+/*
+ * IOCTL command IDs for nameserver_remotenotify
+ *
+ */
+
+/*
+ * Command for nameserver_remotenotify_get_config
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_GETCONFIG _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_GETCONFIG, \
+ struct nameserver_remotenotify_cmd_args)
+/*
+ * Command for nameserver_remotenotify_setup
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_SETUP _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_SETUP, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_setup
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_DESTROY _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_DESTROY, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_destroy
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_PARAMS_INIT _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_PARAMS_INIT, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_create
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_CREATE _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_CREATE, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_delete
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_DELETE _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_DELETE, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_get
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_GET _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_GET, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command for nameserver_remotenotify_shared_memreq
+ */
+#define CMD_NAMESERVERREMOTENOTIFY_SHAREDMEMREQ _IOWR(IPC_IOC_MAGIC, \
+ NAMESERVERREMOTENOTIFY_SHAREDMEMREQ, \
+ struct nameserver_remotenotify_cmd_args)
+
+/*
+ * Command arguments for nameserver_remotenotify
+ */
+union nameserver_remotenotify_arg {
+ struct {
+ struct nameserver_remotenotify_config *config;
+ } get_config;
+
+ struct {
+ struct nameserver_remotenotify_config *config;
+ } setup;
+
+ struct {
+ void *handle;
+ struct nameserver_remotenotify_params *params;
+ } params_init;
+
+ struct {
+ void *handle;
+ u16 proc_id;
+ struct nameserver_remotenotify_params *params;
+ } create;
+
+ struct {
+ void *handle;
+ } delete_instance;
+
+ struct {
+ void *handle;
+ char *instance_name;
+ u32 instance_name_len;
+ char *name;
+ u32 name_len;
+ u8 *value;
+ s32 value_len;
+ void *reserved;
+ s32 len;
+ } get;
+
+ struct {
+ void *handle;
+ struct nameserver_remotenotify_params *params;
+ u32 shared_mem_size;
+ } shared_memreq;
+};
+
+/*
+ * Command arguments for nameserver_remotenotify
+ */
+struct nameserver_remotenotify_cmd_args {
+ union nameserver_remotenotify_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for nameserver_remotenotify module
+ */
+int nameserver_remotenotify_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+
+#endif /* _NAMESERVERREMOTENOTIFY_DRVDEFS_H */
+
diff --git a/arch/arm/plat-omap/include/syslink/notify.h b/arch/arm/plat-omap/include/syslink/notify.h
new file mode 100755
index 000000000000..6cf0e943b85d
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify.h
@@ -0,0 +1,267 @@
+/*
+ * notify.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFY_H
+#define NOTIFY_H
+
+#include <syslink/host_os.h>
+
+#define NOTIFY_MAX_DRIVERS 16
+
+/*
+ * desc Maximum length of the name of Notify drivers, inclusive of NULL
+ * string terminator.
+ *
+ */
+#define NOTIFY_MAX_NAMELEN 32
+
+#define NOTIFY_MODULEID 0x5f84
+
+/*
+ *Status code base for Notify module.
+ */
+#define NOTIFY_STATUSCODEBASE (NOTIFY_MODULEID << 12u)
+
+/*
+ * Macro to make error code.
+ */
+#define NOTIFY_MAKE_FAILURE(x) ((int)(0x80000000\
+ | (NOTIFY_STATUSCODEBASE + (x))))
+
+/*
+ * Macro to make success code.
+ */
+#define NOTIFY_MAKE_SUCCESS(x) (NOTIFY_STATUSCODEBASE + (x))
+
+/*
+ * Generic failure.
+ */
+#define NOTIFY_E_FAIL NOTIFY_MAKE_FAILURE(1)
+
+/*
+ * A timeout occurred while performing the specified operation.
+ */
+#define NOTIFY_E_TIMEOUT NOTIFY_MAKE_FAILURE(2)
+
+/*
+ *Configuration failure.
+ */
+#define NOTIFY_E_CONFIG NOTIFY_MAKE_FAILURE(3)
+
+/*
+ * The module is already initialized
+ */
+#define NOTIFY_E_ALREADYINIT NOTIFY_MAKE_FAILURE(4)
+
+/*
+ * Unable to find the specified entity (e.g. registered event, driver).
+ */
+#define NOTIFY_E_NOTFOUND NOTIFY_MAKE_FAILURE(5)
+
+/*
+ * The specified operation is not supported.
+ */
+#define NOTIFY_E_NOTSUPPORTED NOTIFY_MAKE_FAILURE(6)
+
+/*
+* Invalid event number specified to the Notify operation.
+ */
+#define NOTIFY_E_INVALIDEVENT NOTIFY_MAKE_FAILURE(7)
+
+/*
+ * Invalid pointer provided.
+ */
+#define NOTIFY_E_POINTER NOTIFY_MAKE_FAILURE(8)
+/*
+ * The specified value is out of valid range.
+ */
+#define NOTIFY_E_RANGE NOTIFY_MAKE_FAILURE(9)
+
+/* An invalid handle was provided.
+ */
+#define NOTIFY_E_HANDLE NOTIFY_MAKE_FAILURE(10)
+
+/*
+ * An invalid argument was provided to the API.
+ */
+#define NOTIFY_E_INVALIDARG NOTIFY_MAKE_FAILURE(11)
+
+/*
+ * A memory allocation failure occurred.
+ */
+#define NOTIFY_E_MEMORY NOTIFY_MAKE_FAILURE(12)
+
+/*
+ * The module has not been setup.
+ */
+#define NOTIFY_E_INVALIDSTATE NOTIFY_MAKE_FAILURE(13)
+
+/*
+ * Maximum number of supported drivers have already been registered.
+ */
+#define NOTIFY_E_MAXDRIVERS NOTIFY_MAKE_FAILURE(14)
+
+/*
+ * Invalid attempt to use a reserved event number.
+ */
+#define NOTIFY_E_RESERVEDEVENT NOTIFY_MAKE_FAILURE(15)
+
+/*
+ * The specified entity (e.g. driver) already exists.
+ */
+#define NOTIFY_E_ALREADYEXISTS NOTIFY_MAKE_FAILURE(16)
+
+/*
+ * brief The Notify driver has not been initialized.
+ */
+#define NOTIFY_E_DRIVERINIT NOTIFY_MAKE_FAILURE(17)
+
+/*
+* The remote processor is not ready to receive the event.
+ */
+#define NOTIFY_E_NOTREADY NOTIFY_MAKE_FAILURE(18)
+
+/*
+ * brief Failed to register driver with Notify module.
+ */
+#define NOTIFY_E_REGDRVFAILED NOTIFY_MAKE_FAILURE(19)
+
+/*
+* Failed to unregister driver with Notify module.
+ */
+#define NOTIFY_E_UNREGDRVFAILED NOTIFY_MAKE_FAILURE(20)
+
+/*
+* Failure in an OS-specific operation.
+ */
+#define NOTIFY_E_OSFAILURE NOTIFY_MAKE_FAILURE(21)
+
+/*
+ *Maximum number of supported events have already been registered.
+ */
+#define NOTIFY_E_MAXEVENTS NOTIFY_MAKE_FAILURE(22)
+
+/* Maximum number of supported user clients have already been
+ * registered.
+ */
+#define NOTIFY_E_MAXCLIENTS NOTIFY_MAKE_FAILURE(23)
+
+/* Operation is successful.
+ */
+#define NOTIFY_SUCCESS NOTIFY_MAKE_SUCCESS(0)
+
+/* The ProcMgr module has already been setup in this process.
+ */
+#define NOTIFY_S_ALREADYSETUP NOTIFY_MAKE_SUCCESS(1)
+
+/* Other ProcMgr clients have still setup the ProcMgr module.
+ */
+#define NOTIFY_S_SETUP NOTIFY_MAKE_SUCCESS(2)
+
+/* Other ProcMgr handles are still open in this process.
+ */
+#define NOTIFY_S_OPENHANDLE NOTIFY_MAKE_SUCCESS(3)
+
+/* The ProcMgr instance has already been created/opened in this process
+ */
+#define NOTIFY_S_ALREADYEXISTS NOTIFY_MAKE_SUCCESS(4)
+
+/* Maximum depth for nesting Notify_disable / Notify_restore calls.
+ */
+#define NOTIFY_MAXNESTDEPTH 2
+
+
+/* brief Macro to make a correct module magic number with refCount */
+#define NOTIFY_MAKE_MAGICSTAMP(x) ((NOTIFY_MODULEID << 12u) | (x))
+
+
+/*
+ * const NOTIFYSHMDRV_DRIVERNAME
+ *
+ * desc Name of the Notify Shared Memory Mailbox driver.
+ *
+ */
+#define NOTIFYMBXDRV_DRIVERNAME "NOTIFYMBXDRV"
+
+#define REG volatile
+/*
+ * const NOTIFYSHMDRV_RESERVED_EVENTS
+ *
+ * desc Maximum number of events marked as reserved events by the
+ * notify_shmdrv driver.
+ * If required, this value can be changed by the system integrator.
+ *
+ */
+#define NOTIFYSHMDRV_RESERVED_EVENTS 3
+
+/*
+* This key must be provided as the upper 16 bits of the eventNo when
+ * registering for an event, if any reserved event numbers are to be
+ * used.
+ */
+#define NOTIFY_SYSTEM_KEY 0xC1D2
+
+struct notify_config {
+ u32 maxDrivers;
+ /* Maximum number of drivers that can be created for Notify at a time */
+};
+
+typedef void (*notify_callback_fxn)(u16 proc_id, u32 eventNo, void *arg,
+ u32 payload);
+
+extern struct notify_module_object notify_state;
+
+/* Function to get the default configuration for the Notify module. */
+void notify_get_config(struct notify_config *cfg);
+
+/* Function to setup the Notify Module */
+int notify_setup(struct notify_config *cfg);
+
+/* Function to destroy the Notify module */
+int notify_destroy(void);
+
+/* Function to register an event */
+int notify_register_event(void *notify_driver_handle, u16 proc_id,
+ u32 event_no,
+ notify_callback_fxn notify_callback_fxn,
+ void *cbck_arg);
+
+/* Function to unregister an event */
+int notify_unregister_event(void *notify_driver_handle, u16 proc_id,
+ u32 event_no,
+ notify_callback_fxn notify_callback_fxn,
+ void *cbck_arg);
+
+/* Function to send an event to other processor */
+int notify_sendevent(void *notify_driver_handle, u16 proc_id,
+ u32 event_no, u32 payload, bool wait_clear);
+
+/* Function to disable Notify module */
+u32 notify_disable(u16 procId);
+
+/* Function to restore Notify module state */
+void notify_restore(u32 key, u16 proc_id);
+
+/* Function to disable particular event */
+void notify_disable_event(void *notify_driver_handle, u16 proc_id,
+ u32 event_no);
+
+/* Function to enable particular event */
+void notify_enable_event(void *notify_driver_handle, u16 proc_id, u32 event_no);
+
+#endif /* !defined NOTIFY_H */
+
diff --git a/arch/arm/plat-omap/include/syslink/notify_dispatcher.h b/arch/arm/plat-omap/include/syslink/notify_dispatcher.h
new file mode 100755
index 000000000000..efd87315815e
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_dispatcher.h
@@ -0,0 +1,158 @@
+/*
+ * notify_dispatcher.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#ifndef __TMBX_H__
+#define __TMBX_H__
+
+
+#include <syslink/notifydefs.h>
+#include <linux/interrupt.h>
+
+#include <syslink/notifyerr.h>
+
+#define MAX_MBOX_MODULES 2
+#define MAX_MBOX_ISRS 32
+#define KErrNone 0
+#define KErrNotSupported 1
+#define KErrNotReady 2
+#define KErrArgument 2
+
+typedef void (*isr_call_back)(void *);
+
+struct mbox_config {
+ unsigned long int mbox_linear_addr;
+ unsigned long int mbox_modules;
+ signed long int interrupt_lines[MAX_MBOX_MODULES];
+ signed long int mailboxes[MAX_MBOX_MODULES];
+};
+
+struct mbox_isrs {
+ signed long int isrNo[MAX_MBOX_MODULES];
+ /* TODO: Remove this - seems to be unused.*/
+ isr_call_back isrs[MAX_MBOX_MODULES][MAX_MBOX_ISRS];
+ void *isr_params[MAX_MBOX_MODULES][MAX_MBOX_ISRS];
+};
+
+extern const unsigned long *linear_address;
+
+irqreturn_t notify_mailbx0_user0_isr(int temp, void *anArg, struct pt_regs *p);
+
+/*
+ *func ntfy_disp_bind_interrupt
+ *
+ * desc Bind an ISR to the HW interrupt line coming into the processor
+ */
+int ntfy_disp_bind_interrupt(int interrupt_no,
+ isr_call_back hw_isr,
+ void *isr_arg);
+
+
+/*
+ * desc Print the mailbox registers and other useful debug information
+ *
+ */
+void ntfy_disp_debug(void);
+
+
+/*
+ * func ntfy_disp_deinit
+ * desc Uninitialize the Mailbox Manager module
+ */
+int ntfy_disp_deinit(void);
+
+
+/*
+ * desc Return the pointer to the Mailbox Manager's configuration object
+ */
+struct mbox_config *ntfy_disp_get_config(void);
+
+
+/*
+ * desc Initialize the Mailbox Manager module
+ */
+int ntfy_disp_init(void);
+
+
+/*
+ * desc Disable a particular IRQ bit on a Mailbox IRQ Enable Register
+ */
+int ntfy_disp_interrupt_disable(unsigned long int mbox_module_no,
+ int a_irq_bit);
+
+
+/*
+ * desc Enable a particular IRQ bit on a Mailbox IRQ Enable Register
+ */
+int ntfy_disp_interrupt_enable(unsigned long int mbox_module_no,
+ int a_irq_bit);
+
+
+/*
+ * desc Read a message on a Mailbox FIFO queue
+ */
+int ntfy_disp_read(unsigned long int mbox_module_no,
+ int a_mbox_no,
+ int *messages,
+ int *num_messages,
+ short int read_all);
+
+
+/*
+ * func ntfy_disp_register
+ * desc Register a ISR callback associated with a particular IRQ bit on a
+ * Mailbox IRQ Enable Register
+ */
+int ntfy_disp_register(unsigned long int mbox_module_no,
+ int a_irq_bit,
+ isr_call_back isr_cbck_fn,
+ void *isrCallbackArgs);
+
+
+/*
+ * func ntfy_disp_send
+ * desc Send a message on a Mailbox FIFO queue
+ */
+int ntfy_disp_send(unsigned long int mbox_module_no,
+ int a_mbox_no,
+ int message);
+
+
+/*
+ * func ntfy_disp_unbind_interrupt
+ * desc Remove the ISR to the HW interrupt line coming into the processor
+ */
+int ntfy_disp_unbind_interrupt(int interrupt_no);
+
+
+/*
+ * func ntfy_disp_unregister
+ * desc Unregister a ISR callback associated with a particular IRQ bit on a
+ * Mailbox IRQ Enable Register
+ */
+int ntfy_disp_unregister(unsigned long int mbox_module_no,
+ int a_irq_bit);
+
+/*
+ * func notify_mailbx0_user0_isr
+ * desc mail ISR
+ *
+ */
+
+irqreturn_t notify_mailbx0_user0_isr(int temp, void *anArg, struct pt_regs *p);
+
+
+#endif
diff --git a/arch/arm/plat-omap/include/syslink/notify_driver.h b/arch/arm/plat-omap/include/syslink/notify_driver.h
new file mode 100755
index 000000000000..30a150174654
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_driver.h
@@ -0,0 +1,44 @@
+/*
+ * notify_driver.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFYDRIVER_H
+#define NOTIFYDRIVER_H
+
+#include<linux/list.h>
+
+/* ----------------------------------- Notify */
+#include <syslink/notifyerr.h>
+
+/* ----------------------------------- Notify driver */
+#include <syslink/notify_driverdefs.h>
+
+/* Function to register notify driver */
+int notify_register_driver(char *driver_name,
+ struct notify_interface *fn_table,
+ struct notify_driver_attrs *drv_attrs,
+ struct notify_driver_object **driver_handle);
+
+
+/* Function to unregister notify driver */
+int notify_unregister_driver(struct notify_driver_object *drv_handle);
+
+/* Function to find the driver in the list of drivers */
+int notify_get_driver_handle(char *driver_name,
+ struct notify_driver_object **handle);
+
+#endif /* !defined (NOTIFYDRIVER_H) */
+
diff --git a/arch/arm/plat-omap/include/syslink/notify_driverdefs.h b/arch/arm/plat-omap/include/syslink/notify_driverdefs.h
new file mode 100755
index 000000000000..0e79562d0867
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_driverdefs.h
@@ -0,0 +1,440 @@
+/*
+ * notify_driverdefs.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFYDRIVERDEFS_H
+#define NOTIFYDRIVERDEFS_H
+
+
+#include <syslink/host_os.h>
+
+/* ----------------------------------- Notify */
+#include <syslink/notify.h>
+#include <syslink/notify_shmdriver.h>
+#include <syslink/notifydefs.h>
+#include <syslink/multiproc.h>
+
+#define NOTIFY_BASE_CMD (0x100)
+
+/*
+ * Command for Notify_getConfig
+ */
+#define CMD_NOTIFY_GETCONFIG (NOTIFY_BASE_CMD + 1u)
+
+/*
+ * Command for Notify_setup
+ */
+#define CMD_NOTIFY_SETUP (NOTIFY_BASE_CMD + 2u)
+
+/*
+ * Command for Notify_destroy
+ */
+#define CMD_NOTIFY_DESTROY (NOTIFY_BASE_CMD + 3u)
+
+/*
+ * Command for Notify_registerEvent
+ */
+#define CMD_NOTIFY_REGISTEREVENT (NOTIFY_BASE_CMD + 4u)
+
+/*
+ * Command for Notify_unregisterEvent
+ */
+#define CMD_NOTIFY_UNREGISTEREVENT (NOTIFY_BASE_CMD + 5u)
+
+/*
+ * Command for Notify_sendEvent
+ */
+#define CMD_NOTIFY_SENDEVENT (NOTIFY_BASE_CMD + 6u)
+
+/*
+ * Command for Notify_disable
+ */
+#define CMD_NOTIFY_DISABLE (NOTIFY_BASE_CMD + 7u)
+
+/*
+ * Command for Notify_restore
+ */
+#define CMD_NOTIFY_RESTORE (NOTIFY_BASE_CMD + 8u)
+
+/*
+ * Command for Notify_disableEvent
+ */
+#define CMD_NOTIFY_DISABLEEVENT (NOTIFY_BASE_CMD + 9u)
+
+/*
+ * Command for Notify_enableEvent
+ */
+#define CMD_NOTIFY_ENABLEEVENT (NOTIFY_BASE_CMD + 10u)
+
+/*!
+ * @brief Command for Notify_attach
+ */
+#define CMD_NOTIFY_ATTACH (NOTIFY_BASE_CMD + 11u)
+
+/*!
+ * @brief Command for Notify_detach
+ */
+#define CMD_NOTIFY_DETACH (NOTIFY_BASE_CMD + 12u)
+
+/*
+ * const NOTIFY_SYSTEM_KEY_MASK
+ *
+ * desc Mask to check for system key.
+ *
+ */
+
+#define NOTIFY_SYSTEM_KEY_MASK (unsigned short int) 0xFFFF0000
+
+/*
+ * const NOTIFY_EVENT_MASK
+ *
+ * desc Mask to check for event ID.
+ *
+ */
+
+#define NOTIFY_EVENT_MASK (unsigned short int) 0x0000FFFF
+
+struct notify_cmd_args {
+ int apiStatus;
+ /* Status of the API being called. */
+};
+
+/*
+ * Command arguments for Notify_getConfig
+ */
+struct notify_cmd_args_get_config {
+ struct notify_cmd_args commonArgs;
+ struct notify_config *cfg;
+};
+
+/*
+ * Command arguments for Notify_setup
+ */
+struct notify_cmd_args_setup {
+ struct notify_cmd_args commonArgs;
+ struct notify_config *cfg;
+};
+
+/*
+ * Command arguments for Notify_destroy
+ */
+struct notify_cmd_args_destroy {
+ struct notify_cmd_args commonArgs;
+};
+
+/*
+ * Command arguments for Notify_registerEvent
+ */
+struct notify_cmd_args_register_event {
+ struct notify_cmd_args commonArgs;
+ struct notify_driver_object *handle;
+ u16 procId;
+ u32 eventNo;
+ notify_callback_fxn fnNotifyCbck;
+ void *cbckArg;
+ u32 pid;
+};
+
+/*
+ * Command arguments for Notify_unregisterEvent
+ */
+struct notify_cmd_args_unregister_event {
+ struct notify_cmd_args commonArgs;
+ struct notify_driver_object *handle;
+ u16 procId;
+ u32 eventNo;
+ notify_callback_fxn fnNotifyCbck;
+ void *cbckArg;
+ u32 pid;
+};
+
+/*
+ * Command arguments for Notify_sendEvent
+ */
+struct notify_cmd_args_send_event {
+ struct notify_cmd_args commonArgs;
+ struct notify_driver_object *handle;
+ u16 procId;
+ u32 eventNo;
+ u32 payload;
+ bool waitClear;
+};
+
+/*
+ * Command arguments for Notify_disable
+ */
+struct notify_cmd_args_disable {
+ struct notify_cmd_args commonArgs;
+ u16 procId;
+ u32 flags;
+};
+
+/*
+ * Command arguments for Notify_restore
+ */
+struct notify_cmd_args_restore {
+ struct notify_cmd_args commonArgs;
+ u32 key;
+ u16 procId;
+};
+
+/*
+ * Command arguments for Notify_disableEvent
+ */
+struct notify_cmd_args_disable_event {
+ struct notify_cmd_args commonArgs;
+ struct notify_driver_object *handle;
+ u16 procId;
+ u32 eventNo;
+};
+
+/*
+ * Command arguments for Notify_enableEvent
+ */
+struct notify_cmd_args_enable_event {
+ struct notify_cmd_args commonArgs;
+ void *notify_driver_handle;
+ u16 procId;
+ u32 eventNo;
+};
+
+/*
+ * Command arguments for Notify_exit
+ */
+struct notify_cmd_args_exit {
+ struct notify_cmd_args commonArgs;
+};
+
+
+enum {
+ NOTIFY_DRIVERINITSTATUS_NOTDONE = 0,
+ /* Driver initialization is not done. */
+ NOTIFY_DRIVERINITSTATUS_DONE = 1,
+ /* Driver initialization is complete. */
+ NOTIFY_DRIVERINITSTATUS_INPROGRESS = 2,
+ /* Driver initialization is in progress. */
+ NOTIFY_DRIVERINITSTATUS_ENDVALUE = 3
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ *This structure defines information for all processors supported by
+ *the Notify driver.
+ *An instance of this object is provided for each processor handled by
+ *the Notify driver, when registering itself with the Notify module.
+ *
+ */
+struct notify_driver_proc_info {
+ u32 max_events;
+ u32 reserved_events;
+ bool event_priority;
+ u32 payload_size;
+ u16 proc_id;
+};
+
+/*
+ * This structure defines the structure for specifying Notify driver
+ * attributes to the Notify module.
+ * This structure provides information about the Notify driver to the
+ * Notify module. The information is used by the Notify module mainly
+ * for parameter validation. It may also be used by the Notify module
+ * to take appropriate action if required, based on the characteristics
+ * of the Notify driver.
+ */
+struct notify_driver_attrs {
+ u32 numProc;
+ struct notify_driver_proc_info
+ proc_info[MULTIPROC_MAXPROCESSORS];
+};
+
+
+/* ========================================
+ * Function pointer types
+ * ========================================
+ */
+/*
+ * This type defines the function to register a callback for an event
+ * with the Notify driver.
+ * This function gets called internally from the Notify_registerEvent
+ * API. The Notify_registerEvent () function passes on the
+ * request into the Notify driver identified by the Notify Handle.
+ *
+ */
+typedef int(*NotifyDriver_RegisterEvent)(struct notify_driver_object *handle,
+ u16 procId, u32 eventNo, notify_callback_fxn cbckFxn,
+ void *cbckArg);
+/*
+ * This type defines the function to unregister a callback for an event
+ * with the Notify driver.
+ * This function gets called internally from the Notify_unregisterEvent
+ * API. The Notify_unregisterEvent () function passes on the
+ * request into the Notify driver identified by the Notify Handle.
+ *
+ */
+typedef int(*NotifyDriver_UnregisterEvent) (struct notify_driver_object *handle,
+ u16 procId, u32 eventNo, notify_callback_fxn cbckFxn,
+ void *cbckArg);
+
+/*
+ * This type defines the function to send a notification event to the
+ * registered users for this notification on the specified processor.
+ * This function gets called internally from the Notify_sendEvent ()
+ * API. The Notify_sendEvent () function passes on the initialization
+ * request into the Notify driver identified by the Notify Handle.
+ */
+typedef int(*NotifyDriver_SendEvent) (struct notify_driver_object *handle,
+ u16 procId, u32 eventNo, u32 payload, bool waitClear);
+
+/*
+ * This type defines the function to disable all events for the
+ * specified processor ID.
+ * This function gets called internally from the Notify_disable ()
+ * API. The Notify_disable () function passes on the request into the
+ * Notify driver identified by the Notify Handle.
+ */
+typedef u32(*NotifyDriver_Disable) (struct notify_driver_object *handle,
+ u16 procId);
+
+/*
+ * This type defines the function to restore all events for the
+ * specified processor ID.
+ * This function gets called internally from the Notify_restore ()
+ * API. The Notify_restore () function passes on the request into the
+ * Notify driver identified by the Notify Handle.
+ */
+typedef void (*NotifyDriver_Restore) (struct notify_driver_object *handle,
+ u32 key, u16 procId);
+
+/*
+ * This type defines the function to disable specified event for the
+ * specified processor ID.
+ * This function gets called internally from the Notify_disableEvent ()
+ * API. The Notify_disableEvent () function passes on the request into
+ * the Notify driver identified by the Notify Handle.
+ */
+typedef void (*NotifyDriver_DisableEvent) (struct notify_driver_object *handle,
+ u16 procId, u32 eventNo);
+
+/*
+ * This type defines the function to enable specified event for the
+ * specified processor ID.
+ * This function gets called internally from the Notify_enableEvent ()
+ * API. The Notify_enableEvent () function passes on the request into
+ * the Notify driver identified by the Notify Handle.
+ *
+ */
+typedef void (*NotifyDriver_EnableEvent) (struct notify_driver_object *handle,
+ u16 procId, u32 eventNo);
+
+
+/*
+ * This structure defines the function table interface for the Notify
+ * driver.
+ * This function table interface must be implemented by each Notify
+ * driver and registered with the Notify module.
+ *
+ */
+struct notify_interface {
+ NotifyDriver_RegisterEvent register_event;
+ /* interface function registerEvent */
+ NotifyDriver_UnregisterEvent unregister_event;
+ /* interface function unregisterEvent */
+ NotifyDriver_SendEvent send_event;
+ /* interface function sendEvent */
+ NotifyDriver_Disable disable;
+ /* interface function disable */
+ NotifyDriver_Restore restore;
+ /* interface function restore */
+ NotifyDriver_DisableEvent disable_event;
+ /* interface function disableEvent */
+ NotifyDriver_EnableEvent enable_event;
+};
+
+
+union notify_drv_procevents{
+ struct {
+ struct notify_shmdrv_attrs attrs;
+ struct notify_shmdrv_ctrl *ctrl_ptr;
+ } shm_events;
+
+ struct {
+ /*Attributes */
+ unsigned long int num_events;
+ unsigned long int send_event_pollcount;
+ /*Control Paramters */
+ unsigned long int send_init_status ;
+ struct notify_shmdrv_eventreg_mask reg_mask ;
+ } non_shm_events;
+};
+
+
+/*
+ * This structure defines the Notify driver object and handle used
+ * internally to contain all information required for the Notify driver
+ * This object contains all information for the Notify module to be
+ * able to identify and interact with the Notify driver.
+ */
+struct notify_driver_object {
+ int is_init;
+ struct notify_interface fn_table;
+ char name[NOTIFY_MAX_NAMELEN];
+ struct notify_driver_attrs attrs;
+ u32 *disable_flag[NOTIFY_MAXNESTDEPTH];
+ void *driver_object;
+};
+
+
+struct notify_drv_eventlist {
+ unsigned long int event_handler_count;
+ struct list_head listeners;
+};
+
+
+
+struct notify_drv_eventlistner{
+ struct list_head element;
+ fn_notify_cbck fn_notify_cbck;
+ void *cbck_arg;
+};
+
+
+struct notify_drv_proc_module {
+
+ unsigned long int proc_id;
+ struct notify_drv_eventlist *event_list;
+ struct notify_shmdrv_eventreg *reg_chart;
+ union notify_drv_procevents events_obj;
+};
+
+/*
+ * Defines the Notify state object, which contains all the module
+ * specific information.
+ */
+struct notify_module_object {
+ atomic_t ref_count;
+ struct notify_config cfg;
+ /* Notify configuration structure */
+ struct notify_config def_cfg;
+ /* Default module configuration */
+ struct mutex *gate_handle;
+ /* Handle of gate to be used for local thread safety */
+ struct notify_driver_object drivers[NOTIFY_MAX_DRIVERS];
+ /* Array of configured drivers. */
+ u32 disable_depth;
+ /* Current disable depth for Notify module. */
+};
+#endif /* !defined (NOTIFYDRIVERDEFS_H) */
+
diff --git a/arch/arm/plat-omap/include/syslink/notify_ducatidriver.h b/arch/arm/plat-omap/include/syslink/notify_ducatidriver.h
new file mode 100644
index 000000000000..16ad80e425a7
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_ducatidriver.h
@@ -0,0 +1,200 @@
+/*
+ * notify_ducatidriver.h
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef NOTIFY_DUCATIDRIVER_H_
+#define NOTIFY_DUCATIDRIVER_H_
+
+
+
+/* Notify*/
+#include <syslink/GlobalTypes.h>
+#include <syslink/notifyerr.h>
+#include <syslink/notify_driverdefs.h>
+
+/*
+ * const NOTIFYDUCATI_DRIVERNAME
+ *
+ * desc Name of the ducati driver.
+ *
+ */
+
+#define IPC_BUF_ALIGN 128
+#define IPC_ALIGN(x, y) (unsigned long int)\
+((unsigned long int)((x + y - 1) / y) * y)
+
+
+#define NOTIFYDUCATI_DRIVERNAME "NOTIFY_DUCATIDRV"
+
+#define REG volatile
+
+
+extern u32 get_ducati_virt_mem();
+extern void unmap_ducati_virt_mem(u32 shm_virt_addr);
+
+/*
+* func notify_mbxdrv_register_event
+*
+* desc Register a callback for an event with the Notify driver.
+*
+*
+*/
+
+int notify_ducatidrv_register_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg) ;
+
+/*
+* func notify_mbxdrv_unregevent
+*
+* desc Unregister a callback for an event with the Notify driver.
+*
+*
+*/
+
+int notify_ducatidrv_unregister_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg) ;
+
+/*
+* func notify_mbxdrv_sendevent
+*
+* desc Send a notification event to the registered users for this
+* notification on the specified processor.
+*
+*
+*/
+
+int notify_ducatidrv_sendevent(struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ int payload,
+ short int wait_clear) ;
+
+/*
+* func notify_mbxdrv_disable
+*
+* desc Disable all events for this Notify driver.
+*
+*
+*/
+
+void *notify_ducatidrv_disable(struct notify_driver_object *handle);
+
+/*
+* func notify_mbxdrv_restore
+*
+* desc Restore the Notify driver to the state before the last disable was
+* called.
+*
+*
+*/
+
+int notify_ducatidrv_restore(struct notify_driver_object *handle,
+ void *flags) ;
+
+/*
+* func notify_mbxdrv_disable_event
+*
+* desc Disable a specific event for this Notify driver.
+*
+*
+*/
+
+int notify_ducatidrv_disable_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no) ;
+
+/*
+* func notify_mbxdrv_enable_event
+*
+* desc Enable a specific event for this Notify driver.
+*
+*
+*/
+
+int notify_ducatidrv_enable_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no) ;
+
+
+/*
+* func notify_mbxdrv_debug
+*
+* desc Print debug information for the Notify driver.
+*
+*
+*/
+
+int notify_ducatidrv_debug(struct notify_driver_object *handle) ;
+
+struct notify_ducatidrv_params {
+ int shared_addr;
+ int shared_addr_size;
+ int num_events;
+ int recv_int_id;
+ int send_int_id;
+ int remote_proc_id;
+ int num_reserved_events;
+ int send_event_poll_count;
+} ;
+
+/*
+ * struct notify_ducatidrv_config
+ *
+ */
+
+struct notify_ducatidrv_config {
+ u32 reserved;
+};
+
+/* Function to get the default configuration for the Notify module. */
+void notify_ducatidrv_getconfig(struct notify_ducatidrv_config *cfg);
+
+/* Function to setup the notify ducati driver with the given configuration*/
+int notify_ducatidrv_setup(struct notify_ducatidrv_config *cfg);
+
+/* Function to destroy the notify ducati driver*/
+int notify_ducatidrv_destroy(void);
+
+/* Function to create the ducati driver handle and performs initialization. */
+
+struct notify_driver_object *notify_ducatidrv_create(char *driver_name,
+ const struct notify_ducatidrv_params *params);
+
+/* Function to delete the ducati driver handle and performs de initialization.*/
+int notify_ducatidrv_delete(struct notify_driver_object **handle_ptr);
+
+/*Function to open the ducati driver */
+int notify_ducatidrv_open(char *driver_name,
+ struct notify_driver_object **handle_ptr);
+
+/*Function to close the ducati driver */
+int notify_ducatidrv_close(struct notify_driver_object **handle_ptr);
+
+/*Function to initialize the given parameters */
+void notify_ducatidrv_params_init(struct notify_driver_object *handle,
+ struct notify_ducatidrv_params *params);
+
+#endif /* !defined NOTIFY_SHMDRIVER_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/notify_ducatidriver_defs.h b/arch/arm/plat-omap/include/syslink/notify_ducatidriver_defs.h
new file mode 100755
index 000000000000..6d7b508ae533
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_ducatidriver_defs.h
@@ -0,0 +1,152 @@
+/*
+ * notify_ducati_driverdefs.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#ifndef NOTIFY_DUCATIDRV_DEFS
+#define NOTIFY_DUCATIDRV_DEFS
+
+#include <syslink/notify_ducatidriver.h>
+
+/*
+ * brief Base structure for NotifyDriverShm command args. This needs to be
+ * the first field in all command args structures.
+ */
+struct notify_ducatidrv_cmdargs {
+ int api_status;
+};
+
+
+/*
+ * ioctl command IDs for NotifyDriverShm
+ *
+ */
+/*
+ * brief Base command ID for NotifyDriverShm
+ */
+#define NOTIFYDRIVERSHM_BASE_CMD 0x100
+
+/*
+ * brief Command for NotifyDriverShm_getConfig
+ */
+#define CMD_NOTIFYDRIVERSHM_GETCONFIG (NOTIFYDRIVERSHM_BASE_CMD + 1u)
+
+/*
+ * brief Command for NotifyDriverShm_setup
+ */
+#define CMD_NOTIFYDRIVERSHM_SETUP (NOTIFYDRIVERSHM_BASE_CMD + 2u)
+
+/*
+ * brief Command for NotifyDriverShm_setup
+ */
+#define CMD_NOTIFYDRIVERSHM_DESTROY (NOTIFYDRIVERSHM_BASE_CMD + 3u)
+
+/*
+ * brief Command for NotifyDriverShm_destroy
+ */
+#define CMD_NOTIFYDRIVERSHM_PARAMS_INIT (NOTIFYDRIVERSHM_BASE_CMD + 4u)
+
+/*
+ * brief Command for NotifyDriverShm_create
+ */
+#define CMD_NOTIFYDRIVERSHM_CREATE (NOTIFYDRIVERSHM_BASE_CMD + 5u)
+
+/*
+ * brief Command for NotifyDriverShm_delete
+ */
+#define CMD_NOTIFYDRIVERSHM_DELETE (NOTIFYDRIVERSHM_BASE_CMD + 6u)
+
+/*
+ * brief Command for NotifyDriverShm_open
+ */
+#define CMD_NOTIFYDRIVERSHM_OPEN (NOTIFYDRIVERSHM_BASE_CMD + 7u)
+
+/*
+ * brief Command for NotifyDriverShm_close
+ */
+#define CMD_NOTIFYDRIVERSHM_CLOSE (NOTIFYDRIVERSHM_BASE_CMD + 8u)
+
+
+/*
+ * @brief Command arguments for NotifyDriverShm_getConfig
+ */
+struct notify_ducatidrv_cmdargs_getconfig {
+ struct notify_ducatidrv_cmdargs common_args;
+ struct notify_ducatidrv_config *cfg;
+};
+
+/*
+ * brief Command arguments for NotifyDriverShm_setup
+ */
+struct notify_ducatidrv_cmdargs_setup {
+ struct notify_ducatidrv_cmdargs common_args;
+ struct notify_ducatidrv_config *cfg;
+};
+
+/*
+ * brief Command arguments for NotifyDriverShm_destroy
+ */
+struct notify_ducatidrv_cmdargs_destroy {
+ struct notify_ducatidrv_cmdargs common_args;
+} ;
+
+/*
+ * brief Command arguments for NotifyDriverShm_Params_init
+ */
+
+struct notify_ducatidrv_cmdargs_paramsinit {
+ struct notify_ducatidrv_cmdargs common_args;
+ struct notify_driver_object *handle;
+ struct notify_ducatidrv_params *params;
+};
+
+/*!
+ * @brief Command arguments for NotifyDriverShm_create
+ */
+struct notify_ducatidrv_cmdargs_create {
+ struct notify_ducatidrv_cmdargs common_args;
+ char driverName[NOTIFY_MAX_NAMELEN];
+ struct notify_ducatidrv_params params;
+ struct notify_driver_object *handle;
+};
+
+/*
+ * brief Command arguments for NotifyDriverShm_delete
+ */
+struct notify_ducatidrv_cmdargs_delete {
+ struct notify_ducatidrv_cmdargs common_args;
+ struct notify_driver_object *handle;
+};
+
+/*
+ * brief Command arguments for NotifyDriverShm_open
+ */
+struct notify_ducatidrv_cmdargs_open {
+ struct notify_ducatidrv_cmdargs common_args;
+ char driverName[NOTIFY_MAX_NAMELEN];
+ struct notify_driver_object *handle;
+
+};
+
+/*
+ * brief Command arguments for NotifyDriverShm_close
+ */
+struct notify_ducatidrv_cmdargs_close {
+ struct notify_ducatidrv_cmdargs common_args;
+ struct notify_driver_object *handle;
+
+};
+
+#endif /*NOTIFY_DUCATIDRV_DEFS*/
diff --git a/arch/arm/plat-omap/include/syslink/notify_shmdriver.h b/arch/arm/plat-omap/include/syslink/notify_shmdriver.h
new file mode 100755
index 000000000000..450896160bdf
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_shmdriver.h
@@ -0,0 +1,108 @@
+
+/*
+ * notify_shmdriver.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFY_SHMDRIVER_H_
+#define NOTIFY_SHMDRIVER_H_
+
+/*
+ * const NOTIFYSHMDRV_DRIVERNAME
+ *
+ * desc Name of the Notify Shared Memory Mailbox driver.
+ *
+ */
+#define NOTIFYSHMDRV_DRIVERNAME "NOTIFYSHMDRV"
+
+/*
+ * const NOTIFYSHMDRV_RESERVED_EVENTS
+ *
+ * desc Maximum number of events marked as reserved events by the
+ * NotiyShmDrv driver.
+ * If required, this value can be changed by the system integrator.
+ *
+ */
+
+#define NOTIFYSHMDRV_RESERVED_EVENTS 3
+
+
+/*
+ * name notify_shmdrv_attrs
+ *
+ */
+struct notify_shmdrv_attrs {
+ unsigned long int shm_base_addr;
+ unsigned long int shm_size;
+ unsigned long int num_events;
+ unsigned long int send_event_pollcount;
+};
+
+
+/*
+* name notify_shmdrv_event_entry
+*/
+struct notify_shmdrv_event_entry {
+ REG unsigned long int flag;
+ REG unsigned long int payload;
+ REG unsigned long int reserved;
+ unsigned long int padding[29];
+};
+
+/*
+* name notify_shmdrv_eventreg_mask
+*
+*/
+struct notify_shmdrv_eventreg_mask {
+ REG unsigned long int mask;
+ REG unsigned long int enable_mask;
+ unsigned long int padding[30];
+};
+
+/*
+* name notify_shmdrv_eventreg
+*
+*/
+struct notify_shmdrv_eventreg {
+ unsigned long int reg_event_no;
+ unsigned long int reserved;
+};
+
+/*
+* name notify_shmdrv_proc_ctrl
+*
+*/
+struct notify_shmdrv_proc_ctrl {
+ struct notify_shmdrv_event_entry *self_event_chart;
+ struct notify_shmdrv_event_entry *other_event_chart;
+ unsigned long int recv_init_status;
+ unsigned long int send_init_status;
+ unsigned long int padding[28];
+ struct notify_shmdrv_eventreg_mask reg_mask;
+ struct notify_shmdrv_eventreg *reg_chart;
+};
+
+/*
+ * brief Defines the notify_shmdrv_ctrl structure, which contains all
+ * information shared between the two connected processors
+ * This structure is shared between the two processors.
+ */
+struct notify_shmdrv_ctrl {
+ struct notify_shmdrv_proc_ctrl proc_ctrl[2];
+};
+
+#endif /* !defined NOTIFY_SHMDRIVER_H_ */
+
+
diff --git a/arch/arm/plat-omap/include/syslink/notify_tesladriver.h b/arch/arm/plat-omap/include/syslink/notify_tesladriver.h
new file mode 100755
index 000000000000..50f4ece661f9
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notify_tesladriver.h
@@ -0,0 +1,219 @@
+/*
+ * notify_tesladriver.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+
+
+/* Notify*/
+#include <syslink/GlobalTypes.h>
+#include <syslink/notifyerr.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/notifydefs.h>
+
+/*
+ * const NOTIFYSHMDRV_DRIVERNAME
+ *
+ * desc Name of the Notify Shared Memory Mailbox driver.
+ *
+ */
+#define NOTIFYMBXDRV_DRIVERNAME "NOTIFYMBXDRV"
+
+/*
+* struct notify_tesladrv_params
+*
+* desc driver.params
+*
+*/
+
+
+struct notify_tesladrv_params {
+ int shared_addr;
+ int shared_addr_size;
+ int num_events;
+ int recv_int_id;
+ int send_int_id;
+ int remote_proc_id;
+ int num_reserved_events;
+ int send_event_poll_count;
+};
+
+/*
+* struct notify_tesladrv_config
+*
+* desc driver.configuration
+*
+*/
+
+
+struct notify_tesladrv_config {
+ u32 reserved;
+};
+
+
+
+/*
+* func notify_mbxdrv_register_event
+*
+* desc Register a callback for an event with the Notify driver.
+*
+*
+*/
+
+int notify_tesladrv_register_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg);
+
+/*
+* func notify_mbxdrv_unregevent
+*
+* desc Unregister a callback for an event with the Notify driver.
+*
+*
+*/
+
+int notify_tesladrv_unregister_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg);
+
+/*
+* func notify_mbxdrv_sendevent
+*
+* desc Send a notification event to the registered users for this
+* notification on the specified processor.
+*
+*
+*/
+
+int notify_tesladrv_sendevent(struct notify_driver_object *handle,
+ short int proc_id, int event_no,
+ int payload, short int wait_clear);
+
+/*
+* func notify_mbxdrv_disable
+*
+* desc Disable all events for this Notify driver.
+*
+*
+*/
+
+void *notify_tesladrv_disable(struct notify_driver_object *handle, u16 proc_Id);
+
+/*
+* func notify_mbxdrv_restore
+*
+* desc Restore the Notify driver to the state before the last disable was
+* called.
+*
+*
+*/
+
+int notify_tesladrv_restore(struct notify_driver_object *handle,
+ u32 key, u16 proc_id);
+
+/*
+* func notify_mbxdrv_disable_event
+*
+* desc Disable a specific event for this Notify driver.
+*
+*
+*/
+
+int notify_tesladrv_disable_event(struct notify_driver_object *handle,
+ short int proc_id, int event_no);
+
+/*
+* func notify_mbxdrv_enable_event
+*
+* desc Enable a specific event for this Notify driver.
+*
+*
+*/
+
+int notify_tesladrv_enable_event(struct notify_driver_object *handle,
+ short int proc_id, int event_no);
+
+/*
+* func notify_tesladrv_debug
+*
+* desc Print debug information for the Notify driver.
+*
+*
+*/
+
+int notify_tesladrv_debug(struct notify_driver_object *handle);
+
+/*
+* func notify_tesladrv_create
+*
+* desc creates driver handle.
+*
+*
+*/
+
+struct notify_driver_object *notify_tesladrv_create(char *driver_name,
+ const struct notify_tesladrv_params *params);
+
+/*
+* func notify_tesladrv_delete
+*
+* desc deletes driver handle.
+*/
+
+
+int notify_tesladrv_delete(struct notify_driver_object **handlePtr);
+
+/*
+* func notify_tesladrv_getconfig
+*
+* desc Get the default configuration for driver.
+*/
+void notify_tesladrv_getconfig(struct notify_tesladrv_config *cfg);
+
+
+/*
+* func notify_tesladrv_setup
+*
+* desc setup the driver with the given config.
+*/
+
+
+int notify_tesladrv_setup(struct notify_tesladrv_config *cfg);
+
+/*
+* func notify_tesladrv_params_init
+*
+* desc initializes parameters for driver.
+*/
+
+void notify_tesladrv_params_init(struct notify_driver_object *handle,
+ struct notify_tesladrv_params *params);
+
+/*
+* func notify_tesladrv_destroy
+*
+* desc destroys the driver
+*/
+
+int notify_tesladrv_destroy(void);
+
+
+
diff --git a/arch/arm/plat-omap/include/syslink/notifydefs.h b/arch/arm/plat-omap/include/syslink/notifydefs.h
new file mode 100755
index 000000000000..7f37346a7f75
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notifydefs.h
@@ -0,0 +1,25 @@
+/*
+ * notifydefs.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFYDEFS_H
+#define NOTIFYDEFS_H
+typedef void (*fn_notify_cbck) (unsigned long int procId,
+ u32 eventNo,
+ void *arg,
+ u32 payload) ;
+
+#endif /* !defined (NOTIFYDEFS_H) */
diff --git a/arch/arm/plat-omap/include/syslink/notifyerr.h b/arch/arm/plat-omap/include/syslink/notifyerr.h
new file mode 100755
index 000000000000..9bbaa238fa3a
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/notifyerr.h
@@ -0,0 +1,198 @@
+/*
+ * notifyerr.h
+ *
+ * Notify driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#if !defined NOTIFYERR_H
+#define NOTIFYERR_H
+
+
+/*
+ * name NOTIFY_SUCCEEDED
+ *
+ * desc Check if the provided status code indicates a success code.
+ *
+ * arg status
+ * Status code to be checked
+ *
+ * ret TRUE
+ * If status code indicates success
+ * FALSE
+ * If status code indicates failure
+ *
+ * enter None.
+ *
+ * leave None.
+ *
+ * see NOTIFY_FAILED
+ *
+ */
+#define NOTIFY_SUCCEEDED(status)\
+(((signed long int) (status) >= (NOTIFY_SBASE)) \
+&& ((signed long int) (status) <= (NOTIFY_SLAST)))
+
+
+/*
+ * @name NOTIFY_FAILED
+ *
+ * @desc Check if the provided status code indicates a failure code.
+ *
+ * @arg status
+ * Status code to be checked
+ *
+ * @ret TRUE
+ * If status code indicates failure
+ * FALSE
+ * If status code indicates success
+ *
+ * @enter None.
+ *
+ * @leave None.
+ *
+ * @see NOTIFY_FAILED
+ *
+ */
+#define NOTIFY_FAILED(status) (!NOTIFY_SUCCEEDED(status))
+
+
+
+/*
+ * name NOTIFY_SBASE, NOTIFY_SLAST
+ *
+ * desc Defines the base and range for the success codes used by the
+ * Notify module
+ *
+ */
+#define NOTIFY_SBASE (signed long int)0x00002000l
+#define NOTIFY_SLAST (signed long int)0x000020FFl
+
+/*
+ * name NOTIFY_EBASE, NOTIFY_ELAST
+ *
+ * desc Defines the base and range for the failure codes used by the
+ * Notify module
+ *
+ */
+#define NOTIFY_EBASE (signed long int)0x80002000l
+#define NOTIFY_ELAST (signed long int)0x800020FFl
+
+
+/*
+ * SUCCESS Codes
+ *
+ */
+
+/* Generic success code for Notify module */
+#define NOTIFY_SOK (NOTIFY_SBASE + 0x01l)
+
+/* Indicates that the Notify module (or driver) has already been initialized
+ * by another client, and this process has now successfully acquired the right
+ * to use the Notify module.
+ */
+#define NOTIFY_SALREADYINIT (NOTIFY_SBASE + 0x02l)
+
+/* Indicates that the Notify module (or driver) is now being finalized, since
+ * the calling client is the last one finalizing the module, and all open
+ * handles to it have been closed.
+ */
+#define NOTIFY_SEXIT (NOTIFY_SBASE + 0x03l)
+
+
+/*
+ * FAILURE Codes
+ *
+ */
+
+/* Generic failure code for Notify module */
+#define NOTIFY_EFAIL (NOTIFY_EBASE + 0x01l)
+
+/* This failure code indicates that an operation has timed out. */
+#define NOTIFY_ETIMEOUT (NOTIFY_EBASE + 0x02l)
+
+/* This failure code indicates a configuration error */
+#define NOTIFY_ECONFIG (NOTIFY_EBASE + 0x03l)
+
+/* This failure code indicates that the Notify module has already been
+ * initialized from the calling client (process).
+ */
+#define NOTIFY_EALREADYINIT (NOTIFY_EBASE + 0x04l)
+
+/* This failure code indicates that the specified entity was not found
+ * The interpretation of this error code depends on the function from which it
+ * was returned.
+ */
+#define NOTIFY_ENOTFOUND (NOTIFY_EBASE + 0x05l)
+
+/* This failure code indicates that the specified feature is not supported
+ * The interpretation of this error code depends on the function from which it
+ * was returned.
+ */
+#define NOTIFY_ENOTSUPPORTED (NOTIFY_EBASE + 0x06l)
+
+/* This failure code indicates that the specified event number is
+ * not supported
+ */
+#define NOTIFY_EINVALIDEVENT (NOTIFY_EBASE + 0x07l)
+
+/* This failure code indicates that the specified pointer is invalid */
+#define NOTIFY_EPOINTER (NOTIFY_EBASE + 0x08l)
+
+/* This failure code indicates that a provided parameter was outside its valid
+ * range.
+ * The interpretation of this error code depends on the function from which it
+ * was returned.
+ */
+#define NOTIFY_ERANGE (NOTIFY_EBASE + 0x09l)
+
+/* This failure code indicates that the specified handle is invalid */
+#define NOTIFY_EHANDLE (NOTIFY_EBASE + 0x0Al)
+
+/* This failure code indicates that an invalid argument was specified */
+#define NOTIFY_EINVALIDARG (NOTIFY_EBASE + 0x0Bl)
+
+/* This failure code indicates a memory related failure */
+#define NOTIFY_EMEMORY (NOTIFY_EBASE + 0x0Cl)
+
+/* This failure code indicates that the Notify module has not been initialized*/
+#define NOTIFY_EINIT (NOTIFY_EBASE + 0x0Dl)
+
+/* This failure code indicates that a resource was not available.
+ * The interpretation of this error code depends on the function from which it
+ * was returned.
+ */
+#define NOTIFY_ERESOURCE (NOTIFY_EBASE + 0x0El)
+
+/* This failure code indicates that there was an attempt to register for a
+ * reserved event.
+ */
+#define NOTIFY_ERESERVEDEVENT (NOTIFY_EBASE + 0x0Fl)
+
+/* This failure code indicates that the specified entity already exists.
+ * The interpretation of this error code depends on the function from which it
+ * was returned.
+ */
+#define NOTIFY_EALREADYEXISTS (NOTIFY_EBASE + 0x10l)
+
+/* This failure code indicates that the Notify driver has not been fully
+ * initialized
+ */
+#define NOTIFY_EDRIVERINIT (NOTIFY_EBASE + 0x11l)
+
+/* This failure code indicates that the other side is not ready to receive
+ * notifications.
+ */
+#define NOTIFY_ENOTREADY (NOTIFY_EBASE + 0x12l)
+
+#endif /* !defined (NOTIFYERR_H) */
diff --git a/arch/arm/plat-omap/include/syslink/platform.h b/arch/arm/plat-omap/include/syslink/platform.h
new file mode 100644
index 000000000000..298d20f7ab5d
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/platform.h
@@ -0,0 +1,45 @@
+/*
+ * platform.h
+ *
+ * Defines the platform functions to be used by SysMgr module.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _PLATFORM_H_
+#define _PLATFORM_H_
+
+/* Module headers */
+#include <sysmgr.h>
+
+/* =============================================================================
+ * APIs
+ * =============================================================================
+ */
+/* Function to setup the platform */
+s32 platform_setup(struct sysmgr_config *config);
+
+/* Function to destroy the platform */
+s32 platform_destroy(void);
+
+/* Function called when slave is loaded with executable */
+void platform_load_callback(void *arg);
+
+/* Function called when slave is in started state*/
+void platform_start_callback(void *arg);
+
+/* Function called when slave is stopped state */
+void platform_stop_callback(void *arg);
+
+s32 platform_override_config(struct sysmgr_config *config);
+
+#endif /* ifndef _PLATFORM_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/platform_mem.h b/arch/arm/plat-omap/include/syslink/platform_mem.h
new file mode 100755
index 000000000000..874a1153fc21
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/platform_mem.h
@@ -0,0 +1,137 @@
+/*
+ * platform_mem.c
+ *
+ * Target memory management interface implementation.
+ *
+ * This abstracts the Memory management interface in the kernel
+ * code. Allocation, Freeing-up, copy and address translate are
+ * supported for the kernel memory management.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _PLATFORM_MEM_H_
+#define _PLATFORM_MEM_H_
+
+#include <linux/types.h>
+
+/*
+ * MEMORYOS_MODULEID
+ * Module ID for platform mem module
+ */
+#define PLATFORM_MEM_MODULEID (u16) 0x97D2
+
+/*
+ * Enumerates the types of caching for memory regions
+ */
+enum platform_mem_cache_flags {
+ PLATFORM_MEM_CACHE_FLAGS_DEFAULT = 0x00000000,
+ /* Default flags - Cached */
+ PLATFORM_MEM_CACHE_FLAGS_CACHED = 0x00010000,
+ /* Cached memory */
+ PLATFORM_MEM_CACHE_FLAGS_UNCACHED = 0x00020000,
+ /* Uncached memory */
+ PLATFORM_MEM_CACHE_FLAGS_END_VALUE = 0x00030000
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Enumerates the types of memory allocation
+ */
+enum platform_mem_mtype_flags{
+ PLATFORM_MEM_MTYPE_FLAGS_DEFAULT = 0x00000000,
+ /* Default flags - virtually contiguous */
+ PLATFORM_MEM_MTYPE_FLAGS_PHYSICAL = 0x00000001,
+ /* Physically contiguous */
+ PLATFORM_MEM_MTYPE_FLAGS_DMA = 0x00000002,
+ /* Physically contiguous */
+ PLATFORM_MEM_MTYPE_FLAGS_END_VALUE = 0x00000003
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Enumerates the types of translation
+ */
+enum memory_xlt_flags{
+ PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS = 0x00000000,
+ /* Virtual to physical */
+ PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT = 0x00000001,
+ /* Virtual to physical */
+ PLATFORM_MEM_XLT_FLAGS_END_VALUE = 0x00000002
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Structure containing information required for mapping a
+ * memory region.
+ */
+struct platform_mem_map_info {
+ u32 src;
+ /* Address to be mapped. */
+ u32 size;
+ /* Size of memory region to be mapped. */
+ u32 dst;
+ /* Mapped address. */
+ bool is_cached;
+ /* Whether the mapping is to a cached area or uncached area. */
+ void *drv_handle;
+ /* Handle to the driver that is implementing the mmap call. Ignored for
+ Kernel-side version. */
+};
+
+/*
+ * Structure containing information required for unmapping a
+ * memory region.
+ */
+struct platform_mem_unmap_info {
+ u32 addr;
+ /* Address to be unmapped.*/
+ u32 size;
+ /* Size of memory region to be unmapped.*/
+ bool is_cached;
+ /* Whether the mapping is to a cached area or uncached area. */
+};
+
+/*
+ * Structure containing information required for mapping a
+ * memory region.
+ */
+#define memory_map_info struct platform_mem_map_info
+
+/*
+ * Structure containing information required for unmapping a
+ * memory region.
+ */
+#define memory_unmap_info struct platform_mem_unmap_info
+
+
+/* =============================================================================
+ * APIs
+ * =============================================================================
+ */
+/* Initialize the platform mem module. */
+int platform_mem_setup(void);
+
+/* Finalize the platform mem module. */
+int platform_mem_destroy(void);
+
+/* Maps a memory area into virtual space. */
+int platform_mem_map(memory_map_info *map_info);
+
+/* Unmaps a memory area into virtual space. */
+int platform_mem_unmap(memory_unmap_info *unmap_info);
+
+/* Translate API */
+void *platform_mem_translate(void *srcAddr, enum memory_xlt_flags flags);
+
+#endif /* ifndef _PLATFORM_MEM_H_ */
+
diff --git a/arch/arm/plat-omap/include/syslink/procmgr.h b/arch/arm/plat-omap/include/syslink/procmgr.h
new file mode 100755
index 000000000000..4d113c9fa90d
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/procmgr.h
@@ -0,0 +1,280 @@
+/*
+ * procmgr.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+#ifndef SYSLINK_PROC_MGR_H
+#define SYSLINK_PROC_MGR_H
+
+#include <linux/types.h>
+#include <syslink/multiproc.h>
+
+
+
+#define PROCMGR_MODULEID 0xf2ba
+
+/*
+ * Maximum name length for ProcMgr module strings.
+ */
+#define PROCMGR_MAX_STRLEN 32
+
+/*
+ * Maximum number of memory regions supported by ProcMgr module.
+ */
+#define PROCMGR_MAX_MEMORY_REGIONS 32
+
+/*
+ * IS_VALID_PROCID
+ * Checks if the Processor ID is valid
+ */
+#define IS_VALID_PROCID(id) (id < MULTIPROC_MAXPROCESSORS)
+
+
+/*
+ * Enumerations to indicate Processor states.
+ */
+enum proc_mgr_state {
+ PROC_MGR_STATE_UNKNOWN = 0,
+ /* Unknown Processor state (e.g. at startup or error). */
+ PROC_MGR_STATE_POWERED = 1,
+ /* Indicates the Processor is powered up. */
+ PROC_MGR_STATE_RESET = 2,
+ /* Indicates the Processor is reset. */
+ PROC_MGR_STATE_LOADED = 3,
+ /* Indicates the Processor is loaded. */
+ PROC_MGR_STATE_RUNNNING = 4,
+ /* Indicates the Processor is running. */
+ PROC_MGR_STATE_UNAVAILABLE = 5,
+ /* Indicates the Processor is unavailable to the physical transport. */
+ PROC_MGR_STATE_ENDVALUE = 6
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Enumerations to indicate different types of slave boot modes.
+ */
+enum proc_mgr_boot_mode {
+ PROC_MGR_BOOTMODE_BOOT = 0,
+ /* ProcMgr is responsible for loading the slave and its reset control */
+ PROC_MGR_BOOTMODE_NOLOAD = 1,
+ /* ProcMgr is not responsible for loading the slave. It is responsible
+ for reset control of the slave. */
+ PROC_MGR_BOOTMODE_NOBOOT = 2,
+ /* ProcMgr is not responsible for loading or reset control of the slave.
+ The slave either self-boots, or this is done by some entity outside of
+ the ProcMgr module. */
+ PROC_MGR_BOOTMODE_ENDVALUE = 3
+ /* End delimiter indicating start of invalid values for this enum */
+} ;
+
+/*
+ * Enumerations to indicate address types used for translation
+ */
+enum proc_mgr_addr_type{
+ PROC_MGR_ADDRTYPE_MASTERKNLVIRT = 0,
+ /* Kernel Virtual address on master processor */
+ PROC_MGR_ADDRTYPE_MASTERUSRVIRT = 1,
+ /* User Virtual address on master processor */
+ PROC_MGR_ADDRTYPE_SLAVEVIRT = 2,
+ /* Virtual address on slave processor */
+ PROC_MGR_ADDRTYPE_ENDVALUE = 3
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Enumerations to indicate types of address mapping
+ */
+enum proc_mgr_map_type {
+ PROC_MGR_MAPTYPE_VIRT = 0,
+ /* Map/unmap to virtual address space (kernel/user) */
+ PROC_MGR_MAPTYPE_SLAVE = 1,
+ /* Map/unmap to slave address space */
+ PROC_MGR_MAPTYPE_ENDVALUE = 2
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+/*
+ * Module configuration structure.
+ */
+struct proc_mgr_config {
+ void *gate_handle;
+} ;
+
+/*
+ * Configuration parameters specific to the slave ProcMgr instance.
+ */
+struct proc_mgr_params {
+ void *proc_handle;
+ /* void * to the Processor object associated with this ProcMgr. */
+ void *loader_handle;
+ /*!< Handle to the Loader object associated with this ProcMgr. */
+ void *pwr_handle;
+ /*!< Handle to the PwrMgr object associated with this ProcMgr. */
+};
+
+/*
+ * Configuration parameters specific to the slave ProcMgr instance.
+ */
+struct proc_mgr_attach_params {
+ enum proc_mgr_boot_mode boot_mode;
+ /* Boot mode for the slave processor. */
+} ;
+
+/*
+ * Configuration parameters to be provided while starting the slave
+ * processor.
+ */
+struct proc_mgr_start_params {
+ u32 proc_id;
+};
+
+/*
+ * Configuration parameters to be provided while stopping the slave
+ * processor.
+ */
+struct proc_mgr_stop_params {
+ u32 proc_id;
+};
+
+/*
+ * This structure defines information about memory regions mapped by
+ * the ProcMgr module.
+ */
+struct proc_mgr_addr_info {
+/* bool is_init; */
+ unsigned short is_init;
+ /* Is this memory region initialized? */
+ u32 addr[PROC_MGR_ADDRTYPE_ENDVALUE];
+ /* Addresses for each type of address space */
+ u32 size;
+ /* Size of the memory region in bytes */
+};
+
+/*
+ * Characteristics of the slave processor
+ */
+struct proc_mgr_proc_info {
+ enum proc_mgr_boot_mode boot_mode;
+ /* Boot mode of the processor. */
+ u16 num_mem_entries;
+ /* Number of valid memory entries */
+ struct proc_mgr_addr_info mem_entries[PROCMGR_MAX_MEMORY_REGIONS];
+ /* Configuration of memory regions */
+};
+
+
+/*
+ * Function pointer type that is passed to the proc_mgr_registerNotify function
+*/
+typedef int (*proc_mgr_callback_fxn)(u16 proc_id, void *handle,
+ enum proc_mgr_state from_state, enum proc_mgr_state to_state);
+
+/* Function to get the default configuration for the ProcMgr module. */
+void proc_mgr_get_config(struct proc_mgr_config *cfg);
+
+/* Function to setup the ProcMgr module. */
+int proc_mgr_setup(struct proc_mgr_config *cfg);
+
+/* Function to destroy the ProcMgr module. */
+int proc_mgr_destroy(void);
+
+/* Function to initialize the parameters for the ProcMgr instance. */
+void proc_mgr_params_init(void *handle, struct proc_mgr_params *params);
+
+/* Function to create a ProcMgr object for a specific slave processor. */
+void *proc_mgr_create(u16 proc_id, const struct proc_mgr_params *params);
+
+/* Function to delete a ProcMgr object for a specific slave processor. */
+int proc_mgr_delete(void **handle_ptr);
+
+/* Function to open a handle to an existing ProcMgr object handling the
+ * proc_id.
+ */
+int proc_mgr_open(void **handle, u16 proc_id);
+
+/* Function to close this handle to the ProcMgr instance. */
+int proc_mgr_close(void *handle);
+
+/* Function to initialize the parameters for the ProcMgr attach function. */
+void proc_mgr_get_attach_params(void *handle,
+ struct proc_mgr_attach_params *params);
+
+/* Function to attach the client to the specified slave and also initialize the
+ * slave(if required).
+ */
+int proc_mgr_attach(void *handle, struct proc_mgr_attach_params *params);
+
+/* Function to detach the client from the specified slave and also finalze the
+ * slave(if required).
+ */
+int proc_mgr_detach(void *handle);
+
+/* Function to initialize the parameters for the ProcMgr start function. */
+void proc_mgr_get_start_params(void *handle,
+ struct proc_mgr_start_params *params);
+
+/* Function to starts execution of the loaded code on the slave from the
+ * starting point specified in the slave executable loaded earlier by call to
+ * proc_mgr_load().
+ */
+int proc_mgr_start(void *handle, u32 entry_point,
+ struct proc_mgr_start_params *params);
+
+/* Function to stop execution of the slave Processor. */
+int proc_mgr_stop(void *handle, struct proc_mgr_stop_params *params);
+
+/* Function to get the current state of the slave Processor as maintained on
+ * the master Processor state machine.
+ */
+enum proc_mgr_state proc_mgr_get_state(void *handle);
+
+/* Function to read from the slave Processor's memory space. */
+int proc_mgr_read(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer);
+
+/* Function to read from the slave Processor's memory space. */
+int proc_mgr_write(void *handle, u32 proc_addr, u32 *num_bytes, void *buffer);
+
+/* Function that provides a hook for performing device dependent operations on
+ * the slave Processor.
+ */
+int proc_mgr_control(void *handle, int cmd, void *arg);
+
+int proc_mgr_translate_addr(void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dst_addr_type, void *src_addr,
+ enum proc_mgr_addr_type src_addr_type);
+
+/* Function that maps the specified slave address to master address space. */
+int proc_mgr_map(void *handle, u32 proc_addr, u32 size,
+ u32 *mappedAddr, u32 *mapped_size, u32 map_attribs);
+
+/* Function that unmaps the specified slave address to master address space. */
+int proc_mgr_unmap(void *handle, u32 mapped_addr);
+
+/* Function that registers for notification when the slave processor
+ * transitions to any of the states specified.
+ */
+int proc_mgr_register_notify(void *handle, proc_mgr_callback_fxn fxn,
+ void *args, enum proc_mgr_state state[]);
+
+/* Function that returns information about the characteristics of the slave
+ * processor.
+ */
+int proc_mgr_get_proc_info(void *handle, struct proc_mgr_proc_info *proc_info);
+
+/* Function that returns virtual to physical translations
+ */
+int proc_mgr_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries);
+
+#endif
diff --git a/arch/arm/plat-omap/include/syslink/sharedregion.h b/arch/arm/plat-omap/include/syslink/sharedregion.h
new file mode 100755
index 000000000000..75fe48049b5e
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sharedregion.h
@@ -0,0 +1,110 @@
+/*
+ * sharedregion.h
+ *
+ * The SharedRegion module is designed to be used in a
+ * multi-processor environment where there are memory regions
+ * that are shared and accessed across different processors
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _SHAREDREGION_H_
+#define _SHAREDREGION_H_
+
+#include <linux/types.h>
+
+/*
+ * SHAREDREGION_MODULEID
+ * Module ID for Shared region manager
+ */
+#define SHAREDREGION_MODULEID (0x5D8A)
+
+/*
+ * Name of the reserved nameserver used for application
+ */
+#define SHAREDREGION_NAMESERVER "SHAREDREGION"
+
+/*
+ * Name of the reserved nameserver used for application
+ */
+#define SHAREDREGION_INVALIDSRPTR ((u32 *)0xFFFFFFFF)
+
+
+struct sharedregion_info {
+ bool is_valid; /* table entry is valid or not? */
+ void *base; /* Ptr to the base address of a table entry */
+ u32 len; /* The length of a table entry */
+};
+
+/*
+ * Module configuration structure
+ */
+struct sharedregion_config {
+ void *gate_handle;
+ void *heap_handle;
+ u32 max_regions;
+};
+
+/*
+ * Function to get the configuration
+ */
+int sharedregion_get_config(struct sharedregion_config *config);
+
+/*
+ * Function to setup the SharedRegion module
+ */
+int sharedregion_setup(const struct sharedregion_config *config);
+
+/*
+ * Function to destroy the SharedRegion module
+ */
+int sharedregion_destroy(void);
+
+/* Fucntion to Add a memory segment to the lookup table during
+ * runtime by base and length
+ */
+int sharedregion_add(u32 index, void *base, u32 len);
+
+/* Removes the memory segment at the specified index from the lookup
+ * table at runtime
+ */
+int sharedregion_remove(u32 index);
+
+/*
+ * Returns the index for the specified address pointer
+ */
+int sharedregion_get_index(void *addr);
+
+/*
+ * Returns the address pointer associated with the shared region pointer
+ */
+void *sharedregion_get_ptr(u32 *srptr);
+
+/*
+ * Returns the shared region pointer
+ */
+u32 *sharedregion_get_srptr(void *addr, int index);
+
+/*
+ * Gets the table entry information for the specified index and processor id
+ */
+int sharedregion_get_table_info(u32 index, u16 proc_id,
+ struct sharedregion_info *info);
+
+/*
+ * Sets the base address of the entry in the table
+ */
+int sharedregion_set_table_info(u32 index, u16 proc_id,
+ struct sharedregion_info *info);
+
+#endif /* _SHAREDREGION_H */
+
diff --git a/arch/arm/plat-omap/include/syslink/sharedregion_ioctl.h b/arch/arm/plat-omap/include/syslink/sharedregion_ioctl.h
new file mode 100755
index 000000000000..0b2857110991
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sharedregion_ioctl.h
@@ -0,0 +1,181 @@
+/*
+ * sharedregion_ioctl.h
+ *
+ * The sharedregion module is designed to be used in a
+ * multi-processor environment where there are memory regions
+ * that are shared and accessed across different processors
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _SHAREDREGION_IOCTL_H
+#define _SHAREDREGION_IOCTL_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include <ipc_ioctl.h>
+#include <sharedregion.h>
+
+enum CMD_SHAREDREGION {
+ SHAREDREGION_GETCONFIG = SHAREDREGION_BASE_CMD,
+ SHAREDREGION_SETUP,
+ SHAREDREGION_DESTROY,
+ SHAREDREGION_ADD,
+ SHAREDREGION_GETPTR,
+ SHAREDREGION_GETSRPTR,
+ SHAREDREGION_GETTABLEINFO,
+ SHAREDREGION_REMOVE,
+ SHAREDREGION_SETTABLEINFO,
+ SHAREDREGION_GETINDEX,
+};
+
+/*
+ * IOCTL command IDs for sharedregion
+ *
+ */
+
+/*
+ * Command for sharedregion_get_config
+ */
+#define CMD_SHAREDREGION_GETCONFIG _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_GETCONFIG, \
+ struct sharedregion_cmd_args)
+/*
+ * Command for sharedregion_setup
+ */
+#define CMD_SHAREDREGION_SETUP _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_SETUP, \
+ struct sharedregion_cmd_args)
+/*
+ * Command for sharedregion_setup
+ */
+#define CMD_SHAREDREGION_DESTROY _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_DESTROY, \
+ struct sharedregion_cmd_args)
+/*
+ * Command for sharedregion_ADD
+ */
+#define CMD_SHAREDREGION_ADD _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_ADD, \
+ struct sharedregion_cmd_args)
+/*
+ * Command for sharedregion_get_ptr
+ */
+#define CMD_SHAREDREGION_GETPTR _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_GETPTR, \
+ struct sharedregion_cmd_args)
+
+/*
+ * Command for sharedregion_get_srptr
+ */
+#define CMD_SHAREDREGION_GETSRPTR _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_GETSRPTR, \
+ struct sharedregion_cmd_args)
+
+/*
+ * Command for sharedregion_get_table_info
+ */
+#define CMD_SHAREDREGION_GETTABLEINFO _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_GETTABLEINFO, \
+ struct sharedregion_cmd_args)
+
+/*
+ * Command for sharedregion_remove
+ */
+#define CMD_SHAREDREGION_REMOVE _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_REMOVE, \
+ struct sharedregion_cmd_args)
+/*
+ * Command for sharedregion_set_table_info
+ */
+#define CMD_SHAREDREGION_SETTABLEINFO _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_SETTABLEINFO, \
+ struct sharedregion_cmd_args)
+
+/*
+ * Command for sharedregion_get_index
+ */
+#define CMD_SHAREDREGION_GETINDEX _IOWR(IPC_IOC_MAGIC, \
+ SHAREDREGION_GETINDEX, \
+ struct sharedregion_cmd_args)
+
+/*
+ * Command arguments for sharedregion
+ */
+union sharedregion_arg {
+ struct {
+ struct sharedregion_config *config;
+ } get_config;
+
+ struct {
+ struct sharedregion_config *config;
+ struct sharedregion_config *default_cfg;
+ struct sharedregion_info *table;
+ } setup;
+
+ struct {
+ u32 index;
+ void *base;
+ u32 len;
+ } add;
+
+ struct {
+ void *addr;
+ s32 index;
+ } get_index;
+
+ struct {
+ u32 *srptr;
+ void *addr;
+ } get_ptr;
+
+ struct {
+ u32 *srptr;
+ void *addr;
+ s32 index;
+ } get_srptr;
+
+ struct {
+ u32 index;
+ u16 proc_id;
+ struct sharedregion_info *info;
+ } get_table_info;
+
+ struct {
+ u32 index;
+ } remove;
+
+ struct {
+ u32 index;
+ u16 proc_id;
+ struct sharedregion_info *info;
+ } set_table_info;
+} ;
+
+/*
+ * Command arguments for sharedregion
+ */
+struct sharedregion_cmd_args {
+ union sharedregion_arg args;
+ s32 api_status;
+};
+
+/*
+ * This ioctl interface for sharedregion module
+ */
+int sharedregion_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _SHAREDREGION_IOCTL_H */
+
+
diff --git a/arch/arm/plat-omap/include/syslink/sysmemmgr.h b/arch/arm/plat-omap/include/syslink/sysmemmgr.h
new file mode 100644
index 000000000000..34c3b4182288
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sysmemmgr.h
@@ -0,0 +1,179 @@
+/*
+ * sysmemmgr.h
+ *
+ * Manager for the Slave system memory. Slave system level memory is allocated
+ * through this module.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+
+#ifndef _SYSTEMMEMORYMANAGER_H_
+#define _SYSTEMMEMORYMANAGER_H_
+
+
+/*!
+ * @def SYSMEMMGR_MODULEID
+ * @brief Module identifier for System memory manager.
+ */
+#define SYSMEMMGR_MODULEID (0xb53d)
+
+/*!
+ * @def SYSMEMMGR_STATUSCODEBASE
+ * @brief Error code base for system memory manager module.
+ */
+#define SYSMEMMGR_STATUSCODEBASE (SYSMEMMGR_MODULEID << 12u)
+
+/*!
+ * @def SYSMEMMGR_MAKE_ERROR
+ * @brief Macro to make error code.
+ */
+#define SYSMEMMGR_MAKE_ERROR(x) ((int)(0x80000000 + \
+ (SYSMEMMGR_STATUSCODEBASE + \
+ (x))))
+
+/*!
+ * @def SYSMEMMGR_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define SYSMEMMGR_MAKE_SUCCESS(x) (SYSMEMMGR_STATUSCODEBASE + (x))
+
+/*!
+ * @def SYSMEMMGR_E_CREATEALLOCATOR
+ * @brief Static allocator creation failed.
+ */
+#define SYSMEMMGR_E_CREATEALLOCATOR SYSMEMMGR_MAKE_ERROR(1)
+
+/*!
+ * @def SYSMEMMGR_E_CREATELOCK
+ * @brief Mutex lock creation failed.
+ */
+#define SYSMEMMGR_E_CREATELOCK SYSMEMMGR_MAKE_ERROR(2)
+
+/*!
+ * @def SYSMEMMGR_E_INVALIDSTATE
+ * @brief Module is not initialized.
+ */
+#define SYSMEMMGR_E_INVALIDSTATE SYSMEMMGR_MAKE_ERROR(3)
+
+/*!
+ * @def SYSMEMMGR_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define SYSMEMMGR_E_INVALIDARG SYSMEMMGR_MAKE_ERROR(4)
+
+/*!
+ * @def SYSMEMMGR_E_BPAFREE
+ * @brief Freeing to buddy allocator failed.
+ */
+#define SYSMEMMGR_E_BPAFREE SYSMEMMGR_MAKE_ERROR(5)
+
+/*!
+ * @def SYSMEMMGR_E_MEMORY
+ * @brief Memory allocation failed.
+ */
+#define SYSMEMMGR_E_MEMORY SYSMEMMGR_MAKE_ERROR(6)
+
+/*!
+ * @def SYSMEMMGR_SUCCESS
+ * @brief Operation successful.
+ */
+#define SYSMEMMGR_SUCCESS SYSMEMMGR_MAKE_SUCCESS(0)
+
+/*!
+ * @def SYSMEMMGR_S_ALREADYSETUP
+ * @brief Module already initialized.
+ */
+#define SYSMEMMGR_S_ALREADYSETUP SYSMEMMGR_MAKE_SUCCESS(1)
+
+/*!
+ * @def SYSMEMMGR_S_DRVALREADYOPENED
+ * @brief Internal OS Driver is already opened.
+ */
+#define SYSMEMMGR_S_DRVALREADYOPENED SYSMEMMGR_MAKE_SUCCESS(2)
+
+/*!
+ * @brief Configuration data structure of system memory manager.
+ */
+struct sysmemmgr_config {
+ u32 sizeof_valloc;
+ /* Total size for virtual memory allocation */
+ u32 sizeof_palloc;
+ /* Total size for physical memory allocation */
+ u32 static_phys_base_addr;
+ /* Physical address of static memory region */
+ u32 static_virt_base_addr;
+ /* Virtual address of static memory region */
+ u32 static_mem_size;
+ /* size of static memory region */
+ u32 page_size;
+ /* Page size */
+ u32 event_no;
+ /* Event number to be used */
+};
+
+/*!
+ * @brief Flag used for allocating memory blocks.
+ */
+enum sysmemmgr_allocflag {
+ sysmemmgr_allocflag_uncached = 0u,
+ /* Flag used for allocating uncacheable block */
+ sysmemmgr_allocflag_cached = 1u,
+ /* Flag used for allocating cacheable block */
+ sysmemmgr_allocflag_physical = 2u,
+ /* Flag used for allocating physically contiguous block */
+ sysmemmgr_allocflag_virtual = 3u,
+ /* Flag used for allocating virtually contiguous block */
+ sysmemmgr_allocflag_dma = 4u
+ /* Flag used for allocating DMAable (physically contiguous) block */
+};
+
+/*!
+ * @brief Flag used for translating address.
+ */
+enum sysmemmgr_xltflag {
+ sysmemmgr_xltflag_kvirt2phys = 0x0001u,
+ /* Flag used for converting Kernel virtual address to physical
+ * address */
+ sysmemmgr_xltflag_kvirt2uvirt = 0x0002u,
+ /* Flag used for converting Kernel virtual address to user virtual
+ * address */
+ sysmemmgr_xltflag_uvirt2phys = 0x0003u,
+ /* Flag used for converting user virtual address to physical address */
+ sysmemmgr_xltflag_uvirt2kvirt = 0x0004u,
+ /* Flag used for converting user virtual address to Kernel virtual
+ * address */
+ sysmemmgr_xltflag_phys2kvirt = 0x0005u,
+ /* Flag used for converting physical address to user virtual address */
+ sysmemmgr_xltflag_phys2uvirt = 0x0006u
+ /* Flag used for converting physical address to Kernel virtual
+ * address */
+};
+
+
+/* Function prototypes */
+void sysmemmgr_get_config(struct sysmemmgr_config *config);
+
+int sysmemmgr_setup(struct sysmemmgr_config *params);
+
+int sysmemmgr_destroy(void);
+
+int sysmemmgr_attach(u16 slave_id);
+
+void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag);
+
+int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag);
+
+void *sysmemmgr_translate(void *srcAddr, enum sysmemmgr_xltflag flag);
+
+
+#endif /* _SYSTEMMEMORYMANAGER_H_ */
diff --git a/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h b/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h
new file mode 100644
index 000000000000..4b0d99615560
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h
@@ -0,0 +1,130 @@
+/*
+ * sysmemmgr_ioctl.h
+ *
+ * Definitions of sysmemmgr driver types and structures..
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _SYSMEMMGR_IOCTL_H_
+#define _SYSMEMMGR_IOCTL_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Syslink headers */
+#include <ipc_ioctl.h>
+#include <sysmgr.h>
+
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for sysmemmgr
+ * ----------------------------------------------------------------------------
+ */
+/* IOC Magic Number for sysmemmgr */
+#define SYSMEMMGR_IOC_MAGIC IPC_IOC_MAGIC
+
+/* IOCTL command numbers for sysmemmgr */
+enum sysmemmgr_drv_cmd {
+ SYSMEMMGR_GETCONFIG = SYSMEMMGR_BASE_CMD,
+ SYSMEMMGR_SETUP,
+ SYSMEMMGR_DESTROY,
+ SYSMEMMGR_ALLOC,
+ SYSMEMMGR_FREE,
+ SYSMEMMGR_TRANSLATE
+};
+
+/* Command for sysmemmgr_getConfig */
+#define CMD_SYSMEMMGR_GETCONFIG \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_GETCONFIG, \
+ struct sysmemmgr_cmd_args)
+
+/* Command for sysmemmgr_setup */
+#define CMD_SYSMEMMGR_SETUP \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_SETUP, \
+ struct sysmemmgr_cmd_args)
+
+/* Command for sysmemmgr_destroy */
+#define CMD_SYSMEMMGR_DESTROY \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_DESTROY, \
+ struct sysmemmgr_cmd_args)
+
+/* Command for sysmemmgr_alloc */
+#define CMD_SYSMEMMGR_ALLOC \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_ALLOC, \
+ struct sysmemmgr_cmd_args)
+
+/* Command for sysmemmgr_free */
+#define CMD_SYSMEMMGR_FREE \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_FREE, \
+ struct sysmemmgr_cmd_args)
+
+/* Command for sysmemmgr_translate */
+#define CMD_SYSMEMMGR_TRANSLATE \
+ _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_TRANSLATE, \
+ struct sysmemmgr_cmd_args)
+
+
+/* ----------------------------------------------------------------------------
+ * Command arguments for sysmemmgr
+ * ----------------------------------------------------------------------------
+ */
+/* Command arguments for sysmemmgr */
+struct sysmemmgr_cmd_args {
+ union {
+ struct {
+ struct sysmemmgr_config *config;
+ } get_config;
+
+ struct {
+ struct sysmemmgr_config *config;
+ } setup;
+
+ struct {
+ u32 size;
+ void *buf;
+ void *phys;
+ void *kbuf;
+ enum sysmemmgr_allocflag flags;
+ } alloc;
+
+ struct {
+ u32 size;
+ void *buf;
+ void *phys;
+ void *kbuf;
+ enum sysmemmgr_allocflag flags;
+ } free;
+
+ struct {
+ void *buf;
+ void *ret_ptr;
+ enum sysmemmgr_xltflag flags;
+ } translate;
+ } args;
+
+ s32 api_status;
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL functions for sysmemmgr module
+ * ----------------------------------------------------------------------------
+ */
+/* ioctl interface function for sysmemmgr */
+int sysmemmgr_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* SYSMEMMGR_DRVDEFS_H_0xF414 */
diff --git a/arch/arm/plat-omap/include/syslink/sysmgr.h b/arch/arm/plat-omap/include/syslink/sysmgr.h
new file mode 100644
index 000000000000..19fab220b2c4
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sysmgr.h
@@ -0,0 +1,182 @@
+/*
+ * sysmgr.h
+ *
+ * Defines for System manager.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _SYSMGR_H_
+#define _SYSMGR_H_
+
+
+/* Module headers */
+#include <multiproc.h>
+#include <gatepeterson.h>
+#include <sharedregion.h>
+#include <listmp.h>
+#include <listmp_sharedmemory.h>
+#include <messageq.h>
+#include <messageq_transportshm.h>
+#include <notify.h>
+#include <notify_ducatidriver.h>
+#include <nameserver.h>
+#include <nameserver_remote.h>
+#include <nameserver_remotenotify.h>
+#include <procmgr.h>
+#include <heap.h>
+#include <heapbuf.h>
+#include <sysmemmgr.h>
+
+
+/*!
+ * @def SYSMGR_MODULEID
+ * @brief Unique module ID.
+ */
+#define SYSMGR_MODULEID (0xF086)
+
+
+/* =============================================================================
+ * Module Success and Failure codes
+ * =============================================================================
+ */
+/*!
+ * @def SYSMGR_STATUSCODEBASE
+ * @brief Error code base for System manager.
+ */
+#define SYSMGR_STATUSCODEBASE (SYSMGR_MODULEID << 12u)
+
+/*!
+ * @def SYSMGR_MAKE_FAILURE
+ * @brief Macro to make error code.
+ */
+#define SYSMGR_MAKE_FAILURE(x) ((s32)(0x80000000 + \
+ (SYSMGR_STATUSCODEBASE + \
+ (x))))
+
+/*!
+ * @def SYSMGR_MAKE_SUCCESS
+ * @brief Macro to make success code.
+ */
+#define SYSMGR_MAKE_SUCCESS(x) (SYSMGR_STATUSCODEBASE + (x))
+
+/*!
+ * @def SYSMGR_E_INVALIDARG
+ * @brief Argument passed to a function is invalid.
+ */
+#define SYSMGR_E_INVALIDARG SYSMGR_MAKE_FAILURE(1)
+
+/*!
+ * @def SYSMGR_E_MEMORY
+ * @brief Memory allocation failed.
+ */
+#define SYSMGR_E_MEMORY SYSMGR_MAKE_FAILURE(2)
+
+/*!
+ * @def SYSMGR_E_FAIL
+ * @brief General failure.
+ */
+#define SYSMGR_E_FAIL SYSMGR_MAKE_FAILURE(3)
+
+/*!
+ * @def SYSMGR_E_INVALIDSTATE
+ * @brief Module is in invalid state.
+ */
+#define SYSMGR_E_INVALIDSTATE SYSMGR_MAKE_FAILURE(4)
+
+/*!
+ * @def SYSMGR_E_OSFAILURE
+ * @brief Failure in OS call.
+ */
+#define SYSMGR_E_OSFAILURE SYSMGR_MAKE_FAILURE(5)
+
+/*!
+ * @def SYSMGR_S_ALREADYSETUP
+ * @brief Module is already initialized.
+ */
+#define SYSMGR_S_ALREADYSETUP SYSMGR_MAKE_SUCCESS(1)
+
+/*!
+ * @def SYSMGR_CMD_SCALABILITY
+ * @brief Command ID for scalability info.
+ */
+#define SYSMGR_CMD_SCALABILITY (0x00000000)
+
+/*!
+ * @def SYSMGR_CMD_SHAREDREGION_ENTRY_BASE
+ * @brief Base of command IDs for entries used by Shared region.
+ */
+#define SYSMGR_CMD_SHAREDREGION_ENTRY_START (0x00000001)
+#define SYSMGR_CMD_SHAREDREGION_ENTRY_END (0x00001000)
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/*!
+ * @brief Structure defining config parameters for overall System.
+ */
+struct sysmgr_config {
+ struct sysmemmgr_config sysmemmgr_cfg;
+ /*!< System memory manager config parameter */
+
+ struct multiproc_config multiproc_cfg;
+ /*!< Multiproc config parameter */
+
+ struct gatepeterson_config gatepeterson_cfg;
+ /*!< Gatepeterson config parameter */
+
+ struct sharedregion_config sharedregion_cfg;
+ /*!< SharedRegion config parameter */
+
+ struct messageq_config messageq_cfg;
+ /*!< MessageQ config parameter */
+
+ struct notify_config notify_cfg;
+ /*!< Notify config parameter */
+
+ struct proc_mgr_config proc_mgr_cfg;
+ /*!< Processor manager config parameter */
+
+ struct heapbuf_config heapbuf_cfg;
+ /*!< Heap Buf config parameter */
+
+ struct listmp_config listmp_sharedmemory_cfg;
+ /*!< ListMPSharedMemory config parameter */
+
+ struct messageq_transportshm_config messageq_transportshm_cfg;
+ /*!< MessageQTransportShm config parameter */
+
+ struct notify_ducatidrv_config notify_ducatidrv_cfg;
+ /*!< NotifyDriverShm config parameter */
+
+ struct nameserver_remotenotify_config nameserver_remotenotify_cfg;
+ /*!< NameServerRemoteNotify config parameter */
+};
+
+
+/* =============================================================================
+ * APIs
+ * =============================================================================
+ */
+/* Function to initialize the parameter structure */
+void sysmgr_get_config(struct sysmgr_config *config);
+
+/* Function to initialize sysmgr module */
+s32 sysmgr_setup(const struct sysmgr_config *config);
+
+/* Function to Finalize sysmgr module */
+s32 sysmgr_destroy(void);
+
+
+#endif /* ifndef SYSMGR_H_0xF086 */
diff --git a/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h b/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h
new file mode 100644
index 000000000000..03db7b9511a2
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h
@@ -0,0 +1,100 @@
+/*
+ * sysmgr_ioctl.h
+ *
+ * Definitions of sysmgr driver types and structures..
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef _SYSMGR_IOCTL_H_
+#define _SYSMGR_IOCTL_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Syslink headers */
+#include <ipc_ioctl.h>
+#include <sysmgr.h>
+
+
+/* =============================================================================
+ * Macros and types
+ * =============================================================================
+ */
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for sysmgr
+ * ----------------------------------------------------------------------------
+ */
+/* IOC Magic Number for sysmgr */
+#define SYSMGR_IOC_MAGIC IPC_IOC_MAGIC
+
+/* IOCTL command numbers for sysmgr */
+enum sysmgr_drv_cmd {
+ SYSMGR_SETUP = SYSMGR_BASE_CMD,
+ SYSMGR_DESTROY,
+ SYSMGR_LOADCALLBACK,
+ SYSMGR_STARTCALLBACK,
+ SYSMGR_STOPCALLBACK
+};
+
+/* Command for sysmgr_setup */
+#define CMD_SYSMGR_SETUP \
+ _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_SETUP, \
+ struct sysmgr_cmd_args)
+
+/* Command for sysmgr_destroy */
+#define CMD_SYSMGR_DESTROY \
+ _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_DESTROY, \
+ struct sysmgr_cmd_args)
+
+/* Command for load callback */
+#define CMD_SYSMGR_LOADCALLBACK \
+ _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_LOADCALLBACK, \
+ struct sysmgr_cmd_args)
+
+/* Command for load callback */
+#define CMD_SYSMGR_STARTCALLBACK \
+ _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_STARTCALLBACK, \
+ struct sysmgr_cmd_args)
+
+/* Command for stop callback */
+#define CMD_SYSMGR_STOPCALLBACK \
+ _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_STOPCALLBACK, \
+ struct sysmgr_cmd_args)
+
+
+/* ----------------------------------------------------------------------------
+ * Command arguments for sysmgr
+ * ----------------------------------------------------------------------------
+ */
+/* Command arguments for sysmgr */
+struct sysmgr_cmd_args {
+ union {
+ struct {
+ struct sysmgr_config *config;
+ } setup;
+
+ int proc_id;
+ } args;
+
+ s32 api_status;
+};
+
+/* ----------------------------------------------------------------------------
+ * IOCTL functions for sysmgr module
+ * ----------------------------------------------------------------------------
+ */
+/* ioctl interface function for sysmgr */
+int sysmgr_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+#endif /* _SYSMGR_IOCTL_H_ */
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 4a0301399013..fd4f128bc23e 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -861,9 +861,15 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx()) {
+ obj->clk = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(obj->clk))
+ goto err_clk;
+ }
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 40424edae939..0bc0be3c523c 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -28,54 +28,9 @@
#include <mach/mailbox.h>
-static int enable_seq_bit;
-module_param(enable_seq_bit, bool, 0);
-MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking.");
-
static struct omap_mbox *mboxes;
static DEFINE_RWLOCK(mboxes_lock);
-/*
- * Mailbox sequence bit API
- */
-
-/* seq_rcv should be initialized with any value other than
- * 0 and 1 << 31, to allow either value for the first
- * message. */
-static inline void mbox_seq_init(struct omap_mbox *mbox)
-{
- if (!enable_seq_bit)
- return;
-
- /* any value other than 0 and 1 << 31 */
- mbox->seq_rcv = 0xffffffff;
-}
-
-static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
-{
- if (!enable_seq_bit)
- return;
-
- /* add seq_snd to msg */
- *msg = (*msg & 0x7fffffff) | mbox->seq_snd;
- /* flip seq_snd */
- mbox->seq_snd ^= 1 << 31;
-}
-
-static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
-{
- mbox_msg_t seq;
-
- if (!enable_seq_bit)
- return 0;
-
- seq = msg & (1 << 31);
- if (seq == mbox->seq_rcv)
- return -1;
- mbox->seq_rcv = seq;
- return 0;
-}
-
/* Mailbox FIFO handle functions */
static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{
@@ -95,14 +50,6 @@ static inline int mbox_fifo_full(struct omap_mbox *mbox)
}
/* Mailbox IRQ handle functions */
-static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- mbox->ops->enable_irq(mbox, irq);
-}
-static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- mbox->ops->disable_irq(mbox, irq);
-}
static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
if (mbox->ops->ack_irq)
@@ -113,17 +60,10 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
return mbox->ops->is_irq(mbox, irq);
}
-/* Mailbox Sequence Bit function */
-void omap_mbox_init_seq(struct omap_mbox *mbox)
-{
- mbox_seq_init(mbox);
-}
-EXPORT_SYMBOL(omap_mbox_init_seq);
-
/*
* message sender
*/
-static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
+static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{
int ret = 0, i = 1000;
@@ -134,53 +74,43 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
return -1;
udelay(1);
}
-
- if (arg && mbox->txq->callback) {
- ret = mbox->txq->callback(arg);
- if (ret)
- goto out;
- }
-
- mbox_seq_toggle(mbox, &msg);
mbox_fifo_write(mbox, msg);
- out:
return ret;
}
-struct omap_msg_tx_data {
- mbox_msg_t msg;
- void *arg;
-};
-
+#if 0
static void omap_msg_tx_end_io(struct request *rq, int error)
{
kfree(rq->special);
__blk_put_request(rq->q, rq);
}
+#endif
-int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
+int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{
- struct omap_msg_tx_data *tx_data;
+ return __mbox_msg_send(mbox, msg);
+
+ /* FIXME Work queue is not used to send mailbox messages.
+ Directly calling __mbox_msg_send() */
+#if 0
struct request *rq;
struct request_queue *q = mbox->txq->queue;
-
- tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
- if (unlikely(!tx_data))
- return -ENOMEM;
-
+ int ret = 0;
rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq)) {
- kfree(tx_data);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
- tx_data->msg = msg;
- tx_data->arg = arg;
rq->end_io = omap_msg_tx_end_io;
- blk_insert_request(q, rq, 0, tx_data);
+
+ blk_insert_request(q, rq, 0, (void *)msg);
schedule_work(&mbox->txq->work);
- return 0;
+
+ fail:
+ return ret;
+#endif
}
EXPORT_SYMBOL(omap_mbox_msg_send);
@@ -194,8 +124,6 @@ static void mbox_tx_work(struct work_struct *work)
struct request_queue *q = mbox->txq->queue;
while (1) {
- struct omap_msg_tx_data *tx_data;
-
spin_lock(q->queue_lock);
rq = blk_fetch_request(q);
spin_unlock(q->queue_lock);
@@ -203,11 +131,9 @@ static void mbox_tx_work(struct work_struct *work)
if (!rq)
break;
- tx_data = rq->special;
-
- ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg);
+ ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special);
if (ret) {
- enable_mbox_irq(mbox, IRQ_TX);
+ omap_mbox_enable_irq(mbox, IRQ_TX);
spin_lock(q->queue_lock);
blk_requeue_request(q, rq);
spin_unlock(q->queue_lock);
@@ -215,7 +141,7 @@ static void mbox_tx_work(struct work_struct *work)
}
spin_lock(q->queue_lock);
- __blk_end_request_all(rq, 0);
+ blk_end_request_all(rq, 0);
spin_unlock(q->queue_lock);
}
}
@@ -233,11 +159,6 @@ static void mbox_rx_work(struct work_struct *work)
mbox_msg_t msg;
unsigned long flags;
- if (mbox->rxq->callback == NULL) {
- sysfs_notify(&mbox->dev->kobj, NULL, "mbox");
- return;
- }
-
while (1) {
spin_lock_irqsave(q->queue_lock, flags);
rq = blk_fetch_request(q);
@@ -245,7 +166,8 @@ static void mbox_rx_work(struct work_struct *work)
if (!rq)
break;
- msg = (mbox_msg_t)rq->special;
+ msg = (mbox_msg_t) rq->special;
+
blk_end_request_all(rq, 0);
mbox->rxq->callback((void *)msg);
}
@@ -254,17 +176,17 @@ static void mbox_rx_work(struct work_struct *work)
/*
* Mailbox interrupt handler
*/
-static void mbox_txq_fn(struct request_queue * q)
+static void mbox_txq_fn(struct request_queue *q)
{
}
-static void mbox_rxq_fn(struct request_queue * q)
+static void mbox_rxq_fn(struct request_queue *q)
{
}
static void __mbox_tx_interrupt(struct omap_mbox *mbox)
{
- disable_mbox_irq(mbox, IRQ_TX);
+ omap_mbox_disable_irq(mbox, IRQ_TX);
ack_mbox_irq(mbox, IRQ_TX);
schedule_work(&mbox->txq->work);
}
@@ -275,20 +197,13 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
mbox_msg_t msg;
struct request_queue *q = mbox->rxq->queue;
- disable_mbox_irq(mbox, IRQ_RX);
-
while (!mbox_fifo_empty(mbox)) {
rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq))
goto nomem;
msg = mbox_fifo_read(mbox);
-
- if (unlikely(mbox_seq_test(mbox, msg))) {
- pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
- if (mbox->err_notify)
- mbox->err_notify();
- }
+ rq->special = (void *)msg;
blk_insert_request(q, rq, 0, (void *)msg);
if (mbox->ops->type == OMAP_MBOX_TYPE1)
@@ -297,7 +212,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
/* no more messages in the fifo. clear IRQ source. */
ack_mbox_irq(mbox, IRQ_RX);
- enable_mbox_irq(mbox, IRQ_RX);
nomem:
schedule_work(&mbox->rxq->work);
}
@@ -315,75 +229,8 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
return IRQ_HANDLED;
}
-/*
- * sysfs files
- */
-static ssize_t
-omap_mbox_write(struct device *dev, struct device_attribute *attr,
- const char * buf, size_t count)
-{
- int ret;
- mbox_msg_t *p = (mbox_msg_t *)buf;
- struct omap_mbox *mbox = dev_get_drvdata(dev);
-
- for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) {
- ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL);
- if (ret)
- return -EAGAIN;
- p++;
- }
-
- return (size_t)((char *)p - buf);
-}
-
-static ssize_t
-omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
-{
- unsigned long flags;
- struct request *rq;
- mbox_msg_t *p = (mbox_msg_t *) buf;
- struct omap_mbox *mbox = dev_get_drvdata(dev);
- struct request_queue *q = mbox->rxq->queue;
-
- while (1) {
- spin_lock_irqsave(q->queue_lock, flags);
- rq = blk_fetch_request(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- if (!rq)
- break;
-
- *p = (mbox_msg_t)rq->special;
-
- blk_end_request_all(rq, 0);
-
- if (unlikely(mbox_seq_test(mbox, *p))) {
- pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
- continue;
- }
- p++;
- }
-
- pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
-
- return (size_t) ((char *)p - buf);
-}
-
-static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write);
-
-static ssize_t mbox_show(struct class *class, char *buf)
-{
- return sprintf(buf, "mbox");
-}
-
-static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
-
-static struct class omap_mbox_class = {
- .name = "omap-mailbox",
-};
-
static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
- request_fn_proc * proc,
+ request_fn_proc *proc,
void (*work) (struct work_struct *))
{
struct request_queue *q;
@@ -415,7 +262,7 @@ static void mbox_queue_free(struct omap_mbox_queue *q)
kfree(q);
}
-static int omap_mbox_init(struct omap_mbox *mbox)
+static int omap_mbox_startup(struct omap_mbox *mbox)
{
int ret;
struct omap_mbox_queue *mq;
@@ -426,7 +273,7 @@ static int omap_mbox_init(struct omap_mbox *mbox)
return ret;
}
- ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
+ ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
mbox->name, mbox);
if (unlikely(ret)) {
printk(KERN_ERR
@@ -498,7 +345,7 @@ struct omap_mbox *omap_mbox_get(const char *name)
read_unlock(&mboxes_lock);
- ret = omap_mbox_init(mbox);
+ ret = omap_mbox_startup(mbox);
if (ret)
return ERR_PTR(-ENODEV);
@@ -522,15 +369,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
if (mbox->next)
return -EBUSY;
- mbox->dev = device_create(&omap_mbox_class,
- parent, 0, mbox, "%s", mbox->name);
- if (IS_ERR(mbox->dev))
- return PTR_ERR(mbox->dev);
-
- ret = device_create_file(mbox->dev, &dev_attr_mbox);
- if (ret)
- goto err_sysfs;
-
write_lock(&mboxes_lock);
tmp = find_mboxes(mbox->name);
if (*tmp) {
@@ -544,9 +382,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
return 0;
err_find:
- device_remove_file(mbox->dev, &dev_attr_mbox);
-err_sysfs:
- device_unregister(mbox->dev);
return ret;
}
EXPORT_SYMBOL(omap_mbox_register);
@@ -562,8 +397,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
*tmp = mbox->next;
mbox->next = NULL;
write_unlock(&mboxes_lock);
- device_remove_file(mbox->dev, &dev_attr_mbox);
- device_unregister(mbox->dev);
return 0;
}
tmp = &(*tmp)->next;
@@ -574,23 +407,16 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
}
EXPORT_SYMBOL(omap_mbox_unregister);
-static int __init omap_mbox_class_init(void)
+static int __init omap_mbox_init(void)
{
- int ret = class_register(&omap_mbox_class);
- if (!ret)
- ret = class_create_file(&omap_mbox_class, &class_attr_mbox);
-
- return ret;
+ return 0;
}
+module_init(omap_mbox_init);
-static void __exit omap_mbox_class_exit(void)
+static void __exit omap_mbox_exit(void)
{
- class_remove_file(&omap_mbox_class, &class_attr_mbox);
- class_unregister(&omap_mbox_class);
}
-
-subsys_initcall(omap_mbox_class_init);
-module_exit(omap_mbox_class_exit);
+module_exit(omap_mbox_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index efa0e0111f38..39e594f05dfe 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -934,21 +934,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
mcbsp->rx_irq = pdata->rx_irq;
mcbsp->dma_rx_sync = pdata->dma_rx_sync;
mcbsp->dma_tx_sync = pdata->dma_tx_sync;
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx()) {
+ mcbsp->iclk = clk_get(&pdev->dev, "ick");
+ if (IS_ERR(mcbsp->iclk)) {
+ ret = PTR_ERR(mcbsp->iclk);
+ dev_err(&pdev->dev, "unable to get ick: %d\n", ret);
+ goto err_iclk;
+ }
- mcbsp->iclk = clk_get(&pdev->dev, "ick");
- if (IS_ERR(mcbsp->iclk)) {
- ret = PTR_ERR(mcbsp->iclk);
- dev_err(&pdev->dev, "unable to get ick: %d\n", ret);
- goto err_iclk;
- }
-
- mcbsp->fclk = clk_get(&pdev->dev, "fck");
- if (IS_ERR(mcbsp->fclk)) {
- ret = PTR_ERR(mcbsp->fclk);
- dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
- goto err_fclk;
+ mcbsp->fclk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(mcbsp->fclk)) {
+ ret = PTR_ERR(mcbsp->fclk);
+ dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
+ goto err_fclk;
+ }
}
-
mcbsp->pdata = pdata;
mcbsp->dev = &pdev->dev;
mcbsp_ptr[id] = mcbsp;
diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c
index 8d329fb20740..80b040fd5ca7 100644
--- a/arch/arm/plat-omap/mux.c
+++ b/arch/arm/plat-omap/mux.c
@@ -54,9 +54,6 @@ int __init_or_module omap_cfg_reg(const unsigned long index)
{
struct pin_config *reg;
- if (cpu_is_omap44xx())
- return 0;
-
if (mux_cfg == NULL) {
printk(KERN_ERR "Pin mux table not initialized\n");
return -ENODEV;
diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
new file mode 100644
index 000000000000..68ae16ff7963
--- /dev/null
+++ b/arch/arm/plat-omap/vram.c
@@ -0,0 +1,632 @@
+/*
+ * linux/arch/arm/plat-omap/vram.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*#define DEBUG*/
+
+#include <linux/vmalloc.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+#include <linux/omapfb.h>
+#include <linux/completion.h>
+#include <linux/debugfs.h>
+
+#include <asm/setup.h>
+
+#include <mach/sram.h>
+#include <mach/vram.h>
+#include <mach/dma.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define OMAP2_SRAM_START 0x40200000
+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
+#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
+
+#define REG_MAP_SIZE(_page_cnt) \
+ ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+#define REG_MAP_PTR(_rg, _page_nr) \
+ (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+#define REG_MAP_MASK(_page_nr) \
+ (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+
+/* #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
+
+/* postponed regions are used to temporarily store region information at boot
+ * time when we cannot yet allocate the region list */
+#define MAX_POSTPONED_REGIONS 10
+
+static bool vram_initialized;
+static int postponed_cnt;
+static struct {
+ unsigned long paddr;
+ size_t size;
+} postponed_regions[MAX_POSTPONED_REGIONS];
+
+struct vram_alloc {
+ struct list_head list;
+ unsigned long paddr;
+ unsigned pages;
+};
+
+struct vram_region {
+ struct list_head list;
+ struct list_head alloc_list;
+ unsigned long paddr;
+ unsigned pages;
+};
+
+static DEFINE_MUTEX(region_mutex);
+static LIST_HEAD(region_list);
+
+static inline int region_mem_type(unsigned long paddr)
+{
+ if (paddr >= OMAP2_SRAM_START &&
+ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+ return OMAPFB_MEMTYPE_SRAM;
+ else
+ return OMAPFB_MEMTYPE_SDRAM;
+}
+
+static struct vram_region *omap_vram_create_region(unsigned long paddr,
+ unsigned pages)
+{
+ struct vram_region *rm;
+
+ rm = kzalloc(sizeof(*rm), GFP_KERNEL);
+
+ if (rm) {
+ INIT_LIST_HEAD(&rm->alloc_list);
+ rm->paddr = paddr;
+ rm->pages = pages;
+ }
+
+ return rm;
+}
+
+#if 0
+static void omap_vram_free_region(struct vram_region *vr)
+{
+ list_del(&vr->list);
+ kfree(vr);
+}
+#endif
+
+static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
+ unsigned long paddr, unsigned pages)
+{
+ struct vram_alloc *va;
+ struct vram_alloc *new;
+
+ new = kzalloc(sizeof(*va), GFP_KERNEL);
+
+ if (!new)
+ return NULL;
+
+ new->paddr = paddr;
+ new->pages = pages;
+
+ list_for_each_entry(va, &vr->alloc_list, list) {
+ if (va->paddr > new->paddr)
+ break;
+ }
+
+ list_add_tail(&new->list, &va->list);
+
+ return new;
+}
+
+static void omap_vram_free_allocation(struct vram_alloc *va)
+{
+ list_del(&va->list);
+ kfree(va);
+}
+
+int omap_vram_add_region(unsigned long paddr, size_t size)
+{
+ struct vram_region *rm;
+ unsigned pages;
+
+ if (vram_initialized) {
+ DBG("adding region paddr %08lx size %d\n",
+ paddr, size);
+
+ size &= PAGE_MASK;
+ pages = size >> PAGE_SHIFT;
+
+ rm = omap_vram_create_region(paddr, pages);
+ if (rm == NULL)
+ return -ENOMEM;
+
+ list_add(&rm->list, &region_list);
+ } else {
+ if (postponed_cnt == MAX_POSTPONED_REGIONS)
+ return -ENOMEM;
+
+ postponed_regions[postponed_cnt].paddr = paddr;
+ postponed_regions[postponed_cnt].size = size;
+
+ ++postponed_cnt;
+ }
+ return 0;
+}
+
+int omap_vram_free(unsigned long paddr, size_t size)
+{
+ struct vram_region *rm;
+ struct vram_alloc *alloc;
+ unsigned start, end;
+
+ DBG("free mem paddr %08lx size %d\n", paddr, size);
+
+ size = PAGE_ALIGN(size);
+
+ mutex_lock(&region_mutex);
+
+ list_for_each_entry(rm, &region_list, list) {
+ list_for_each_entry(alloc, &rm->alloc_list, list) {
+ start = alloc->paddr;
+ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
+
+ if (start >= paddr && end < paddr + size)
+ goto found;
+ }
+ }
+
+ mutex_unlock(&region_mutex);
+ return -EINVAL;
+
+found:
+ omap_vram_free_allocation(alloc);
+
+ mutex_unlock(&region_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(omap_vram_free);
+
+static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
+{
+ struct vram_region *rm;
+ struct vram_alloc *alloc;
+ size_t size;
+
+ size = pages << PAGE_SHIFT;
+
+ list_for_each_entry(rm, &region_list, list) {
+ unsigned long start, end;
+
+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
+
+ if (region_mem_type(rm->paddr) != region_mem_type(paddr))
+ continue;
+
+ start = rm->paddr;
+ end = start + (rm->pages << PAGE_SHIFT) - 1;
+ if (start > paddr || end < paddr + size - 1)
+ continue;
+
+ DBG("block ok, checking allocs\n");
+
+ list_for_each_entry(alloc, &rm->alloc_list, list) {
+ end = alloc->paddr - 1;
+
+ if (start <= paddr && end >= paddr + size - 1)
+ goto found;
+
+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
+ }
+
+ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
+
+ if (!(start <= paddr && end >= paddr + size - 1))
+ continue;
+found:
+ DBG("FOUND area start %lx, end %lx\n", start, end);
+
+ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ return -ENOMEM;
+}
+
+int omap_vram_reserve(unsigned long paddr, size_t size)
+{
+ unsigned pages;
+ int r;
+
+ DBG("reserve mem paddr %08lx size %d\n", paddr, size);
+
+ size = PAGE_ALIGN(size);
+ pages = size >> PAGE_SHIFT;
+
+ mutex_lock(&region_mutex);
+
+ r = _omap_vram_reserve(paddr, pages);
+
+ mutex_unlock(&region_mutex);
+
+ return r;
+}
+EXPORT_SYMBOL(omap_vram_reserve);
+
+static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
+{
+ struct completion *compl = data;
+ complete(compl);
+}
+
+static int _omap_vram_clear(u32 paddr, unsigned pages)
+{
+ struct completion compl;
+ unsigned elem_count;
+ unsigned frame_count;
+ int r;
+ int lch;
+
+ init_completion(&compl);
+
+ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
+ _omap_vram_dma_cb,
+ &compl, &lch);
+ if (r) {
+ pr_err("VRAM: request_dma failed for memory clear\n");
+ return -EBUSY;
+ }
+
+ elem_count = pages * PAGE_SIZE / 4;
+ frame_count = 1;
+
+ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
+ elem_count, frame_count,
+ OMAP_DMA_SYNC_ELEMENT,
+ 0, 0);
+
+ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
+ paddr, 0, 0);
+
+ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
+
+ omap_start_dma(lch);
+
+ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
+ omap_stop_dma(lch);
+ pr_err("VRAM: dma timeout while clearing memory\n");
+ r = -EIO;
+ goto err;
+ }
+
+ r = 0;
+err:
+ omap_free_dma(lch);
+
+ return r;
+}
+
+static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
+{
+ struct vram_region *rm;
+ struct vram_alloc *alloc;
+
+ list_for_each_entry(rm, &region_list, list) {
+ unsigned long start, end;
+
+ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
+
+ if (region_mem_type(rm->paddr) != mtype)
+ continue;
+
+ start = rm->paddr;
+
+ list_for_each_entry(alloc, &rm->alloc_list, list) {
+ end = alloc->paddr;
+
+ if (end - start >= pages << PAGE_SHIFT)
+ goto found;
+
+ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
+ }
+
+ end = rm->paddr + (rm->pages << PAGE_SHIFT);
+found:
+ if (end - start < pages << PAGE_SHIFT)
+ continue;
+
+ DBG("FOUND %lx, end %lx\n", start, end);
+
+ alloc = omap_vram_create_allocation(rm, start, pages);
+ if (alloc == NULL)
+ return -ENOMEM;
+
+ *paddr = start;
+
+ _omap_vram_clear(start, pages);
+
+ return 0;
+ }
+
+ return -ENOMEM;
+}
+
+int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
+{
+ unsigned pages;
+ int r;
+
+ BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
+
+ DBG("alloc mem type %d size %d\n", mtype, size);
+
+ size = PAGE_ALIGN(size);
+ pages = size >> PAGE_SHIFT;
+
+ mutex_lock(&region_mutex);
+
+ r = _omap_vram_alloc(mtype, pages, paddr);
+
+ mutex_unlock(&region_mutex);
+
+ return r;
+}
+EXPORT_SYMBOL(omap_vram_alloc);
+
+#if defined(CONFIG_DEBUG_FS)
+static int vram_debug_show(struct seq_file *s, void *unused)
+{
+ struct vram_region *vr;
+ struct vram_alloc *va;
+ unsigned size;
+
+ mutex_lock(&region_mutex);
+
+ list_for_each_entry(vr, &region_list, list) {
+ size = vr->pages << PAGE_SHIFT;
+ seq_printf(s, "%08lx-%08lx (%d bytes)\n",
+ vr->paddr, vr->paddr + size - 1,
+ size);
+
+ list_for_each_entry(va, &vr->alloc_list, list) {
+ size = va->pages << PAGE_SHIFT;
+ seq_printf(s, " %08lx-%08lx (%d bytes)\n",
+ va->paddr, va->paddr + size - 1,
+ size);
+ }
+ }
+
+ mutex_unlock(&region_mutex);
+
+ return 0;
+}
+
+static int vram_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, vram_debug_show, inode->i_private);
+}
+
+static const struct file_operations vram_debug_fops = {
+ .open = vram_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init omap_vram_create_debugfs(void)
+{
+ struct dentry *d;
+
+ d = debugfs_create_file("vram", S_IRUGO, NULL,
+ NULL, &vram_debug_fops);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+
+ return 0;
+}
+#endif
+
+static __init int omap_vram_init(void)
+{
+ int i;
+
+ vram_initialized = 1;
+
+ for (i = 0; i < postponed_cnt; i++)
+ omap_vram_add_region(postponed_regions[i].paddr,
+ postponed_regions[i].size);
+
+#ifdef CONFIG_DEBUG_FS
+ if (omap_vram_create_debugfs())
+ pr_err("VRAM: Failed to create debugfs file\n");
+#endif
+
+ return 0;
+}
+
+arch_initcall(omap_vram_init);
+
+/* boottime vram alloc stuff */
+
+/* set from board file */
+static u32 omapfb_sram_vram_start __initdata;
+static u32 omapfb_sram_vram_size __initdata;
+
+/* set from board file */
+static u32 omapfb_sdram_vram_start __initdata;
+static u32 omapfb_sdram_vram_size __initdata;
+
+/* set from kernel cmdline */
+static u32 omapfb_def_sdram_vram_size __initdata;
+static u32 omapfb_def_sdram_vram_start __initdata;
+
+static void __init omapfb_early_vram(char **p)
+{
+ omapfb_def_sdram_vram_size = memparse(*p, p);
+ if (**p == ',')
+ omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
+}
+__early_param("vram=", omapfb_early_vram);
+
+/*
+ * Called from map_io. We need to call to this early enough so that we
+ * can reserve the fixed SDRAM regions before VM could get hold of them.
+ */
+void __init omapfb_reserve_sdram(void)
+{
+ struct bootmem_data *bdata;
+ unsigned long sdram_start, sdram_size;
+ u32 paddr;
+ u32 size = 0;
+
+ /* cmdline arg overrides the board file definition */
+ if (omapfb_def_sdram_vram_size) {
+ size = omapfb_def_sdram_vram_size;
+ paddr = omapfb_def_sdram_vram_start;
+ }
+
+ if (!size) {
+ size = omapfb_sdram_vram_size;
+ paddr = omapfb_sdram_vram_start;
+ }
+
+#ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
+ if (!size) {
+ size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024;
+ paddr = 0;
+ }
+#endif
+
+ if (!size)
+ return;
+
+ size = PAGE_ALIGN(size);
+
+ bdata = NODE_DATA(0)->bdata;
+ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
+ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
+
+ if (paddr) {
+ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
+ paddr + size > sdram_start + sdram_size) {
+ printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
+ return;
+ }
+
+ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
+ pr_err("FB: failed to reserve VRAM\n");
+ return;
+ }
+ } else {
+ if (size > sdram_size) {
+ printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
+ return;
+ }
+
+ paddr = virt_to_phys(alloc_bootmem_pages(size));
+ BUG_ON(paddr & ~PAGE_MASK);
+ }
+
+ omap_vram_add_region(paddr, size);
+
+ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
+}
+
+/*
+ * Called at sram init time, before anything is pushed to the SRAM stack.
+ * Because of the stack scheme, we will allocate everything from the
+ * start of the lowest address region to the end of SRAM. This will also
+ * include padding for page alignment and possible holes between regions.
+ *
+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
+ * this point, since the driver built as a module would have problem with
+ * freeing / reallocating the regions.
+ */
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_vstart,
+ unsigned long sram_size,
+ unsigned long pstart_avail,
+ unsigned long size_avail)
+{
+ unsigned long pend_avail;
+ unsigned long reserved;
+ u32 paddr;
+ u32 size;
+
+ paddr = omapfb_sram_vram_start;
+ size = omapfb_sram_vram_size;
+
+ if (!size)
+ return 0;
+
+ reserved = 0;
+ pend_avail = pstart_avail + size_avail;
+
+ if (!paddr) {
+ /* Dynamic allocation */
+ if ((size_avail & PAGE_MASK) < size) {
+ printk(KERN_ERR "Not enough SRAM for VRAM\n");
+ return 0;
+ }
+ size_avail = (size_avail - size) & PAGE_MASK;
+ paddr = pstart_avail + size_avail;
+ }
+
+ if (paddr < sram_pstart ||
+ paddr + size > sram_pstart + sram_size) {
+ printk(KERN_ERR "Illegal SRAM region for VRAM\n");
+ return 0;
+ }
+
+ /* Reserve everything above the start of the region. */
+ if (pend_avail - paddr > reserved)
+ reserved = pend_avail - paddr;
+ size_avail = pend_avail - reserved - pstart_avail;
+
+ omap_vram_add_region(paddr, size);
+
+ if (reserved)
+ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
+
+ return reserved;
+}
+
+void __init omap2_set_sdram_vram(u32 size, u32 start)
+{
+ omapfb_sdram_vram_start = start;
+ omapfb_sdram_vram_size = size;
+}
+
+void __init omap2_set_sram_vram(u32 size, u32 start)
+{
+ omapfb_sram_vram_start = start;
+ omapfb_sram_vram_size = size;
+}
+
+/*#endif */
+
diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
new file mode 100644
index 000000000000..201640ad1301
--- /dev/null
+++ b/arch/arm/plat-omap/vrfb.c
@@ -0,0 +1,282 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+
+#include <mach/io.h>
+#include <mach/vrfb.h>
+/*#define DEBUG*/
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define SMS_ROT_VIRT_BASE(context, rot) \
+ (((context >= 4) ? 0xD0000000 : 0x70000000) \
+ + (0x4000000 * (context)) \
+ + (0x1000000 * (rot)))
+
+#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
+
+#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
+#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
+#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
+#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
+#define SMS_IMAGEHEIGHT_OFFSET 16
+#define SMS_IMAGEWIDTH_OFFSET 0
+#define SMS_PH_OFFSET 8
+#define SMS_PW_OFFSET 4
+#define SMS_PS_OFFSET 0
+
+#define OMAP_SMS_BASE 0x6C000000
+#define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context)
+#define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context)
+
+#define VRFB_NUM_CTXS 12
+/* bitmap of reserved contexts */
+static unsigned long ctx_map;
+/* bitmap of contexts for which we have to keep the HW context valid */
+static unsigned long ctx_map_active;
+
+static DEFINE_MUTEX(ctx_lock);
+
+/*
+ * Access to this happens from client drivers or the PM core after wake-up.
+ * For the first case we require locking at the driver level, for the second
+ * we don't need locking, since no drivers will run until after the wake-up
+ * has finished.
+ */
+static struct {
+ u32 physical_ba;
+ u32 control;
+ u32 size;
+} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static inline void restore_hw_context(int ctx)
+{
+ omap_writel(vrfb_hw_context[ctx].control, SMS_ROT_CONTROL(ctx));
+ omap_writel(vrfb_hw_context[ctx].size, SMS_ROT_SIZE(ctx));
+ omap_writel(vrfb_hw_context[ctx].physical_ba, SMS_ROT_PHYSICAL_BA(ctx));
+}
+
+void omap_vrfb_restore_context(void)
+{
+ int i;
+ unsigned long map = ctx_map_active;
+
+ for (i = ffs(map); i; i = ffs(map)) {
+ /* i=1..32 */
+ i--;
+ map &= ~(1 << i);
+ restore_hw_context(i);
+ }
+}
+
+void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp)
+{
+ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+ *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
+}
+EXPORT_SYMBOL(omap_vrfb_adjust_size);
+
+void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode)
+{
+ unsigned pixel_size_exp;
+ u16 vrfb_width;
+ u16 vrfb_height;
+ u8 ctx = vrfb->context;
+ u8 bytespp;
+ u32 size;
+ u32 control;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+ width, height, color_mode);
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ bytespp = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ bytespp = 3;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ bytespp = 4;
+ break;
+
+ default:
+ BUG();
+ }
+
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width >>= 1;
+
+ if (bytespp == 4)
+ pixel_size_exp = 2;
+ else if (bytespp == 2)
+ pixel_size_exp = 1;
+ else
+ BUG();
+
+ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
+
+ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
+
+ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
+ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
+
+ control = pixel_size_exp << SMS_PS_OFFSET;
+ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
+ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
+
+ vrfb_hw_context[ctx].physical_ba = paddr;
+ vrfb_hw_context[ctx].size = size;
+ vrfb_hw_context[ctx].control = control;
+
+ omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
+ omap_writel(size, SMS_ROT_SIZE(ctx));
+ omap_writel(control, SMS_ROT_CONTROL(ctx));
+
+ DBG("vrfb offset pixels %d, %d\n",
+ vrfb_width - width, vrfb_height - height);
+
+ vrfb->xoffset = vrfb_width - width;
+ vrfb->yoffset = vrfb_height - height;
+ vrfb->bytespp = bytespp;
+}
+EXPORT_SYMBOL(omap_vrfb_setup);
+
+void omap_vrfb_release_ctx(struct vrfb *vrfb)
+{
+ int rot;
+ int ctx = vrfb->context;
+
+ if (ctx == 0xff)
+ return;
+
+ DBG("release ctx %d\n", ctx);
+
+ mutex_lock(&ctx_lock);
+
+ BUG_ON(!(ctx_map & (1 << ctx)));
+
+ clear_bit(ctx, &ctx_map_active);
+ clear_bit(ctx, &ctx_map);
+
+ for (rot = 0; rot < 4; ++rot) {
+ if (vrfb->paddr[rot]) {
+ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
+ vrfb->paddr[rot] = 0;
+ }
+ }
+
+ vrfb->context = 0xff;
+
+ mutex_unlock(&ctx_lock);
+}
+EXPORT_SYMBOL(omap_vrfb_release_ctx);
+
+int omap_vrfb_request_ctx(struct vrfb *vrfb)
+{
+ int rot;
+ u32 paddr;
+ u8 ctx;
+ int r;
+
+ DBG("request ctx\n");
+
+ mutex_lock(&ctx_lock);
+
+ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+ if ((ctx_map & (1 << ctx)) == 0)
+ break;
+
+ if (ctx == VRFB_NUM_CTXS) {
+ printk(KERN_ERR "vrfb: no free contexts\n");
+ r = -EBUSY;
+ goto out;
+ }
+
+ DBG("found free ctx %d\n", ctx);
+
+ set_bit(ctx, &ctx_map);
+ WARN_ON(ctx_map_active & (1 << ctx));
+ set_bit(ctx, &ctx_map_active);
+
+ memset(vrfb, 0, sizeof(*vrfb));
+
+ vrfb->context = ctx;
+
+ for (rot = 0; rot < 4; ++rot) {
+ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
+ printk(KERN_ERR "vrfb: failed to reserve VRFB "
+ "area for ctx %d, rotation %d\n",
+ ctx, rot * 90);
+ omap_vrfb_release_ctx(vrfb);
+ r = -ENOMEM;
+ goto out;
+ }
+
+ vrfb->paddr[rot] = paddr;
+
+ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
+ }
+
+ r = 0;
+out:
+ mutex_unlock(&ctx_lock);
+ return r;
+}
+EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
+{
+ DBG("suspend ctx %d\n", vrfb->context);
+ mutex_lock(&ctx_lock);
+
+ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
+ BUG_ON(!((1 << vrfb->context) & ctx_map_active));
+
+ clear_bit(vrfb->context, &ctx_map_active);
+ mutex_unlock(&ctx_lock);
+}
+EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
+
+void omap_vrfb_resume_ctx(struct vrfb *vrfb)
+{
+ DBG("resume ctx %d\n", vrfb->context);
+ mutex_lock(&ctx_lock);
+
+ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
+ BUG_ON((1 << vrfb->context) & ctx_map_active);
+
+ /*
+ * omap_vrfb_restore_context is normally called by the core domain
+ * save / restore logic, but since this VRFB context was suspended
+ * those calls didn't actually restore the context and now we might
+ * have an invalid context. Do an explicit restore here.
+ */
+ restore_hw_context(vrfb->context);
+ set_bit(vrfb->context, &ctx_map_active);
+ mutex_unlock(&ctx_lock);
+}
+EXPORT_SYMBOL(omap_vrfb_resume_ctx);
+
diff --git a/drivers/Makefile b/drivers/Makefile
index 8a973d6e65a8..210ae0b69142 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -111,3 +111,11 @@ obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
obj-y += ieee802154/
obj-$(CONFIG_DMM_TILER) += media/
+obj-$(CONFIG_MPU_SYSLINK_IPC) += dsp/syslink/multicore_ipc/
+obj-$(CONFIG_MPU_BRIDGE_NOTIFY) += dsp/syslink/omap_notify/
+obj-$(CONFIG_NOTIFY_DISPATCHER) += dsp/syslink/notify_dispatcher/
+obj-$(CONFIG_NOTIFY_TESLA) += dsp/syslink/notify_tesladriver/
+obj-$(CONFIG_NOTIFY_DUCATI) += dsp/syslink/notify_ducatidriver/
+obj-$(CONFIG_SYSLINK_PROC) += dsp/syslink/procmgr/
+obj-$(CONFIG_SYSLINK_PROC4430) += dsp/syslink/procmgr/proc4430/
+obj-$(CONFIG_MPU_BRIDGE) += dsp/bridge/
diff --git a/drivers/dsp/bridge/Kbuild b/drivers/dsp/bridge/Kbuild
new file mode 100644
index 000000000000..992101d83fb1
--- /dev/null
+++ b/drivers/dsp/bridge/Kbuild
@@ -0,0 +1,39 @@
+obj-$(CONFIG_MPU_BRIDGE) += bridgedriver.o
+
+libgen = gen/gb.o gen/gt.o gen/gs.o gen/gh.o gen/_gt_para.o gen/uuidutil.o
+libservices = services/csl.o services/mem.o services/list.o services/dpc.o \
+ services/kfile.o services/sync.o \
+ services/clk.o services/cfg.o services/reg.o \
+ services/regsup.o services/ntfy.o \
+ services/dbg.o services/services.o
+libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \
+ wmd/tiomap3430_pwr.o wmd/tiomap_sm.o wmd/tiomap_io.o \
+ wmd/mmu_fault.o wmd/ue_deh.o
+libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/wcd.o \
+ pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
+librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
+ rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
+ rmgr/nldr.o rmgr/drv_interface.o
+libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o
+libhw = hw/hw_prcm.o hw/hw_dspssC64P.o hw/hw_mmu.o
+
+bridgedriver-objs = $(libgen) $(libservices) $(libwmd) $(libpmgr) $(librmgr) \
+ $(libdload) $(libhw)
+
+# Debug
+ifeq ($(CONFIG_BRIDGE_DEBUG),y)
+ccflags-y += -DGT_TRACE -DDEBUG
+endif
+
+#Machine dependent
+ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
+ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
+ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS -DOMAP44XX -DCONFIG_DISABLE_BRIDGE_PM
+
+#Header files
+ccflags-y += -Idrivers/dsp/bridge/services
+ccflags-y += -Idrivers/dsp/bridge/wmd
+ccflags-y += -Idrivers/dsp/bridge/pmgr
+ccflags-y += -Idrivers/dsp/bridge/rmgr
+ccflags-y += -Idrivers/dsp/bridge/hw
+ccflags-y += -Iarch/arm
diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig
new file mode 100644
index 000000000000..4a0ac79d6852
--- /dev/null
+++ b/drivers/dsp/bridge/Kconfig
@@ -0,0 +1,37 @@
+#
+# DSP Bridge Driver Support
+#
+
+menuconfig MPU_BRIDGE
+ tristate "DSP Bridge driver"
+ depends on MPU_BRIDGE_NOTIFY && NOTIFY_TESLA
+ default m
+ help
+ DSP/BIOS Bridge is designed for platforms that contain a GPP and
+ one or more attached DSPs. The GPP is considered the master or
+ "host" processor, and the attached DSPs are processing resources
+ that can be utilized by applications and drivers running on the GPP.
+
+config BRIDGE_DVFS
+ bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
+ depends on MPU_BRIDGE && OMAP_PM_SRF
+ default n
+ help
+ DVFS allows DSP Bridge to initiate the operating point change to
+ scale the chip voltage and frequency in order to match the
+ performance and power consumption to the current processing
+ requirements.
+
+config BRIDGE_MEMPOOL_SIZE
+ hex "Physical memory pool size (Byte)"
+ depends on MPU_BRIDGE
+ default 0x600000
+ help
+ Allocate specified size of memory at booting time to avoid allocation
+ failure under heavy memory fragmentation after some use time.
+
+config BRIDGE_DEBUG
+ bool "DSP Bridge Debug Support"
+ depends on MPU_BRIDGE
+ help
+ Say Y to enable Bridge debugging capabilities
diff --git a/drivers/dsp/bridge/dynload/cload.c b/drivers/dsp/bridge/dynload/cload.c
new file mode 100644
index 000000000000..271ab81292c4
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/cload.c
@@ -0,0 +1,1854 @@
+/*
+ * cload.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#include "header.h"
+
+#include "module_list.h"
+#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
+
+/*
+ * we use the fact that DOFF section records are shaped just like
+ * LDR_SECTION_INFO to reduce our section storage usage. This macro marks
+ * the places where that assumption is made
+ */
+#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
+
+/*
+ * forward references
+ */
+static void dload_symbols(struct dload_state *dlthis);
+static void dload_data(struct dload_state *dlthis);
+static void allocate_sections(struct dload_state *dlthis);
+static void string_table_free(struct dload_state *dlthis);
+static void symbol_table_free(struct dload_state *dlthis);
+static void section_table_free(struct dload_state *dlthis);
+static void init_module_handle(struct dload_state *dlthis);
+#if BITS_PER_AU > BITS_PER_BYTE
+static char *unpack_name(struct dload_state *dlthis, u32 soffset);
+#endif
+
+static const char CINITNAME[] = { ".cinit" };
+static const char LOADER_DLLVIEW_ROOT[] = { "?DLModules?" };
+
+/*
+ * Error strings
+ */
+static const char E_READSTRM[] = { "Error reading %s from input stream" };
+static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
+static const char E_TGTALLOC[] =
+ { "Target memory allocate failed, section %s size " FMT_UI32 };
+static const char E_INITFAIL[] = { "%s to target address " FMT_UI32 " failed" };
+static const char E_DLVWRITE[] = { "Write to DLLview list failed" };
+static const char E_ICONNECT[] = { "Connect call to init interface failed" };
+static const char E_CHECKSUM[] = { "Checksum failed on %s" };
+
+/*************************************************************************
+ * Procedure dload_error
+ *
+ * Parameters:
+ * errtxt description of the error, printf style
+ * ... additional information
+ *
+ * Effect:
+ * Reports or records the error as appropriate.
+ ************************************************************************/
+void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
+{
+ va_list args;
+
+ va_start(args, errtxt);
+ dlthis->mysym->Error_Report(dlthis->mysym, errtxt, args);
+ va_end(args);
+ dlthis->dload_errcount += 1;
+
+} /* dload_error */
+
+#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
+
+/*************************************************************************
+ * Procedure dload_syms_error
+ *
+ * Parameters:
+ * errtxt description of the error, printf style
+ * ... additional information
+ *
+ * Effect:
+ * Reports or records the error as appropriate.
+ ************************************************************************/
+void dload_syms_error(struct Dynamic_Loader_Sym *syms, const char *errtxt, ...)
+{
+ va_list args;
+
+ va_start(args, errtxt);
+ syms->Error_Report(syms, errtxt, args);
+ va_end(args);
+}
+
+/*************************************************************************
+ * Procedure Dynamic_Load_Module
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ * init Target-side memory initialization
+ * options Option flags DLOAD_*
+ * mhandle A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ * The module image is read using *module. Target storage for the new
+ * image is
+ * obtained from *alloc. Symbols defined and referenced by the module are
+ * managed using *syms. The image is then relocated and references
+ * resolved as necessary, and the resulting executable bits are placed
+ * into target memory using *init.
+ *
+ * Returns:
+ * On a successful load, a module handle is placed in *mhandle,
+ * and zero is returned. On error, the number of errors detected is
+ * returned. Individual errors are reported during the load process
+ * using syms->Error_Report().
+ ***********************************************************************/
+int Dynamic_Load_Module(struct Dynamic_Loader_Stream *module,
+ struct Dynamic_Loader_Sym *syms ,
+ struct Dynamic_Loader_Allocate *alloc,
+ struct Dynamic_Loader_Initialize *init,
+ unsigned options, DLOAD_mhandle *mhandle)
+{
+ register unsigned *dp, sz;
+ struct dload_state dl_state; /* internal state for this call */
+
+ /* blast our internal state */
+ dp = (unsigned *)&dl_state;
+ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
+ *dp++ = 0;
+
+ /* Enable _only_ BSS initialization if enabled by user */
+ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
+ dl_state.myoptions = DLOAD_INITBSS;
+
+ /* Check that mandatory arguments are present */
+ if (!module || !syms) {
+ dload_error(&dl_state, "Required parameter is NULL");
+ } else {
+ dl_state.strm = module;
+ dl_state.mysym = syms;
+ dload_headers(&dl_state);
+ if (!dl_state.dload_errcount)
+ dload_strings(&dl_state, false);
+ if (!dl_state.dload_errcount)
+ dload_sections(&dl_state);
+
+ if (init && !dl_state.dload_errcount) {
+ if (init->connect(init)) {
+ dl_state.myio = init;
+ dl_state.myalloc = alloc;
+ /* do now, before reducing symbols */
+ allocate_sections(&dl_state);
+ } else
+ dload_error(&dl_state, E_ICONNECT);
+ }
+
+ if (!dl_state.dload_errcount) {
+ /* fix up entry point address */
+ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
+ if (sref < dl_state.allocated_secn_count)
+ dl_state.dfile_hdr.df_entrypt +=
+ dl_state.ldr_sections[sref].run_addr;
+
+ dload_symbols(&dl_state);
+ }
+
+ if (init && !dl_state.dload_errcount)
+ dload_data(&dl_state);
+
+ init_module_handle(&dl_state);
+
+ if (dl_state.myio) {
+ if ((!dl_state.dload_errcount) &&
+ (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF)) {
+ if (init != NULL) {
+ if (!init->execute(init,
+ dl_state.dfile_hdr.df_entrypt))
+ dload_error(&dl_state,
+ "Init->Execute Failed");
+ } else {
+ dload_error(&dl_state, "init is NULL");
+ }
+ }
+ init->release(init);
+ }
+
+ symbol_table_free(&dl_state);
+ section_table_free(&dl_state);
+ string_table_free(&dl_state);
+
+ if (dl_state.dload_errcount) {
+ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
+ init);
+ dl_state.myhandle = NULL;
+ }
+ }
+
+ if (mhandle)
+ *mhandle = dl_state.myhandle; /* give back the handle */
+
+ return dl_state.dload_errcount;
+} /* DLOAD_File */
+
+/*************************************************************************
+ * Procedure Dynamic_Open_Module
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ * init Target-side memory initialization
+ * options Option flags DLOAD_*
+ * mhandle A module handle for use with Dynamic_Unload
+ *
+ * Effect:
+ * The module image is read using *module. Target storage for the new
+ * image is
+ * obtained from *alloc. Symbols defined and referenced by the module are
+ * managed using *syms. The image is then relocated and references
+ * resolved as necessary, and the resulting executable bits are placed
+ * into target memory using *init.
+ *
+ * Returns:
+ * On a successful load, a module handle is placed in *mhandle,
+ * and zero is returned. On error, the number of errors detected is
+ * returned. Individual errors are reported during the load process
+ * using syms->Error_Report().
+ ***********************************************************************/
+int
+Dynamic_Open_Module(struct Dynamic_Loader_Stream *module,
+ struct Dynamic_Loader_Sym *syms,
+ struct Dynamic_Loader_Allocate *alloc,
+ struct Dynamic_Loader_Initialize *init,
+ unsigned options, DLOAD_mhandle *mhandle)
+{
+ register unsigned *dp, sz;
+ struct dload_state dl_state; /* internal state for this call */
+
+ /* blast our internal state */
+ dp = (unsigned *)&dl_state;
+ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
+ *dp++ = 0;
+
+ /* Enable _only_ BSS initialization if enabled by user */
+ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
+ dl_state.myoptions = DLOAD_INITBSS;
+
+ /* Check that mandatory arguments are present */
+ if (!module || !syms) {
+ dload_error(&dl_state, "Required parameter is NULL");
+ } else {
+ dl_state.strm = module;
+ dl_state.mysym = syms;
+ dload_headers(&dl_state);
+ if (!dl_state.dload_errcount)
+ dload_strings(&dl_state, false);
+ if (!dl_state.dload_errcount)
+ dload_sections(&dl_state);
+
+ if (init && !dl_state.dload_errcount) {
+ if (init->connect(init)) {
+ dl_state.myio = init;
+ dl_state.myalloc = alloc;
+ /* do now, before reducing symbols */
+ allocate_sections(&dl_state);
+ } else
+ dload_error(&dl_state, E_ICONNECT);
+ }
+
+ if (!dl_state.dload_errcount) {
+ /* fix up entry point address */
+ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
+ if (sref < dl_state.allocated_secn_count)
+ dl_state.dfile_hdr.df_entrypt +=
+ dl_state.ldr_sections[sref].run_addr;
+
+ dload_symbols(&dl_state);
+ }
+
+ init_module_handle(&dl_state);
+
+ if (dl_state.myio) {
+ if ((!dl_state.dload_errcount)
+ && (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF))
+ if (!init->execute(init,
+ dl_state.dfile_hdr.df_entrypt))
+ dload_error(&dl_state,
+ "Init->Execute Failed");
+ init->release(init);
+ }
+
+ symbol_table_free(&dl_state);
+ section_table_free(&dl_state);
+ string_table_free(&dl_state);
+
+ if (dl_state.dload_errcount) {
+ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
+ init);
+ dl_state.myhandle = NULL;
+ }
+ }
+
+ if (mhandle)
+ *mhandle = dl_state.myhandle; /* give back the handle */
+
+ return dl_state.dload_errcount;
+} /* DLOAD_File */
+
+/*************************************************************************
+ * Procedure dload_headers
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Loads the DOFF header and verify record. Deals with any byte-order
+ * issues and checks them for validity.
+ ************************************************************************/
+#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
+ sizeof(struct doff_verify_rec_t))
+
+void dload_headers(struct dload_state *dlthis)
+{
+ u32 map;
+
+ /* Read the header and the verify record as one. If we don't get it
+ all, we're done */
+ if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
+ COMBINED_HEADER_SIZE) != COMBINED_HEADER_SIZE) {
+ DL_ERROR(E_READSTRM, "File Headers");
+ return;
+ }
+ /*
+ * Verify that we have the byte order of the file correct.
+ * If not, must fix it before we can continue
+ */
+ map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
+ if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
+ /* input is either byte-shuffled or bad */
+ if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
+ dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
+ map);
+ }
+ if (dlthis->dfile_hdr.df_byte_reshuffle !=
+ BYTE_RESHUFFLE_VALUE) {
+ /* didn't fix the problem, the byte swap map is bad */
+ dload_error(dlthis,
+ "Bad byte swap map " FMT_UI32 " in header",
+ dlthis->dfile_hdr.df_byte_reshuffle);
+ return;
+ }
+ dlthis->reorder_map = map; /* keep map for future use */
+ }
+
+ /*
+ * Verify checksum of header and verify record
+ */
+ if (~dload_checksum(&dlthis->dfile_hdr,
+ sizeof(struct doff_filehdr_t)) ||
+ ~dload_checksum(&dlthis->verify,
+ sizeof(struct doff_verify_rec_t))) {
+ DL_ERROR(E_CHECKSUM, "header or verify record");
+ return;
+ }
+#if HOST_ENDIANNESS
+ dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
+#endif
+
+ /* Check for valid target ID */
+ if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
+ -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
+ dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
+ dlthis->dfile_hdr.df_target_id, TARGET_ID);
+ return;
+ }
+ /* Check for valid file format */
+ if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
+ dload_error(dlthis, "Bad DOFF version 0x%x",
+ dlthis->dfile_hdr.df_doff_version);
+ return;
+ }
+
+ /*
+ * Apply reasonableness checks to count fields
+ */
+ if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
+ dload_error(dlthis, "Excessive string table size " FMT_UI32,
+ dlthis->dfile_hdr.df_strtab_size);
+ return;
+ }
+ if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
+ dload_error(dlthis, "Excessive section count 0x%x",
+ dlthis->dfile_hdr.df_no_scns);
+ return;
+ }
+#ifndef TARGET_ENDIANNESS
+ /*
+ * Check that endianness does not disagree with explicit specification
+ */
+ if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
+ dlthis->myoptions & ENDIANNESS_MASK) {
+ dload_error(dlthis,
+ "Input endianness disagrees with specified option");
+ return;
+ }
+ dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
+#endif
+
+} /* dload_headers */
+
+/* COFF Section Processing
+ *
+ * COFF sections are read in and retained intact. Each record is embedded
+ * in a new structure that records the updated load and
+ * run addresses of the section */
+
+static const char SECN_ERRID[] = { "section" };
+
+/*************************************************************************
+ * Procedure dload_sections
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Loads the section records into an internal table.
+ ************************************************************************/
+void
+dload_sections(struct dload_state *dlthis)
+{
+ s16 siz;
+ struct doff_scnhdr_t *shp;
+ unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
+
+ /* allocate space for the DOFF section records */
+ siz = nsecs * sizeof(struct doff_scnhdr_t);
+ shp = (struct doff_scnhdr_t *)dlthis->mysym->Allocate(dlthis->mysym,
+ siz);
+ if (!shp) { /* not enough storage */
+ DL_ERROR(E_ALLOC, siz);
+ return;
+ }
+ dlthis->sect_hdrs = shp;
+
+ /* read in the section records */
+ if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
+ DL_ERROR(E_READSTRM, SECN_ERRID);
+ return;
+ }
+
+ /* if we need to fix up byte order, do it now */
+ if (dlthis->reorder_map)
+ dload_reorder(shp, siz, dlthis->reorder_map);
+
+ /* check for validity */
+ if (~dload_checksum(dlthis->sect_hdrs, siz) !=
+ dlthis->verify.dv_scn_rec_checksum) {
+ DL_ERROR(E_CHECKSUM, SECN_ERRID);
+ return;
+ }
+
+} /* dload_sections */
+
+/*****************************************************************************
+ * Procedure allocate_sections
+ *
+ * Parameters:
+ * alloc target memory allocator class
+ *
+ * Effect:
+ * Assigns new (target) addresses for sections
+ *****************************************************************************/
+static void allocate_sections(struct dload_state *dlthis)
+{
+ u16 curr_sect, nsecs, siz;
+ struct doff_scnhdr_t *shp;
+ struct LDR_SECTION_INFO *asecs;
+ struct my_handle *hndl;
+ nsecs = dlthis->dfile_hdr.df_no_scns;
+ if (!nsecs)
+ return;
+ if ((dlthis->myalloc == NULL) &&
+ (dlthis->dfile_hdr.df_target_scns > 0)) {
+ DL_ERROR("Arg 3 (alloc) required but NULL", 0);
+ return;
+ }
+ /* allocate space for the module handle, which we will
+ * keep for unload purposes */
+ siz = dlthis->dfile_hdr.df_target_scns *
+ sizeof(struct LDR_SECTION_INFO) + MY_HANDLE_SIZE;
+ hndl = (struct my_handle *)dlthis->mysym->Allocate(dlthis->mysym, siz);
+ if (!hndl) { /* not enough storage */
+ DL_ERROR(E_ALLOC, siz);
+ return;
+ }
+ /* initialize the handle header */
+ hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
+ hndl->dm.hroot = NULL;
+ hndl->dm.dbthis = 0;
+ dlthis->myhandle = hndl; /* save away for return */
+ /* pointer to the section list of allocated sections */
+ dlthis->ldr_sections = asecs = hndl->secns;
+ /* * Insert names into all sections, make copies of
+ the sections we allocate */
+ shp = dlthis->sect_hdrs;
+ for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
+ u32 soffset = shp->ds_offset;
+#if BITS_PER_AU <= BITS_PER_BYTE
+ /* attempt to insert the name of this section */
+ if (soffset < dlthis->dfile_hdr.df_strtab_size)
+ DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
+ soffset;
+ else {
+ dload_error(dlthis, "Bad name offset in section %d",
+ curr_sect);
+ DOFFSEC_IS_LDRSEC(shp)->name = NULL;
+ }
+#endif
+ /* allocate target storage for sections that require it */
+ if (DS_NEEDS_ALLOCATION(shp)) {
+ *asecs = *DOFFSEC_IS_LDRSEC(shp);
+ asecs->context = 0; /* zero the context field */
+#if BITS_PER_AU > BITS_PER_BYTE
+ asecs->name = unpack_name(dlthis, soffset);
+ dlthis->debug_string_size = soffset + dlthis->temp_len;
+#else
+ dlthis->debug_string_size = soffset;
+#endif
+ if (dlthis->myalloc != NULL) {
+ if (!dlthis->myalloc->Allocate(dlthis->myalloc, asecs,
+ DS_ALIGNMENT(asecs->type))) {
+ dload_error(dlthis, E_TGTALLOC, asecs->name,
+ asecs->size);
+ return;
+ }
+ }
+ /* keep address deltas in original section table */
+ shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
+ shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
+ dlthis->allocated_secn_count += 1;
+ } /* allocate target storage */
+ shp += 1;
+ asecs += 1;
+ }
+#if BITS_PER_AU <= BITS_PER_BYTE
+ dlthis->debug_string_size +=
+ strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
+#endif
+} /* allocate sections */
+
+/*************************************************************************
+ * Procedure section_table_free
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Frees any state used by the symbol table.
+ *
+ * WARNING:
+ * This routine is not allowed to declare errors!
+ ************************************************************************/
+static void section_table_free(struct dload_state *dlthis)
+{
+ struct doff_scnhdr_t *shp;
+
+ shp = dlthis->sect_hdrs;
+ if (shp)
+ dlthis->mysym->Deallocate(dlthis->mysym, shp);
+
+} /* section_table_free */
+
+/*************************************************************************
+ * Procedure dload_strings
+ *
+ * Parameters:
+ * sec_names_only If true only read in the "section names"
+ * portion of the string table
+ *
+ * Effect:
+ * Loads the DOFF string table into memory. DOFF keeps all strings in a
+ * big unsorted array. We just read that array into memory in bulk.
+ ************************************************************************/
+static const char S_STRINGTBL[] = { "string table" };
+void dload_strings(struct dload_state *dlthis, boolean sec_names_only)
+{
+ u32 ssiz;
+ char *strbuf;
+
+ if (sec_names_only) {
+ ssiz = BYTE_TO_HOST(DOFF_ALIGN
+ (dlthis->dfile_hdr.df_scn_name_size));
+ } else {
+ ssiz = BYTE_TO_HOST(DOFF_ALIGN
+ (dlthis->dfile_hdr.df_strtab_size));
+ }
+ if (ssiz == 0)
+ return;
+
+ /* get some memory for the string table */
+#if BITS_PER_AU > BITS_PER_BYTE
+ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz +
+ dlthis->dfile_hdr.df_max_str_len);
+#else
+ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz);
+#endif
+ if (strbuf == NULL) {
+ DL_ERROR(E_ALLOC, ssiz);
+ return;
+ }
+ dlthis->str_head = strbuf;
+#if BITS_PER_AU > BITS_PER_BYTE
+ dlthis->str_temp = strbuf + ssiz;
+#endif
+ /* read in the strings and verify them */
+ if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
+ ssiz)) != ssiz) {
+ DL_ERROR(E_READSTRM, S_STRINGTBL);
+ }
+ /* if we need to fix up byte order, do it now */
+#ifndef _BIG_ENDIAN
+ if (dlthis->reorder_map)
+ dload_reorder(strbuf, ssiz, dlthis->reorder_map);
+
+ if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
+ dlthis->verify.dv_str_tab_checksum)) {
+ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
+ }
+#else
+ if (dlthis->dfile_hdr.df_byte_reshuffle !=
+ HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
+ /* put strings in big-endian order, not in PC order */
+ dload_reorder(strbuf, ssiz, HOST_BYTE_ORDER(dlthis->dfile_hdr.
+ df_byte_reshuffle));
+ }
+ if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
+ dlthis->verify.dv_str_tab_checksum)) {
+ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
+ }
+#endif
+} /* dload_strings */
+
+/*************************************************************************
+ * Procedure string_table_free
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Frees any state used by the string table.
+ *
+ * WARNING:
+ * This routine is not allowed to declare errors!
+ *************************************************************************/
+static void string_table_free(struct dload_state *dlthis)
+{
+ if (dlthis->str_head)
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
+
+} /* string_table_free */
+
+/*
+ * Symbol Table Maintenance Functions
+ *
+ * COFF symbols are read by dload_symbols(), which is called after
+ * sections have been allocated. Symbols which might be used in
+ * relocation (ie, not debug info) are retained in an internal temporary
+ * compressed table (type Local_Symbol). A particular symbol is recovered
+ * by index by calling dload_find_symbol(). dload_find_symbol
+ * reconstructs a more explicit representation (type SLOTVEC) which is
+ * used by reloc.c
+ */
+/* real size of debug header */
+#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
+
+static const char SYM_ERRID[] = { "symbol" };
+
+/**************************************************************************
+ * Procedure dload_symbols
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Reads in symbols and retains ones that might be needed for relocation
+ * purposes.
+ ************************************************************************/
+/* size of symbol buffer no bigger than target data buffer, to limit stack
+ * usage*/
+#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
+ sizeof(struct doff_syment_t))
+
+static void dload_symbols(struct dload_state *dlthis)
+{
+ u32 s_count, siz, dsiz, symbols_left;
+ u32 checks;
+ struct Local_Symbol *sp;
+ struct dynload_symbol *symp;
+ struct dynload_symbol *newsym;
+
+ s_count = dlthis->dfile_hdr.df_no_syms;
+ if (s_count == 0)
+ return;
+
+ /* We keep a local symbol table for all of the symbols in the input.
+ * This table contains only section & value info, as we do not have
+ * to do any name processing for locals. We reuse this storage
+ * as a temporary for .dllview record construction.
+ * Allocate storage for the whole table.*/
+ siz = s_count * sizeof(struct Local_Symbol);
+ dsiz = DBG_HDR_SIZE +
+ (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
+ BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
+ if (dsiz > siz)
+ siz = dsiz; /* larger of symbols and .dllview temp */
+ sp = (struct Local_Symbol *)dlthis->mysym->Allocate(dlthis->mysym, siz);
+ if (!sp) {
+ DL_ERROR(E_ALLOC, siz);
+ return;
+ }
+ dlthis->local_symtab = sp;
+ /* Read the symbols in the input, store them in the table, and post any
+ * globals to the global symbol table. In the process, externals
+ become defined from the global symbol table */
+ checks = dlthis->verify.dv_sym_tab_checksum;
+ symbols_left = s_count;
+ do { /* read all symbols */
+ char *sname;
+ u32 val;
+ s32 delta;
+ struct doff_syment_t *input_sym;
+ unsigned syms_in_buf;
+ struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
+ input_sym = my_sym_buf;
+ syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
+ MY_SYM_BUF_SIZ : symbols_left;
+ siz = syms_in_buf * sizeof(struct doff_syment_t);
+ if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
+ siz) {
+ DL_ERROR(E_READSTRM, SYM_ERRID);
+ return;
+ }
+ if (dlthis->reorder_map)
+ dload_reorder(input_sym, siz, dlthis->reorder_map);
+
+ checks += dload_checksum(input_sym, siz);
+ do { /* process symbols in buffer */
+ symbols_left -= 1;
+ /* attempt to derive the name of this symbol */
+ sname = NULL;
+ if (input_sym->dn_offset > 0) {
+#if BITS_PER_AU <= BITS_PER_BYTE
+ if ((u32) input_sym->dn_offset <
+ dlthis->dfile_hdr.df_strtab_size)
+ sname = dlthis->str_head +
+ BYTE_TO_HOST(input_sym->dn_offset);
+ else
+ dload_error(dlthis,
+ "Bad name offset in symbol %d",
+ symbols_left);
+#else
+ sname = unpack_name(dlthis,
+ input_sym->dn_offset);
+#endif
+ }
+ val = input_sym->dn_value;
+ delta = 0;
+ sp->sclass = input_sym->dn_sclass;
+ sp->secnn = input_sym->dn_scnum;
+ /* if this is an undefined symbol,
+ * define it (or fail) now */
+ if (sp->secnn == DN_UNDEF) {
+ /* pointless for static undefined */
+ if (input_sym->dn_sclass != DN_EXT)
+ goto loop_cont;
+
+ /* try to define symbol from previously
+ * loaded images */
+ symp = dlthis->mysym->Find_Matching_Symbol
+ (dlthis->mysym, sname);
+ if (!symp) {
+ DL_ERROR
+ ("Undefined external symbol %s",
+ sname);
+ goto loop_cont;
+ }
+ val = delta = symp->value;
+ goto loop_cont;
+ }
+ /* symbol defined by this module */
+ if (sp->secnn > 0) { /* symbol references a section */
+ if ((unsigned)sp->secnn <=
+ dlthis->allocated_secn_count) {
+ /* section was allocated */
+ struct doff_scnhdr_t *srefp =
+ &dlthis->sect_hdrs
+ [sp->secnn - 1];
+
+ if (input_sym->dn_sclass ==
+ DN_STATLAB ||
+ input_sym->dn_sclass == DN_EXTLAB){
+ /* load */
+ delta = srefp->ds_vaddr;
+ } else {
+ /* run */
+ delta = srefp->ds_paddr;
+ }
+ val += delta;
+ }
+ goto loop_itr;
+ }
+ /* This symbol is an absolute symbol */
+ if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
+ (sp->sclass == DN_EXTLAB))) {
+ symp = dlthis->mysym->Find_Matching_Symbol
+ (dlthis->mysym, sname);
+ if (!symp)
+ goto loop_itr;
+ /* This absolute symbol is already defined. */
+ if (symp->value == input_sym->dn_value) {
+ /* If symbol values are equal, continue
+ * but don't add to the global symbol
+ * table */
+ sp->value = val;
+ sp->delta = delta;
+ sp += 1;
+ input_sym += 1;
+ continue;
+ } else {
+ /* If symbol values are not equal,
+ * return with redefinition error */
+ DL_ERROR("Absolute symbol %s is "
+ "defined multiple times with "
+ "different values", sname);
+ return;
+ }
+ }
+loop_itr:
+ /* if this is a global symbol, post it to the
+ * global table */
+ if (input_sym->dn_sclass == DN_EXT ||
+ input_sym->dn_sclass == DN_EXTLAB) {
+ /* Keep this global symbol for subsequent
+ * modules. Don't complain on error, to allow
+ * symbol API to suppress global symbols */
+ if (!sname)
+ goto loop_cont;
+
+ newsym = dlthis->mysym->Add_To_Symbol_Table
+ (dlthis->mysym, sname,
+ (unsigned)dlthis->myhandle);
+ if (newsym)
+ newsym->value = val;
+
+ } /* global */
+loop_cont:
+ sp->value = val;
+ sp->delta = delta;
+ sp += 1;
+ input_sym += 1;
+ } while ((syms_in_buf -= 1) > 0); /* process sym in buffer */
+ } while (symbols_left > 0); /* read all symbols */
+ if (~checks)
+ dload_error(dlthis, "Checksum of symbols failed");
+
+} /* dload_symbols */
+
+/*****************************************************************************
+ * Procedure symbol_table_free
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Frees any state used by the symbol table.
+ *
+ * WARNING:
+ * This routine is not allowed to declare errors!
+ *****************************************************************************/
+static void symbol_table_free(struct dload_state *dlthis)
+{
+ if (dlthis->local_symtab) {
+ if (dlthis->dload_errcount) { /* blow off our symbols */
+ dlthis->mysym->Purge_Symbol_Table(dlthis->mysym,
+ (unsigned)dlthis->myhandle);
+ }
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->local_symtab);
+ }
+} /* symbol_table_free */
+
+/* .cinit Processing
+ *
+ * The dynamic loader does .cinit interpretation. cload_cinit()
+ * acts as a special write-to-target function, in that it takes relocated
+ * data from the normal data flow, and interprets it as .cinit actions.
+ * Because the normal data flow does not necessarily process the whole
+ * .cinit section in one buffer, cload_cinit() must be prepared to
+ * interpret the data piecemeal. A state machine is used for this
+ * purpose.
+ */
+
+/* The following are only for use by reloc.c and things it calls */
+static const struct LDR_SECTION_INFO CINIT_INFO_INIT = { CINITNAME, 0, 0,
+ (LDR_ADDR) -1, 0, DLOAD_BSS, 0 };
+
+/*************************************************************************
+ * Procedure cload_cinit
+ *
+ * Parameters:
+ * ipacket Pointer to data packet to be loaded
+ *
+ * Effect:
+ * Interprets the data in the buffer as .cinit data, and performs the
+ * appropriate initializations.
+ ************************************************************************/
+static void cload_cinit(struct dload_state *dlthis,
+ struct image_packet_t *ipacket)
+{
+#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
+ s32 init_count, left;
+#else
+ s16 init_count, left;
+#endif
+ unsigned char *pktp = ipacket->i_bits;
+ unsigned char *pktend = pktp +
+ BYTE_TO_HOST_ROUND(ipacket->i_packet_size);
+ int temp;
+ LDR_ADDR atmp;
+ struct LDR_SECTION_INFO cinit_info;
+
+ /* PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
+ while (true) {
+ left = pktend - pktp;
+ switch (dlthis->cinit_state) {
+ case CI_count: /* count field */
+ if (left < TDATA_TO_HOST(CINIT_COUNT))
+ goto loopexit;
+ temp = dload_unpack(dlthis, (TgtAU_t *)pktp,
+ CINIT_COUNT * TDATA_AU_BITS, 0,
+ ROP_SGN);
+ pktp += TDATA_TO_HOST(CINIT_COUNT);
+ /* negative signifies BSS table, zero means done */
+ if (temp <= 0) {
+ dlthis->cinit_state = CI_done;
+ break;
+ }
+ dlthis->cinit_count = temp;
+ dlthis->cinit_state = CI_address;
+ break;
+#if CINIT_ALIGN < CINIT_ADDRESS
+ case CI_partaddress:
+ pktp -= TDATA_TO_HOST(CINIT_ALIGN);
+ /* back up pointer into space courtesy of caller */
+ *(uint16_t *)pktp = dlthis->cinit_addr;
+ /* stuff in saved bits !! FALL THRU !! */
+#endif
+ case CI_address: /* Address field for a copy packet */
+ if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
+#if CINIT_ALIGN < CINIT_ADDRESS
+ if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
+ /* address broken into halves */
+ dlthis->cinit_addr = *(uint16_t *)pktp;
+ /* remember 1st half */
+ dlthis->cinit_state = CI_partaddress;
+ left = 0;
+ }
+#endif
+ goto loopexit;
+ }
+ atmp = dload_unpack(dlthis, (TgtAU_t *)pktp,
+ CINIT_ADDRESS * TDATA_AU_BITS, 0,
+ ROP_UNS);
+ pktp += TDATA_TO_HOST(CINIT_ADDRESS);
+#if CINIT_PAGE_BITS > 0
+ dlthis->cinit_page = atmp &
+ ((1 << CINIT_PAGE_BITS) - 1);
+ atmp >>= CINIT_PAGE_BITS;
+#else
+ dlthis->cinit_page = CINIT_DEFAULT_PAGE;
+#endif
+ dlthis->cinit_addr = atmp;
+ dlthis->cinit_state = CI_copy;
+ break;
+ case CI_copy: /* copy bits to the target */
+ init_count = HOST_TO_TDATA(left);
+ if (init_count > dlthis->cinit_count)
+ init_count = dlthis->cinit_count;
+ if (init_count == 0)
+ goto loopexit; /* get more bits */
+ cinit_info = CINIT_INFO_INIT;
+ cinit_info.page = dlthis->cinit_page;
+ if (!dlthis->myio->writemem(dlthis->myio, pktp,
+ TDATA_TO_TADDR(dlthis->cinit_addr),
+ &cinit_info,
+ TDATA_TO_HOST(init_count))) {
+ dload_error(dlthis, E_INITFAIL, "write",
+ dlthis->cinit_addr);
+ }
+ dlthis->cinit_count -= init_count;
+ if (dlthis->cinit_count <= 0) {
+ dlthis->cinit_state = CI_count;
+ init_count = (init_count + CINIT_ALIGN - 1) &
+ -CINIT_ALIGN;
+ /* align to next init */
+ }
+ pktp += TDATA_TO_HOST(init_count);
+ dlthis->cinit_addr += init_count;
+ break;
+ case CI_done: /* no more .cinit to do */
+ return;
+ } /* switch (cinit_state) */
+ } /* while */
+
+loopexit:
+ if (left > 0) {
+ dload_error(dlthis, "%d bytes left over in cinit packet", left);
+ dlthis->cinit_state = CI_done; /* left over bytes are bad */
+ }
+} /* cload_cinit */
+
+/* Functions to interface to reloc.c
+ *
+ * reloc.c is the relocation module borrowed from the linker, with
+ * minimal (we hope) changes for our purposes. cload_sect_data() invokes
+ * this module on a section to relocate and load the image data for that
+ * section. The actual read and write actions are supplied by the global
+ * routines below.
+ */
+
+/************************************************************************
+ * Procedure relocate_packet
+ *
+ * Parameters:
+ * ipacket Pointer to an image packet to relocate
+ *
+ * Effect:
+ * Performs the required relocations on the packet. Returns a checksum
+ * of the relocation operations.
+ ************************************************************************/
+#define MY_RELOC_BUF_SIZ 8
+/* careful! exists at the same time as the image buffer*/
+static int relocate_packet(struct dload_state *dlthis,
+ struct image_packet_t *ipacket, u32 *checks)
+{
+ u32 rnum;
+
+ rnum = ipacket->i_num_relocs;
+ do { /* all relocs */
+ unsigned rinbuf;
+ int siz;
+ struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
+ rp = rrec;
+ rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
+ siz = rinbuf * sizeof(struct reloc_record_t);
+ if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
+ DL_ERROR(E_READSTRM, "relocation");
+ return 0;
+ }
+ /* reorder the bytes if need be */
+ if (dlthis->reorder_map)
+ dload_reorder(rp, siz, dlthis->reorder_map);
+
+ *checks += dload_checksum(rp, siz);
+ do {
+ /* perform the relocation operation */
+ dload_relocate(dlthis, (TgtAU_t *) ipacket->i_bits, rp);
+ rp += 1;
+ rnum -= 1;
+ } while ((rinbuf -= 1) > 0);
+ } while (rnum > 0); /* all relocs */
+ return 1;
+} /* dload_read_reloc */
+
+#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
+
+/* VERY dangerous */
+static const char IMAGEPAK[] = { "image packet" };
+
+/*************************************************************************
+ * Procedure dload_data
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Read image data from input file, relocate it, and download it to the
+ * target.
+ ************************************************************************/
+static void dload_data(struct dload_state *dlthis)
+{
+ u16 curr_sect;
+ struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
+ struct LDR_SECTION_INFO *lptr = dlthis->ldr_sections;
+#ifdef OPT_ZERO_COPY_LOADER
+ boolean bZeroCopy = false;
+#endif
+ u8 *pDest;
+
+ struct {
+ struct image_packet_t ipacket;
+ u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
+ } ibuf;
+
+ /* Indicates whether CINIT processing has occurred */
+ boolean cinit_processed = false;
+
+ /* Loop through the sections and load them one at a time.
+ */
+ for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
+ curr_sect += 1) {
+ if (DS_NEEDS_DOWNLOAD(sptr)) {
+ s32 nip;
+ LDR_ADDR image_offset = 0;
+ /* set relocation info for this section */
+ if (curr_sect < dlthis->allocated_secn_count)
+ dlthis->delta_runaddr = sptr->ds_paddr;
+ else {
+ lptr = DOFFSEC_IS_LDRSEC(sptr);
+ dlthis->delta_runaddr = 0;
+ }
+ dlthis->image_secn = lptr;
+#if BITS_PER_AU > BITS_PER_BYTE
+ lptr->name = unpack_name(dlthis, sptr->ds_offset);
+#endif
+ nip = sptr->ds_nipacks;
+ while ((nip -= 1) >= 0) { /* process packets */
+
+ s32 ipsize;
+ u32 checks;
+ /* get the fixed header bits */
+ if (dlthis->strm->read_buffer(dlthis->strm,
+ &ibuf.ipacket, IPH_SIZE) != IPH_SIZE) {
+ DL_ERROR(E_READSTRM, IMAGEPAK);
+ return;
+ }
+ /* reorder the header if need be */
+ if (dlthis->reorder_map) {
+ dload_reorder(&ibuf.ipacket, IPH_SIZE,
+ dlthis->reorder_map);
+ }
+ /* now read the rest of the packet */
+ ipsize =
+ BYTE_TO_HOST(DOFF_ALIGN
+ (ibuf.ipacket.i_packet_size));
+ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
+ DL_ERROR("Bad image packet size %d",
+ ipsize);
+ return;
+ }
+ pDest = ibuf.bufr;
+#ifdef OPT_ZERO_COPY_LOADER
+ bZeroCopy = false;
+ if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
+ dlthis->myio->writemem(dlthis->myio,
+ &pDest, lptr->load_addr +
+ image_offset, lptr, 0);
+ bZeroCopy = (pDest != ibuf.bufr);
+ }
+#endif
+ /* End of determination */
+
+ if (dlthis->strm->read_buffer(dlthis->strm,
+ ibuf.bufr, ipsize) != ipsize) {
+ DL_ERROR(E_READSTRM, IMAGEPAK);
+ return;
+ }
+ ibuf.ipacket.i_bits = pDest;
+
+ /* reorder the bytes if need be */
+#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
+ if (dlthis->reorder_map) {
+ dload_reorder(pDest, ipsize,
+ dlthis->reorder_map);
+ }
+ checks = dload_checksum(pDest, ipsize);
+#else
+ if (dlthis->dfile_hdr.df_byte_reshuffle !=
+ TARGET_ORDER(REORDER_MAP
+ (BYTE_RESHUFFLE_VALUE))) {
+ /* put image bytes in big-endian order,
+ * not PC order */
+ dload_reorder(pDest, ipsize,
+ TARGET_ORDER
+ (dlthis->dfile_hdr.df_byte_reshuffle));
+ }
+#if TARGET_AU_BITS > 8
+ checks = dload_reverse_checksum_16(pDest,
+ ipsize);
+#else
+ checks = dload_reverse_checksum(pDest,
+ ipsize);
+#endif
+#endif
+
+ checks += dload_checksum(&ibuf.ipacket,
+ IPH_SIZE);
+ /* relocate the image bits as needed */
+ if (ibuf.ipacket.i_num_relocs) {
+ dlthis->image_offset = image_offset;
+ if (!relocate_packet(dlthis,
+ &ibuf.ipacket, &checks))
+ return; /* serious error */
+ }
+ if (~checks)
+ DL_ERROR(E_CHECKSUM, IMAGEPAK);
+ /* stuff the result into target memory */
+ if (DLOAD_SECT_TYPE(sptr) == DLOAD_CINIT) {
+ cload_cinit(dlthis, &ibuf.ipacket);
+ cinit_processed = true;
+ } else {
+#ifdef OPT_ZERO_COPY_LOADER
+ if (!bZeroCopy) {
+#endif
+
+ if (!dlthis->myio->writemem
+ (dlthis->myio, ibuf.bufr,
+ lptr->load_addr + image_offset, lptr,
+ BYTE_TO_HOST
+ (ibuf.ipacket.i_packet_size))) {
+ DL_ERROR(
+ "Write to " FMT_UI32 " failed",
+ lptr->load_addr + image_offset);
+ }
+#ifdef OPT_ZERO_COPY_LOADER
+ }
+#endif
+
+ }
+ image_offset +=
+ BYTE_TO_TADDR(ibuf.ipacket.i_packet_size);
+ } /* process packets */
+ /* if this is a BSS section, we may want to fill it */
+ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
+ goto loop_cont;
+
+ if (!(dlthis->myoptions & DLOAD_INITBSS))
+ goto loop_cont;
+
+ if (cinit_processed) {
+ /* Don't clear BSS after load-time
+ * initialization */
+ DL_ERROR
+ ("Zero-initialization at " FMT_UI32 " after "
+ "load-time initialization!", lptr->load_addr);
+ goto loop_cont;
+ }
+ /* fill the .bss area */
+ dlthis->myio->fillmem(dlthis->myio,
+ TADDR_TO_HOST(lptr->load_addr),
+ lptr, TADDR_TO_HOST(lptr->size),
+ dload_fill_bss);
+ goto loop_cont;
+ } /* if DS_DOWNLOAD_MASK */
+ /* If not loading, but BSS, zero initialize */
+ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
+ goto loop_cont;
+
+ if (!(dlthis->myoptions & DLOAD_INITBSS))
+ goto loop_cont;
+
+ if (curr_sect >= dlthis->allocated_secn_count)
+ lptr = DOFFSEC_IS_LDRSEC(sptr);
+
+ if (cinit_processed) {
+ /*Don't clear BSS after load-time initialization */
+ DL_ERROR(
+ "Zero-initialization at " FMT_UI32 " attempted after "
+ "load-time initialization!", lptr->load_addr);
+ goto loop_cont;
+ }
+ /* fill the .bss area */
+ dlthis->myio->fillmem(dlthis->myio,
+ TADDR_TO_HOST(lptr->load_addr), lptr,
+ TADDR_TO_HOST(lptr->size), dload_fill_bss);
+loop_cont:
+ sptr += 1;
+ lptr += 1;
+ } /* load sections */
+} /* dload_data */
+
+/*************************************************************************
+ * Procedure dload_reorder
+ *
+ * Parameters:
+ * data 32-bit aligned pointer to data to be byte-swapped
+ * dsiz size of the data to be reordered in sizeof() units.
+ * map 32-bit map defining how to reorder the data. Value
+ * must be REORDER_MAP() of some permutation
+ * of 0x00 01 02 03
+ *
+ * Effect:
+ * Re-arranges the bytes in each word according to the map specified.
+ *
+ ************************************************************************/
+/* mask for byte shift count */
+#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
+
+void dload_reorder(void *data, int dsiz, unsigned int map)
+{
+ register u32 tmp, tmap, datv;
+ u32 *dp = (u32 *)data;
+
+ map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
+ do {
+ tmp = 0;
+ datv = *dp;
+ tmap = map;
+ do {
+ tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
+ tmap >>= BITS_PER_BYTE;
+ } while (datv >>= BITS_PER_BYTE);
+ *dp++ = tmp;
+ } while ((dsiz -= sizeof(u32)) > 0);
+} /* dload_reorder */
+
+/*************************************************************************
+ * Procedure dload_checksum
+ *
+ * Parameters:
+ * data 32-bit aligned pointer to data to be checksummed
+ * siz size of the data to be checksummed in sizeof() units.
+ *
+ * Effect:
+ * Returns a checksum of the specified block
+ *
+ ************************************************************************/
+u32 dload_checksum(void *data, unsigned siz)
+{
+ u32 sum;
+ u32 *dp;
+ int left;
+
+ sum = 0;
+ dp = (u32 *)data;
+ for (left = siz; left > 0; left -= sizeof(u32))
+ sum += *dp++;
+ return sum;
+} /* dload_checksum */
+
+#if HOST_ENDIANNESS
+/*************************************************************************
+ * Procedure dload_reverse_checksum
+ *
+ * Parameters:
+ * data 32-bit aligned pointer to data to be checksummed
+ * siz size of the data to be checksummed in sizeof() units.
+ *
+ * Effect:
+ * Returns a checksum of the specified block, which is assumed to be bytes
+ * in big-endian order.
+ *
+ * Notes:
+ * In a big-endian host, things like the string table are stored as bytes
+ * in host order. But dllcreate always checksums in little-endian order.
+ * It is most efficient to just handle the difference a word at a time.
+ *
+ ***********************************************************************/
+u32 dload_reverse_checksum(void *data, unsigned siz)
+{
+ u32 sum, temp;
+ u32 *dp;
+ int left;
+
+ sum = 0;
+ dp = (u32 *)data;
+
+ for (left = siz; left > 0; left -= sizeof(u32)) {
+ temp = *dp++;
+ sum += temp << BITS_PER_BYTE * 3;
+ sum += temp >> BITS_PER_BYTE * 3;
+ sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
+ sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
+ }
+
+ return sum;
+} /* dload_reverse_checksum */
+
+#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
+u32 dload_reverse_checksum_16(void *data, unsigned siz)
+{
+ uint_fast32_t sum, temp;
+ u32 *dp;
+ int left;
+
+ sum = 0;
+ dp = (u32 *)data;
+
+ for (left = siz; left > 0; left -= sizeof(u32)) {
+ temp = *dp++;
+ sum += temp << BITS_PER_BYTE * 2;
+ sum += temp >> BITS_PER_BYTE * 2;
+ }
+
+ return sum;
+} /* dload_reverse_checksum_16 */
+#endif
+#endif
+
+/*************************************************************************
+ * Procedure swap_words
+ *
+ * Parameters:
+ * data 32-bit aligned pointer to data to be swapped
+ * siz size of the data to be swapped.
+ * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
+ * 0 => 1 long
+ *
+ * Effect:
+ * Swaps the specified data according to the specified map
+ *
+ ************************************************************************/
+static void swap_words(void *data, unsigned siz, unsigned bitmap)
+{
+ register int i;
+#if TARGET_AU_BITS < 16
+ register u16 *sp;
+#endif
+ register u32 *lp;
+
+ siz /= sizeof(u16);
+
+#if TARGET_AU_BITS < 16
+ /* pass 1: do all the bytes */
+ i = siz;
+ sp = (u16 *) data;
+ do {
+ register u16 tmp;
+ tmp = *sp;
+ *sp++ = SWAP16BY8(tmp);
+ } while ((i -= 1) > 0);
+#endif
+
+#if TARGET_AU_BITS < 32
+ /* pass 2: fixup the 32-bit words */
+ i = siz >> 1;
+ lp = (u32 *) data;
+ do {
+ if ((bitmap & 1) == 0) {
+ register u32 tmp;
+ tmp = *lp;
+ *lp = SWAP32BY16(tmp);
+ }
+ lp += 1;
+ bitmap >>= 1;
+ } while ((i -= 1) > 0);
+#endif
+} /* swap_words */
+
+/*************************************************************************
+ * Procedure copy_tgt_strings
+ *
+ * Parameters:
+ * dstp Destination address. Assumed to be 32-bit aligned
+ * srcp Source address. Assumed to be 32-bit aligned
+ * charcount Number of characters to copy.
+ *
+ * Effect:
+ * Copies strings from the source (which is in usual .dof file order on
+ * the loading processor) to the destination buffer (which should be in proper
+ * target addressable unit order). Makes sure the last string in the
+ * buffer is NULL terminated (for safety).
+ * Returns the first unused destination address.
+ ************************************************************************/
+static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
+{
+ register TgtAU_t *src = (TgtAU_t *)srcp;
+ register TgtAU_t *dst = (TgtAU_t *)dstp;
+ register int cnt = charcount;
+ do {
+#if TARGET_AU_BITS <= BITS_PER_AU
+ /* byte-swapping issues may exist for strings on target */
+ *dst++ = *src++;
+#elif TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)
+ register TgtAU_t tmp;
+ tmp = *src++;
+ *dst++ = SWAP16BY8(tmp); /* right for TARGET_AU_BITS == 16 */
+#else
+ *dst++ = *src++;
+#endif
+ } while ((cnt -= (sizeof(TgtAU_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
+ /*apply force to make sure that the string table has null terminator */
+#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
+ dst[-1] = 0;
+#elif TARGET_BIG_ENDIAN
+ dst[-1] &= ~BYTE_MASK; /* big-endian */
+#else
+ dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1; /* little endian */
+#endif
+ return (char *)dst;
+} /* copy_tgt_strings */
+
+/*************************************************************************
+ * Procedure init_module_handle
+ *
+ * Parameters:
+ * none
+ *
+ * Effect:
+ * Initializes the module handle we use to enable unloading, and installs
+ * the debug information required by the target.
+ *
+ * Notes:
+ * The handle returned from Dynamic_Load_Module needs to encapsulate all the
+ * allocations done for the module, and enable them plus the modules symbols to
+ * be deallocated.
+ *
+ ************************************************************************/
+#ifndef _BIG_ENDIAN
+static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
+ (LDR_ADDR) -1, DBG_LIST_PAGE, DLOAD_DATA, 0 };
+#else
+static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
+ (LDR_ADDR) -1, DLOAD_DATA, DBG_LIST_PAGE, 0 };
+#endif
+static void init_module_handle(struct dload_state *dlthis)
+{
+ struct my_handle *hndl;
+ u16 curr_sect;
+ struct LDR_SECTION_INFO *asecs;
+ struct dll_module *dbmod;
+ struct dll_sect *dbsec;
+ struct dbg_mirror_root *mlist;
+ register char *cp;
+ struct modules_header mhdr;
+ struct LDR_SECTION_INFO dllview_info;
+ struct dynload_symbol *debug_mirror_sym;
+ hndl = dlthis->myhandle;
+ if (!hndl)
+ return; /* must be errors detected, so forget it */
+ hndl->secn_count = dlthis->allocated_secn_count << 1;
+#ifndef TARGET_ENDIANNESS
+ if (dlthis->big_e_target)
+ hndl->secn_count += 1; /* flag for big-endian */
+#endif
+ if (dlthis->dload_errcount)
+ return; /* abandon if errors detected */
+ /* Locate the symbol that names the header for the CCS debug list
+ of modules. If not found, we just don't generate the debug record.
+ If found, we create our modules list. We make sure to create the
+ LOADER_DLLVIEW_ROOT even if there is no relocation info to record,
+ just to try to put both symbols in the same symbol table and
+ module.*/
+ debug_mirror_sym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
+ LOADER_DLLVIEW_ROOT);
+ if (!debug_mirror_sym) {
+ struct dynload_symbol *dlmodsym;
+ struct dbg_mirror_root *mlst;
+
+ /* our root symbol is not yet present;
+ check if we have DLModules defined */
+ dlmodsym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
+ LINKER_MODULES_HEADER);
+ if (!dlmodsym)
+ return; /* no DLModules list so no debug info */
+ /* if we have DLModules defined, construct our header */
+ mlst = (struct dbg_mirror_root *)
+ dlthis->mysym->Allocate(dlthis->mysym,
+ sizeof(struct dbg_mirror_root));
+ if (!mlst) {
+ DL_ERROR(E_ALLOC, sizeof(struct dbg_mirror_root));
+ return;
+ }
+ mlst->hnext = NULL;
+ mlst->changes = 0;
+ mlst->refcount = 0;
+ mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
+ /* add our root symbol */
+ debug_mirror_sym = dlthis->mysym->Add_To_Symbol_Table
+ (dlthis->mysym, LOADER_DLLVIEW_ROOT,
+ (unsigned)dlthis->myhandle);
+ if (!debug_mirror_sym) {
+ /* failed, recover memory */
+ dlthis->mysym->Deallocate(dlthis->mysym, mlst);
+ return;
+ }
+ debug_mirror_sym->value = (u32)mlst;
+ }
+ /* First create the DLLview record and stuff it into the buffer.
+ Then write it to the DSP. Record pertinent locations in our hndl,
+ and add it to the per-processor list of handles with debug info.*/
+#ifndef DEBUG_HEADER_IN_LOADER
+ mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
+ if (!mlist)
+ return;
+#else
+ mlist = (struct dbg_mirror_root *)&debug_list_header;
+#endif
+ hndl->dm.hroot = mlist; /* set pointer to root into our handle */
+ if (!dlthis->allocated_secn_count)
+ return; /* no load addresses to be recorded */
+ /* reuse temporary symbol storage */
+ dbmod = (struct dll_module *) dlthis->local_symtab;
+ /* Create the DLLview record in the memory we retain for our handle*/
+ dbmod->num_sects = dlthis->allocated_secn_count;
+ dbmod->timestamp = dlthis->verify.dv_timdat;
+ dbmod->version = INIT_VERSION;
+ dbmod->verification = VERIFICATION;
+ asecs = dlthis->ldr_sections;
+ dbsec = dbmod->sects;
+ for (curr_sect = dlthis->allocated_secn_count;
+ curr_sect > 0; curr_sect -= 1) {
+ dbsec->sect_load_adr = asecs->load_addr;
+ dbsec->sect_run_adr = asecs->run_addr;
+ dbsec += 1;
+ asecs += 1;
+ }
+ /* now cram in the names */
+ cp = copy_tgt_strings(dbsec, dlthis->str_head,
+ dlthis->debug_string_size);
+
+ /* round off the size of the debug record, and remember same */
+ hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
+ *cp = 0; /* strictly to make our test harness happy */
+ dllview_info = DLLVIEW_INFO_INIT;
+ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
+ /* Initialize memory context to default heap */
+ dllview_info.context = 0;
+ hndl->dm.context = 0;
+ /* fill in next pointer and size */
+ if (mlist->hnext) {
+ dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
+ dbmod->next_module_size = mlist->hnext->dm.dbsiz;
+ } else {
+ dbmod->next_module_size = 0;
+ dbmod->next_module = 0;
+ }
+ /* allocate memory for on-DSP DLLview debug record */
+ if (!dlthis->myalloc)
+ return;
+ if (!dlthis->myalloc->Allocate(dlthis->myalloc, &dllview_info,
+ HOST_TO_TADDR(sizeof(u32)))) {
+ return;
+ }
+ /* Store load address of .dllview section */
+ hndl->dm.dbthis = dllview_info.load_addr;
+ /* Store memory context (segid) in which .dllview section
+ * was allocated */
+ hndl->dm.context = dllview_info.context;
+ mlist->refcount += 1;
+ /* swap bytes in the entire debug record, but not the string table */
+ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
+ swap_words(dbmod, (char *)dbsec - (char *)dbmod,
+ DLL_MODULE_BITMAP);
+ }
+ /* Update the DLLview list on the DSP write new record */
+ if (!dlthis->myio->writemem(dlthis->myio, dbmod,
+ dllview_info.load_addr, &dllview_info,
+ TADDR_TO_HOST(dllview_info.size))) {
+ return;
+ }
+ /* write new header */
+ mhdr.first_module_size = hndl->dm.dbsiz;
+ mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
+ /* swap bytes in the module header, if needed */
+ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
+ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
+ MODULES_HEADER_BITMAP);
+ }
+ dllview_info = DLLVIEW_INFO_INIT;
+ if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
+ &dllview_info, sizeof(struct modules_header) -
+ sizeof(u16))) {
+ return;
+ }
+ /* Add the module handle to this processor's list
+ of handles with debug info */
+ hndl->dm.hnext = mlist->hnext;
+ if (hndl->dm.hnext)
+ hndl->dm.hnext->dm.hprev = hndl;
+ hndl->dm.hprev = (struct my_handle *) mlist;
+ mlist->hnext = hndl; /* insert after root*/
+} /* init_module_handle */
+
+/*************************************************************************
+ * Procedure Dynamic_Unload_Module
+ *
+ * Parameters:
+ * mhandle A module handle from Dynamic_Load_Module
+ * syms Host-side symbol table and malloc/free functions
+ * alloc Target-side memory allocation
+ *
+ * Effect:
+ * The module specified by mhandle is unloaded. Unloading causes all
+ * target memory to be deallocated, all symbols defined by the module to
+ * be purged, and any host-side storage used by the dynamic loader for
+ * this module to be released.
+ *
+ * Returns:
+ * Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->Error_Report().
+ ************************************************************************/
+int Dynamic_Unload_Module(DLOAD_mhandle mhandle,
+ struct Dynamic_Loader_Sym *syms,
+ struct Dynamic_Loader_Allocate *alloc,
+ struct Dynamic_Loader_Initialize *init)
+{
+ s16 curr_sect;
+ struct LDR_SECTION_INFO *asecs;
+ struct my_handle *hndl;
+ struct dbg_mirror_root *root;
+ unsigned errcount = 0;
+ struct LDR_SECTION_INFO dllview_info = DLLVIEW_INFO_INIT;
+ struct modules_header mhdr;
+
+ hndl = (struct my_handle *)mhandle;
+ if (!hndl)
+ return 0; /* if handle is null, nothing to do */
+ /* Clear out the module symbols
+ * Note that if this is the module that defined MODULES_HEADER
+ (the head of the target debug list)
+ * then this operation will blow away that symbol.
+ It will therefore be impossible for subsequent
+ * operations to add entries to this un-referenceable list.*/
+ if (!syms)
+ return 1;
+ syms->Purge_Symbol_Table(syms, (unsigned) hndl);
+ /* Deallocate target memory for sections */
+ asecs = hndl->secns;
+ if (alloc)
+ for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
+ curr_sect -= 1) {
+ asecs->name = NULL;
+ alloc->Deallocate(alloc, asecs++);
+ }
+ root = hndl->dm.hroot;
+ if (!root) {
+ /* there is a debug list containing this module */
+ goto func_end;
+ }
+ if (!hndl->dm.dbthis) { /* target-side dllview record exists */
+ goto loop_end;
+ }
+ /* Retrieve memory context in which .dllview was allocated */
+ dllview_info.context = hndl->dm.context;
+ if (hndl->dm.hprev == hndl)
+ goto exitunltgt;
+
+ /* target-side dllview record is in list */
+ /* dequeue this record from our GPP-side mirror list */
+ hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
+ if (hndl->dm.hnext)
+ hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
+ /* Update next_module of previous entry in target list
+ * We are using mhdr here as a surrogate for either a
+ struct modules_header or a dll_module */
+ if (hndl->dm.hnext) {
+ mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
+ mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
+ } else {
+ mhdr.first_module = 0;
+ mhdr.first_module_size = 0;
+ }
+ if (!init)
+ goto exitunltgt;
+
+ if (!init->connect(init)) {
+ dload_syms_error(syms, E_ICONNECT);
+ errcount += 1;
+ goto exitunltgt;
+ }
+ /* swap bytes in the module header, if needed */
+ if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
+ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
+ MODULES_HEADER_BITMAP);
+ }
+ if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
+ &dllview_info, sizeof(struct modules_header) -
+ sizeof(mhdr.update_flag))) {
+ dload_syms_error(syms, E_DLVWRITE);
+ errcount += 1;
+ }
+ /* update change counter */
+ root->changes += 1;
+ if (!init->writemem(init, &(root->changes),
+ root->dbthis + HOST_TO_TADDR
+ (sizeof(mhdr.first_module) +
+ sizeof(mhdr.first_module_size)),
+ &dllview_info,
+ sizeof(mhdr.update_flag))) {
+ dload_syms_error(syms, E_DLVWRITE);
+ errcount += 1;
+ }
+ init->release(init);
+exitunltgt:
+ /* release target storage */
+ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
+ dllview_info.load_addr = hndl->dm.dbthis;
+ if (alloc)
+ alloc->Deallocate(alloc, &dllview_info);
+ root->refcount -= 1;
+ /* target-side dllview record exists */
+loop_end:
+#ifndef DEBUG_HEADER_IN_LOADER
+ if (root->refcount <= 0) {
+ /* if all references gone, blow off the header */
+ /* our root symbol may be gone due to the Purge above,
+ but if not, do not destroy the root */
+ if (syms->Find_Matching_Symbol
+ (syms, LOADER_DLLVIEW_ROOT) == NULL)
+ syms->Deallocate(syms, root);
+ }
+#endif
+func_end:
+ /* there is a debug list containing this module */
+ syms->Deallocate(syms, mhandle); /* release our storage */
+ return errcount;
+} /* Dynamic_Unload_Module */
+
+#if BITS_PER_AU > BITS_PER_BYTE
+/*************************************************************************
+ * Procedure unpack_name
+ *
+ * Parameters:
+ * soffset Byte offset into the string table
+ *
+ * Effect:
+ * Returns a pointer to the string specified by the offset supplied, or
+ * NULL for error.
+ *
+ ************************************************************************/
+static char *unpack_name(struct dload_state *dlthis, u32 soffset)
+{
+ u8 tmp, *src;
+ char *dst;
+
+ if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
+ dload_error(dlthis, "Bad string table offset " FMT_UI32,
+ soffset);
+ return NULL;
+ }
+ src = (uint_least8_t *)dlthis->str_head +
+ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
+ dst = dlthis->str_temp;
+ if (soffset & 1)
+ *dst++ = *src++; /* only 1 character in first word */
+ do {
+ tmp = *src++;
+ *dst = (tmp >> BITS_PER_BYTE);
+ if (!(*dst++))
+ break;
+ } while ((*dst++ = tmp & BYTE_MASK));
+ dlthis->temp_len = dst - dlthis->str_temp;
+ /* squirrel away length including terminating null */
+ return dlthis->str_temp;
+} /* unpack_name */
+#endif
diff --git a/drivers/dsp/bridge/dynload/dlclasses_hdr.h b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
new file mode 100644
index 000000000000..04f136e76ad5
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
@@ -0,0 +1,41 @@
+/*
+ * dlclasses_hdr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#ifndef _DLCLASSES_HDR_H
+#define _DLCLASSES_HDR_H
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * DLCLASSES_HDR.H
+ *
+ * Sample classes in support of the dynamic loader
+ *
+ * These are just concrete derivations of the virtual ones in dynamic_loader.h
+ * with a few additional interfaces for init, etc.
+ *****************************************************************************
+ *****************************************************************************/
+
+#include <dspbridge/dynamic_loader.h>
+
+#include "DLstream.h"
+#include "DLsymtab.h"
+#include "DLalloc.h"
+#include "DLinit.h"
+
+#endif /* _DLCLASSES_HDR_H */
diff --git a/drivers/dsp/bridge/dynload/dload_internal.h b/drivers/dsp/bridge/dynload/dload_internal.h
new file mode 100644
index 000000000000..78f50586d7ab
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/dload_internal.h
@@ -0,0 +1,237 @@
+/*
+ * dload_internal.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#ifndef __DLOAD_INTERNAL__
+#define __DLOAD_INTERNAL__
+
+#include <linux/types.h>
+
+/*
+ * Internal state definitions for the dynamic loader
+ */
+
+#define TRUE 1
+#define FALSE 0
+typedef int boolean;
+
+
+/* type used for relocation intermediate results */
+typedef s32 RVALUE;
+
+/* unsigned version of same; must have at least as many bits */
+typedef u32 URVALUE;
+
+/*
+ * Dynamic loader configuration constants
+ */
+/* error issued if input has more sections than this limit */
+#define REASONABLE_SECTION_LIMIT 100
+
+/* (Addressable unit) value used to clear BSS section */
+#define dload_fill_bss 0
+
+/*
+ * Reorder maps explained (?)
+ *
+ * The doff file format defines a 32-bit pattern used to determine the
+ * byte order of an image being read. That value is
+ * BYTE_RESHUFFLE_VALUE == 0x00010203
+ * For purposes of the reorder routine, we would rather have the all-is-OK
+ * for 32-bits pattern be 0x03020100. This first macro makes the
+ * translation from doff file header value to MAP value: */
+#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
+/* This translation is made in dload_headers. Thereafter, the all-is-OK
+ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
+ * But sadly, not all bits of the doff file are 32-bit integers.
+ * The notable exceptions are strings and image bits.
+ * Strings obey host byte order: */
+#if defined(_BIG_ENDIAN)
+#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
+#else
+#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
+#endif
+/* Target bits consist of target AUs (could be bytes, or 16-bits,
+ * or 32-bits) stored as an array in host order. A target order
+ * map is defined by: */
+#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
+#define TARGET_ORDER(cookedmap) (cookedmap)
+#elif TARGET_AU_BITS > 8
+#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
+#else
+#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
+#endif
+
+/* forward declaration for handle returned by dynamic loader */
+struct my_handle;
+
+/*
+ * a list of module handles, which mirrors the debug list on the target
+ */
+struct dbg_mirror_root {
+ /* must be same as dbg_mirror_list; __DLModules address on target */
+ u32 dbthis;
+ struct my_handle *hnext; /* must be same as dbg_mirror_list */
+ u16 changes; /* change counter */
+ u16 refcount; /* number of modules referencing this root */
+} ;
+
+struct dbg_mirror_list {
+ u32 dbthis;
+ struct my_handle *hnext, *hprev;
+ struct dbg_mirror_root *hroot;
+ u16 dbsiz;
+ u32 context; /* Save context for .dllview memory allocation */
+} ;
+
+#define VARIABLE_SIZE 1
+/*
+ * the structure we actually return as an opaque module handle
+ */
+struct my_handle {
+ struct dbg_mirror_list dm; /* !!! must be first !!! */
+ /* sections following << 1, LSB is set for big-endian target */
+ u16 secn_count;
+ struct LDR_SECTION_INFO secns[VARIABLE_SIZE];
+} ;
+#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
+ sizeof(struct LDR_SECTION_INFO))
+/* real size of my_handle */
+
+/*
+ * reduced symbol structure used for symbols during relocation
+ */
+struct Local_Symbol {
+ s32 value; /* Relocated symbol value */
+ s32 delta; /* Original value in input file */
+ s16 secnn; /* section number */
+ s16 sclass; /* symbol class */
+} ;
+
+/*
+ * States of the .cinit state machine
+ */
+enum cinit_mode {
+ CI_count = 0, /* expecting a count */
+ CI_address, /* expecting an address */
+#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
+ CI_partaddress, /* have only part of the address */
+#endif
+ CI_copy, /* in the middle of copying data */
+ CI_done /* end of .cinit table */
+};
+
+/*
+ * The internal state of the dynamic loader, which is passed around as
+ * an object
+ */
+struct dload_state {
+ struct Dynamic_Loader_Stream *strm; /* The module input stream */
+ struct Dynamic_Loader_Sym *mysym; /* Symbols for this session */
+ struct Dynamic_Loader_Allocate *myalloc; /* target memory allocator */
+ struct Dynamic_Loader_Initialize *myio; /* target memory initializer */
+ unsigned myoptions; /* Options parameter Dynamic_Load_Module */
+
+ char *str_head; /* Pointer to string table */
+#if BITS_PER_AU > BITS_PER_BYTE
+ char *str_temp; /* Pointer to temporary buffer for strings */
+ /* big enough to hold longest string */
+ unsigned temp_len; /* length of last temporary string */
+ char *xstrings; /* Pointer to buffer for expanded */
+ /* strings for sec names */
+#endif
+ /* Total size of strings for DLLView section names */
+ unsigned debug_string_size;
+ /* Pointer to parallel section info for allocated sections only */
+ struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
+ struct LDR_SECTION_INFO *ldr_sections;
+#if TMS32060
+ /* The address of the start of the .bss section */
+ LDR_ADDR bss_run_base;
+#endif
+ struct Local_Symbol *local_symtab; /* Relocation symbol table */
+
+ /* pointer to DL section info for the section being relocated */
+ struct LDR_SECTION_INFO *image_secn;
+ /* change in run address for current section during relocation */
+ LDR_ADDR delta_runaddr;
+ LDR_ADDR image_offset; /* offset of current packet in section */
+ enum cinit_mode cinit_state; /* current state of cload_cinit() */
+ int cinit_count; /* the current count */
+ LDR_ADDR cinit_addr; /* the current address */
+ s16 cinit_page; /* the current page */
+ /* Handle to be returned by Dynamic_Load_Module */
+ struct my_handle *myhandle;
+ unsigned dload_errcount; /* Total # of errors reported so far */
+ /* Number of target sections that require allocation and relocation */
+ unsigned allocated_secn_count;
+#ifndef TARGET_ENDIANNESS
+ boolean big_e_target; /* Target data in big-endian format */
+#endif
+ /* map for reordering bytes, 0 if not needed */
+ u32 reorder_map;
+ struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
+ struct doff_verify_rec_t verify; /* Verify record */
+
+ int relstkidx; /* index into relocation value stack */
+ /* relocation value stack used in relexp.c */
+ RVALUE relstk[STATIC_EXPR_STK_SIZE];
+
+} ;
+
+#ifdef TARGET_ENDIANNESS
+#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
+#else
+#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
+#endif
+
+/*
+ * Exports from cload.c to rest of the world
+ */
+extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
+extern void dload_syms_error(struct Dynamic_Loader_Sym *syms,
+ const char *errtxt, ...);
+extern void dload_headers(struct dload_state *dlthis);
+extern void dload_strings(struct dload_state *dlthis, boolean sec_names_only);
+extern void dload_sections(struct dload_state *dlthis);
+extern void dload_reorder(void *data, int dsiz, u32 map);
+extern u32 dload_checksum(void *data, unsigned siz);
+
+#if HOST_ENDIANNESS
+extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
+#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
+extern uint32_t dload_reverse_checksum_16(void *data, unsigned siz);
+#endif
+#endif
+
+#define is_data_scn(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
+#define is_data_scn_num(zzz) \
+ (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
+
+/*
+ * exported by reloc.c
+ */
+extern void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
+ struct reloc_record_t *rp);
+
+extern RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data,
+ int fieldsz, int offset, unsigned sgn);
+
+extern int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
+ int fieldsz, int offset, unsigned sgn);
+
+#endif /* __DLOAD_INTERNAL__ */
diff --git a/drivers/dsp/bridge/dynload/doff.h b/drivers/dsp/bridge/dynload/doff.h
new file mode 100644
index 000000000000..2b8fc372fe82
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/doff.h
@@ -0,0 +1,347 @@
+/*
+ * doff.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*****************************************************************************/
+/* DOFF.H - Structures & definitions used for dynamically */
+/* loaded modules file format. This format is a reformatted */
+/* version of COFF.(see coff.h for details) It optimizes the */
+/* layout for the dynamic loader. */
+/* */
+/* .dof files, when viewed as a sequence of 32-bit integers, look the same */
+/* on big-endian and little-endian machines. */
+/*****************************************************************************/
+#ifndef _DOFF_H
+#define _DOFF_H
+
+#ifndef UINT32_C
+#define UINT32_C(zzz) ((u32)zzz)
+#endif
+
+#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
+
+/* DOFF file header containing fields categorizing the remainder of the file */
+struct doff_filehdr_t {
+
+ /* string table size, including filename, in bytes */
+ u32 df_strtab_size;
+
+ /* entry point if one exists */
+ u32 df_entrypt;
+
+ /* identifies byte ordering of file;
+ * always set to BYTE_RESHUFFLE_VALUE */
+ u32 df_byte_reshuffle;
+
+ /* Size of the string table up to and including the last section name */
+ /* Size includes the name of the COFF file also */
+ u32 df_scn_name_size;
+
+#ifndef _BIG_ENDIAN
+ /* number of symbols */
+ u16 df_no_syms;
+
+ /* length in bytes of the longest string, including terminating NULL */
+ /* excludes the name of the file */
+ u16 df_max_str_len;
+
+ /* total number of sections including no-load ones */
+ u16 df_no_scns;
+
+ /* number of sections containing target code allocated or downloaded */
+ u16 df_target_scns;
+
+ /* unique id for dll file format & version */
+ u16 df_doff_version;
+
+ /* identifies ISA */
+ u16 df_target_id;
+
+ /* useful file flags */
+ u16 df_flags;
+
+ /* section reference for entry point, N_UNDEF for none, */
+ /* N_ABS for absolute address */
+ s16 df_entry_secn;
+#else
+ /* length of the longest string, including terminating NULL */
+ u16 df_max_str_len;
+
+ /* number of symbols */
+ u16 df_no_syms;
+
+ /* number of sections containing target code allocated or downloaded */
+ u16 df_target_scns;
+
+ /* total number of sections including no-load ones */
+ u16 df_no_scns;
+
+ /* identifies ISA */
+ u16 df_target_id;
+
+ /* unique id for dll file format & version */
+ u16 df_doff_version;
+
+ /* section reference for entry point, N_UNDEF for none, */
+ /* N_ABS for absolute address */
+ s16 df_entry_secn;
+
+ /* useful file flags */
+ u16 df_flags;
+#endif
+ /* checksum for file header record */
+ u32 df_checksum;
+
+} ;
+
+/* flags in the df_flags field */
+#define DF_LITTLE 0x100
+#define DF_BIG 0x200
+#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
+
+/* Supported processors */
+#define TMS470_ID 0x97
+#define LEAD_ID 0x98
+#define TMS32060_ID 0x99
+#define LEAD3_ID 0x9c
+
+/* Primary processor for loading */
+#if TMS32060
+#define TARGET_ID TMS32060_ID
+#endif
+
+/* Verification record containing values used to test integrity of the bits */
+struct doff_verify_rec_t {
+
+ /* time and date stamp */
+ u32 dv_timdat;
+
+ /* checksum for all section records */
+ u32 dv_scn_rec_checksum;
+
+ /* checksum for string table */
+ u32 dv_str_tab_checksum;
+
+ /* checksum for symbol table */
+ u32 dv_sym_tab_checksum;
+
+ /* checksum for verification record */
+ u32 dv_verify_rec_checksum;
+
+} ;
+
+/* String table is an array of null-terminated strings. The first entry is
+ * the filename, which is added by DLLcreate. No new structure definitions
+ * are required.
+ */
+
+/* Section Records including information on the corresponding image packets */
+/*
+ * !!WARNING!!
+ *
+ * This structure is expected to match in form LDR_SECTION_INFO in
+ * dynamic_loader.h
+ */
+
+struct doff_scnhdr_t {
+
+ s32 ds_offset; /* offset into string table of name */
+ s32 ds_paddr; /* RUN address, in target AU */
+ s32 ds_vaddr; /* LOAD address, in target AU */
+ s32 ds_size; /* section size, in target AU */
+#ifndef _BIG_ENDIAN
+ u16 ds_page; /* memory page id */
+ u16 ds_flags; /* section flags */
+#else
+ u16 ds_flags; /* section flags */
+ u16 ds_page; /* memory page id */
+#endif
+ u32 ds_first_pkt_offset;
+ /* Absolute byte offset into the file */
+ /* where the first image record resides */
+
+ s32 ds_nipacks; /* number of image packets */
+
+};
+
+/* Symbol table entry */
+struct doff_syment_t {
+
+ s32 dn_offset; /* offset into string table of name */
+ s32 dn_value; /* value of symbol */
+#ifndef _BIG_ENDIAN
+ s16 dn_scnum; /* section number */
+ s16 dn_sclass; /* storage class */
+#else
+ s16 dn_sclass; /* storage class */
+ s16 dn_scnum; /* section number, 1-based */
+#endif
+
+} ;
+
+/* special values for dn_scnum */
+#define DN_UNDEF 0 /* undefined symbol */
+#define DN_ABS (-1) /* value of symbol is absolute */
+/* special values for dn_sclass */
+#define DN_EXT 2
+#define DN_STATLAB 20
+#define DN_EXTLAB 21
+
+/* Default value of image bits in packet */
+/* Configurable by user on the command line */
+#define IMAGE_PACKET_SIZE 1024
+
+/* An image packet contains a chunk of data from a section along with */
+/* information necessary for its processing. */
+struct image_packet_t {
+
+ s32 i_num_relocs; /* number of relocations for */
+ /* this packet */
+
+ s32 i_packet_size; /* number of bytes in array */
+ /* "bits" occupied by */
+ /* valid data. Could be */
+ /* < IMAGE_PACKET_SIZE to */
+ /* prevent splitting a */
+ /* relocation across packets. */
+ /* Last packet of a section */
+ /* will most likely contain */
+ /* < IMAGE_PACKET_SIZE bytes */
+ /* of valid data */
+
+ s32 i_checksum; /* Checksum for image packet */
+ /* and the corresponding */
+ /* relocation records */
+
+ u8 *i_bits; /* Actual data in section */
+
+};
+
+/* The relocation structure definition matches the COFF version. Offsets */
+/* however are relative to the image packet base not the section base. */
+struct reloc_record_t {
+
+ s32 r_vaddr;
+
+ /* expressed in target AUs */
+
+ union {
+ struct {
+#ifndef _BIG_ENDIAN
+ u8 _offset; /* bit offset of rel fld */
+ u8 _fieldsz; /* size of rel fld */
+ u8 _wordsz; /* # bytes containing rel fld */
+ u8 _dum1;
+ u16 _dum2;
+ u16 _type;
+#else
+ unsigned _dum1:8;
+ unsigned _wordsz:8; /* # bytes containing rel fld */
+ unsigned _fieldsz:8; /* size of rel fld */
+ unsigned _offset:8; /* bit offset of rel fld */
+ u16 _type;
+ u16 _dum2;
+#endif
+ } _r_field;
+
+ struct {
+ u32 _spc; /* image packet relative PC */
+#ifndef _BIG_ENDIAN
+ u16 _dum;
+ u16 _type; /* relocation type */
+#else
+ u16 _type; /* relocation type */
+ u16 _dum;
+#endif
+ } _r_spc;
+
+ struct {
+ u32 _uval; /* constant value */
+#ifndef _BIG_ENDIAN
+ u16 _dum;
+ u16 _type; /* relocation type */
+#else
+ u16 _type; /* relocation type */
+ u16 _dum;
+#endif
+ } _r_uval;
+
+ struct {
+ s32 _symndx; /* 32-bit sym tbl index */
+#ifndef _BIG_ENDIAN
+ u16 _disp; /* extra addr encode data */
+ u16 _type; /* relocation type */
+#else
+ u16 _type; /* relocation type */
+ u16 _disp; /* extra addr encode data */
+#endif
+ } _r_sym;
+ } _u_reloc;
+
+} ;
+
+/* abbreviations for convenience */
+#ifndef r_type
+#define r_type _u_reloc._r_sym._type
+#define r_uval _u_reloc._r_uval._uval
+#define r_symndx _u_reloc._r_sym._symndx
+#define r_offset _u_reloc._r_field._offset
+#define r_fieldsz _u_reloc._r_field._fieldsz
+#define r_wordsz _u_reloc._r_field._wordsz
+#define r_disp _u_reloc._r_sym._disp
+#endif
+
+/*****************************************************************************/
+/* */
+/* Important DOFF macros used for file processing */
+/* */
+/*****************************************************************************/
+
+/* DOFF Versions */
+#define DOFF0 0
+
+/* Return the address/size >= to addr that is at a 32-bit boundary */
+/* This assumes that a byte is 8 bits */
+#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
+
+/*****************************************************************************/
+/* */
+/* The DOFF section header flags field is laid out as follows: */
+/* */
+/* Bits 0-3 : Section Type */
+/* Bit 4 : Set when section requires target memory to be allocated by DL */
+/* Bit 5 : Set when section requires downloading */
+/* Bits 8-11: Alignment, same as COFF */
+/* */
+/*****************************************************************************/
+
+/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
+
+/* Macros to help processing of sections */
+#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
+
+/* DS_ALLOCATE indicates whether a section needs space on the target */
+#define DS_ALLOCATE_MASK 0x10
+#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
+
+/* DS_DOWNLOAD indicates that the loader needs to copy bits */
+#define DS_DOWNLOAD_MASK 0x20
+#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
+
+/* Section alignment requirement in AUs */
+#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
+
+#endif /* _DOFF_H */
diff --git a/drivers/dsp/bridge/dynload/getsection.c b/drivers/dsp/bridge/dynload/getsection.c
new file mode 100644
index 000000000000..78a301a7411c
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/getsection.c
@@ -0,0 +1,412 @@
+/*
+ * getsection.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#include <dspbridge/getsection.h>
+#include "header.h"
+
+/*
+ * Error strings
+ */
+static const char E_READSTRM[] = { "Error reading %s from input stream" };
+static const char E_SEEK[] = { "Set file position to %d failed" };
+static const char E_ISIZ[] = { "Bad image packet size %d" };
+static const char E_CHECKSUM[] = { "Checksum failed on %s" };
+static const char E_RELOC[] = { "DLOAD_GetSection unable to read"
+ "sections containing relocation entries"};
+#if BITS_PER_AU > BITS_PER_BYTE
+static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
+static const char E_STBL[] = { "Bad string table offset " FMT_UI32 };
+#endif
+
+/*
+ * we use the fact that DOFF section records are shaped just like
+ * LDR_SECTION_INFO to reduce our section storage usage. These macros
+ * marks the places where that assumption is made
+ */
+#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
+#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
+
+/***************************************************************/
+/********************* SUPPORT FUNCTIONS ***********************/
+/***************************************************************/
+
+#if BITS_PER_AU > BITS_PER_BYTE
+/**************************************************************************
+ * Procedure unpack_sec_name
+ *
+ * Parameters:
+ * dlthis Handle from DLOAD_module_open for this module
+ * soffset Byte offset into the string table
+ * dst Place to store the expanded string
+ *
+ * Effect:
+ * Stores a string from the string table into the destination, expanding
+ * it in the process. Returns a pointer just past the end of the stored
+ * string on success, or NULL on failure.
+ *
+ *************************************************************************/
+static char *unpack_sec_name(struct dload_state *dlthis,
+ u32 soffset, char *dst)
+{
+ u8 tmp, *src;
+
+ if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
+ dload_error(dlthis, E_STBL, soffset);
+ return NULL;
+ }
+ src = (u8 *)dlthis->str_head +
+ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
+ if (soffset & 1)
+ *dst++ = *src++; /* only 1 character in first word */
+ do {
+ tmp = *src++;
+ *dst = (tmp >> BITS_PER_BYTE)
+ if (!(*dst++))
+ break;
+ } while ((*dst++ = tmp & BYTE_MASK));
+
+ return dst;
+}
+
+/**************************************************************************
+ * Procedure expand_sec_names
+ *
+ * Parameters:
+ * dlthis Handle from DLOAD_module_open for this module
+ *
+ * Effect:
+ * Allocates a buffer, unpacks and copies strings from string table into it.
+ * Stores a pointer to the buffer into a state variable.
+ **************************************************************************/
+static void expand_sec_names(struct dload_state *dlthis)
+{
+ char *xstrings, *curr, *next;
+ u32 xsize;
+ u16 sec;
+ struct LDR_SECTION_INFO *shp;
+ /* assume worst-case size requirement */
+ xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
+ xstrings = (char *)dlthis->mysym->Allocate(dlthis->mysym, xsize);
+ if (xstrings == NULL) {
+ dload_error(dlthis, E_ALLOC, xsize);
+ return;
+ }
+ dlthis->xstrings = xstrings;
+ /* For each sec, copy and expand its name */
+ curr = xstrings;
+ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+ next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
+ if (next == NULL)
+ break; /* error */
+ shp->name = curr;
+ curr = next;
+ }
+}
+
+#endif
+
+/***************************************************************/
+/********************* EXPORTED FUNCTIONS **********************/
+/***************************************************************/
+
+/**************************************************************************
+ * Procedure DLOAD_module_open
+ *
+ * Parameters:
+ * module The input stream that supplies the module image
+ * syms Host-side malloc/free and error reporting functions.
+ * Other methods are unused.
+ *
+ * Effect:
+ * Reads header information from a dynamic loader module using the
+ specified
+ * stream object, and returns a handle for the module information. This
+ * handle may be used in subsequent query calls to obtain information
+ * contained in the module.
+ *
+ * Returns:
+ * NULL if an error is encountered, otherwise a module handle for use
+ * in subsequent operations.
+ **************************************************************************/
+DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream *module,
+ struct Dynamic_Loader_Sym *syms)
+{
+ struct dload_state *dlthis; /* internal state for this call */
+ unsigned *dp, sz;
+ u32 sec_start;
+#if BITS_PER_AU <= BITS_PER_BYTE
+ u16 sec;
+#endif
+
+ /* Check that mandatory arguments are present */
+ if (!module || !syms) {
+ if (syms != NULL)
+ dload_syms_error(syms, "Required parameter is NULL");
+
+ return NULL;
+ }
+
+ dlthis = (struct dload_state *)
+ syms->Allocate(syms, sizeof(struct dload_state));
+ if (!dlthis) {
+ /* not enough storage */
+ dload_syms_error(syms, "Can't allocate module info");
+ return NULL;
+ }
+
+ /* clear our internal state */
+ dp = (unsigned *)dlthis;
+ for (sz = sizeof(struct dload_state) / sizeof(unsigned);
+ sz > 0; sz -= 1)
+ *dp++ = 0;
+
+ dlthis->strm = module;
+ dlthis->mysym = syms;
+
+ /* read in the doff image and store in our state variable */
+ dload_headers(dlthis);
+
+ if (!dlthis->dload_errcount)
+ dload_strings(dlthis, true);
+
+ /* skip ahead past the unread portion of the string table */
+ sec_start = sizeof(struct doff_filehdr_t) +
+ sizeof(struct doff_verify_rec_t) +
+ BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
+
+ if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
+ dload_error(dlthis, E_SEEK, sec_start);
+ return NULL;
+ }
+
+ if (!dlthis->dload_errcount)
+ dload_sections(dlthis);
+
+ if (dlthis->dload_errcount) {
+ DLOAD_module_close(dlthis); /* errors, blow off our state */
+ dlthis = NULL;
+ return NULL;
+ }
+#if BITS_PER_AU > BITS_PER_BYTE
+ /* Expand all section names from the string table into the */
+ /* state variable, and convert section names from a relative */
+ /* string table offset to a pointers to the expanded string. */
+ expand_sec_names(dlthis);
+#else
+ /* Convert section names from a relative string table offset */
+ /* to a pointer into the string table. */
+ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+ struct LDR_SECTION_INFO *shp =
+ DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+ shp->name = dlthis->str_head + *(u32 *)&shp->name;
+ }
+#endif
+
+ return dlthis;
+}
+
+/***************************************************************************
+ * Procedure DLOAD_GetSectionInfo
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ * sectionName Pointer to the string name of the section desired
+ * sectionInfo Address of a section info structure pointer to be
+ * initialized
+ *
+ * Effect:
+ * Finds the specified section in the module information, and initializes
+ * the provided struct LDR_SECTION_INFO pointer.
+ *
+ * Returns:
+ * true for success, false for section not found
+ **************************************************************************/
+int DLOAD_GetSectionInfo(DLOAD_module_info minfo, const char *sectionName,
+ const struct LDR_SECTION_INFO **const sectionInfo)
+{
+ struct dload_state *dlthis;
+ struct LDR_SECTION_INFO *shp;
+ u16 sec;
+
+ dlthis = (struct dload_state *)minfo;
+ if (!dlthis)
+ return false;
+
+ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
+ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
+ if (strcmp(sectionName, shp->name) == 0) {
+ *sectionInfo = shp;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
+#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
+
+/**************************************************************************
+ * Procedure DLOAD_GetSection
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ * sectionInfo Pointer to a section info structure for the desired
+ * section
+ * sectionData Buffer to contain the section initialized data
+ *
+ * Effect:
+ * Copies the initialized data for the specified section into the
+ * supplied buffer.
+ *
+ * Returns:
+ * true for success, false for section not found
+ **************************************************************************/
+int DLOAD_GetSection(DLOAD_module_info minfo,
+ const struct LDR_SECTION_INFO *sectionInfo, void *sectionData)
+{
+ struct dload_state *dlthis;
+ u32 pos;
+ struct doff_scnhdr_t *sptr = NULL;
+ s32 nip;
+ struct image_packet_t ipacket;
+ s32 ipsize;
+ u32 checks;
+ s8 *dest = (s8 *)sectionData;
+
+ dlthis = (struct dload_state *)minfo;
+ if (!dlthis)
+ return false;
+ sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
+ if (sptr == NULL)
+ return false;
+
+ /* skip ahead to the start of the first packet */
+ pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
+ if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
+ dload_error(dlthis, E_SEEK, pos);
+ return false;
+ }
+
+ nip = sptr->ds_nipacks;
+ while ((nip -= 1) >= 0) { /* for each packet */
+ /* get the fixed header bits */
+ if (dlthis->strm->
+ read_buffer(dlthis->strm, &ipacket, IPH_SIZE) != IPH_SIZE) {
+ dload_error(dlthis, E_READSTRM, "image packet");
+ return false;
+ }
+ /* reorder the header if need be */
+ if (dlthis->reorder_map)
+ dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
+
+ /* Now read the packet image bits. Note: round the size up to
+ * the next multiple of 4 bytes; this is what checksum
+ * routines want. */
+ ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.i_packet_size));
+ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
+ dload_error(dlthis, E_ISIZ, ipsize);
+ return false;
+ }
+ if (dlthis->strm->read_buffer
+ (dlthis->strm, dest, ipsize) != ipsize) {
+ dload_error(dlthis, E_READSTRM, "image packet");
+ return false;
+ }
+ /* reorder the bytes if need be */
+#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
+ if (dlthis->reorder_map)
+ dload_reorder(dest, ipsize, dlthis->reorder_map);
+
+ checks = dload_checksum(dest, ipsize);
+#else
+ if (dlthis->dfile_hdr.df_byte_reshuffle !=
+ TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
+ /* put image bytes in big-endian order, not PC order */
+ dload_reorder(dest, ipsize,
+ TARGET_ORDER(dlthis->dfile_hdr.
+ df_byte_reshuffle));
+ }
+#if TARGET_AU_BITS > 8
+ checks = dload_reverse_checksum_16(dest, ipsize);
+#else
+ checks = dload_reverse_checksum(dest, ipsize);
+#endif
+#endif
+ checks += dload_checksum(&ipacket, IPH_SIZE);
+
+ /* NYI: unable to handle relocation entries here. Reloc
+ * entries referring to fields that span the packet boundaries
+ * may result in packets of sizes that are not multiple of
+ * 4 bytes. Our checksum implementation works on 32-bit words
+ * only. */
+ if (ipacket.i_num_relocs != 0) {
+ dload_error(dlthis, E_RELOC, ipsize);
+ return false;
+ }
+
+ if (~checks) {
+ dload_error(dlthis, E_CHECKSUM, "image packet");
+ return false;
+ }
+
+ /*Advance destination ptr by the size of the just-read packet*/
+ dest += ipsize;
+ }
+
+ return true;
+}
+
+/***************************************************************************
+ * Procedure DLOAD_module_close
+ *
+ * Parameters:
+ * minfo Handle from DLOAD_module_open for this module
+ *
+ * Effect:
+ * Releases any storage associated with the module handle. On return,
+ * the module handle is invalid.
+ *
+ * Returns:
+ * Zero for success. On error, the number of errors detected is returned.
+ * Individual errors are reported using syms->Error_Report(), where syms was
+ * an argument to DLOAD_module_open
+ **************************************************************************/
+void DLOAD_module_close(DLOAD_module_info minfo)
+{
+ struct dload_state *dlthis;
+
+ dlthis = (struct dload_state *)minfo;
+ if (!dlthis)
+ return;
+
+ if (dlthis->str_head)
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
+
+ if (dlthis->sect_hdrs)
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->sect_hdrs);
+
+#if BITS_PER_AU > BITS_PER_BYTE
+ if (dlthis->xstrings)
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->xstrings);
+
+#endif
+
+ dlthis->mysym->Deallocate(dlthis->mysym, dlthis);
+}
diff --git a/drivers/dsp/bridge/dynload/header.h b/drivers/dsp/bridge/dynload/header.h
new file mode 100644
index 000000000000..0de744b2ca1b
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/header.h
@@ -0,0 +1,59 @@
+/*
+ * header.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#define TRUE 1
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include <linux/string.h>
+#define DL_STRCMP strcmp
+
+/* maximum parenthesis nesting in relocation stack expressions */
+#define STATIC_EXPR_STK_SIZE 10
+
+#include <linux/types.h>
+typedef unsigned int uint_least32_t;
+typedef unsigned short int uint_least16_t;
+
+#include "doff.h"
+#include <dspbridge/dynamic_loader.h>
+#include "params.h"
+#include "dload_internal.h"
+#include "reloc_table.h"
+
+/*
+ * Plausibility limits
+ *
+ * These limits are imposed upon the input DOFF file as a check for validity.
+ * They are hard limits, in that the load will fail if they are exceeded.
+ * The numbers selected are arbitrary, in that the loader implementation does
+ * not require these limits.
+ */
+
+/* maximum number of bytes in string table */
+#define MAX_REASONABLE_STRINGTAB (0x100000)
+/* maximum number of code,data,etc. sections */
+#define MAX_REASONABLE_SECTIONS (200)
+/* maximum number of linker symbols */
+#define MAX_REASONABLE_SYMBOLS (100000)
+
+/* shift count to align F_BIG with DLOAD_LITTLE */
+#define ALIGN_COFF_ENDIANNESS 7
+#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
diff --git a/drivers/dsp/bridge/dynload/module_list.h b/drivers/dsp/bridge/dynload/module_list.h
new file mode 100644
index 000000000000..9c4876ae7c40
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/module_list.h
@@ -0,0 +1,161 @@
+/*
+ * dspbridge/mpu_driver/src/dynload/module_list.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/*============================================================================
+ Filename: module_list.h
+
+ Copyright (C) 2002 Texas Instruments Incorporated
+
+
+ This C header file gives the layout of the data structure created by the
+ dynamic loader to describe the set of modules loaded into the DSP.
+
+ Linked List Structure:
+ ----------------------
+ The data structure defined here is a singly-linked list. The list
+ represents the set of modules which are currently loaded in the DSP memory.
+ The first entry in the list is a header record which contains a flag
+ representing the state of the list. The rest of the entries in the list
+ are module records.
+
+ Global symbol _DLModules designates the first record in the list (i.e. the
+ header record). This symbol must be defined in any program that wishes to
+ use DLLview plug-in.
+
+ String Representation:
+ ----------------------
+ The string names of the module and its sections are stored in a block of
+ memory which follows the module record itself. The strings are ordered:
+ module name first, followed by section names in order from the first
+ section to the last. String names are tightly packed arrays of 8-bit
+ characters (two characters per 16-bit word on the C55x). Strings are
+ zero-byte-terminated.
+
+ Creating and updating the list:
+-------------------------------
+ Upon loading a new module into the DSP memory the dynamic loader inserts a
+new module record as the first module record in the list. The fields of
+ this module record are initialized to reflect the properties of the module.
+ The dynamic loader does NOT increment the flag/counter in the list's header
+ record.
+
+ Upon unloading a module from the DSP memory the dynamic loader removes the
+module's record from this list. The dynamic loader also increments the
+ flag/counter in the list's header record to indicate that the list has been
+ changed.
+
+============================================================================*/
+
+#ifndef _MODULE_LIST_H_
+#define _MODULE_LIST_H_
+
+#include <linux/types.h>
+
+/* Global pointer to the modules_header structure*/
+#define MODULES_HEADER "_DLModules"
+#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
+
+/* Initial version number*/
+#define INIT_VERSION 1
+
+/* Verification number -- to be recorded in each module record */
+#define VERIFICATION 0x79
+
+/* forward declarations */
+struct dll_module;
+struct dll_sect;
+
+/* the first entry in the list is the modules_header record;
+ * its address is contained in the global _DLModules pointer */
+struct modules_header {
+
+ /* Address of the first dll_module record in the list or NULL.
+ Note: for C55x this is a word address (C55x data is word-addressable)*/
+ u32 first_module;
+
+ /* Combined storage size (in target addressable units) of the
+ * dll_module record which follows this header record, or zero
+ * if the list is empty. This size includes the module's string table.
+ * Note: for C55x the unit is a 16-bit word */
+ u16 first_module_size;
+
+ /* Counter is incremented whenever a module record is removed from
+ * the list */
+ u16 update_flag;
+
+} ;
+
+/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
+ * 0 => a 32-bit value, 1 => 2 16-bit values */
+#define MODULES_HEADER_BITMAP 0x2 /* swapping bitmap for type modules_header */
+
+/* information recorded about each section in a module */
+struct dll_sect {
+
+ /* Load-time address of the section.
+ * Note: for C55x this is a byte address for program sections, and
+ * a word address for data sections. C55x program memory is
+ * byte-addressable, while data memory is word-addressable. */
+ u32 sect_load_adr;
+
+ /* Run-time address of the section.
+ * Note 1: for C55x this is a byte address for program sections, and
+ * a word address for data sections.
+ * Note 2: for C55x two most significant bits of this field indicate
+ * the section type: '00' for a code section, '11' for a data section
+ * (C55 addresses are really only 24-bits wide). */
+ u32 sect_run_adr;
+
+} ;
+
+/* the rest of the entries in the list are module records */
+struct dll_module {
+
+ /* Address of the next dll_module record in the list, or 0 if this is
+ * the last record in the list.
+ * Note: for C55x this is a word address (C55x data is
+ * word-addressable) */
+ u32 next_module;
+
+ /* Combined storage size (in target addressable units) of the
+ * dll_module record which follows this one, or zero if this is the
+ * last record in the list. This size includes the module's string
+ * table.
+ * Note: for C55x the unit is a 16-bit word. */
+ u16 next_module_size;
+
+ /* version number of the tooling; set to INIT_VERSION for Phase 1 */
+ u16 version;
+
+ /* the verification word; set to VERIFICATION */
+ u16 verification;
+
+ /* Number of sections in the sects array */
+ u16 num_sects;
+
+ /* Module's "unique" id; copy of the timestamp from the host
+ * COFF file */
+ u32 timestamp;
+
+ /* Array of num_sects elements of the module's section records */
+ struct dll_sect sects[1];
+} ;
+
+/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
+ * 0 => a 32-bit value, 1 => 2 16-bit values */
+#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
+
+#endif /* _MODULE_LIST_H_ */
diff --git a/drivers/dsp/bridge/dynload/params.h b/drivers/dsp/bridge/dynload/params.h
new file mode 100644
index 000000000000..ade430d90baf
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/params.h
@@ -0,0 +1,231 @@
+/*
+ * params.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+/******************************************************************************
+ *
+ * This file defines host and target properties for all machines
+ * supported by the dynamic loader. To be tedious...
+ *
+ * host == the machine on which the dynamic loader runs
+ * target == the machine that the dynamic loader is loading
+ *
+ * Host and target may or may not be the same, depending upon the particular
+ * use.
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * Host Properties
+ *
+ *****************************************************************************/
+
+#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
+#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
+#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
+
+#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
+#define BITS_PER_AU 16
+#define LOG_BITS_PER_AU 4
+ /* use this print string in error messages for uint32_t */
+#define FMT_UI32 "0x%lx"
+#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
+#else
+#define BITS_PER_AU 8 /* bits in the smallest addressable data storage unit */
+#define LOG_BITS_PER_AU 3 /* log base 2 of the same; useful for shift counts */
+#define FMT_UI32 "0x%x"
+#define FMT8_UI32 "%08x"
+#endif
+
+/* generic fastest method for swapping bytes and shorts */
+#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
+#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
+
+/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
+
+/******************************************************************************
+ *
+ * Target Properties
+ *
+ *****************************************************************************/
+
+
+/*--------------------------------------------------------------------------*/
+/* TMS320C6x Target Specific Parameters (byte-addressable) */
+/*--------------------------------------------------------------------------*/
+#if TMS32060
+#define MEMORG 0x0L /* Size of configured memory */
+#define MEMSIZE 0x0L /* (full address space) */
+
+#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
+#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
+#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
+#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
+ * are page number */
+
+#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
+
+#undef TARGET_ENDIANNESS /* may be big or little endian */
+
+/* align a target address to a word boundary */
+#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
+#endif
+
+
+/*--------------------------------------------------------------------------
+ *
+ * DEFAULT SETTINGS and DERIVED PROPERTIES
+ *
+ * This section establishes defaults for values not specified above
+ *--------------------------------------------------------------------------*/
+#ifndef TARGET_AU_BITS
+#define TARGET_AU_BITS 8 /* width of the target addressable unit */
+#define LOG_TARGET_AU_BITS 3 /* log2 of same */
+#endif
+
+#ifndef CINIT_DEFAULT_PAGE
+#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
+#endif
+
+#ifndef DATA_RUN2LOAD
+#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
+#endif
+
+#ifndef DBG_LIST_PAGE
+#define DBG_LIST_PAGE 0 /* page number for .dllview section */
+#endif
+
+#ifndef TARGET_WORD_ALIGN
+/* align a target address to a word boundary */
+#define TARGET_WORD_ALIGN(zz) (zz)
+#endif
+
+#ifndef TDATA_TO_TADDR
+#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
+#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
+#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
+#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
+#endif
+
+/*
+ *
+ * Useful properties and conversions derived from the above
+ *
+ */
+
+/*
+ * Conversions between host and target addresses
+ */
+#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
+/* translate target addressable unit to host address */
+#define TADDR_TO_HOST(x) (x)
+/* translate host address to target addressable unit */
+#define HOST_TO_TADDR(x) (x)
+#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
+#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
+#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
+#else
+#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
+#endif
+
+#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
+/* translate target addressable unit to host address */
+#define TDATA_TO_HOST(x) (x)
+/* translate host address to target addressable unit */
+#define HOST_TO_TDATA(x) (x)
+/* translate host address to target addressable unit, round up */
+#define HOST_TO_TDATA_ROUND(x) (x)
+/* byte offset to host offset, rounded up for TDATA size */
+#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
+#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
+#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
+#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
+#else
+#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define HOST_TO_TDATA_ROUND(x) (((x) +\
+ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
+ (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
+#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
+ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
+ -(TDATA_AU_BITS/BITS_PER_AU))
+#endif
+
+/*
+ * Input in DOFF format is always expresed in bytes, regardless of loading host
+ * so we wind up converting from bytes to target and host units even when the
+ * host is not a byte machine.
+ */
+#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
+#define BYTE_TO_HOST(x) (x)
+#define BYTE_TO_HOST_ROUND(x) (x)
+#define HOST_TO_BYTE(x) (x)
+#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
+#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
+ (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
+#else
+/* lets not try to deal with sub-8-bit byte machines */
+#endif
+
+#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
+/* translate target addressable unit to byte address */
+#define TADDR_TO_BYTE(x) (x)
+/* translate byte address to target addressable unit */
+#define BYTE_TO_TADDR(x) (x)
+#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
+#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
+#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
+#else
+/* lets not try to deal with sub-8-bit byte machines */
+#endif
+
+#ifdef _BIG_ENDIAN
+#define HOST_ENDIANNESS 1
+#else
+#define HOST_ENDIANNESS 0
+#endif
+
+#ifdef TARGET_ENDIANNESS
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
+#elif HOST_ENDIANNESS
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
+#else
+#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
+#endif
+
+/* the unit in which we process target image data */
+#if TARGET_AU_BITS <= 8
+typedef u8 TgtAU_t;
+#elif TARGET_AU_BITS <= 16
+typedef u16 TgtAU_t;
+#else
+typedef u32 TgtAU_t;
+#endif
+
+/* size of that unit */
+#if TARGET_AU_BITS < BITS_PER_AU
+#define TGTAU_BITS BITS_PER_AU
+#define LOG_TGTAU_BITS LOG_BITS_PER_AU
+#else
+#define TGTAU_BITS TARGET_AU_BITS
+#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
+#endif
diff --git a/drivers/dsp/bridge/dynload/reloc.c b/drivers/dsp/bridge/dynload/reloc.c
new file mode 100644
index 000000000000..54e460ef2045
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/reloc.c
@@ -0,0 +1,425 @@
+/*
+ * reloc.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#include "header.h"
+
+#if TMS32060
+/* the magic symbol for the start of BSS */
+static const char BSSSYMBOL[] = {".bss"};
+#endif
+
+#if TMS32060
+#include "reloc_table_c6000.c"
+#endif
+
+#if TMS32060
+/* From coff.h - ignore these relocation operations */
+#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
+#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
+#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
+#endif
+
+/**************************************************************************
+ * Procedure dload_unpack
+ *
+ * Parameters:
+ * data pointer to storage unit containing lowest host address of
+ * image data
+ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
+ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
+ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
+ *
+ * Effect:
+ * Extracts the specified field and returns it.
+ **************************************************************************/
+RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data, int fieldsz,
+ int offset, unsigned sgn)
+{
+ register RVALUE objval;
+ register int shift, direction;
+ register TgtAU_t *dp = data;
+
+ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value*/
+ /* * collect up enough bits to contain the desired field */
+ if (TARGET_BIG_ENDIAN) {
+ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
+ direction = -1;
+ } else
+ direction = 1;
+ objval = *dp >> offset;
+ shift = TGTAU_BITS - offset;
+ while (shift <= fieldsz) {
+ dp += direction;
+ objval += (RVALUE)*dp << shift;
+ shift += TGTAU_BITS;
+ }
+
+ /* * sign or zero extend the value appropriately */
+ if (sgn == ROP_UNS)
+ objval &= (2 << fieldsz) - 1;
+ else {
+ shift = sizeof(RVALUE) * BITS_PER_AU-1 - fieldsz;
+ objval = (objval << shift) >> shift;
+ }
+
+ return objval;
+
+} /* dload_unpack */
+
+
+/**************************************************************************
+ * Procedure dload_repack
+ *
+ * Parameters:
+ * val Value to insert
+ * data Pointer to storage unit containing lowest host address of
+ * image data
+ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
+ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
+ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
+ *
+ * Effect:
+ * Stuffs the specified value in the specified field. Returns 0 for
+ * success
+ * or 1 if the value will not fit in the specified field according to the
+ * specified signedness rule.
+ **************************************************************************/
+static const unsigned char ovf_limit[] = {1, 2, 2};
+int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
+ int fieldsz, int offset, unsigned sgn)
+{
+ register URVALUE objval, mask;
+ register int shift, direction;
+ register TgtAU_t *dp = data;
+
+
+ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
+ /* clip the bits */
+ mask = ((UINT32_C(2) << fieldsz) - 1);
+ objval = (val & mask);
+ /* * store the bits through the specified mask */
+ if (TARGET_BIG_ENDIAN) {
+ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
+ direction = -1;
+ } else
+ direction = 1;
+
+ /* insert LSBs */
+ *dp = (*dp & ~(mask << offset)) + (objval << offset);
+ shift = TGTAU_BITS-offset;
+ /* align mask and objval with AU boundary */
+ objval >>= shift;
+ mask >>= shift;
+
+ while (mask) {
+ dp += direction;
+ *dp = (*dp & ~mask) + objval;
+ objval >>= TGTAU_BITS;
+ mask >>= TGTAU_BITS;
+ }
+
+ /*
+ * check for overflow
+ */
+ if (sgn) {
+ unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
+ if (tmp > ovf_limit[sgn-1])
+ return 1;
+ }
+ return 0;
+
+} /* dload_repack */
+
+/* lookup table for the scaling amount in a C6x instruction */
+#if TMS32060
+#define SCALE_BITS 4 /* there are 4 bits in the scale field */
+#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
+static const u8 C60_Scale[SCALE_MASK+1] = {
+ 1, 0, 0, 0, 1, 1, 2, 2
+};
+#endif
+
+/**************************************************************************
+ * Procedure dload_relocate
+ *
+ * Parameters:
+ * data Pointer to base of image data
+ * rp Pointer to relocation operation
+ *
+ * Effect:
+ * Performs the specified relocation operation
+ **************************************************************************/
+void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
+ struct reloc_record_t *rp)
+{
+ RVALUE val = 0;
+ RVALUE reloc_amt = 0;
+ unsigned int fieldsz = 0;
+ unsigned int offset = 0;
+ unsigned int reloc_info = 0;
+ unsigned int reloc_action = 0;
+ register int rx = 0;
+ RVALUE *stackp = NULL;
+ int top;
+ struct Local_Symbol *svp = NULL;
+#ifdef RFV_SCALE
+ unsigned int scale = 0;
+#endif
+
+ rx = HASH_FUNC(rp->r_type);
+ while (rop_map1[rx] != rp->r_type) {
+ rx = HASH_L(rop_map2[rx]);
+ if (rx < 0) {
+#if TMS32060
+ switch (rp->r_type) {
+ case R_C60ALIGN:
+ case R_C60NOCMP:
+ case R_C60FPHEAD:
+ /* Ignore these reloc types and return */
+ break;
+ default:
+ /* Unknown reloc type, print error and return */
+ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
+ }
+#else
+ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
+#endif
+ return;
+ }
+ }
+ rx = HASH_I(rop_map2[rx]);
+ if ((rx < (sizeof(rop_action)/sizeof(uint_least16_t)))
+ && (rx < (sizeof(rop_info)/sizeof(uint_least16_t))) && (rx > 0)) {
+ reloc_action = rop_action[rx]; reloc_info = rop_info[rx];
+ } else {
+ dload_error(dlthis, "Buffer Overflow - Array Index Out of Bounds");
+ }
+
+ /* Compute the relocation amount for the referenced symbol, if any */
+ reloc_amt = rp->r_uval;
+ if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
+ if ((u32)rp->r_symndx < dlthis->dfile_hdr.df_no_syms) {
+ /* real symbol reference */
+ svp = &dlthis->local_symtab[rp->r_symndx];
+ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
+ svp->delta : svp->value;
+ }
+ /* reloc references current section */
+ else if (rp->r_symndx == -1)
+ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
+ dlthis->delta_runaddr : dlthis->image_secn->run_addr;
+ } /* relocation uses a symbol reference */
+ /* Handle stack adjustment */
+ val = 0;
+ top = RFV_STK(reloc_info);
+ if (top) {
+ top += dlthis->relstkidx - RSTK_UOP;
+ if (top >= STATIC_EXPR_STK_SIZE) {
+ dload_error(dlthis,
+ "Expression stack overflow in %s at offset "
+ FMT_UI32, dlthis->image_secn->name,
+ rp->r_vaddr + dlthis->image_offset);
+ return;
+ }
+ val = dlthis->relstk[dlthis->relstkidx];
+ dlthis->relstkidx = top;
+ stackp = &dlthis->relstk[top];
+ }
+ /* Derive field position and size, if we need them */
+ if (reloc_info & ROP_RW) { /* read or write action in our future */
+ fieldsz = RFV_WIDTH(reloc_action);
+ if (fieldsz) { /* field info from table */
+ offset = RFV_POSN(reloc_action);
+ if (TARGET_BIG_ENDIAN)
+ /* make sure r_vaddr is the lowest target
+ * address containing bits */
+ rp->r_vaddr += RFV_BIGOFF(reloc_info);
+ } else { /* field info from relocation op */
+ fieldsz = rp->r_fieldsz; offset = rp->r_offset;
+ if (TARGET_BIG_ENDIAN)
+ /* make sure r_vaddr is the lowest target
+ address containing bits */
+ rp->r_vaddr += (rp->r_wordsz - offset - fieldsz)
+ >> LOG_TARGET_AU_BITS;
+ }
+ data = (TgtAU_t *)((char *)data + TADDR_TO_HOST(rp->r_vaddr));
+ /* compute lowest host location of referenced data */
+#if BITS_PER_AU > TARGET_AU_BITS
+ /* conversion from target address to host address may lose
+ address bits; add loss to offset */
+ if (TARGET_BIG_ENDIAN) {
+ offset += -((rp->r_vaddr << LOG_TARGET_AU_BITS) +
+ offset + fieldsz) &
+ (BITS_PER_AU-TARGET_AU_BITS);
+ } else {
+ offset += (rp->r_vaddr << LOG_TARGET_AU_BITS) &
+ (BITS_PER_AU-1);
+ }
+#endif
+#ifdef RFV_SCALE
+ scale = RFV_SCALE(reloc_info);
+#endif
+ }
+ /* read the object value from the current image, if so ordered */
+ if (reloc_info & ROP_R) { /* relocation reads current image value */
+ val = dload_unpack(dlthis, data, fieldsz, offset,
+ RFV_SIGN(reloc_info));
+#ifdef RFV_SCALE
+ val <<= scale;
+#endif
+ }
+ /* perform the necessary arithmetic */
+ switch (RFV_ACTION(reloc_action)) { /* relocation actions */
+ case RACT_VAL:
+ break;
+ case RACT_ASGN:
+ val = reloc_amt;
+ break;
+ case RACT_ADD:
+ val += reloc_amt;
+ break;
+ case RACT_PCR:
+ /*-----------------------------------------------------------
+ * Handle special cases of jumping from absolute sections
+ * (special reloc type) or to absolute destination
+ * (symndx == -1). In either case, set the appropriate
+ * relocation amount to 0.
+ *-----------------------------------------------------------*/
+ if (rp->r_symndx == -1)
+ reloc_amt = 0;
+ val += reloc_amt - dlthis->delta_runaddr;
+ break;
+ case RACT_ADDISP:
+ val += rp->r_disp + reloc_amt;
+ break;
+ case RACT_ASGPC:
+ val = dlthis->image_secn->run_addr + reloc_amt;
+ break;
+ case RACT_PLUS:
+ if (stackp != NULL)
+ val += *stackp;
+ break;
+ case RACT_SUB:
+ if (stackp != NULL)
+ val = *stackp - val;
+ break;
+ case RACT_NEG:
+ val = -val;
+ break;
+ case RACT_MPY:
+ if (stackp != NULL)
+ val *= *stackp;
+ break;
+ case RACT_DIV:
+ if (stackp != NULL)
+ val = *stackp / val;
+ break;
+ case RACT_MOD:
+ if (stackp != NULL)
+ val = *stackp % val;
+ break;
+ case RACT_SR:
+ if (val >= sizeof(RVALUE) * BITS_PER_AU)
+ val = 0;
+ else if (stackp != NULL)
+ val = (URVALUE)*stackp >> val;
+ break;
+ case RACT_ASR:
+ if (val >= sizeof(RVALUE)*BITS_PER_AU)
+ val = sizeof(RVALUE)*BITS_PER_AU - 1;
+ else if (stackp != NULL)
+ val = *stackp >> val;
+ break;
+ case RACT_SL:
+ if (val >= sizeof(RVALUE)*BITS_PER_AU)
+ val = 0;
+ else if (stackp != NULL)
+ val = *stackp << val;
+ break;
+ case RACT_AND:
+ if (stackp != NULL)
+ val &= *stackp;
+ break;
+ case RACT_OR:
+ if (stackp != NULL)
+ val |= *stackp;
+ break;
+ case RACT_XOR:
+ if (stackp != NULL)
+ val ^= *stackp;
+ break;
+ case RACT_NOT:
+ val = ~val;
+ break;
+#if TMS32060
+ case RACT_C6SECT:
+ /* actually needed address of secn containing symbol */
+ if (svp != NULL) {
+ if (rp->r_symndx >= 0)
+ if (svp->secnn > 0)
+ reloc_amt = dlthis->ldr_sections
+ [svp->secnn-1].run_addr;
+ }
+ /* !!! FALL THRU !!! */
+ case RACT_C6BASE:
+ if (dlthis->bss_run_base == 0) {
+ struct dynload_symbol *symp;
+ symp = dlthis->mysym->Find_Matching_Symbol
+ (dlthis->mysym, BSSSYMBOL);
+ /* lookup value of global BSS base */
+ if (symp)
+ dlthis->bss_run_base = symp->value;
+ else
+ dload_error(dlthis,
+ "Global BSS base referenced in %s offset"\
+ FMT_UI32 " but not defined",
+ dlthis->image_secn->name,
+ rp->r_vaddr + dlthis->image_offset);
+ }
+ reloc_amt -= dlthis->bss_run_base;
+ /* !!! FALL THRU !!! */
+ case RACT_C6DSPL:
+ /* scale factor determined by 3 LSBs of field */
+ scale = C60_Scale[val & SCALE_MASK];
+ offset += SCALE_BITS;
+ fieldsz -= SCALE_BITS;
+ val >>= SCALE_BITS; /* ignore the scale field hereafter */
+ val <<= scale;
+ val += reloc_amt; /* do the usual relocation */
+ if (((1 << scale)-1) & val)
+ dload_error(dlthis,
+ "Unaligned reference in %s offset " FMT_UI32,
+ dlthis->image_secn->name,
+ rp->r_vaddr + dlthis->image_offset);
+ break;
+#endif
+ } /* relocation actions */
+ /* * Put back result as required */
+ if (reloc_info & ROP_W) { /* relocation writes image value */
+#ifdef RFV_SCALE
+ val >>= scale;
+#endif
+ if (dload_repack(dlthis, val, data, fieldsz, offset,
+ RFV_SIGN(reloc_info))) {
+ dload_error(dlthis, "Relocation value " FMT_UI32
+ " overflows %d bits in %s offset " FMT_UI32, val,
+ fieldsz, dlthis->image_secn->name,
+ dlthis->image_offset + rp->r_vaddr);
+ }
+ } else if (top)
+ *stackp = val;
+} /* reloc_value */
+
diff --git a/drivers/dsp/bridge/dynload/reloc_table.h b/drivers/dsp/bridge/dynload/reloc_table.h
new file mode 100644
index 000000000000..6326146c6dc9
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/reloc_table.h
@@ -0,0 +1,102 @@
+/*
+ * reloc_table.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#ifndef __RELOC_TABLE_H__
+#define __RELOC_TABLE_H__
+/*
+ * Table of relocation operator properties
+ */
+#include <linux/types.h>
+
+/* How does this relocation operation access the program image? */
+#define ROP_N 0 /* does not access image */
+#define ROP_R 1 /* read from image */
+#define ROP_W 2 /* write to image */
+#define ROP_RW 3 /* read from and write to image */
+
+/* For program image access, what are the overflow rules for the bit field? */
+/* Beware! Procedure repack depends on this encoding */
+#define ROP_ANY 0 /* no overflow ever, just truncate the value */
+#define ROP_SGN 1 /* signed field */
+#define ROP_UNS 2 /* unsigned field */
+#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
+
+/* How does the relocation operation use the symbol reference */
+#define ROP_IGN 0 /* no symbol is referenced */
+#define ROP_LIT 0 /* use rp->r_uval literal field */
+#define ROP_SYM 1 /* symbol value is used in relocation */
+#define ROP_SYMD 2 /* delta value vs last link is used */
+
+/* How does the reloc op use the stack? */
+#define RSTK_N 0 /* Does not use */
+#define RSTK_POP 1 /* Does a POP */
+#define RSTK_UOP 2 /* Unary op, stack position unaffected */
+#define RSTK_PSH 3 /* Does a push */
+
+/*
+ * Computational actions performed by the dynamic loader
+ */
+enum Dload_Actions {
+ RACT_VAL, /* don't alter the current val (from stack or mem fetch) */
+ RACT_ASGN, /* set value to reference amount (from symbol reference) */
+ RACT_ADD, /* add reference to value */
+ RACT_PCR, /* add reference minus PC delta to value */
+ RACT_ADDISP, /* add reference plus r_disp */
+ RACT_ASGPC, /* set value to section address plus reference */
+
+ RACT_PLUS, /* stack + */
+ RACT_SUB, /* stack - */
+ RACT_NEG, /* stack unary - */
+
+ RACT_MPY, /* stack * */
+ RACT_DIV, /* stack / */
+ RACT_MOD, /* stack % */
+
+ RACT_SR, /* stack unsigned >> */
+ RACT_ASR, /* stack signed >> */
+ RACT_SL, /* stack << */
+ RACT_AND, /* stack & */
+ RACT_OR, /* stack | */
+ RACT_XOR, /* stack ^ */
+ RACT_NOT, /* stack ~ */
+ RACT_C6SECT, /* for C60 R_SECT op */
+ RACT_C6BASE, /* for C60 R_BASE op */
+ RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
+ RACT_PCR23T /* for ARM Thumb long branch */
+};
+
+/*
+ * macros used to extract values
+ */
+#define RFV_POSN(aaa) ((aaa) & 0xF)
+#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
+#define RFV_ACTION(aaa) ((aaa) >> 10)
+
+#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
+#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
+#define RFV_STK(iii) (((iii) >> 6) & 0x3)
+#define RFV_ACCS(iii) ((iii) & 0x3)
+
+#if (TMS32060)
+#define RFV_SCALE(iii) ((iii) >> 11)
+#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
+#else
+#define RFV_BIGOFF(iii) ((iii) >> 8)
+#endif
+
+#endif /* __RELOC_TABLE_H__ */
diff --git a/drivers/dsp/bridge/dynload/reloc_table_c6000.c b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
new file mode 100644
index 000000000000..978834c069e0
--- /dev/null
+++ b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
@@ -0,0 +1,258 @@
+/*
+ * reloc_table_c6000.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/* Tables generated for c6000 */
+
+#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
+#define HASH_L(zz) ((zz) >> 8)
+#define HASH_I(zz) ((zz) & 0xFF)
+
+static const u16 rop_map1[] = {
+ 0,
+ 1,
+ 2,
+ 20,
+ 4,
+ 5,
+ 6,
+ 15,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 17,
+ 18,
+ 19,
+ 21,
+ 16,
+ 16394,
+ 16404,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 32,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 40,
+ 112,
+ 113,
+ 65535,
+ 16384,
+ 16385,
+ 16386,
+ 16387,
+ 16388,
+ 16389,
+ 16390,
+ 16391,
+ 16392,
+ 16393,
+ 16395,
+ 16396,
+ 16397,
+ 16398,
+ 16399,
+ 16400,
+ 16401,
+ 16402,
+ 16403,
+ 16405,
+ 16406,
+ 65535,
+ 65535,
+ 65535
+};
+
+static const s16 rop_map2[] = {
+ -256,
+ -255,
+ -254,
+ -245,
+ -253,
+ -252,
+ -251,
+ -250,
+ -241,
+ -240,
+ -239,
+ -238,
+ -237,
+ -236,
+ 1813,
+ 5142,
+ -248,
+ -247,
+ 778,
+ -244,
+ -249,
+ -221,
+ -211,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -243,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -242,
+ -233,
+ -232,
+ -1,
+ -231,
+ -230,
+ -229,
+ -228,
+ -227,
+ -226,
+ -225,
+ -224,
+ -223,
+ 5410,
+ -220,
+ -219,
+ -218,
+ -217,
+ -216,
+ -215,
+ -214,
+ -213,
+ 5676,
+ -210,
+ -209,
+ -1,
+ -1,
+ -1
+};
+
+static const u16 rop_action[] = {
+ 2560,
+ 2304,
+ 2304,
+ 2432,
+ 2432,
+ 2560,
+ 2176,
+ 2304,
+ 2560,
+ 3200,
+ 3328,
+ 3584,
+ 3456,
+ 2304,
+ 4208,
+ 20788,
+ 21812,
+ 3415,
+ 3245,
+ 2311,
+ 4359,
+ 19764,
+ 2311,
+ 3191,
+ 3280,
+ 6656,
+ 7680,
+ 8704,
+ 9728,
+ 10752,
+ 11776,
+ 12800,
+ 13824,
+ 14848,
+ 15872,
+ 16896,
+ 17920,
+ 18944,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1536,
+ 1536,
+ 1536,
+ 5632,
+ 512,
+ 0
+};
+
+static const u16 rop_info[] = {
+ 0,
+ 35,
+ 35,
+ 35,
+ 35,
+ 35,
+ 35,
+ 35,
+ 35,
+ 39,
+ 39,
+ 39,
+ 39,
+ 35,
+ 34,
+ 283,
+ 299,
+ 4135,
+ 4391,
+ 291,
+ 33059,
+ 283,
+ 295,
+ 4647,
+ 4135,
+ 64,
+ 64,
+ 128,
+ 64,
+ 64,
+ 64,
+ 64,
+ 64,
+ 64,
+ 64,
+ 64,
+ 64,
+ 128,
+ 201,
+ 197,
+ 74,
+ 70,
+ 208,
+ 196,
+ 200,
+ 192,
+ 192,
+ 66
+};
diff --git a/drivers/dsp/bridge/gen/_gt_para.c b/drivers/dsp/bridge/gen/_gt_para.c
new file mode 100644
index 000000000000..181fe41b54e5
--- /dev/null
+++ b/drivers/dsp/bridge/gen/_gt_para.c
@@ -0,0 +1,107 @@
+/*
+ * _gt_para.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _gt_para.c ========
+ * Description:
+ * Configuration parameters for GT. This file is separated from
+ * gt.c so that GT_assert() can reference the error function without
+ * forcing the linker to include all the code for GT_set(), GT_init(),
+ * etc. into a fully bound image. Thus, GT_assert() can be retained in
+ * a program for which GT_?trace() has been compiled out.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 vp: Code Review Updates.
+ *! 18-Oct-2002 sb: Ported to Linux platform.
+ *! 03-Jul-2001 rr: Removed kfuncs.h because of build errors.
+ *! 07-Dec-1999 ag: Fxn error now causes a WinCE DebugBreak;
+ *! 30-Aug-1999 ag: Now uses GP_printf for printf and error.
+ *!
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- Function Prototypes */
+static void error(char *msg, ...);
+static s32 GT_nop(void);
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+
+struct GT_Config _GT_params = {
+ (Fxn) printk, /* printf */
+ (Fxn) NULL, /* procid */
+ (Fxn) GT_nop, /* taskid */
+ (Fxn) error, /* error */
+};
+
+/* ----------------------------------- Globals */
+struct GT_Config *GT = &_GT_params;
+
+/*
+ * ======== GT_nop ========
+ */
+static s32 GT_nop(void)
+{
+ return 0;
+}
+
+/*
+ * ======== error ========
+ * purpose:
+ * Prints error onto the standard output.
+ */
+static void error(char *fmt, ...)
+{
+ s32 arg1, arg2, arg3, arg4, arg5, arg6;
+
+ va_list va;
+
+ va_start(va, fmt);
+
+ arg1 = va_arg(va, s32);
+ arg2 = va_arg(va, s32);
+ arg3 = va_arg(va, s32);
+ arg4 = va_arg(va, s32);
+ arg5 = va_arg(va, s32);
+ arg6 = va_arg(va, s32);
+
+ va_end(va);
+
+ printk("ERROR: ");
+ printk(fmt, arg1, arg2, arg3, arg4, arg5, arg6);
+
+#if defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)
+ if (in_interrupt()) {
+ printk(KERN_INFO "Not stopping after error since ISR/DPC "
+ "are disabled\n");
+ } else {
+ set_current_state(TASK_INTERRUPTIBLE);
+ flush_signals(current);
+ schedule();
+ flush_signals(current);
+ printk(KERN_INFO "Signaled in error function\n");
+ }
+#endif
+}
diff --git a/drivers/dsp/bridge/gen/gb.c b/drivers/dsp/bridge/gen/gb.c
new file mode 100644
index 000000000000..1d21e9743cca
--- /dev/null
+++ b/drivers/dsp/bridge/gen/gb.c
@@ -0,0 +1,182 @@
+/*
+ * gb.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== gb.c ========
+ * Description: Generic bitmap operations.
+ *
+ *! Revision History
+ *! ================
+ *! 24-Feb-2003 vp Code review updates.
+ *! 17-Dec-2002 map Fixed GB_minset(), GB_empty(), and GB_full(),
+ *! to ensure only 'len' bits are considered in the map
+ *! 18-Oct-2002 sb Ported to Linux platform.
+ *! 06-Dec-2001 jeh Fixed bug in GB_minclear().
+ *!
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <linux/types.h>
+/* ----------------------------------- This */
+#include <dspbridge/gs.h>
+#include <dspbridge/gb.h>
+
+typedef GB_BitNum GB_WordNum;
+
+struct GB_TMap {
+ GB_BitNum len;
+ GB_WordNum wcnt;
+ u32 *words;
+};
+
+/*
+ * ======== GB_clear ========
+ * purpose:
+ * Clears a bit in the bit map.
+ */
+
+void GB_clear(struct GB_TMap *map, GB_BitNum bitn)
+{
+ u32 mask;
+
+ mask = 1L << (bitn % BITS_PER_LONG);
+ map->words[bitn / BITS_PER_LONG] &= ~mask;
+}
+
+/*
+ * ======== GB_create ========
+ * purpose:
+ * Creates a bit map.
+ */
+
+struct GB_TMap *GB_create(GB_BitNum len)
+{
+ struct GB_TMap *map;
+ GB_WordNum i;
+ map = (struct GB_TMap *)GS_alloc(sizeof(struct GB_TMap));
+ if (map != NULL) {
+ map->len = len;
+ map->wcnt = len / BITS_PER_LONG + 1;
+ map->words = (u32 *)GS_alloc(map->wcnt * sizeof(u32));
+ if (map->words != NULL) {
+ for (i = 0; i < map->wcnt; i++)
+ map->words[i] = 0L;
+
+ } else {
+ GS_frees(map, sizeof(struct GB_TMap));
+ map = NULL;
+ }
+ }
+
+ return map;
+}
+
+/*
+ * ======== GB_delete ========
+ * purpose:
+ * Frees a bit map.
+ */
+
+void GB_delete(struct GB_TMap *map)
+{
+ GS_frees(map->words, map->wcnt * sizeof(u32));
+ GS_frees(map, sizeof(struct GB_TMap));
+}
+
+/*
+ * ======== GB_findandset ========
+ * purpose:
+ * Finds a free bit and sets it.
+ */
+GB_BitNum GB_findandset(struct GB_TMap *map)
+{
+ GB_BitNum bitn;
+
+ bitn = GB_minclear(map);
+
+ if (bitn != GB_NOBITS)
+ GB_set(map, bitn);
+
+ return bitn;
+}
+
+/*
+ * ======== GB_minclear ========
+ * purpose:
+ * returns the location of the first unset bit in the bit map.
+ */
+GB_BitNum GB_minclear(struct GB_TMap *map)
+{
+ GB_BitNum bit_location = 0;
+ GB_BitNum bitAcc = 0;
+ GB_WordNum i;
+ GB_BitNum bit;
+ u32 *word;
+
+ for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
+ if (~*word) {
+ for (bit = 0; bit < BITS_PER_LONG; bit++, bitAcc++) {
+ if (bitAcc == map->len)
+ return GB_NOBITS;
+
+ if (~*word & (1L << bit)) {
+ bit_location = i * BITS_PER_LONG + bit;
+ return bit_location;
+ }
+
+ }
+ } else {
+ bitAcc += BITS_PER_LONG;
+ }
+ }
+
+ return GB_NOBITS;
+}
+
+/*
+ * ======== GB_set ========
+ * purpose:
+ * Sets a bit in the bit map.
+ */
+
+void GB_set(struct GB_TMap *map, GB_BitNum bitn)
+{
+ u32 mask;
+
+ mask = 1L << (bitn % BITS_PER_LONG);
+ map->words[bitn / BITS_PER_LONG] |= mask;
+}
+
+/*
+ * ======== GB_test ========
+ * purpose:
+ * Returns true if the bit is set in the specified location.
+ */
+
+bool GB_test(struct GB_TMap *map, GB_BitNum bitn)
+{
+ bool state;
+ u32 mask;
+ u32 word;
+
+ mask = 1L << (bitn % BITS_PER_LONG);
+ word = map->words[bitn / BITS_PER_LONG];
+ state = word & mask ? TRUE : FALSE;
+
+ return state;
+}
diff --git a/drivers/dsp/bridge/gen/gh.c b/drivers/dsp/bridge/gen/gh.c
new file mode 100644
index 000000000000..a20ae16314e8
--- /dev/null
+++ b/drivers/dsp/bridge/gen/gh.c
@@ -0,0 +1,191 @@
+/*
+ * gh.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== gh.c ========
+ */
+
+#include <dspbridge/std.h>
+
+#include <dspbridge/host_os.h>
+
+#include <dspbridge/gs.h>
+
+#include <dspbridge/gh.h>
+
+struct Elem {
+ struct Elem *next;
+ u8 data[1];
+};
+
+struct GH_THashTab {
+ u16 maxBucket;
+ u16 valSize;
+ struct Elem **buckets;
+ u16(*hash) (void *, u16);
+ bool(*match) (void *, void *);
+ void(*delete) (void *);
+};
+
+static void Nop(void *p);
+static s32 curInit;
+static void myfree(void *ptr, s32 size);
+
+/*
+ * ======== GH_create ========
+ */
+
+struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
+ u16(*hash)(void *, u16), bool(*match)(void *, void *),
+ void(*delete)(void *))
+{
+ struct GH_THashTab *hashTab;
+ u16 i;
+ hashTab = (struct GH_THashTab *)GS_alloc(sizeof(struct GH_THashTab));
+ if (hashTab == NULL)
+ return NULL;
+ hashTab->maxBucket = maxBucket;
+ hashTab->valSize = valSize;
+ hashTab->hash = hash;
+ hashTab->match = match;
+ hashTab->delete = delete == NULL ? Nop : delete;
+
+ hashTab->buckets = (struct Elem **)
+ GS_alloc(sizeof(struct Elem *) * maxBucket);
+ if (hashTab->buckets == NULL) {
+ GH_delete(hashTab);
+ return NULL;
+ }
+
+ for (i = 0; i < maxBucket; i++)
+ hashTab->buckets[i] = NULL;
+
+ return hashTab;
+}
+
+/*
+ * ======== GH_delete ========
+ */
+void GH_delete(struct GH_THashTab *hashTab)
+{
+ struct Elem *elem, *next;
+ u16 i;
+
+ if (hashTab != NULL) {
+ if (hashTab->buckets != NULL) {
+ for (i = 0; i < hashTab->maxBucket; i++) {
+ for (elem = hashTab->buckets[i]; elem != NULL;
+ elem = next) {
+ next = elem->next;
+ (*hashTab->delete) (elem->data);
+ myfree(elem, sizeof(struct Elem) - 1 +
+ hashTab->valSize);
+ }
+ }
+
+ myfree(hashTab->buckets, sizeof(struct Elem *)
+ * hashTab->maxBucket);
+ }
+
+ myfree(hashTab, sizeof(struct GH_THashTab));
+ }
+}
+
+/*
+ * ======== GH_exit ========
+ */
+
+void GH_exit(void)
+{
+ if (curInit-- == 1)
+ GS_exit();
+
+}
+
+/*
+ * ======== GH_find ========
+ */
+
+void *GH_find(struct GH_THashTab *hashTab, void *key)
+{
+ struct Elem *elem;
+
+ elem = hashTab->buckets[(*hashTab->hash)(key, hashTab->maxBucket)];
+
+ for (; elem; elem = elem->next) {
+ if ((*hashTab->match)(key, elem->data))
+ return elem->data;
+ }
+
+ return NULL;
+}
+
+/*
+ * ======== GH_init ========
+ */
+
+void GH_init(void)
+{
+ if (curInit++ == 0)
+ GS_init();
+}
+
+/*
+ * ======== GH_insert ========
+ */
+
+void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value)
+{
+ struct Elem *elem;
+ u16 i;
+ char *src, *dst;
+
+ elem = (struct Elem *)GS_alloc(sizeof(struct Elem) - 1 +
+ hashTab->valSize);
+ if (elem != NULL) {
+
+ dst = (char *)elem->data;
+ src = (char *)value;
+ for (i = 0; i < hashTab->valSize; i++)
+ *dst++ = *src++;
+
+ i = (*hashTab->hash)(key, hashTab->maxBucket);
+ elem->next = hashTab->buckets[i];
+ hashTab->buckets[i] = elem;
+
+ return elem->data;
+ }
+
+ return NULL;
+}
+
+/*
+ * ======== Nop ========
+ */
+/* ARGSUSED */
+static void Nop(void *p)
+{
+ p = p; /* stifle compiler warning */
+}
+
+/*
+ * ======== myfree ========
+ */
+static void myfree(void *ptr, s32 size)
+{
+ GS_free(ptr);
+}
diff --git a/drivers/dsp/bridge/gen/gs.c b/drivers/dsp/bridge/gen/gs.c
new file mode 100644
index 000000000000..ef5f923f5423
--- /dev/null
+++ b/drivers/dsp/bridge/gen/gs.c
@@ -0,0 +1,108 @@
+/*
+ * gs.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== gs.c ========
+ * Description:
+ * General storage memory allocator services.
+ *
+ *! Revision History
+ *! ================
+ *! 29-Sep-1999 ag: Un-commented MEM_Init in GS_init().
+ *! 14-May-1997 mg: Modified to use new GS API for GS_free() and GS_frees().
+ *! 06-Nov-1996 gp: Re-commented MEM_Init in GS_init(). GS needs GS_Exit().
+ *! 21-Oct-1996 db: Un-commented MEM_Init in GS_init().
+ *! 21-May-1996 mg: Created from original stdlib implementation.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <linux/types.h>
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/gs.h>
+
+/* ----------------------------------- Globals */
+static u32 cumsize;
+
+/*
+ * ======== GS_alloc ========
+ * purpose:
+ * Allocates memory of the specified size.
+ */
+void *GS_alloc(u32 size)
+{
+ void *p;
+
+ p = MEM_Calloc(size, MEM_PAGED);
+ if (p == NULL)
+ return NULL;
+ cumsize += size;
+ return p;
+}
+
+/*
+ * ======== GS_exit ========
+ * purpose:
+ * Discontinue the usage of the GS module.
+ */
+void GS_exit(void)
+{
+ MEM_Exit();
+}
+
+/*
+ * ======== GS_free ========
+ * purpose:
+ * Frees the memory.
+ */
+void GS_free(void *ptr)
+{
+ MEM_Free(ptr);
+ /* ack! no size info */
+ /* cumsize -= size; */
+}
+
+/*
+ * ======== GS_frees ========
+ * purpose:
+ * Frees the memory.
+ */
+void GS_frees(void *ptr, u32 size)
+{
+ MEM_Free(ptr);
+ cumsize -= size;
+}
+
+/*
+ * ======== GS_init ========
+ * purpose:
+ * Initializes the GS module.
+ */
+void GS_init(void)
+{
+ static bool curInit;
+
+ if (curInit == false) {
+ curInit = true;
+
+ MEM_Init();
+ }
+}
diff --git a/drivers/dsp/bridge/gen/gt.c b/drivers/dsp/bridge/gen/gt.c
new file mode 100644
index 000000000000..452d6e6661fe
--- /dev/null
+++ b/drivers/dsp/bridge/gen/gt.c
@@ -0,0 +1,348 @@
+/*
+ * gt.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== gt.c ========
+ * Description: This module implements the trace mechanism for bridge.
+ *
+ *! Revision History
+ *! ================
+ *! 16-May-1997 dr Changed GT_Config member names to conform to coding
+ *! standards.
+ *! 23-Apr-1997 ge Check for GT->TIDFXN for NULL before calling it.
+ *! 03-Jan-1997 ge Changed GT_Config structure member names to eliminate
+ *! preprocessor confusion with other macros.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/gt.h>
+
+#define GT_WILD '*'
+
+#define GT_CLEAR '='
+#define GT_ON '+'
+#define GT_OFF '-'
+
+enum GT_State {
+ GT_SEP,
+ GT_FIRST,
+ GT_SECOND,
+ GT_OP,
+ GT_DIGITS
+} ;
+
+#ifdef CONFIG_BRIDGE_DEBUG
+static char *GT_1format = "%s - %d: ";
+static char *GT_2format = "%s - %d(%d): ";
+#endif /* CONFIG_BRIDGE_DEBUG */
+
+static unsigned char *GT_tMask[GT_BOUND];
+
+static bool curInit;
+static char *separator;
+static unsigned char tabMem[GT_BOUND][sizeof(unsigned char) * GT_BOUND];
+
+static void error(char *string);
+static void setMask(s16 index1, s16 index2, char op, unsigned char mask);
+
+/*
+ * ======== _GT_create ========
+ * purpose:
+ * Creates GT mask.
+ */
+void _GT_create(struct GT_Mask *mask, char *modName)
+{
+ mask->modName = modName;
+ mask->flags = &(GT_tMask[modName[0] - 'A'][modName[1] - 'A']);
+}
+
+/*
+ * ======== GT_init ========
+ * purpose:
+ * Initializes GT module.
+ */
+#ifdef GT_init
+#undef GT_init
+#endif
+void GT_init(void)
+{
+ register unsigned char index1;
+ register unsigned char index2;
+
+ if (!curInit) {
+ curInit = true;
+
+ separator = " ,;/";
+
+ for (index1 = 0; index1 < GT_BOUND; index1++) {
+ GT_tMask[index1] = tabMem[index1];
+ for (index2 = 0; index2 < GT_BOUND; index2++) {
+ /* no tracing */
+ GT_tMask[index1][index2] = 0x00;
+ }
+ }
+ }
+}
+
+/*
+ * ======== _GT_set ========
+ * purpose:
+ * Sets the trace string format.
+ */
+
+void _GT_set(char *str)
+{
+ enum GT_State state;
+ char *sep;
+ s16 index1 = GT_BOUND; /* indicates all values */
+ s16 index2 = GT_BOUND; /* indicates all values */
+ char op = GT_CLEAR;
+ bool maskValid;
+ s16 digit;
+ register unsigned char mask = 0x0; /* no tracing */
+
+ if (str == NULL)
+ return;
+
+ maskValid = false;
+ state = GT_SEP;
+ while (*str != '\0') {
+ switch ((s32) state) {
+ case (s32) GT_SEP:
+ maskValid = false;
+ sep = separator;
+ while (*sep != '\0') {
+ if (*str == *sep) {
+ str++;
+ break;
+ } else {
+ sep++;
+ }
+ }
+ if (*sep == '\0')
+ state = GT_FIRST;
+
+ break;
+ case (s32) GT_FIRST:
+ if (*str == GT_WILD) {
+ /* indicates all values */
+ index1 = GT_BOUND;
+ /* indicates all values */
+ index2 = GT_BOUND;
+ state = GT_OP;
+ } else {
+ if (*str >= 'a')
+ index1 = (s16) (*str - 'a');
+ else
+ index1 = (s16) (*str - 'A');
+ if ((index1 >= 0) && (index1 < GT_BOUND))
+ state = GT_SECOND;
+ else
+ state = GT_SEP;
+ }
+ str++;
+ break;
+ case (s32) GT_SECOND:
+ if (*str == GT_WILD) {
+ index2 = GT_BOUND; /* indicates all values */
+ state = GT_OP;
+ str++;
+ } else {
+ if (*str >= 'a')
+ index2 = (s16) (*str - 'a');
+ else
+ index2 = (s16) (*str - 'A');
+ if ((index2 >= 0) && (index2 < GT_BOUND)) {
+ state = GT_OP;
+ str++;
+ } else {
+ state = GT_SEP;
+ }
+ }
+ break;
+ case (s32) GT_OP:
+ op = *str;
+ mask = 0x0; /* no tracing */
+ switch (op) {
+ case (s32) GT_CLEAR:
+ maskValid = true;
+ case (s32) GT_ON:
+ case (s32) GT_OFF:
+ state = GT_DIGITS;
+ str++;
+ break;
+ default:
+ state = GT_SEP;
+ break;
+ }
+ break;
+ case (s32) GT_DIGITS:
+ digit = (s16) (*str - '0');
+ if ((digit >= 0) && (digit <= 7)) {
+ mask |= (0x01 << digit);
+ maskValid = true;
+ str++;
+ } else {
+ if (maskValid == true) {
+ setMask(index1, index2, op, mask);
+ maskValid = false;
+ }
+ state = GT_SEP;
+ }
+ break;
+ default:
+ error("illegal trace mask");
+ break;
+ }
+ }
+
+ if (maskValid)
+ setMask(index1, index2, op, mask);
+}
+
+/*
+ * ======== _GT_trace ========
+ * purpose:
+ * Prints the input string onto standard output
+ */
+
+s32 _GT_trace(struct GT_Mask *mask, char *format, ...)
+{
+ s32 arg1, arg2, arg3, arg4, arg5, arg6;
+ va_list va;
+
+ va_start(va, format);
+
+ arg1 = va_arg(va, s32);
+ arg2 = va_arg(va, s32);
+ arg3 = va_arg(va, s32);
+ arg4 = va_arg(va, s32);
+ arg5 = va_arg(va, s32);
+ arg6 = va_arg(va, s32);
+
+ va_end(va);
+#ifdef DEBUG
+ if (GT->PIDFXN == NULL) {
+ printk(GT_1format, mask->modName, GT->TIDFXN ?
+ (*GT->TIDFXN)() : 0);
+ } else {
+ printk(GT_2format, mask->modName, (*GT->PIDFXN)(),
+ GT->TIDFXN ? (*GT->TIDFXN)() : 0);
+ }
+#endif
+ printk(format, arg1, arg2, arg3, arg4, arg5, arg6);
+
+ return 0;
+}
+
+/*
+ * ======== error ========
+ * purpose:
+ * Prints errors onto the standard output.
+ */
+static void error(char *string)
+{
+ printk("GT: %s", string);
+}
+
+/*
+ * ======== setmask ========
+ * purpose:
+ * Sets mask for the GT module.
+ */
+
+static void setMask(s16 index1, s16 index2, char op, u8 mask)
+{
+ register s16 index;
+
+ if (index1 < GT_BOUND) {
+ if (index2 < GT_BOUND) {
+ switch (op) {
+ case (s32) GT_CLEAR:
+ GT_tMask[index1][index2] = mask;
+ break;
+ case (s32) GT_ON:
+ GT_tMask[index1][index2] |= mask;
+ break;
+ case (s32) GT_OFF:
+ GT_tMask[index1][index2] &= ~mask;
+ break;
+ default:
+ error("illegal trace mask");
+ break;
+ }
+ } else {
+ for (index2--; index2 >= 0; index2--) {
+ switch (op) {
+ case (s32) GT_CLEAR:
+ GT_tMask[index1][index2] = mask;
+ break;
+ case (s32) GT_ON:
+ GT_tMask[index1][index2] |= mask;
+ break;
+ case (s32) GT_OFF:
+ GT_tMask[index1][index2] &= ~mask;
+ break;
+ default:
+ error("illegal trace mask");
+ break;
+ }
+ }
+ }
+ } else {
+ for (index1--; index1 >= 0; index1--) {
+ if (index2 < GT_BOUND) {
+ switch (op) {
+ case (s32) GT_CLEAR:
+ GT_tMask[index1][index2] = mask;
+ break;
+ case (s32) GT_ON:
+ GT_tMask[index1][index2] |= mask;
+ break;
+ case (s32) GT_OFF:
+ GT_tMask[index1][index2] &= ~mask;
+ break;
+ default:
+ error("illegal trace mask");
+ break;
+ }
+ } else {
+ index = GT_BOUND;
+ for (index--; index >= 0; index--) {
+ switch (op) {
+ case (s32) GT_CLEAR:
+ GT_tMask[index1][index] = mask;
+ break;
+ case (s32) GT_ON:
+ GT_tMask[index1][index] |= mask;
+ break;
+ case (s32) GT_OFF:
+ GT_tMask[index1][index] &=
+ ~mask;
+ break;
+ default:
+ error("illegal trace mask");
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/drivers/dsp/bridge/gen/uuidutil.c b/drivers/dsp/bridge/gen/uuidutil.c
new file mode 100644
index 000000000000..a45f448847eb
--- /dev/null
+++ b/drivers/dsp/bridge/gen/uuidutil.c
@@ -0,0 +1,238 @@
+/*
+ * uuidutil.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== uuidutil.c ========
+ * Description:
+ * This file contains the implementation of UUID helper functions.
+ *
+ *! Revision History
+ *! ================
+ *! 23-Feb-2003 vp: Code review updates.
+ *! 18-Oct-2003 vp: Ported to Linux platform.
+ *! 31-Aug-2000 rr: UUID_UuidFromString bug fixed.
+ *! 29-Aug-2000 rr: Modified UUID_UuidFromString.
+ *! 09-Nov-2000 kc: Modified UUID_UuidFromString to simplify implementation.
+ *! 30-Oct-2000 kc: Modified UUID utility module function prefix.
+ *! 10-Aug-2000 kc: Created.
+ *!
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/uuidutil.h>
+
+/*
+ * ======== UUID_UuidToString ========
+ * Purpose:
+ * Converts a struct DSP_UUID to a string.
+ * Note: snprintf format specifier is:
+ * %[flags] [width] [.precision] [{h | l | I64 | L}]type
+ */
+void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
+ IN s32 size)
+{
+ s32 i; /* return result from snprintf. */
+
+ DBC_Require(pUuid && pszUuid);
+
+ i = snprintf(pszUuid, size,
+ "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
+ pUuid->ulData1, pUuid->usData2, pUuid->usData3,
+ pUuid->ucData4, pUuid->ucData5, pUuid->ucData6[0],
+ pUuid->ucData6[1], pUuid->ucData6[2], pUuid->ucData6[3],
+ pUuid->ucData6[4], pUuid->ucData6[5]);
+
+ DBC_Ensure(i != -1);
+}
+
+/*
+ * ======== htoi ========
+ * Purpose:
+ * Converts a hex value to a decimal integer.
+ */
+
+static int htoi(char c)
+{
+ switch (c) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'A':
+ return 10;
+ case 'B':
+ return 11;
+ case 'C':
+ return 12;
+ case 'D':
+ return 13;
+ case 'E':
+ return 14;
+ case 'F':
+ return 15;
+ case 'a':
+ return 10;
+ case 'b':
+ return 11;
+ case 'c':
+ return 12;
+ case 'd':
+ return 13;
+ case 'e':
+ return 14;
+ case 'f':
+ return 15;
+ }
+ return 0;
+}
+
+/*
+ * ======== UUID_UuidFromString ========
+ * Purpose:
+ * Converts a string to a struct DSP_UUID.
+ */
+void UUID_UuidFromString(IN char *pszUuid, OUT struct DSP_UUID *pUuid)
+{
+ char c;
+ s32 i, j;
+ s32 result;
+ char *temp = pszUuid;
+
+ result = 0;
+ for (i = 0; i < 8; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->ulData1 = result;
+
+ /* Step over underscore */
+ temp++;
+
+ result = 0;
+ for (i = 0; i < 4; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->usData2 = (u16)result;
+
+ /* Step over underscore */
+ temp++;
+
+ result = 0;
+ for (i = 0; i < 4; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->usData3 = (u16)result;
+
+ /* Step over underscore */
+ temp++;
+
+ result = 0;
+ for (i = 0; i < 2; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->ucData4 = (u8)result;
+
+ result = 0;
+ for (i = 0; i < 2; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->ucData5 = (u8)result;
+
+ /* Step over underscore */
+ temp++;
+
+ for (j = 0; j < 6; j++) {
+ result = 0;
+ for (i = 0; i < 2; i++) {
+ /* Get first character in string */
+ c = *temp;
+
+ /* Increase the results by new value */
+ result *= 16;
+ result += htoi(c);
+
+ /* Go to next character in string */
+ temp++;
+ }
+ pUuid->ucData6[j] = (u8)result;
+ }
+}
diff --git a/drivers/dsp/bridge/hw/EasiGlobal.h b/drivers/dsp/bridge/hw/EasiGlobal.h
new file mode 100644
index 000000000000..b023826d4394
--- /dev/null
+++ b/drivers/dsp/bridge/hw/EasiGlobal.h
@@ -0,0 +1,42 @@
+/*
+ * EasiGlobal.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef __EASIGLOBAL_H
+#define __EASIGLOBAL_H
+#include <linux/types.h>
+
+/*
+ * DEFINE: READ_ONLY, WRITE_ONLY & READ_WRITE
+ *
+ * DESCRIPTION: Defines used to describe register types for EASI-checker tests.
+ */
+
+#define READ_ONLY 1
+#define WRITE_ONLY 2
+#define READ_WRITE 3
+
+/*
+ * MACRO: _DEBUG_LEVEL_1_EASI
+ *
+ * DESCRIPTION: A MACRO which can be used to indicate that a particular beach
+ * register access function was called.
+ *
+ * NOTE: We currently dont use this functionality.
+ */
+#define _DEBUG_LEVEL_1_EASI(easiNum) ((void)0)
+
+#endif /* __EASIGLOBAL_H */
+
diff --git a/drivers/dsp/bridge/hw/GlobalTypes.h b/drivers/dsp/bridge/hw/GlobalTypes.h
new file mode 100644
index 000000000000..9004a37c0862
--- /dev/null
+++ b/drivers/dsp/bridge/hw/GlobalTypes.h
@@ -0,0 +1,325 @@
+/*
+ * GlobalTypes.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+/*
+ * ======== GlobalTypes.h ========
+ * Description:
+ * Global HW definitions
+ *
+ *! Revision History:
+ *! ================
+ *! 16 Feb 2003 sb: Initial version
+ */
+#ifndef __GLOBALTYPES_H
+#define __GLOBALTYPES_H
+
+/*
+ * Definition: TRUE, FALSE
+ *
+ * DESCRIPTION: Boolean Definitions
+ */
+#ifndef TRUE
+#define FALSE 0
+#define TRUE (!(FALSE))
+#endif
+
+/*
+ * Definition: NULL
+ *
+ * DESCRIPTION: Invalid pointer
+ */
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+/*
+ * Definition: RET_CODE_BASE
+ *
+ * DESCRIPTION: Base value for return code offsets
+ */
+#define RET_CODE_BASE 0
+
+/*
+ * Definition: *BIT_OFFSET
+ *
+ * DESCRIPTION: offset in bytes from start of 32-bit word.
+ */
+#define LOWER_16BIT_OFFSET 0
+#define UPPER_16BIT_OFFSET 2
+
+#define LOWER_8BIT_OFFSET 0
+#define LOWER_MIDDLE_8BIT_OFFSET 1
+#define UPPER_MIDDLE_8BIT_OFFSET 2
+#define UPPER_8BIT_OFFSET 3
+
+#define LOWER_8BIT_OF16_OFFSET 0
+#define UPPER_8BIT_OF16_OFFSET 1
+
+/*
+ * Definition: *BIT_SHIFT
+ *
+ * DESCRIPTION: offset in bits from start of 32-bit word.
+ */
+#define LOWER_16BIT_SHIFT 0
+#define UPPER_16BIT_SHIFT 16
+
+#define LOWER_8BIT_SHIFT 0
+#define LOWER_MIDDLE_8BIT_SHIFT 8
+#define UPPER_MIDDLE_8BIT_SHIFT 16
+#define UPPER_8BIT_SHIFT 24
+
+#define LOWER_8BIT_OF16_SHIFT 0
+#define UPPER_8BIT_OF16_SHIFT 8
+
+
+/*
+ * Definition: LOWER_16BIT_MASK
+ *
+ * DESCRIPTION: 16 bit mask used for inclusion of lower 16 bits i.e. mask out
+ * the upper 16 bits
+ */
+#define LOWER_16BIT_MASK 0x0000FFFF
+
+
+/*
+ * Definition: LOWER_8BIT_MASK
+ *
+ * DESCRIPTION: 8 bit masks used for inclusion of 8 bits i.e. mask out
+ * the upper 16 bits
+ */
+#define LOWER_8BIT_MASK 0x000000FF
+
+/*
+ * Definition: RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits, upper16Bits)
+ *
+ * DESCRIPTION: Returns a 32 bit value given a 16 bit lower value and a 16
+ * bit upper value
+ */
+#define RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits,upper16Bits)\
+ (((((u32)lower16Bits) & LOWER_16BIT_MASK)) | \
+ (((((u32)upper16Bits) & LOWER_16BIT_MASK) << UPPER_16BIT_SHIFT)))
+
+/*
+ * Definition: RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower16Bits, upper16Bits)
+ *
+ * DESCRIPTION: Returns a 16 bit value given a 8 bit lower value and a 8
+ * bit upper value
+ */
+#define RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower8Bits,upper8Bits)\
+ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
+ (((((u32)upper8Bits) & LOWER_8BIT_MASK) << UPPER_8BIT_OF16_SHIFT)))
+
+/*
+ * Definition: RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,
+ * lowerUpper8Bits, upper8Bits)
+ *
+ * DESCRIPTION: Returns a 32 bit value given four 8 bit values
+ */
+#define RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,\
+ lowerUpper8Bits, upper8Bits)\
+ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
+ (((((u32)lowerMiddle8Bits) & LOWER_8BIT_MASK) <<\
+ LOWER_MIDDLE_8BIT_SHIFT)) | \
+ (((((u32)lowerUpper8Bits) & LOWER_8BIT_MASK) <<\
+ UPPER_MIDDLE_8BIT_SHIFT)) | \
+ (((((u32)upper8Bits) & LOWER_8BIT_MASK) <<\
+ UPPER_8BIT_SHIFT)))
+
+/*
+ * Definition: READ_LOWER_16BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 16 lower bits of 32bit value
+ */
+#define READ_LOWER_16BITS_OF_32(value32bits)\
+ ((u16)((u32)(value32bits) & LOWER_16BIT_MASK))
+
+/*
+ * Definition: READ_UPPER_16BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 16 lower bits of 32bit value
+ */
+#define READ_UPPER_16BITS_OF_32(value32bits)\
+ (((u16)((u32)(value32bits) >> UPPER_16BIT_SHIFT)) &\
+ LOWER_16BIT_MASK)
+
+
+/*
+ * Definition: READ_LOWER_8BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 8 lower bits of 32bit value
+ */
+#define READ_LOWER_8BITS_OF_32(value32bits)\
+ ((u8)((u32)(value32bits) & LOWER_8BIT_MASK))
+
+/*
+ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
+ */
+#define READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)\
+ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
+ LOWER_8BIT_MASK)
+
+/*
+ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
+ */
+#define READ_UPPER_MIDDLE_8BITS_OF_32(value32bits)\
+ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
+ LOWER_8BIT_MASK)
+
+/*
+ * Definition: READ_UPPER_8BITS_OF_32(value32bits)
+ *
+ * DESCRIPTION: Returns a 8 upper bits of 32bit value
+ */
+#define READ_UPPER_8BITS_OF_32(value32bits)\
+ (((u8)((u32)(value32bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
+
+
+/*
+ * Definition: READ_LOWER_8BITS_OF_16(value16bits)
+ *
+ * DESCRIPTION: Returns a 8 lower bits of 16bit value
+ */
+#define READ_LOWER_8BITS_OF_16(value16bits)\
+ ((u8)((u16)(value16bits) & LOWER_8BIT_MASK))
+
+/*
+ * Definition: READ_UPPER_8BITS_OF_16(value32bits)
+ *
+ * DESCRIPTION: Returns a 8 upper bits of 16bit value
+ */
+#define READ_UPPER_8BITS_OF_16(value16bits)\
+ (((u8)((u32)(value16bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
+
+
+
+/* UWORD16: 16 bit tpyes */
+
+
+/* REG_UWORD8, REG_WORD8: 8 bit register types */
+typedef volatile unsigned char REG_UWORD8;
+typedef volatile signed char REG_WORD8;
+
+/* REG_UWORD16, REG_WORD16: 16 bit register types */
+#ifndef OMAPBRIDGE_TYPES
+typedef volatile unsigned short REG_UWORD16;
+#endif
+typedef volatile short REG_WORD16;
+
+/* REG_UWORD32, REG_WORD32: 32 bit register types */
+typedef volatile unsigned long REG_UWORD32;
+
+/* FLOAT
+ *
+ * Type to be used for floating point calculation. Note that floating point
+ * calculation is very CPU expensive, and you should only use if you
+ * absolutely need this. */
+
+
+/* boolean_t: Boolean Type True, False */
+/* ReturnCode_t: Return codes to be returned by all library functions */
+typedef enum ReturnCode_label {
+ RET_OK = 0,
+ RET_FAIL = -1,
+ RET_BAD_NULL_PARAM = -2,
+ RET_PARAM_OUT_OF_RANGE = -3,
+ RET_INVALID_ID = -4,
+ RET_EMPTY = -5,
+ RET_FULL = -6,
+ RET_TIMEOUT = -7,
+ RET_INVALID_OPERATION = -8,
+
+ /* Add new error codes at end of above list */
+
+ RET_NUM_RET_CODES /* this should ALWAYS be LAST entry */
+} ReturnCode_t, *pReturnCode_t;
+
+/* MACRO: RD_MEM_8, WR_MEM_8
+ *
+ * DESCRIPTION: 32 bit memory access macros
+ */
+#define RD_MEM_8(addr) ((u8)(*((u8 *)(addr))))
+#define WR_MEM_8(addr, data) (*((u8 *)(addr)) = (u8)(data))
+
+/* MACRO: RD_MEM_8_VOLATILE, WR_MEM_8_VOLATILE
+ *
+ * DESCRIPTION: 8 bit register access macros
+ */
+#define RD_MEM_8_VOLATILE(addr) ((u8)(*((REG_UWORD8 *)(addr))))
+#define WR_MEM_8_VOLATILE(addr, data) (*((REG_UWORD8 *)(addr)) = (u8)(data))
+
+
+/*
+ * MACRO: RD_MEM_16, WR_MEM_16
+ *
+ * DESCRIPTION: 16 bit memory access macros
+ */
+#define RD_MEM_16(addr) ((u16)(*((u16 *)(addr))))
+#define WR_MEM_16(addr, data) (*((u16 *)(addr)) = (u16)(data))
+
+/*
+ * MACRO: RD_MEM_16_VOLATILE, WR_MEM_16_VOLATILE
+ *
+ * DESCRIPTION: 16 bit register access macros
+ */
+#define RD_MEM_16_VOLATILE(addr) ((u16)(*((REG_UWORD16 *)(addr))))
+#define WR_MEM_16_VOLATILE(addr, data) (*((REG_UWORD16 *)(addr)) =\
+ (u16)(data))
+
+/*
+ * MACRO: RD_MEM_32, WR_MEM_32
+ *
+ * DESCRIPTION: 32 bit memory access macros
+ */
+#define RD_MEM_32(addr) ((u32)(*((u32 *)(addr))))
+#define WR_MEM_32(addr, data) (*((u32 *)(addr)) = (u32)(data))
+
+/*
+ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
+ *
+ * DESCRIPTION: 32 bit register access macros
+ */
+#define RD_MEM_32_VOLATILE(addr) ((u32)(*((REG_UWORD32 *)(addr))))
+#define WR_MEM_32_VOLATILE(addr, data) (*((REG_UWORD32 *)(addr)) =\
+ (u32)(data))
+
+/* Not sure if this all belongs here */
+
+#define CHECK_RETURN_VALUE(actualValue, expectedValue, returnCodeIfMismatch,\
+ spyCodeIfMisMatch)
+#define CHECK_RETURN_VALUE_RET(actualValue, expectedValue, returnCodeIfMismatch)
+#define CHECK_RETURN_VALUE_RES(actualValue, expectedValue, spyCodeIfMisMatch)
+#define CHECK_RETURN_VALUE_RET_VOID(actualValue, expectedValue,\
+ spyCodeIfMisMatch)
+
+#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
+ spyCodeIfMisMatch)
+#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue,\
+ returnCodeIfMismatch)
+#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue,\
+ returnCodeIfMismatch, spyCodeIfMisMatch)
+#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue, maxValidValue,\
+ returnCodeIfMismatch)
+#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue,\
+ returnCodeIfMismatch, spyCodeIfMisMatch)
+#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, maxValidValue,\
+ returnCodeIfMismatch)
+
+#endif /* __GLOBALTYPES_H */
diff --git a/drivers/dsp/bridge/hw/IPIAccInt.h b/drivers/dsp/bridge/hw/IPIAccInt.h
new file mode 100644
index 000000000000..b88a58c47838
--- /dev/null
+++ b/drivers/dsp/bridge/hw/IPIAccInt.h
@@ -0,0 +1,41 @@
+/*
+ * IPIAccInt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#ifndef _IPI_ACC_INT_H
+#define _IPI_ACC_INT_H
+
+/* Bitfield mask and offset declarations */
+#define SYSC_IVA2BOOTMOD_OFFSET 0x404
+#define SYSC_IVA2BOOTADDR_OFFSET 0x400
+#define SYSC_IVA2BOOTADDR_MASK 0xfffffc00
+
+
+/* The following represent the enumerated values for each bitfield */
+
+enum IPIIPI_SYSCONFIGAutoIdleE {
+ IPIIPI_SYSCONFIGAutoIdleclkfree = 0x0000,
+ IPIIPI_SYSCONFIGAutoIdleautoclkgate = 0x0001
+} ;
+
+enum IPIIPI_ENTRYElemSizeValueE {
+ IPIIPI_ENTRYElemSizeValueElemSz8b = 0x0000,
+ IPIIPI_ENTRYElemSizeValueElemSz16b = 0x0001,
+ IPIIPI_ENTRYElemSizeValueElemSz32b = 0x0002,
+ IPIIPI_ENTRYElemSizeValueReserved = 0x0003
+} ;
+
+#endif /* _IPI_ACC_INT_H */
+/* EOF */
diff --git a/drivers/dsp/bridge/hw/IVA2RegAcM.h b/drivers/dsp/bridge/hw/IVA2RegAcM.h
new file mode 100644
index 000000000000..6c1e30054e5c
--- /dev/null
+++ b/drivers/dsp/bridge/hw/IVA2RegAcM.h
@@ -0,0 +1,28 @@
+/*
+ * IVA1RegAcM.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+
+#ifndef _IVA2_REG_ACM_H
+#define _IVA2_REG_ACM_H
+
+#include <GlobalTypes.h>
+#include <EasiGlobal.h>
+
+#define SYSC_IVA2BOOTMOD_OFFSET 0x404
+#define SYSC_IVA2BOOTADDR_OFFSET 0x400
+
+#endif
diff --git a/drivers/dsp/bridge/hw/MLBAccInt.h b/drivers/dsp/bridge/hw/MLBAccInt.h
new file mode 100644
index 000000000000..7a03c6ae2afa
--- /dev/null
+++ b/drivers/dsp/bridge/hw/MLBAccInt.h
@@ -0,0 +1,132 @@
+/*
+ * MLBAccInt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+#ifndef _MLB_ACC_INT_H
+#define _MLB_ACC_INT_H
+
+/* Mappings of level 1 EASI function numbers to function names */
+
+#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32 (MLB_BASE_EASIL1 + 3)
+#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32 (MLB_BASE_EASIL1 + 4)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32 (MLB_BASE_EASIL1 + 7)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32 (MLB_BASE_EASIL1 + 17)
+#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
+#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
+ (MLB_BASE_EASIL1 + 33)
+#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32 (MLB_BASE_EASIL1 + 39)
+#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32 (MLB_BASE_EASIL1 + 44)
+#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
+ (MLB_BASE_EASIL1 + 50)
+#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32 \
+ (MLB_BASE_EASIL1 + 51)
+#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32 \
+ (MLB_BASE_EASIL1 + 56)
+#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
+ (MLB_BASE_EASIL1 + 57)
+#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32 \
+ (MLB_BASE_EASIL1 + 60)
+#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32 \
+ (MLB_BASE_EASIL1 + 62)
+#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
+ (MLB_BASE_EASIL1 + 63)
+#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32 \
+ (MLB_BASE_EASIL1 + 192)
+#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32 \
+ (MLB_BASE_EASIL1 + 193)
+
+/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (u32)(0x0040)
+#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_MESSAGE___REGSET_0_15 */
+
+#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (u32)(0x0080)
+#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (u32)(0x00c0)
+#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (u32)(0x0004)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_MSGSTATUS___REGSET_0_15 */
+
+#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (u32)(0x0100)
+#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (u32)(0x0008)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_IRQSTATUS___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (u32)(0x0)
+
+
+/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
+ * increment and number of banks */
+
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (u32)(0x0104)
+#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (u32)(0x0008)
+
+/* Register offset address definitions relative to register set
+ * MAILBOX_IRQENABLE___REGSET_0_3 */
+
+#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (u32)(0x0)
+
+
+/* Register offset address definitions */
+
+#define MLB_MAILBOX_SYSCONFIG_OFFSET (u32)(0x10)
+#define MLB_MAILBOX_SYSSTATUS_OFFSET (u32)(0x14)
+
+
+/* Bitfield mask and offset declarations */
+
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (u32)(0x18)
+#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (u32)(3)
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (u32)(0x2)
+#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (u32)(1)
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (u32)(0x1)
+#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (u32)(0)
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (u32)(0x1)
+#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (u32)(0)
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (u32)(0x1)
+#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (u32)(0)
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (u32)(0x7f)
+#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (u32)(0)
+
+#endif /* _MLB_ACC_INT_H */
diff --git a/drivers/dsp/bridge/hw/MLBRegAcM.h b/drivers/dsp/bridge/hw/MLBRegAcM.h
new file mode 100644
index 000000000000..29f6de3a6fc9
--- /dev/null
+++ b/drivers/dsp/bridge/hw/MLBRegAcM.h
@@ -0,0 +1,201 @@
+/*
+ * MLBRegAcM.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _MLB_REG_ACM_H
+#define _MLB_REG_ACM_H
+
+#include <GlobalTypes.h>
+#include <linux/io.h>
+#include <EasiGlobal.h>
+#include "MLBAccInt.h"
+
+#if defined(USE_LEVEL_1_MACROS)
+
+#define MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
+ __raw_readl(((baseAddress))+ \
+ MLB_MAILBOX_SYSCONFIG_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
+ __raw_writel(newValue, ((baseAddress))+offset);\
+}
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
+ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(baseAddress, value)\
+{\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data = __raw_readl(((u32)(baseAddress)) +\
+ offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(baseAddress, value)\
+{\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data =\
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
+ MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
+ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
+
+
+#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
+{\
+ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
+ register u32 data =\
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
+ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
+ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
+ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define MLBMAILBOX_SYSSTATUSResetDoneRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
+ MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
+ MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
+
+
+#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
+ __raw_readl(((baseAddress))+\
+ (MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
+ (bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
+
+
+#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, bank, value)\
+{\
+ const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
+ ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
+ __raw_writel(newValue, ((baseAddress))+offset);\
+}
+
+
+#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(\
+ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+\
+ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
+ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
+
+
+#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(\
+ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
+ (((__raw_readl(((baseAddress))+\
+ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
+ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
+ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
+ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
+
+
+#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(\
+ EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
+ (((__raw_readl(((baseAddress))+\
+ (MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
+ MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
+ ((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
+ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
+ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
+
+
+#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
+ __raw_readl(((baseAddress))+\
+ (MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
+ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
+
+
+#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, bank, value)\
+{\
+ const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
+ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
+ __raw_writel(newValue, ((baseAddress))+offset);\
+}
+
+
+#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress, bank)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
+ __raw_readl(((baseAddress))+\
+ (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
+ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
+
+
+#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, bank, value)\
+{\
+ const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
+ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
+ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
+ __raw_writel(newValue, ((baseAddress))+offset);\
+}
+
+
+#endif /* USE_LEVEL_1_MACROS */
+
+#endif /* _MLB_REG_ACM_H */
diff --git a/drivers/dsp/bridge/hw/MMUAccInt.h b/drivers/dsp/bridge/hw/MMUAccInt.h
new file mode 100644
index 000000000000..6ca15737fd3c
--- /dev/null
+++ b/drivers/dsp/bridge/hw/MMUAccInt.h
@@ -0,0 +1,76 @@
+/*
+ * MMUAccInt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _MMU_ACC_INT_H
+#define _MMU_ACC_INT_H
+
+/* Mappings of level 1 EASI function numbers to function names */
+
+#define EASIL1_MMUMMU_SYSCONFIGReadRegister32 (MMU_BASE_EASIL1 + 3)
+#define EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32 (MMU_BASE_EASIL1 + 17)
+#define EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32 (MMU_BASE_EASIL1 + 39)
+#define EASIL1_MMUMMU_IRQSTATUSWriteRegister32 (MMU_BASE_EASIL1 + 51)
+#define EASIL1_MMUMMU_IRQENABLEReadRegister32 (MMU_BASE_EASIL1 + 102)
+#define EASIL1_MMUMMU_IRQENABLEWriteRegister32 (MMU_BASE_EASIL1 + 103)
+#define EASIL1_MMUMMU_WALKING_STTWLRunningRead32 (MMU_BASE_EASIL1 + 156)
+#define EASIL1_MMUMMU_CNTLTWLEnableRead32 (MMU_BASE_EASIL1 + 174)
+#define EASIL1_MMUMMU_CNTLTWLEnableWrite32 (MMU_BASE_EASIL1 + 180)
+#define EASIL1_MMUMMU_CNTLMMUEnableWrite32 (MMU_BASE_EASIL1 + 190)
+#define EASIL1_MMUMMU_FAULT_ADReadRegister32 (MMU_BASE_EASIL1 + 194)
+#define EASIL1_MMUMMU_TTBWriteRegister32 (MMU_BASE_EASIL1 + 198)
+#define EASIL1_MMUMMU_LOCKReadRegister32 (MMU_BASE_EASIL1 + 203)
+#define EASIL1_MMUMMU_LOCKWriteRegister32 (MMU_BASE_EASIL1 + 204)
+#define EASIL1_MMUMMU_LOCKBaseValueRead32 (MMU_BASE_EASIL1 + 205)
+#define EASIL1_MMUMMU_LOCKCurrentVictimRead32 (MMU_BASE_EASIL1 + 209)
+#define EASIL1_MMUMMU_LOCKCurrentVictimWrite32 (MMU_BASE_EASIL1 + 211)
+#define EASIL1_MMUMMU_LOCKCurrentVictimSet32 (MMU_BASE_EASIL1 + 212)
+#define EASIL1_MMUMMU_LD_TLBReadRegister32 (MMU_BASE_EASIL1 + 213)
+#define EASIL1_MMUMMU_LD_TLBWriteRegister32 (MMU_BASE_EASIL1 + 214)
+#define EASIL1_MMUMMU_CAMWriteRegister32 (MMU_BASE_EASIL1 + 226)
+#define EASIL1_MMUMMU_RAMWriteRegister32 (MMU_BASE_EASIL1 + 268)
+#define EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32 (MMU_BASE_EASIL1 + 322)
+
+/* Register offset address definitions */
+#define MMU_MMU_SYSCONFIG_OFFSET 0x10
+#define MMU_MMU_IRQSTATUS_OFFSET 0x18
+#define MMU_MMU_IRQENABLE_OFFSET 0x1c
+#define MMU_MMU_WALKING_ST_OFFSET 0x40
+#define MMU_MMU_CNTL_OFFSET 0x44
+#define MMU_MMU_FAULT_AD_OFFSET 0x48
+#define MMU_MMU_TTB_OFFSET 0x4c
+#define MMU_MMU_LOCK_OFFSET 0x50
+#define MMU_MMU_LD_TLB_OFFSET 0x54
+#define MMU_MMU_CAM_OFFSET 0x58
+#define MMU_MMU_RAM_OFFSET 0x5c
+#define MMU_MMU_GFLUSH_OFFSET 0x60
+#define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64
+/* Bitfield mask and offset declarations */
+#define MMU_MMU_SYSCONFIG_IdleMode_MASK 0x18
+#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET 3
+#define MMU_MMU_SYSCONFIG_AutoIdle_MASK 0x1
+#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET 0
+#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
+#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET 0
+#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
+#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
+#define MMU_MMU_CNTL_MMUEnable_MASK 0x2
+#define MMU_MMU_CNTL_MMUEnable_OFFSET 1
+#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
+#define MMU_MMU_LOCK_BaseValue_OFFSET 10
+#define MMU_MMU_LOCK_CurrentVictim_MASK 0x3f0
+#define MMU_MMU_LOCK_CurrentVictim_OFFSET 4
+
+#endif /* _MMU_ACC_INT_H */
diff --git a/drivers/dsp/bridge/hw/MMURegAcM.h b/drivers/dsp/bridge/hw/MMURegAcM.h
new file mode 100644
index 000000000000..6ef591512dd8
--- /dev/null
+++ b/drivers/dsp/bridge/hw/MMURegAcM.h
@@ -0,0 +1,253 @@
+/*
+ * MMURegAcM.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+#ifndef _MMU_REG_ACM_H
+#define _MMU_REG_ACM_H
+
+#include <GlobalTypes.h>
+#include <linux/io.h>
+#include <EasiGlobal.h>
+
+#include "MMUAccInt.h"
+
+#if defined(USE_LEVEL_1_MACROS)
+
+
+#define MMUMMU_SYSCONFIGReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_SYSCONFIG_OFFSET))
+
+
+#define MMUMMU_SYSCONFIGIdleModeWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32);\
+ data &= ~(MMU_MMU_SYSCONFIG_IdleMode_MASK);\
+ newValue <<= MMU_MMU_SYSCONFIG_IdleMode_OFFSET;\
+ newValue &= MMU_MMU_SYSCONFIG_IdleMode_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32);\
+ data &= ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK);\
+ newValue <<= MMU_MMU_SYSCONFIG_AutoIdle_OFFSET;\
+ newValue &= MMU_MMU_SYSCONFIG_AutoIdle_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_IRQSTATUSReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_IRQSTATUS_OFFSET))
+
+
+#define MMUMMU_IRQSTATUSWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_IRQENABLEReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_IRQENABLE_OFFSET))
+
+
+#define MMUMMU_IRQENABLEWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_WALKING_STTWLRunningRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_WALKING_STTWLRunningRead32),\
+ (((__raw_readl(((baseAddress)+(MMU_MMU_WALKING_ST_OFFSET))))\
+ & MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
+ MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
+
+
+#define MMUMMU_CNTLTWLEnableRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableRead32),\
+ (((__raw_readl(((baseAddress)+(MMU_MMU_CNTL_OFFSET)))) &\
+ MMU_MMU_CNTL_TWLEnable_MASK) >>\
+ MMU_MMU_CNTL_TWLEnable_OFFSET))
+
+
+#define MMUMMU_CNTLTWLEnableWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_CNTL_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableWrite32);\
+ data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
+ newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
+ newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_CNTLMMUEnableWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_CNTL_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLMMUEnableWrite32);\
+ data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
+ newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
+ newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_FAULT_ADReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FAULT_ADReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_FAULT_AD_OFFSET))
+
+
+#define MMUMMU_TTBWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_TTB_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_TTBWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_LOCKReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_LOCK_OFFSET))
+
+
+#define MMUMMU_LOCKWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_LOCKBaseValueRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueRead32),\
+ (((__raw_readl(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
+ MMU_MMU_LOCK_BaseValue_MASK) >>\
+ MMU_MMU_LOCK_BaseValue_OFFSET))
+
+
+#define MMUMMU_LOCKBaseValueWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueWrite32);\
+ data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
+ newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
+ newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_LOCKCurrentVictimRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimRead32),\
+ (((__raw_readl(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
+ MMU_MMU_LOCK_CurrentVictim_MASK) >>\
+ MMU_MMU_LOCK_CurrentVictim_OFFSET))
+
+
+#define MMUMMU_LOCKCurrentVictimWrite32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_LOCK_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimWrite32);\
+ data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
+ newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
+ newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, baseAddress+offset);\
+}
+
+
+#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimSet32),\
+ (((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
+ (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
+ MMU_MMU_LOCK_CurrentVictim_MASK)))
+
+
+#define MMUMMU_LD_TLBReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBReadRegister32),\
+ __raw_readl((baseAddress)+MMU_MMU_LD_TLB_OFFSET))
+
+
+#define MMUMMU_LD_TLBWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_CAMWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_CAM_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CAMWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_RAMWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_RAM_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_RAMWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
+ register u32 newValue = (value);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32);\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#endif /* USE_LEVEL_1_MACROS */
+
+#endif /* _MMU_REG_ACM_H */
diff --git a/drivers/dsp/bridge/hw/PRCMAccInt.h b/drivers/dsp/bridge/hw/PRCMAccInt.h
new file mode 100644
index 000000000000..73f8b676c1ff
--- /dev/null
+++ b/drivers/dsp/bridge/hw/PRCMAccInt.h
@@ -0,0 +1,463 @@
+/*
+ * PRCMAccInt.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _PRCM_ACC_INT_H
+#define _PRCM_ACC_INT_H
+
+/* Mappings of level 1 EASI function numbers to function names */
+#ifdef OMAP_3430
+
+#define EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32 \
+ (PRCM_BASE_EASIL1 + 349)
+#define EASIL1_PRCMCM_FCLKEN1_COREReadRegister32 (PRCM_BASE_EASIL1 + 743)
+#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32 (PRCM_BASE_EASIL1 + 951)
+#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32 (PRCM_BASE_EASIL1 + 961)
+#define EASIL1_PRCMCM_ICLKEN1_COREReadRegister32 \
+ (PRCM_BASE_EASIL1 + 1087)
+#define EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32 \
+ (PRCM_BASE_EASIL1 + 1105)
+#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32 \
+ (PRCM_BASE_EASIL1 + 1305)
+#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32 \
+ (PRCM_BASE_EASIL1 + 1315)
+#define EASIL1_PRCMCM_CLKSEL1_CORECLKSEL_L3ReadIssel132 \
+ (PRCM_BASE_EASIL1 + 2261)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32 \
+ (PRCM_BASE_EASIL1 + 2364)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32 \
+ (PRCM_BASE_EASIL1 + 2365)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32 \
+ (PRCM_BASE_EASIL1 + 2366)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32 \
+ (PRCM_BASE_EASIL1 + 2380)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32 \
+ (PRCM_BASE_EASIL1 + 2381)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32 \
+ (PRCM_BASE_EASIL1 + 2382)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32 \
+ (PRCM_BASE_EASIL1 + 2397)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32 \
+ (PRCM_BASE_EASIL1 + 2398)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32 \
+ (PRCM_BASE_EASIL1 + 2413)
+#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32 \
+ (PRCM_BASE_EASIL1 + 2414)
+#define EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32 \
+ (PRCM_BASE_EASIL1 + 3747)
+#define EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32 (PRCM_BASE_EASIL1 + 3834)
+#define EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32 \
+ (PRCM_BASE_EASIL1 + 3846)
+#define EASIL1_PRCMCM_IDLEST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3850)
+#define EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32 (PRCM_BASE_EASIL1 + 3857)
+#define EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32 (PRCM_BASE_EASIL1 + 3863)
+#define EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32 \
+ (PRCM_BASE_EASIL1 + 3877)
+#define EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32 (PRCM_BASE_EASIL1 + 3927)
+#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32 \
+ (PRCM_BASE_EASIL1 + 3941)
+#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32 \
+ (PRCM_BASE_EASIL1 + 3965)
+#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32 \
+ (PRCM_BASE_EASIL1 + 3987)
+#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32 \
+ (PRCM_BASE_EASIL1 + 3993)
+#define EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3997)
+#define EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32 \
+ (PRCM_BASE_EASIL1 + 4025)
+#define EASIL1_PRCMRM_RSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4029)
+#define EASIL1_PRCMRM_RSTST_DSPWriteRegister32 (PRCM_BASE_EASIL1 + 4030)
+#define EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32 \
+ (PRCM_BASE_EASIL1 + 4165)
+#define EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32 \
+ (PRCM_BASE_EASIL1 + 4193)
+#define EASIL1_PRCMPM_PWSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4197)
+#define EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32 \
+ (PRCM_BASE_EASIL1 + 4198)
+#define EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32 \
+ (PRCM_BASE_EASIL1 + 4235)
+#define EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32 \
+ (PRCM_BASE_EASIL1 + 4368)
+#define EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32 \
+ (PRCM_BASE_EASIL1 + 4370)
+#define EASIL1_CM_CLKSEL_PER_GPT5Write32k32 (PRCM_BASE_EASIL1 + 4372)
+#define EASIL1_CM_CLKSEL_PER_GPT6Write32k32 (PRCM_BASE_EASIL1 + 4373)
+#define EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32 \
+ (PRCM_BASE_EASIL1 + 4374)
+#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32 \
+ (PRCM_BASE_EASIL1 + 4375)
+#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32 \
+ (PRCM_BASE_EASIL1 + 4376)
+#define EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32 \
+ (PRCM_BASE_EASIL1 + 4377)
+#define EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32 \
+ (PRCM_BASE_EASIL1 + 4378)
+#define EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32 (PRCM_BASE_EASIL1 + 4379)
+
+/* Register offset address definitions */
+
+#define PRCM_PRCM_CLKCFG_CTRL_OFFSET (u32)(0x80)
+#define PRCM_CM_FCLKEN1_CORE_OFFSET (u32)(0x200)
+#define PRCM_CM_ICLKEN1_CORE_OFFSET (u32)(0x210)
+#define PRCM_CM_CLKSEL2_CORE_OFFSET (u32)(0x244)
+#define PRCM_CM_CLKSEL1_PLL_OFFSET (u32)(0x540)
+#define PRCM_CM_ICLKEN_DSP_OFFSET (u32)(0x810)
+#define PRCM_CM_IDLEST_DSP_OFFSET (u32)(0x820)
+#define PRCM_CM_AUTOIDLE_DSP_OFFSET (u32)(0x830)
+#define PRCM_CM_CLKSEL_DSP_OFFSET (u32)(0x840)
+#define PRCM_CM_CLKSTCTRL_DSP_OFFSET (u32)(0x848)
+#define PRCM_RM_RSTCTRL_DSP_OFFSET (u32)(0x850)
+#define PRCM_RM_RSTST_DSP_OFFSET (u32)(0x858)
+#define PRCM_PM_PWSTCTRL_DSP_OFFSET (u32)(0x8e0)
+#define PRCM_PM_PWSTST_DSP_OFFSET (u32)(0x8e4)
+#define PRCM_PM_PWSTST_IVA2_OFFSET (u32)(0xE4)
+#define PRCM_PM_PWSTCTRL_IVA2_OFFSET (u32)(0xE0)
+#define PRCM_CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x48)
+#define CM_CLKSEL_PER_OFFSET (u32)(0x40)
+
+/* Bitfield mask and offset declarations */
+
+#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK (u32)(0x1)
+#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET (u32)(0)
+
+#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
+#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
+
+#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
+#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
+
+#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
+#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
+
+#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
+#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
+
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK (u32)(0xc000)
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET (u32)(14)
+
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK (u32)(0x3000)
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET (u32)(12)
+
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK (u32)(0xc00)
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET (u32)(10)
+
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK (u32)(0x300)
+#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET (u32)(8)
+
+#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK (u32)(0x3800000)
+#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET (u32)(23)
+
+#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK (u32)(0x2)
+#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET (u32)(1)
+
+#define PRCM_CM_IDLEST_DSP_ST_IPI_MASK (u32)(0x2)
+#define PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET (u32)(1)
+
+#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK (u32)(0x2)
+#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET (u32)(1)
+
+#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK (u32)(0x80)
+#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET (u32)(7)
+
+#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK (u32)(0x60)
+#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET (u32)(5)
+
+#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK (u32)(0x1f)
+#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET (u32)(0)
+
+#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK (u32)(0x1)
+#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET (u32)(0)
+
+#define PRCM_PM_PWSTCTRL_DSP_ForceState_MASK (u32)(0x40000)
+#define PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET (u32)(18)
+
+#define PRCM_PM_PWSTCTRL_DSP_PowerState_MASK (u32)(0x3)
+#define PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET (u32)(0)
+
+#define PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK (u32)(0x3)
+#define PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET (u32)(0)
+
+#define PRCM_PM_PWSTST_DSP_InTransition_MASK (u32)(0x100000)
+#define PRCM_PM_PWSTST_DSP_InTransition_OFFSET (u32)(20)
+
+#define PRCM_PM_PWSTST_IVA2_InTransition_MASK (u32)(0x100000)
+#define PRCM_PM_PWSTST_IVA2_InTransition_OFFSET (u32)(20)
+
+#define PRCM_PM_PWSTST_DSP_PowerStateSt_MASK (u32)(0x3)
+#define PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET (u32)(0)
+
+#define PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK (u32)(0x3)
+#define PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET (u32)(0)
+
+#define CM_FCLKEN_PER_OFFSET (u32)(0x0)
+#define CM_FCLKEN_PER_GPT5_OFFSET (u32)(6)
+#define CM_FCLKEN_PER_GPT5_MASK (u32)(0x40)
+
+#define CM_FCLKEN_PER_GPT6_OFFSET (u32)(7)
+#define CM_FCLKEN_PER_GPT6_MASK (u32)(0x80)
+
+#define CM_ICLKEN_PER_OFFSET (u32)(0x10)
+#define CM_ICLKEN_PER_GPT5_OFFSET (u32)(6)
+#define CM_ICLKEN_PER_GPT5_MASK (u32)(0x40)
+
+#define CM_ICLKEN_PER_GPT6_OFFSET (u32)(7)
+#define CM_ICLKEN_PER_GPT6_MASK (u32)(0x80)
+
+#define CM_CLKSEL_PER_GPT5_OFFSET (u32)(3)
+#define CM_CLKSEL_PER_GPT5_MASK (u32)(0x8)
+
+#define CM_CLKSEL_PER_GPT6_OFFSET (u32)(4)
+#define CM_CLKSEL_PER_GPT6_MASK (u32)(0x10)
+
+
+#define CM_FCLKEN_IVA2_OFFSET (u32)(0x0)
+#define CM_FCLKEN_IVA2_EN_MASK (u32)(0x1)
+#define CM_FCLKEN_IVA2_EN_OFFSET (u32)(0x0)
+
+#define CM_IDLEST_IVA2_OFFSET (u32)(0x20)
+#define CM_IDLEST_IVA2_ST_IVA2_MASK (u32) (0x01)
+#define CM_IDLEST_IVA2_ST_IVA2_OFFSET (u32) (0x00)
+
+#define CM_FCLKEN1_CORE_OFFSET (u32)(0xA00)
+
+#define CM_ICLKEN1_CORE_OFFSET (u32)(0xA10)
+#define CM_ICLKEN1_CORE_EN_MAILBOXES_MASK (u32)(0x00000080) /* bit 7 */
+#define CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET (u32)(7)
+
+#define CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x0)
+#define CM_CLKSTCTRL_IVA2_MASK (u32)(0x3)
+
+
+#define PRM_RSTCTRL_IVA2_OFFSET (u32)(0x50)
+#define PRM_RSTCTRL_IVA2_RST1_MASK (u32)(0x1)
+#define PRM_RSTCTRL_IVA2_RST1_OFFSET (u32)(0x0)
+#define PRM_RSTCTRL_IVA2_RST2_MASK (u32)(0x2)
+#define PRM_RSTCTRL_IVA2_RST2_OFFSET (u32)(0x1)
+#define PRM_RSTCTRL_IVA2_RST3_MASK (u32)(0x4)
+#define PRM_RSTCTRL_IVA2_RST3_OFFSET (u32)(0x2)
+
+
+/* The following represent the enumerated values for each bitfield */
+
+enum PRCMPRCM_CLKCFG_CTRLValid_configE {
+ PRCMPRCM_CLKCFG_CTRLValid_configUpdated = 0x0000,
+ PRCMPRCM_CLKCFG_CTRLValid_configClk_valid = 0x0001
+} ;
+
+enum PRCMCM_CLKSEL2_CORECLKSEL_GPT8E {
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT832k = 0x0000,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys = 0x0001,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext = 0x0002,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Reserved = 0x0003
+} ;
+
+enum PRCMCM_CLKSEL2_CORECLKSEL_GPT7E {
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT732k = 0x0000,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys = 0x0001,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext = 0x0002,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Reserved = 0x0003
+} ;
+
+enum PRCMCM_CLKSEL2_CORECLKSEL_GPT6E {
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT632k = 0x0000,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys = 0x0001,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext = 0x0002,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Reserved = 0x0003
+} ;
+
+enum PRCMCM_CLKSEL2_CORECLKSEL_GPT5E {
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT532k = 0x0000,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys = 0x0001,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext = 0x0002,
+ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Reserved = 0x0003
+} ;
+
+enum PRCMPM_PWSTCTRL_DSPPowerStateE {
+ PRCMPM_PWSTCTRL_DSPPowerStateON = 0x0000,
+ PRCMPM_PWSTCTRL_DSPPowerStateRET = 0x0001,
+ PRCMPM_PWSTCTRL_DSPPowerStateReserved = 0x0002,
+ PRCMPM_PWSTCTRL_DSPPowerStateOFF = 0x0003
+} ;
+
+enum PRCMPM_PWSTCTRL_IVA2PowerStateE {
+ PRCMPM_PWSTCTRL_IVA2PowerStateON = 0x0003,
+ PRCMPM_PWSTCTRL_IVA2PowerStateRET = 0x0001,
+ PRCMPM_PWSTCTRL_IVA2PowerStateReserved = 0x0002,
+ PRCMPM_PWSTCTRL_IVA2PowerStateOFF = 0x0000
+} ;
+
+#else
+
+#define PRM_PRM_IRQSTATUS_TESLA_OFFSET (u32)(0x030)
+#define PRM_PRM_IRQENABLE_TESLA_OFFSET (u32)(0x038)
+
+/*TESLA_PRM*/
+#define PRM_PM_TESLA_PWRSTCTRL_OFFSET (u32)(0x400)
+#define PRM_PM_TESLA_PWRSTST_OFFSET (u32)(0x404)
+#define PRM_RM_TESLA_RSTCTRL_OFFSET (u32)(0x410)
+#define PRM_RM_TESLA_RSTST_OFFSET (u32)(0x414)
+#define PRM_RM_TESLA_TESLA_CONTEXT_OFFSET (u32)(0x424)
+
+/*CORE_PRM*/
+#define PRM_PM_CORE_PWRSTCTRL_OFFSET (u32)(0x700)
+
+/*ALWAYS_ON_PRM*/
+#define PRM_PM_ALWON_SR_IVA_WKDEP_OFFSET (u32)(0x630)
+#define PRM_RM_ALWON_SR_IVA_CONTEXT_OFFSET (u32)(0x634)
+
+
+/*CM1*/
+/*base address = 0x4A00_5000*/
+
+/*CKGEN_CM1*/
+#define CM1_CM_CLKMODE_DPLL_IVA_OFFSET (u32)(0x1A0)
+#define CM1_CM_IDLEST_DPLL_IVA_OFFSET (u32)(0x1A4)
+#define CM1_CM_AUTOIDLE_DPLL_IVA_OFFSET (u32)(0x1A8)
+#define CM1_CM_CLKSEL_DPLL_IVA_OFFSET (u32)(0x1AC)
+#define CM1_CM_DIV_M2_DPLL_IVA_OFFSET (u32)(0x1B0)
+#define CM1_CM_DIV_M4_DPLL_IVA_OFFSET (u32)(0x1B8)
+#define CM1_CM_DIV_M5_DPLL_IVA_OFFSET (u32)(0x1BC)
+#define CM1_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET (u32)(0x1C8)
+#define CM1_CM_SSC_MODFREQDIV_DPLL_IVA_OFFSET (u32)(0x1CC)
+#define CM1_CM_BYPCLK_DPLL_IVA_OFFSET (u32)(0x1DC)
+
+/*TESLA_CM1*/
+#define CM1_CM_TESLA_CLKSTCTRL_OFFSET (u32)(0x400)
+#define CM1_CM_TESLA_STATICDEP_OFFSET (u32)(0x404)
+#define CM1_CM_TESLA_DYNAMICDEP_OFFSET (u32)(0x408)
+#define CM1_CM_TESLA_TESLA_CLKCTRL_OFFSET (u32)(0x420)
+
+/*ABE_CM1*/
+#define CM1_CM1_ABE_CLKSTCTRL_OFFSET (u32)(0x500)
+#define CM1_CM1_ABE_MCBSP1_CLKCTRL_OFFSET (u32)(0x548)
+#define CM1_CM1_ABE_MCBSP2_CLKCTRL_OFFSET (u32)(0x550)
+#define CM1_CM1_ABE_MCBSP3_CLKCTRL_OFFSET (u32)(0x558)
+#define CM1_CM1_ABE_TIMER5_CLKCTRL_OFFSET (u32)(0x568)
+#define CM1_CM1_ABE_TIMER6_CLKCTRL_OFFSET (u32)(0x570)
+#define CM1_CM1_ABE_TIMER7_CLKCTRL_OFFSET (u32)(0x578)
+#define CM1_CM1_ABE_TIMER8_CLKCTRL_OFFSET (u32)(0x580)
+
+/*CM2*/
+/*base address = 0x4A00_8000*/
+
+/*CKGEN_CM2*/
+#define CM2_CM_IVA_DVFS_PERF_TESLA_OFFSET (u32)(0x128)
+#define CM2_CM_IVA_DVFS_PERF_IVAHD_OFFSET (u32)(0x12C)
+#define CM2_CM_IVA_DVFS_PERF_ABE_OFFSET (u32)(0x130)
+#define CM2_CM_IVA_DVFS_RESULT_OFFSET (u32)(0x134)
+#define CM2_CM_IVA_DVFS_CURRENT_OFFSET (u32)(0x138)
+
+/*L4PER_CM2*/
+#define CM2_CM_L4PER_CLKSTCTRL_OFFSET (u32)(0x1400)
+#define CM2_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET (u32)(0x1428)
+#define CM2_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET (u32)(0x1430)
+#define CM2_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET (u32)(0x1438)
+#define CM2_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET (u32)(0x1440)
+#define CM2_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET (u32)(0x1448)
+#define CM2_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET (u32)(0x1450)
+#define CM2_CM_L4PER_MCBSP4_CLKCTRL_OFFSET (u32)(0x14E0)
+#define CM2_CM_L4PER_MCBSP5_CLKCTRL_OFFSET (u32)(0x14E8)
+
+
+/*BITS MASKS & OFFSETS*/
+
+/*PM_TESLA_PWRSTCTRL*/
+#define PM_TESLA_PWRSTCTRL_PowerState_OFFSET (u32)(0x0)
+#define PM_TESLA_PWRSTCTRL_PowerState_MASK (u32)(0x3)
+#define PM_TESLA_PWRSTCTRL_LogicRetState_OFFSET (u32)(0x2)
+#define PM_TESLA_PWRSTCTRL_LogicRetState_MASK (u32)(0x4)
+#define PM_TESLA_PWRSTCTRL_L1RetState_OFFSET (u32)(0x8)
+#define PM_TESLA_PWRSTCTRL_L1RetState_MASK (u32)(0x100)
+#define PM_TESLA_PWRSTCTRL_L2RetState_OFFSET (u32)(0x9)
+#define PM_TESLA_PWRSTCTRL_L2RetState_MASK (u32)(0x200)
+
+/*PRM_PM_TESLA_PWRSTST*/
+#define PM_TESLA_PWRSTST_PowerState_OFFSET (u32)(0x0)
+#define PM_TESLA_PWRSTST_PowerState_MASK (u32)(0x3)
+
+/*RM_TESLA_RSTCTRL*/
+#define RM_TESLA_RSTCTRL_RST1_MASK (u32)(0x1)
+#define RM_TESLA_RSTCTRL_RST1_OFFSET (u32)(0x0)
+#define RM_TESLA_RSTCTRL_RST2_MASK (u32)(0x2)
+#define RM_TESLA_RSTCTRL_RST2_OFFSET (u32)(0x1)
+
+/*RM_TESLA_RSTST*/
+
+#define RM_TESLA_RSTST_Clear_MASK (u32)(0x0F)
+
+/*RM_TESLA_TESLA_CONTEXT*/
+
+#define RM_TESLA_TESLA_CONTEXT_Clear_MASK (u32)(0x701)
+
+/*PM_CORE_PWRSTCTRL*/
+
+#define PRM_PM_CORE_PWRSTCTRL_PowerControl_OFFSET (u32)(0x0)
+#define PRM_PM_CORE_PWRSTCTRL_PowerControl_MASK (u32)(0x3)
+
+/*PM_ALWON_SR_IVA_WKDEP*/
+
+#define PM_ALWON_SR_IVA_WKDEP_MPU_OFFSET (u32)(0x0)
+#define PM_ALWON_SR_IVA_WKDEP_MPU_MASK (u32)(0x1)
+#define PM_ALWON_SR_IVA_WKDEP_DUCATI_OFFSET (u32)(0x1)
+#define PM_ALWON_SR_IVA_WKDEP_DUCATI_MASK (u32)(0x2)
+
+/*CM_TESLA_CLKSTCTRL*/
+
+#define CM_TESLA_CLKSTCTRL_Transition_OFFSET (u32)(0x0)
+#define CM_TESLA_CLKSTCTRL_Transition_MASK (u32)(0x3)
+
+/*CM_TESLA_TESLA_CLKCTRL*/
+#define CM_TESLA_TESLA_CLKCTRL_STBY_MASK (u32)(0x40000)
+#define CM_TESLA_TESLA_CLKCTRL_STBY_OFFSET (u32)(0x18)
+#define CM_TESLA_TESLA_CLKCTRL_IDLE_MASK (u32)(0x30000)
+#define CM_TESLA_TESLA_CLKCTRL_IDLE_OFFSET (u32)(0x16)
+#define CM_TESLA_TESLA_CLKCTRL_MODMODE_OFFSET (u32)(0x0)
+#define CM_TESLA_TESLA_CLKCTRL_MODMODE_MASK (u32)(0x03)
+
+/*CM1_ABE_CLKSTCTRL*/
+
+#define CM1_ABE_CLKSTCTRL_Transition_OFFSET (u32)(0x0)
+#define CM1_ABE_CLKSTCTRL_Transition_MASK (u32)(0x3)
+
+/*CM1_ABE_MCBSPX&TIMERX_CLKCTRL*/
+#define CM1_ABE_CLKCTRL_OFFSET (u32)(0x0)
+#define CM1_ABE_CLKCTRL_MASK (u32)(0x3)
+
+/*CM1_L4PER_CLKSTCTRL*/
+
+#define CM1_L4PER_CLKSTCTRL_Transition_OFFSET (u32)(0x0)
+#define CM1_L4PER_CLKSTCTRL_Transition_MASK (u32)(0x3)
+
+/*CM1_L4PER_MCBSPX&DMTIMERX_CLKCTRL*/
+#define CM1_L4PER_CLKCTRL_OFFSET (u32)(0x0)
+#define CM1_L4PER_CLKCTRL_MASK (u32)(0x3)
+
+/*CM_IVA_DVFS_PERF*/
+#define CM_IVA_DVFS_PERF_OFFSET (u32)(0x0)
+#define CM_IVA_DVFS_PERF_MASK (u32)(0xFF)
+
+/* The following type definitions represent the
+* enumerated values for each bitfield
+*/
+
+enum PRM_PM_TESLA_PWRSTCTRLE {
+ PM_TESLA_PWRSTCTRLPowerStateOFF = 0x0000,
+ PM_TESLA_PWRSTCTRLPowerStateRET = 0x0001,
+ PM_TESLA_PWRSTCTRLPowerStateINACTIVE = 0x0002,
+ PM_TESLA_PWRSTCTRLPowerStateON = 0x0003
+};
+
+#endif
+#endif
diff --git a/drivers/dsp/bridge/hw/PRCMRegAcM.h b/drivers/dsp/bridge/hw/PRCMRegAcM.h
new file mode 100644
index 000000000000..b811377d7da5
--- /dev/null
+++ b/drivers/dsp/bridge/hw/PRCMRegAcM.h
@@ -0,0 +1,1187 @@
+/*
+ * PRCMRegAcM.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef _PRCM_REG_ACM_H
+#define _PRCM_REG_ACM_H
+
+#include <GlobalTypes.h>
+#include <linux/io.h>
+
+#include <EasiGlobal.h>
+
+#include "PRCMAccInt.h"
+
+#if defined(USE_LEVEL_1_MACROS)
+
+#ifdef OMAP_3430
+
+#define PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32(baseAddress)\
+{\
+ const u32 offset = PRCM_PRCM_CLKCFG_CTRL_OFFSET;\
+ const u32 newValue = \
+ (u32)PRCMPRCM_CLKCFG_CTRLValid_configClk_valid <<\
+ PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(\
+ EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32);\
+ data &= ~(PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define CM_FCLKEN_PERReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+CM_FCLKEN_PER_OFFSET))
+
+
+#define CM_ICLKEN_PERReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+CM_ICLKEN_PER_OFFSET))
+
+
+#define CM_FCLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
+{\
+ const u32 offset = CM_FCLKEN_PER_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
+ data &= ~(CM_FCLKEN_PER_GPT5_MASK);\
+ newValue <<= CM_FCLKEN_PER_GPT5_OFFSET;\
+ newValue &= CM_FCLKEN_PER_GPT5_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, ((u32)(baseAddress))+offset);\
+}
+
+
+#define CM_FCLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
+{\
+ const u32 offset = CM_FCLKEN_PER_OFFSET;\
+ register u32 data =\
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
+ data &= ~(CM_FCLKEN_PER_GPT6_MASK);\
+ newValue <<= CM_FCLKEN_PER_GPT6_OFFSET;\
+ newValue &= CM_FCLKEN_PER_GPT6_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, ((u32)(baseAddress))+offset);\
+}
+
+
+#define CM_ICLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
+{\
+ const u32 offset = CM_ICLKEN_PER_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
+ data &= ~(CM_ICLKEN_PER_GPT5_MASK);\
+ newValue <<= CM_ICLKEN_PER_GPT5_OFFSET;\
+ newValue &= CM_ICLKEN_PER_GPT5_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, ((u32)(baseAddress))+offset);\
+}
+
+
+#define CM_ICLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
+{\
+ const u32 offset = CM_ICLKEN_PER_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
+ data &= ~(CM_ICLKEN_PER_GPT6_MASK);\
+ newValue <<= CM_ICLKEN_PER_GPT6_OFFSET;\
+ newValue &= CM_ICLKEN_PER_GPT6_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, ((u32)(baseAddress))+offset);\
+}
+
+
+#define CM_FCLKEN1_COREReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+CM_FCLKEN1_CORE_OFFSET))
+
+
+#define PRCMCM_FCLKEN1_COREEN_GPT8Write32(baseAddress,value)\
+{\
+ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32);\
+ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK);\
+ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET;\
+ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_FCLKEN1_COREEN_GPT7Write32(baseAddress,value)\
+{\
+ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32);\
+ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK);\
+ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET;\
+ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define CM_ICLKEN1_COREReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+CM_ICLKEN1_CORE_OFFSET))
+
+
+#define CM_ICLKEN1_COREEN_MAILBOXESWrite32(baseAddress, value)\
+{\
+ const u32 offset = CM_ICLKEN1_CORE_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32);\
+ data &= ~(CM_ICLKEN1_CORE_EN_MAILBOXES_MASK);\
+ newValue <<= CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET;\
+ newValue &= CM_ICLKEN1_CORE_EN_MAILBOXES_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_ICLKEN1_COREEN_GPT8Write32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32);\
+ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK);\
+ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET;\
+ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_ICLKEN1_COREEN_GPT7Write32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
+ register u32 data =\
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32);\
+ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK);\
+ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET;\
+ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT832k <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT732k <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define CM_CLKSEL_PER_GPT5Write32k32(baseAddress)\
+{\
+ const u32 offset = CM_CLKSEL_PER_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
+ CM_CLKSEL_PER_GPT5_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT5Write32k32);\
+ data &= ~(CM_CLKSEL_PER_GPT5_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define CM_CLKSEL_PER_GPT6Write32k32(baseAddress)\
+{\
+ const u32 offset = CM_CLKSEL_PER_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
+ CM_CLKSEL_PER_GPT6_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT6Write32k32);\
+ data &= ~(CM_CLKSEL_PER_GPT6_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32(baseAddress)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
+ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext <<\
+ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
+ register u32 data = __raw_readl((u32)(baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32);\
+ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (PRCM_CM_CLKSEL1_PLL_OFFSET)))) &\
+ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK) >>\
+ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET))
+
+
+#define CM_FCLKEN_IVA2EN_DSPWrite32(baseAddress,value)\
+{\
+ const u32 offset = CM_FCLKEN_IVA2_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32);\
+ data &= ~(CM_FCLKEN_IVA2_EN_MASK);\
+ newValue <<= CM_FCLKEN_IVA2_EN_OFFSET;\
+ newValue &= CM_FCLKEN_IVA2_EN_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_ICLKEN_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32);\
+ data &= ~(PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK);\
+ newValue <<= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET;\
+ newValue &= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_IDLEST_DSPReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+PRCM_CM_IDLEST_DSP_OFFSET))
+
+
+#define PRCMCM_IDLEST_DSPST_IPIRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (PRCM_CM_IDLEST_DSP_OFFSET)))) &\
+ PRCM_CM_IDLEST_DSP_ST_IPI_MASK) >>\
+ PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET))
+
+
+#define PRM_IDLEST_IVA2ST_IVA2Read32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (CM_IDLEST_IVA2_OFFSET)))) &\
+ CM_IDLEST_IVA2_ST_IVA2_MASK) >>\
+ CM_IDLEST_IVA2_ST_IVA2_OFFSET))
+
+
+#define PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_AUTOIDLE_DSP_OFFSET;\
+ register u32 data =\
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32);\
+ data &= ~(PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK);\
+ newValue <<= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET;\
+ newValue &= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL_DSPSYNC_DSPWrite32(baseAddress,value)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32);\
+ data &= ~(PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK);\
+ newValue <<= PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET;\
+ newValue &= PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32);\
+ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK);\
+ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET;\
+ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32);\
+ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK);\
+ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET;\
+ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_CLKSTCTRL_IVA2_OFFSET;\
+ register u32 data = \
+ __raw_readl(((baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32);\
+ data &= ~(CM_CLKSTCTRL_IVA2_MASK);\
+ newValue <<= CM_CLKSTCTRL_IVA2_OFFSET;\
+ newValue &= CM_CLKSTCTRL_IVA2_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (PRCM_CM_CLKSTCTRL_DSP_OFFSET)))) &\
+ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK) >>\
+ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET))
+
+
+#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_CM_CLKSTCTRL_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32);\
+ data &= ~(PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK);\
+ newValue <<= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET;\
+ newValue &= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32),\
+ __raw_readl(((baseAddress))+PRCM_RM_RSTCTRL_DSP_OFFSET))
+
+
+#define PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress,value)\
+{\
+ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
+ register u32 data =\
+ __raw_readl(((baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
+ data &= ~(PRM_RSTCTRL_IVA2_RST1_MASK);\
+ newValue <<= PRM_RSTCTRL_IVA2_RST1_OFFSET;\
+ newValue &= PRM_RSTCTRL_IVA2_RST1_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress,value)\
+{\
+ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
+ register u32 data =\
+ __raw_readl(((baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
+ data &= ~(PRM_RSTCTRL_IVA2_RST2_MASK);\
+ newValue <<= PRM_RSTCTRL_IVA2_RST2_OFFSET;\
+ newValue &= PRM_RSTCTRL_IVA2_RST2_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress,value)\
+{\
+ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
+ register u32 data =\
+ __raw_readl(((baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
+ data &= ~(PRM_RSTCTRL_IVA2_RST3_MASK);\
+ newValue <<= PRM_RSTCTRL_IVA2_RST3_OFFSET;\
+ newValue &= PRM_RSTCTRL_IVA2_RST3_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (baseAddress)+offset);\
+}
+
+
+#define PRCMRM_RSTST_DSPReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPReadRegister32),\
+ __raw_readl(((baseAddress))+PRCM_RM_RSTST_DSP_OFFSET))
+
+
+#define PRCMRM_RSTST_DSPWriteRegister32(baseAddress,value)\
+{\
+ const u32 offset = PRCM_RM_RSTST_DSP_OFFSET;\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPWriteRegister32);\
+ __raw_writel(newValue, ((u32)(baseAddress))+offset);\
+}
+
+
+#define PRCMPM_PWSTCTRL_DSPForceStateWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
+ register u32 data = \
+ __raw_readl(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32);\
+ data &= ~(PRCM_PM_PWSTCTRL_DSP_ForceState_MASK);\
+ newValue <<= PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET;\
+ newValue &= PRCM_PM_PWSTCTRL_DSP_ForceState_MASK;\
+ newValue |= data;\
+ __raw_writel(newValue, (u32)(baseAddress)+offset);\
+}
+
+
+#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress)\
+{\
+ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
+ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateON <<\
+ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32);\
+ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (baseAddress)+offset);\
+}
+
+
+#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress)\
+{\
+ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
+ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateOFF <<\
+ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32);\
+ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (baseAddress)+offset);\
+}
+
+
+#define PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress)\
+{\
+ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
+ const u32 newValue = (u32)PRCMPM_PWSTCTRL_DSPPowerStateRET <<\
+ PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET;\
+ register u32 data = __raw_readl((baseAddress)+offset);\
+ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32);\
+ data &= ~(PRCM_PM_PWSTCTRL_DSP_PowerState_MASK);\
+ data |= newValue;\
+ __raw_writel(data, (baseAddress)+offset);\
+}
+
+
+#define PRCMPM_PWSTST_DSPReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPReadRegister32),\
+ __raw_readl(((u32)(baseAddress))+PRCM_PM_PWSTST_DSP_OFFSET))
+
+
+#define PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32),\
+ __raw_readl((baseAddress) + PRCM_PM_PWSTST_IVA2_OFFSET))
+
+
+#define PRCMPM_PWSTST_DSPInTransitionRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32),\
+ (((__raw_readl((((u32)(baseAddress))+\
+ (PRCM_PM_PWSTST_DSP_OFFSET)))) &\
+ PRCM_PM_PWSTST_DSP_InTransition_MASK) >>\
+ PRCM_PM_PWSTST_DSP_InTransition_OFFSET))
+
+
+#define PRCMPM_PWSTST_IVA2InTransitionRead32(baseAddress)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32),\
+ (((__raw_readl((((baseAddress))+\
+ (PRCM_PM_PWSTST_IVA2_OFFSET)))) &\
+ PRCM_PM_PWSTST_IVA2_InTransition_MASK) >>\
+ PRCM_PM_PWSTST_IVA2_InTransition_OFFSET))
+
+
+#define PRCMPM_PWSTST_DSPPowerStateStGet32(var)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32),\
+ (u32)((((u32)(var)) & PRCM_PM_PWSTST_DSP_PowerStateSt_MASK) >>\
+ PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET))
+
+
+#define PRCMPM_PWSTST_IVA2PowerStateStGet32(var)\
+ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32),\
+ (u32)((((u32)(var)) & PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK) >>\
+ PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET))
+
+#else
+
+#define PRM_TESLA_PWRSTCTRLReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_PM_TESLA_PWRSTCTRL_OFFSET))
+
+
+
+#define PRM_TESLA_PWRSTCTRLWriteON32(baseAddress)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ const u32 newValue = (u32)PM_TESLA_PWRSTCTRLPowerStateON <<\
+ PM_TESLA_PWRSTCTRL_PowerState_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
+ data &= ~(PM_TESLA_PWRSTCTRL_PowerState_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteINACTIVE32(baseAddress)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ const u32 newValue = (u32)PM_TESLA_PWRSTCTRLPowerStateINACTIVE <<\
+ PM_TESLA_PWRSTCTRL_PowerState_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
+ data &= ~(PM_TESLA_PWRSTCTRL_PowerState_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteRET32(baseAddress)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ const u32 newValue = (u32)PM_TESLA_PWRSTCTRLPowerStateRET <<\
+ PM_TESLA_PWRSTCTRL_PowerState_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
+ data &= ~(PM_TESLA_PWRSTCTRL_PowerState_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteOFF32(baseAddress)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ const u32 newValue = (u32)PM_TESLA_PWRSTCTRLPowerStateOFF <<\
+ PM_TESLA_PWRSTCTRL_PowerState_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
+ data &= ~(PM_TESLA_PWRSTCTRL_PowerState_MASK);\
+ data |= newValue;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteLOGICRETSTATE32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ register u32 data = \
+ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PM_TESLA_PWRSTCTRL_LogicRetState_MASK);\
+ newValue <<= PM_TESLA_PWRSTCTRL_LogicRetState_OFFSET;\
+ newValue &= PM_TESLA_PWRSTCTRL_LogicRetState_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteL1RETSTATE32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ register u32 data = \
+ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PM_TESLA_PWRSTCTRL_L1RetState_MASK);\
+ newValue <<= PM_TESLA_PWRSTCTRL_L1RetState_OFFSET;\
+ newValue &= PM_TESLA_PWRSTCTRL_L1RetState_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define PRM_TESLA_PWRSTCTRLWriteL2RETSTATE32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_TESLA_PWRSTCTRL_OFFSET;\
+ register u32 data = \
+ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PM_TESLA_PWRSTCTRL_L2RetState_MASK);\
+ newValue <<= PM_TESLA_PWRSTCTRL_L2RetState_OFFSET;\
+ newValue &= PM_TESLA_PWRSTCTRL_L2RetState_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+
+#define PRM_TESLA_PWRSTSTReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_PM_TESLA_PWRSTST_OFFSET))
+
+
+#define PRM_TESLA_PWRSTSTGet32(baseAddress)\
+ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_PM_TESLA_PWRSTST_OFFSET))&\
+ PM_TESLA_PWRSTST_PowerState_MASK) >>\
+ PM_TESLA_PWRSTST_PowerState_OFFSET)
+
+
+#define PRM_CORE_PWRSTCTRLWrite32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_CORE_PWRSTCTRL_OFFSET;\
+ register u32 data = \
+ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PRM_PM_CORE_PWRSTCTRL_PowerControl_MASK);\
+ newValue <<= PRM_PM_CORE_PWRSTCTRL_PowerControl_OFFSET;\
+ newValue &= PRM_PM_CORE_PWRSTCTRL_PowerControl_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define PRM_TESLA_RSTCTRLReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_RM_TESLA_RSTCTRL_OFFSET))
+
+#define PRM_TESLA_RSTCTRL_RST1_Write32(baseAddress, value)\
+{\
+ const u32 offset = PRM_RM_TESLA_RSTCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(RM_TESLA_RSTCTRL_RST1_MASK);\
+ newValue <<= RM_TESLA_RSTCTRL_RST1_OFFSET;\
+ newValue &= RM_TESLA_RSTCTRL_RST1_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define PRM_TESLA_RSTCTRL_RST2_Write32(baseAddress, value)\
+{\
+ const u32 offset = PRM_RM_TESLA_RSTCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(RM_TESLA_RSTCTRL_RST2_MASK);\
+ newValue <<= RM_TESLA_RSTCTRL_RST2_OFFSET;\
+ newValue &= RM_TESLA_RSTCTRL_RST2_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+
+#define PRM_TESLA_RSTSTReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_RM_TESLA_RSTST_OFFSET))
+
+
+#define PRM_TESLA_RSTST_Clear32(baseAddress)\
+{\
+ const u32 offset = PRM_RM_TESLA_RSTST_OFFSET;\
+ register u32 newValue = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ newValue &= ~(RM_TESLA_RSTST_Clear_MASK);\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define PRM_TESLA_CONTEXTReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_RM_TESLA_TESLA_CONTEXT_OFFSET))
+
+
+#define PRM_TESLA_CONTEXT_Clear32(baseAddress)\
+{\
+ const u32 offset = PRM_RM_TESLA_TESLA_CONTEXT_OFFSET;\
+ register u32 newValue = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ newValue &= ~(RM_TESLA_TESLA_CONTEXT_Clear_MASK);\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define PRM_WKUP_IVA_ReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_PM_ALWON_SR_IVA_WKDEP_OFFSET))
+
+
+#define PRM_WKUP_IVA_MPU_Write32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_ALWON_SR_IVA_WKDEP_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PM_ALWON_SR_IVA_WKDEP_MPU_MASK);\
+ newValue <<= PM_ALWON_SR_IVA_WKDEP_MPU_OFFSET;\
+ newValue &= PM_ALWON_SR_IVA_WKDEP_MPU_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define PRM_WKUP_IVA_DUCATI_Write32(baseAddress, value)\
+{\
+ const u32 offset = PRM_PM_ALWON_SR_IVA_WKDEP_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(PM_ALWON_SR_IVA_WKDEP_DUCATI_MASK);\
+ newValue <<= PM_ALWON_SR_IVA_WKDEP_DUCATI_OFFSET;\
+ newValue &= PM_ALWON_SR_IVA_WKDEP_DUCATI_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define PRM_ALWON_CONTEXTReadRegister32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRM_RM_ALWON_SR_IVA_CONTEXT_OFFSET))
+
+
+#define CM_CLKSTCTRL_TESLAWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM_TESLA_CLKSTCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM_TESLA_CLKSTCTRL_Transition_MASK);\
+ newValue <<= CM_TESLA_CLKSTCTRL_Transition_OFFSET;\
+ newValue &= CM_TESLA_CLKSTCTRL_Transition_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define CM_TESLA_TESLA_CLKCTRLWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM_TESLA_TESLA_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM_TESLA_TESLA_CLKCTRL_MODMODE_MASK);\
+ newValue <<= CM_TESLA_TESLA_CLKCTRL_MODMODE_OFFSET;\
+ newValue &= CM_TESLA_TESLA_CLKCTRL_MODMODE_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_TESLA_STBYST_Read32(baseAddress)\
+ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM1_CM_TESLA_TESLA_CLKCTRL_OFFSET))&\
+ CM_TESLA_TESLA_CLKCTRL_STBY_MASK) >>\
+ CM_TESLA_TESLA_CLKCTRL_STBY_OFFSET)
+
+#define CM_TESLA_IDLEST_Read32(baseAddress)\
+ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM1_CM_TESLA_TESLA_CLKCTRL_OFFSET))&\
+ CM_TESLA_TESLA_CLKCTRL_IDLE_MASK) >>\
+ CM_TESLA_TESLA_CLKCTRL_IDLE_OFFSET)
+
+
+/********************************************************************/
+
+#define CM_IVA_DVFS_PERFTESTLA_Read32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM2_CM_IVA_DVFS_PERF_TESLA_OFFSET))
+
+
+#define CM_IVA_DVFS_PERFTESTLA_Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_IVA_DVFS_PERF_TESLA_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM_IVA_DVFS_PERF_MASK);\
+ newValue <<= CM_IVA_DVFS_PERF_OFFSET;\
+ newValue &= CM_IVA_DVFS_PERF_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_IVA_DVFS_PERFIVAHD_Read32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM2_CM_IVA_DVFS_PERF_IVAHD_OFFSET))
+
+
+#define CM_IVA_DVFS_PERFIVAHD_Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_IVA_DVFS_PERF_IVAHD_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM_IVA_DVFS_PERF_MASK);\
+ newValue <<= CM_IVA_DVFS_PERF_OFFSET;\
+ newValue &= CM_IVA_DVFS_PERF_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define CM_IVA_DVFS_PERFABE_Read32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM2_CM_IVA_DVFS_PERF_ABE_OFFSET))
+
+
+#define CM_IVA_DVFS_PERFABE_Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_IVA_DVFS_PERF_ABE_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM_IVA_DVFS_PERF_MASK);\
+ newValue <<= CM_IVA_DVFS_PERF_OFFSET;\
+ newValue &= CM_IVA_DVFS_PERF_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define CM_IVA_DVFS_RESULT_Read32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM2_CM_IVA_DVFS_RESULT_OFFSET))
+
+
+#define CM_IVA_DVFS_CURRENT_Read32(baseAddress)\
+ (RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM2_CM_IVA_DVFS_CURRENT_OFFSET))
+
+
+
+#define CM_CLKSTCTRL_ABEWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_CLKSTCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKSTCTRL_Transition_MASK);\
+ newValue <<= CM1_ABE_CLKSTCTRL_Transition_OFFSET;\
+ newValue &= CM1_ABE_CLKSTCTRL_Transition_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+#define CM_ABEEN_MCBSP1Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_MCBSP1_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+
+#define CM_ABEEN_MCBSP2Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_MCBSP2_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_ABEEN_MCBSP3Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_MCBSP3_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_ABEEN_TIMER5Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_TIMER5_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_ABEEN_TIMER6Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_TIMER6_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_ABEEN_TIMER7Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_TIMER7_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_ABEEN_TIMER8Write32(baseAddress, value)\
+{\
+ const u32 offset = CM1_CM1_ABE_TIMER8_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_ABE_CLKCTRL_MASK);\
+ newValue <<= CM1_ABE_CLKCTRL_OFFSET;\
+ newValue &= CM1_ABE_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_CLKSTCTRL_L4PERWriteRegister32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_CLKSTCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKSTCTRL_Transition_MASK);\
+ newValue <<= CM1_L4PER_CLKSTCTRL_Transition_OFFSET;\
+ newValue &= CM1_L4PER_CLKSTCTRL_Transition_MASK;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_MCBSP4Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_MCBSP4_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_MCBSP5Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_MCBSP5_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER2Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER3Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER4Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER9Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER10Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+#define CM_L4PEREN_DMTIMER11Write32(baseAddress, value)\
+{\
+ const u32 offset = CM2_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET;\
+ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
+ register u32 newValue = ((u32)(value));\
+ data &= ~(CM1_L4PER_CLKCTRL_MASK);\
+ newValue <<= CM1_L4PER_CLKCTRL_OFFSET;\
+ newValue &= CM1_L4PER_CLKCTRL_MASK ;\
+ newValue |= data;\
+ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
+}
+
+
+
+#endif
+
+#endif /* USE_LEVEL_1_MACROS */
+
+#endif /* _PRCM_REG_ACM_H */
diff --git a/drivers/dsp/bridge/hw/hw_defs.h b/drivers/dsp/bridge/hw/hw_defs.h
new file mode 100644
index 000000000000..a973f5c6a712
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_defs.h
@@ -0,0 +1,73 @@
+/*
+ * hw_defs.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+/*
+ * ======== hw_defs.h ========
+ * Description:
+ * Global HW definitions
+ *
+ *! Revision History:
+ *! ================
+ *! 19 Apr 2004 sb: Added generic page size, endianness and element size defns
+ *! 16 Feb 2003 sb: Initial version
+ */
+#ifndef __HW_DEFS_H
+#define __HW_DEFS_H
+
+#include <GlobalTypes.h>
+
+/* Page size */
+#define HW_PAGE_SIZE_4KB 0x1000
+#define HW_PAGE_SIZE_64KB 0x10000
+#define HW_PAGE_SIZE_1MB 0x100000
+#define HW_PAGE_SIZE_16MB 0x1000000
+
+/* HW_STATUS: return type for HW API */
+typedef long HW_STATUS;
+
+/* HW_SetClear_t: Enumerated Type used to set and clear any bit */
+enum HW_SetClear_t {
+ HW_CLEAR,
+ HW_SET
+} ;
+
+/* HW_Endianism_t: Enumerated Type used to specify the endianism
+ * Do NOT change these values. They are used as bit fields. */
+enum HW_Endianism_t {
+ HW_LITTLE_ENDIAN,
+ HW_BIG_ENDIAN
+
+} ;
+
+/* HW_ElementSize_t: Enumerated Type used to specify the element size
+ * Do NOT change these values. They are used as bit fields. */
+enum HW_ElementSize_t {
+ HW_ELEM_SIZE_8BIT,
+ HW_ELEM_SIZE_16BIT,
+ HW_ELEM_SIZE_32BIT,
+ HW_ELEM_SIZE_64BIT
+
+} ;
+
+/* HW_IdleMode_t: Enumerated Type used to specify Idle modes */
+ enum HW_IdleMode_t {
+ HW_FORCE_IDLE,
+ HW_NO_IDLE,
+ HW_SMART_IDLE
+ } ;
+
+#endif /* __HW_DEFS_H */
diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.c b/drivers/dsp/bridge/hw/hw_dspssC64P.c
new file mode 100644
index 000000000000..c61af812e2bd
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_dspssC64P.c
@@ -0,0 +1,56 @@
+/*
+ * hw_dspss64P.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== hw_dspss64P.c ========
+ * Description:
+ * API definitions to configure DSP Subsystem modules like IPI
+ *
+ *! Revision History:
+ *! ================
+ *! 19 Apr 2004 sb: Implemented HW_DSPSS_IPIEndianismSet
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+/* PROJECT SPECIFIC INCLUDE FILES */
+#include <GlobalTypes.h>
+#include <linux/io.h>
+#include <hw_defs.h>
+#include <hw_dspssC64P.h>
+#include <IVA2RegAcM.h>
+#include <IPIAccInt.h>
+
+/* HW FUNCTIONS */
+HW_STATUS HW_DSPSS_BootModeSet(const void __iomem *baseAddress,
+ enum HW_DSPSYSC_BootMode_t bootMode,
+ const u32 bootAddress)
+{
+ HW_STATUS status = RET_OK;
+ u32 offset = SYSC_IVA2BOOTMOD_OFFSET;
+ u32 alignedBootAddr;
+
+ /* if Boot mode it DIRECT BOOT, check that the bootAddress is
+ * aligned to atleast 1K :: TODO */
+ __raw_writel(bootMode, (baseAddress) + offset);
+
+ offset = SYSC_IVA2BOOTADDR_OFFSET;
+
+ alignedBootAddr = bootAddress & SYSC_IVA2BOOTADDR_MASK;
+
+ __raw_writel(alignedBootAddr, (baseAddress) + offset);
+
+ return status;
+}
diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.h b/drivers/dsp/bridge/hw/hw_dspssC64P.h
new file mode 100644
index 000000000000..50f9af455f48
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_dspssC64P.h
@@ -0,0 +1,48 @@
+/*
+ * hw_dspssC64P.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== hw_dspss.h ========
+ * Description:
+ * DSP Subsystem API declarations
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb: Removed redundant argument from HW_DSPSS_IPIEndianismSet
+ *! Moved endianness and element size to generic hw_defs.h
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+#ifndef __HW_DSPSS_H
+#define __HW_DSPSS_H
+#include <linux/types.h>
+
+ enum HW_DSPSYSC_BootMode_t {
+ HW_DSPSYSC_DIRECTBOOT = 0x0,
+ HW_DSPSYSC_IDLEBOOT = 0x1,
+ HW_DSPSYSC_SELFLOOPBOOT = 0x2,
+ HW_DSPSYSC_USRBOOTSTRAP = 0x3,
+ HW_DSPSYSC_DEFAULTRESTORE = 0x4
+ } ;
+
+#define HW_DSP_IDLEBOOT_ADDR 0x007E0000
+
+ extern HW_STATUS HW_DSPSS_BootModeSet(const void __iomem *baseAddress,
+ enum HW_DSPSYSC_BootMode_t bootMode,
+ const u32 bootAddress);
+
+#endif /* __HW_DSPSS_H */
diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c
new file mode 100644
index 000000000000..ee790327b7b0
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_mbox.c
@@ -0,0 +1,245 @@
+/*
+ * hw_mbox.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+/*
+ * ======== hw_mbox.c ========
+ * Description:
+ * Mailbox messaging & configuration API definitions
+ *
+ *! Revision History:
+ *! ================
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+#include <GlobalTypes.h>
+#include "MLBRegAcM.h"
+#include <hw_defs.h>
+#include <hw_mbox.h>
+
+/* width in bits of MBOX Id */
+#define HW_MBOX_ID_WIDTH 2
+
+struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1};
+
+/* Saves the mailbox context */
+HW_STATUS HW_MBOX_saveSettings(void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+
+ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
+ /* Get current enable status */
+ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (baseAddress, HW_MBOX_U0_ARM);
+ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (baseAddress, HW_MBOX_U1_DSP1);
+ return status;
+}
+
+/* Restores the mailbox context */
+HW_STATUS HW_MBOX_restoreSettings(void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+ /* Restor IRQ enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U0_ARM,
+ mboxsetting.irqEnable0);
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U1_DSP1,
+ mboxsetting.irqEnable1);
+ /* Restore Sysconfig register */
+ MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, mboxsetting.sysconfig);
+ return status;
+}
+
+/* Reads a u32 from the sub module message box Specified. if there are no
+ * messages in the mailbox then and error is returned. */
+HW_STATUS HW_MBOX_MsgRead(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId, u32 *const pReadValue)
+{
+ HW_STATUS status = RET_OK;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_PARAM(pReadValue, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Read 32-bit message in mail box */
+ *pReadValue = MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress,
+ (u32)mailBoxId);
+
+ return status;
+}
+
+/* Writes a u32 from the sub module message box Specified. */
+HW_STATUS HW_MBOX_MsgWrite(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId, const u32 writeValue)
+{
+ HW_STATUS status = RET_OK;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Write 32-bit value to mailbox */
+ MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, (u32)mailBoxId,
+ (u32)writeValue);
+
+ return status;
+}
+
+/* Gets number of messages in a specified mailbox. */
+HW_STATUS HW_MBOX_NumMsgGet(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId, u32 *const pNumMsg)
+{
+ HW_STATUS status = RET_OK;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_PARAM(pNumMsg, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Get number of messages available for MailBox */
+ *pNumMsg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress,
+ (u32)mailBoxId);
+
+ return status;
+}
+
+/* Enables the specified IRQ. */
+HW_STATUS HW_MBOX_EventEnable(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const HW_MBOX_UserId_t userId,
+ const u32 events)
+{
+ HW_STATUS status = RET_OK;
+ u32 irqEnableReg;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(enableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Get current enable status */
+ irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
+ (u32)userId);
+
+ /* update enable value */
+ irqEnableReg |= ((u32)(events)) << (((u32)(mailBoxId)) *
+ HW_MBOX_ID_WIDTH);
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
+ (u32)irqEnableReg);
+
+ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
+ /* Get current enable status */
+ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (baseAddress, HW_MBOX_U0_ARM);
+ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (baseAddress, HW_MBOX_U1_DSP1);
+ return status;
+}
+
+/* Disables the specified IRQ. */
+HW_STATUS HW_MBOX_EventDisable(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const HW_MBOX_UserId_t userId,
+ const u32 events)
+{
+ HW_STATUS status = RET_OK;
+ u32 irqDisableReg;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(disableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Get current enable status */
+ irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
+ (u32)userId);
+
+ /* update enable value */
+ irqDisableReg &= ~(((u32)(events)) << (((u32)(mailBoxId)) *
+ HW_MBOX_ID_WIDTH));
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
+ (u32)irqDisableReg);
+
+ return status;
+}
+
+/* Sets the status of the specified IRQ. */
+HW_STATUS HW_MBOX_EventAck(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId, const HW_MBOX_UserId_t userId,
+ const u32 event)
+{
+ HW_STATUS status = RET_OK;
+ u32 irqStatusReg;
+
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
+ RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(irqStatus, HW_MBOX_INT_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* calculate status to write */
+ irqStatusReg = ((u32)event) << (((u32)(mailBoxId)) *
+ HW_MBOX_ID_WIDTH);
+
+ /* clear Irq Status for specified mailbox/User Id */
+ MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, (u32)userId,
+ (u32)irqStatusReg);
+
+ /*
+ * FIXME: Replace all this custom register access with standard
+ * __raw_read/write().
+ *
+ * FIXME: Replace all interrupt handlers with standard linux style
+ * interrupt handlers.
+ *
+ * FIXME: Replace direct access to PRCM registers with omap standard
+ * PRCM register access.
+ *
+ * Flush posted write for the irq status to avoid spurious interrupts.
+ */
+ MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, (u32)userId);
+
+ return status;
+}
diff --git a/drivers/dsp/bridge/hw/hw_mbox.h b/drivers/dsp/bridge/hw/hw_mbox.h
new file mode 100644
index 000000000000..ad1a89c08d41
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_mbox.h
@@ -0,0 +1,323 @@
+/*
+ * hw_mbox.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * ======== hw_mbox.h ========
+ * Description:
+ * HW Mailbox API and types definitions
+ *
+ *! Revision History:
+ *! ================
+ *! 16 Feb 2003 sb: Initial version
+ */
+#ifndef __MBOX_H
+#define __MBOX_H
+
+/* Bitmasks for Mailbox interrupt sources */
+#define HW_MBOX_INT_NEW_MSG 0x1
+#define HW_MBOX_INT_NOT_FULL 0x2
+#define HW_MBOX_INT_ALL 0x3
+
+/* Maximum number of messages that mailbox can hald at a time. */
+#define HW_MBOX_MAX_NUM_MESSAGES 4
+
+/* HW_MBOX_Id_t: Enumerated Type used to specify Mailbox Sub Module Id Number */
+typedef enum HW_MBOX_Id_label {
+ HW_MBOX_ID_0,
+ HW_MBOX_ID_1,
+ HW_MBOX_ID_2,
+ HW_MBOX_ID_3,
+ HW_MBOX_ID_4,
+ HW_MBOX_ID_5
+
+} HW_MBOX_Id_t, *pHW_MBOX_Id_t;
+
+/* HW_MBOX_UserId_t: Enumerated Type used to specify Mail box User Id */
+typedef enum HW_MBOX_UserId_label {
+ HW_MBOX_U0_ARM,
+ HW_MBOX_U1_DSP1,
+ HW_MBOX_U2_DSP2,
+ HW_MBOX_U3_ARM
+
+} HW_MBOX_UserId_t, *pHW_MBOX_UserId_t;
+
+/* Mailbox context settings */
+struct MAILBOX_CONTEXT {
+ u32 sysconfig;
+ u32 irqEnable0;
+ u32 irqEnable1;
+};
+
+/*
+* FUNCTION : HW_MBOX_MsgRead
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to read
+*
+* OUTPUTS:
+*
+* Identifier : pReadValue
+* Type : u32 *const
+* Description : Value read from MailBox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/ptr Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE: : this function reads a u32 from the sub module message
+* box Specified. if there are no messages in the mailbox
+* then and error is returned.
+*/
+extern HW_STATUS HW_MBOX_MsgRead(const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ u32 *const pReadValue);
+
+/*
+* FUNCTION : HW_MBOX_MsgWrite
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to write
+*
+* Identifier : writeValue
+* Type : const u32
+* Description : Value to write to MailBox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function writes a u32 from the sub module message
+* box Specified.
+*/
+extern HW_STATUS HW_MBOX_MsgWrite(
+ const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const u32 writeValue
+ );
+
+/*
+* FUNCTION : HW_MBOX_NumMsgGet
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to get num messages
+*
+* OUTPUTS:
+*
+* Identifier : pNumMsg
+* Type : u32 *const
+* Description : Number of messages in mailbox
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Inavlid ID input at parameter
+*
+* PURPOSE: : this function gets number of messages in a specified mailbox.
+*/
+extern HW_STATUS HW_MBOX_NumMsgGet(
+ const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ u32 *const pNumMsg
+ );
+
+/*
+* FUNCTION : HW_MBOX_EventEnable
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to enable
+*
+* Identifier : userId
+* Type : const HW_MBOX_UserId_t
+* Description : Mail box User Id to enable
+*
+* Identifier : enableIrq
+* Type : const u32
+* Description : Irq value to enable
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function enables the specified IRQ.
+*/
+extern HW_STATUS HW_MBOX_EventEnable(
+ const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const HW_MBOX_UserId_t userId,
+ const u32 events
+ );
+
+/*
+* FUNCTION : HW_MBOX_EventDisable
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to disable
+*
+* Identifier : userId
+* Type : const HW_MBOX_UserId_t
+* Description : Mail box User Id to disable
+*
+* Identifier : enableIrq
+* Type : const u32
+* Description : Irq value to disable
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function disables the specified IRQ.
+*/
+extern HW_STATUS HW_MBOX_EventDisable(
+ const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const HW_MBOX_UserId_t userId,
+ const u32 events
+ );
+
+/*
+* FUNCTION : HW_MBOX_EventAck
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+* Identifier : mailBoxId
+* Type : const HW_MBOX_Id_t
+* Description : Mail Box Sub module Id to set
+*
+* Identifier : userId
+* Type : const HW_MBOX_UserId_t
+* Description : Mail box User Id to set
+*
+* Identifier : irqStatus
+* Type : const u32
+* Description : The value to write IRQ status
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address Paramater was set to 0
+* RET_INVALID_ID Invalid Id used
+*
+* PURPOSE: : this function sets the status of the specified IRQ.
+*/
+extern HW_STATUS HW_MBOX_EventAck(
+ const void __iomem *baseAddress,
+ const HW_MBOX_Id_t mailBoxId,
+ const HW_MBOX_UserId_t userId,
+ const u32 event
+ );
+
+/*
+* FUNCTION : HW_MBOX_saveSettings
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE: : this function saves the context of mailbox
+*/
+extern HW_STATUS HW_MBOX_saveSettings(void __iomem *baseAddres);
+
+/*
+* FUNCTION : HW_MBOX_restoreSettings
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of Mailbox module
+*
+*
+* RETURNS:
+*
+* Type : ReturnCode_t
+* Description : RET_OK No errors occured
+* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
+* RET_INVALID_ID Invalid Id used
+* RET_EMPTY Mailbox empty
+*
+* PURPOSE: : this function restores the context of mailbox
+*/
+extern HW_STATUS HW_MBOX_restoreSettings(void __iomem *baseAddres);
+
+#endif /* __MBOX_H */
diff --git a/drivers/dsp/bridge/hw/hw_mmu.c b/drivers/dsp/bridge/hw/hw_mmu.c
new file mode 100644
index 000000000000..ce9d5868d442
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_mmu.c
@@ -0,0 +1,599 @@
+/*
+ * hw_mmu.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * ======== hw_mmu.c ========
+ * Description:
+ * API definitions to setup MMU TLB and PTE
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb TLBAdd and TLBFlush input the page size in bytes instead
+ of an enum. TLBAdd inputs mapping attributes struct instead
+ of individual arguments.
+ Removed MMU.h and other cosmetic updates.
+ *! 08-Mar-2004 sb Added the Page Table Management APIs
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+#include <GlobalTypes.h>
+#include <linux/io.h>
+#include "MMURegAcM.h"
+#include <hw_defs.h>
+#include <hw_mmu.h>
+#include <linux/types.h>
+
+#define MMU_BASE_VAL_MASK 0xFC00
+#define MMU_PAGE_MAX 3
+#define MMU_ELEMENTSIZE_MAX 3
+#define MMU_ADDR_MASK 0xFFFFF000
+#define MMU_TTB_MASK 0xFFFFC000
+#define MMU_SECTION_ADDR_MASK 0xFFF00000
+#define MMU_SSECTION_ADDR_MASK 0xFF000000
+#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
+#define MMU_LARGE_PAGE_MASK 0xFFFF0000
+#define MMU_SMALL_PAGE_MASK 0xFFFFF000
+
+#define MMU_LOAD_TLB 0x00000001
+
+/* HW_MMUPageSize_t: Enumerated Type used to specify the MMU Page Size(SLSS) */
+enum HW_MMUPageSize_t {
+ HW_MMU_SECTION,
+ HW_MMU_LARGE_PAGE,
+ HW_MMU_SMALL_PAGE,
+ HW_MMU_SUPERSECTION
+} ;
+
+/*
+* FUNCTION : MMU_FlushEntry
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of MMU module
+*
+* RETURNS:
+*
+* Type : HW_STATUS
+* Description : RET_OK -- No errors occured
+* RET_BAD_NULL_PARAM -- A Pointer
+* Paramater was set to NULL
+*
+* PURPOSE: : Flush the TLB entry pointed by the
+* lock counter register
+* even if this entry is set protected
+*
+* METHOD: : Check the Input parameter and Flush a
+* single entry in the TLB.
+*/
+static HW_STATUS MMU_FlushEntry(const void __iomem *baseAddress);
+
+/*
+* FUNCTION : MMU_SetCAMEntry
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* TypE : const u32
+* Description : Base Address of instance of MMU module
+*
+* Identifier : pageSize
+* TypE : const u32
+* Description : It indicates the page size
+*
+* Identifier : preservedBit
+* Type : const u32
+* Description : It indicates the TLB entry is preserved entry
+* or not
+*
+* Identifier : validBit
+* Type : const u32
+* Description : It indicates the TLB entry is valid entry or not
+*
+*
+* Identifier : virtualAddrTag
+* Type : const u32
+* Description : virtual Address
+*
+* RETURNS:
+*
+* Type : HW_STATUS
+* Description : RET_OK -- No errors occured
+* RET_BAD_NULL_PARAM -- A Pointer Paramater
+* was set to NULL
+* RET_PARAM_OUT_OF_RANGE -- Input Parameter out
+* of Range
+*
+* PURPOSE: : Set MMU_CAM reg
+*
+* METHOD: : Check the Input parameters and set the CAM entry.
+*/
+static HW_STATUS MMU_SetCAMEntry(const void __iomem *baseAddress,
+ const u32 pageSize,
+ const u32 preservedBit,
+ const u32 validBit,
+ const u32 virtualAddrTag);
+
+/*
+* FUNCTION : MMU_SetRAMEntry
+*
+* INPUTS:
+*
+* Identifier : baseAddress
+* Type : const u32
+* Description : Base Address of instance of MMU module
+*
+* Identifier : physicalAddr
+* Type : const u32
+* Description : Physical Address to which the corresponding
+* virtual Address shouldpoint
+*
+* Identifier : endianism
+* Type : HW_Endianism_t
+* Description : endianism for the given page
+*
+* Identifier : elementSize
+* Type : HW_ElementSize_t
+* Description : The element size ( 8,16, 32 or 64 bit)
+*
+* Identifier : mixedSize
+* Type : HW_MMUMixedSize_t
+* Description : Element Size to follow CPU or TLB
+*
+* RETURNS:
+*
+* Type : HW_STATUS
+* Description : RET_OK -- No errors occured
+* RET_BAD_NULL_PARAM -- A Pointer Paramater
+* was set to NULL
+* RET_PARAM_OUT_OF_RANGE -- Input Parameter
+* out of Range
+*
+* PURPOSE: : Set MMU_CAM reg
+*
+* METHOD: : Check the Input parameters and set the RAM entry.
+*/
+static HW_STATUS MMU_SetRAMEntry(const void __iomem *baseAddress,
+ const u32 physicalAddr,
+ enum HW_Endianism_t endianism,
+ enum HW_ElementSize_t elementSize,
+ enum HW_MMUMixedSize_t mixedSize);
+
+/* HW FUNCTIONS */
+
+HW_STATUS HW_MMU_Enable(const void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_SET);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_Disable(const void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_CLEAR);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_NumLockedSet(const void __iomem *baseAddress,
+ u32 numLockedEntries)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_LOCKBaseValueWrite32(baseAddress, numLockedEntries);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_VictimNumSet(const void __iomem *baseAddress,
+ u32 victimEntryNum)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, victimEntryNum);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_EventAck(const void __iomem *baseAddress, u32 irqMask)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_IRQSTATUSWriteRegister32(baseAddress, irqMask);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_EventDisable(const void __iomem *baseAddress,
+ u32 irqMask)
+{
+ HW_STATUS status = RET_OK;
+ u32 irqReg;
+
+ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
+
+ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg & ~irqMask);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_EventEnable(const void __iomem *baseAddress, u32 irqMask)
+{
+ HW_STATUS status = RET_OK;
+ u32 irqReg;
+
+ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
+
+ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg | irqMask);
+
+ return status;
+}
+
+
+HW_STATUS HW_MMU_EventStatus(const void __iomem *baseAddress, u32 *irqMask)
+{
+ HW_STATUS status = RET_OK;
+
+ *irqMask = MMUMMU_IRQSTATUSReadRegister32(baseAddress);
+
+ return status;
+}
+
+
+HW_STATUS HW_MMU_FaultAddrRead(const void __iomem *baseAddress, u32 *addr)
+{
+ HW_STATUS status = RET_OK;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* read values from register */
+ *addr = MMUMMU_FAULT_ADReadRegister32(baseAddress);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_TTBSet(const void __iomem *baseAddress, u32 TTBPhysAddr)
+{
+ HW_STATUS status = RET_OK;
+ u32 loadTTB;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ loadTTB = TTBPhysAddr & ~0x7FUL;
+ /* write values to register */
+ MMUMMU_TTBWriteRegister32(baseAddress, loadTTB);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_TWLEnable(const void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_SET);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_TWLDisable(const void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+
+ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_CLEAR);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_TLBFlush(const void __iomem *baseAddress, u32 virtualAddr,
+ u32 pageSize)
+{
+ HW_STATUS status = RET_OK;
+ u32 virtualAddrTag;
+ enum HW_MMUPageSize_t pgSizeBits;
+
+ switch (pageSize) {
+ case HW_PAGE_SIZE_4KB:
+ pgSizeBits = HW_MMU_SMALL_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ pgSizeBits = HW_MMU_LARGE_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ pgSizeBits = HW_MMU_SECTION;
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ pgSizeBits = HW_MMU_SUPERSECTION;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ /* Generate the 20-bit tag from virtual address */
+ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
+
+ MMU_SetCAMEntry(baseAddress, pgSizeBits, 0, 0, virtualAddrTag);
+
+ MMU_FlushEntry(baseAddress);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_TLBAdd(const void __iomem *baseAddress,
+ u32 physicalAddr,
+ u32 virtualAddr,
+ u32 pageSize,
+ u32 entryNum,
+ struct HW_MMUMapAttrs_t *mapAttrs,
+ enum HW_SetClear_t preservedBit,
+ enum HW_SetClear_t validBit)
+{
+ HW_STATUS status = RET_OK;
+ u32 lockReg;
+ u32 virtualAddrTag;
+ enum HW_MMUPageSize_t mmuPgSize;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(pageSize, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mapAttrs->elementSize, MMU_ELEMENTSIZE_MAX,
+ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
+ RES_INVALID_INPUT_PARAM);
+
+ switch (pageSize) {
+ case HW_PAGE_SIZE_4KB:
+ mmuPgSize = HW_MMU_SMALL_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ mmuPgSize = HW_MMU_LARGE_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ mmuPgSize = HW_MMU_SECTION;
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ mmuPgSize = HW_MMU_SUPERSECTION;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ lockReg = MMUMMU_LOCKReadRegister32(baseAddress);
+
+ /* Generate the 20-bit tag from virtual address */
+ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
+
+ /* Write the fields in the CAM Entry Register */
+ MMU_SetCAMEntry(baseAddress, mmuPgSize, preservedBit, validBit,
+ virtualAddrTag);
+
+ /* Write the different fields of the RAM Entry Register */
+ /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit)*/
+ MMU_SetRAMEntry(baseAddress, physicalAddr, mapAttrs->endianism,
+ mapAttrs->elementSize, mapAttrs->mixedSize);
+
+ /* Update the MMU Lock Register */
+ /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1)*/
+ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, entryNum);
+
+ /* Enable loading of an entry in TLB by writing 1
+ into LD_TLB_REG register */
+ MMUMMU_LD_TLBWriteRegister32(baseAddress, MMU_LOAD_TLB);
+
+
+ MMUMMU_LOCKWriteRegister32(baseAddress, lockReg);
+
+ return status;
+}
+
+HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
+ u32 physicalAddr,
+ u32 virtualAddr,
+ u32 pageSize,
+ struct HW_MMUMapAttrs_t *mapAttrs)
+{
+ HW_STATUS status = RET_OK;
+ u32 pteAddr, pteVal;
+ s32 numEntries = 1;
+
+ switch (pageSize) {
+ case HW_PAGE_SIZE_4KB:
+ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
+ virtualAddr & MMU_SMALL_PAGE_MASK);
+ pteVal = ((physicalAddr & MMU_SMALL_PAGE_MASK) |
+ (mapAttrs->endianism << 9) |
+ (mapAttrs->elementSize << 4) |
+ (mapAttrs->mixedSize << 11) | 2
+ );
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ numEntries = 16;
+ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
+ virtualAddr & MMU_LARGE_PAGE_MASK);
+ pteVal = ((physicalAddr & MMU_LARGE_PAGE_MASK) |
+ (mapAttrs->endianism << 9) |
+ (mapAttrs->elementSize << 4) |
+ (mapAttrs->mixedSize << 11) | 1
+ );
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
+ virtualAddr & MMU_SECTION_ADDR_MASK);
+ pteVal = ((((physicalAddr & MMU_SECTION_ADDR_MASK) |
+ (mapAttrs->endianism << 15) |
+ (mapAttrs->elementSize << 10) |
+ (mapAttrs->mixedSize << 17)) &
+ ~0x40000) | 0x2
+ );
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ numEntries = 16;
+ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
+ virtualAddr & MMU_SSECTION_ADDR_MASK);
+ pteVal = (((physicalAddr & MMU_SSECTION_ADDR_MASK) |
+ (mapAttrs->endianism << 15) |
+ (mapAttrs->elementSize << 10) |
+ (mapAttrs->mixedSize << 17)
+ ) | 0x40000 | 0x2
+ );
+ break;
+
+ case HW_MMU_COARSE_PAGE_SIZE:
+ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
+ virtualAddr & MMU_SECTION_ADDR_MASK);
+ pteVal = (physicalAddr & MMU_PAGE_TABLE_MASK) | 1;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ while (--numEntries >= 0)
+ ((u32 *)pteAddr)[numEntries] = pteVal;
+
+ return status;
+}
+
+HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
+ u32 virtualAddr,
+ u32 pgSize)
+{
+ HW_STATUS status = RET_OK;
+ u32 pteAddr;
+ s32 numEntries = 1;
+
+ switch (pgSize) {
+ case HW_PAGE_SIZE_4KB:
+ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
+ virtualAddr & MMU_SMALL_PAGE_MASK);
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ numEntries = 16;
+ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
+ virtualAddr & MMU_LARGE_PAGE_MASK);
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ case HW_MMU_COARSE_PAGE_SIZE:
+ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
+ virtualAddr & MMU_SECTION_ADDR_MASK);
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ numEntries = 16;
+ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
+ virtualAddr & MMU_SSECTION_ADDR_MASK);
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ while (--numEntries >= 0)
+ ((u32 *)pteAddr)[numEntries] = 0;
+
+ return status;
+}
+
+/* MMU_FlushEntry */
+static HW_STATUS MMU_FlushEntry(const void __iomem *baseAddress)
+{
+ HW_STATUS status = RET_OK;
+ u32 flushEntryData = 0x1;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* write values to register */
+ MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, flushEntryData);
+
+ return status;
+}
+
+/* MMU_SetCAMEntry */
+static HW_STATUS MMU_SetCAMEntry(const void __iomem *baseAddress,
+ const u32 pageSize,
+ const u32 preservedBit,
+ const u32 validBit,
+ const u32 virtualAddrTag)
+{
+ HW_STATUS status = RET_OK;
+ u32 mmuCamReg;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ mmuCamReg = (virtualAddrTag << 12);
+ mmuCamReg = (mmuCamReg) | (pageSize) | (validBit << 2) |
+ (preservedBit << 3) ;
+
+ /* write values to register */
+ MMUMMU_CAMWriteRegister32(baseAddress, mmuCamReg);
+
+ return status;
+}
+
+/* MMU_SetRAMEntry */
+static HW_STATUS MMU_SetRAMEntry(const void __iomem *baseAddress,
+ const u32 physicalAddr,
+ enum HW_Endianism_t endianism,
+ enum HW_ElementSize_t elementSize,
+ enum HW_MMUMixedSize_t mixedSize)
+{
+ HW_STATUS status = RET_OK;
+ u32 mmuRamReg;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(elementSize, MMU_ELEMENTSIZE_MAX,
+ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
+ RES_INVALID_INPUT_PARAM);
+
+
+ mmuRamReg = (physicalAddr & MMU_ADDR_MASK);
+ mmuRamReg = (mmuRamReg) | ((endianism << 9) | (elementSize << 7) |
+ (mixedSize << 6));
+
+ /* write values to register */
+ MMUMMU_RAMWriteRegister32(baseAddress, mmuRamReg);
+
+ return status;
+
+}
diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h
new file mode 100644
index 000000000000..b1e245821924
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_mmu.h
@@ -0,0 +1,177 @@
+/*
+ * hw_mmu.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+
+/*
+ * ======== hw_mmu.h ========
+ * Description:
+ * MMU types and API declarations
+ *
+ *! Revision History:
+ *! ================
+ *! 19-Apr-2004 sb Moved & renamed endianness, page size, element size
+ TLBAdd takes in MMUMapAttrs instead of separate arguments
+ *! 08-Mar-2004 sb Added the Page Table management APIs
+ *! 16 Feb 2003 sb: Initial version
+ */
+#ifndef __HW_MMU_H
+#define __HW_MMU_H
+
+#include <linux/types.h>
+
+/* Bitmasks for interrupt sources */
+#define HW_MMU_TRANSLATION_FAULT 0x2
+#define HW_MMU_ALL_INTERRUPTS 0x1F
+
+#define HW_MMU_COARSE_PAGE_SIZE 0x400
+
+/* HW_MMUMixedSize_t: Enumerated Type used to specify whether to follow
+ CPU/TLB Element size */
+enum HW_MMUMixedSize_t {
+ HW_MMU_TLBES,
+ HW_MMU_CPUES
+
+} ;
+
+/* HW_MMUMapAttrs_t: Struct containing MMU mapping attributes */
+struct HW_MMUMapAttrs_t {
+ enum HW_Endianism_t endianism;
+ enum HW_ElementSize_t elementSize;
+ enum HW_MMUMixedSize_t mixedSize;
+ bool donotlockmpupage;
+} ;
+
+extern HW_STATUS HW_MMU_Enable(const void __iomem *baseAddress);
+
+extern HW_STATUS HW_MMU_Disable(const void __iomem *baseAddress);
+
+extern HW_STATUS HW_MMU_NumLockedSet(const void __iomem *baseAddress,
+ u32 numLockedEntries);
+
+extern HW_STATUS HW_MMU_VictimNumSet(const void __iomem *baseAddress,
+ u32 victimEntryNum);
+
+/* For MMU faults */
+extern HW_STATUS HW_MMU_EventAck(const void __iomem *baseAddress,
+ u32 irqMask);
+
+extern HW_STATUS HW_MMU_EventDisable(const void __iomem *baseAddress,
+ u32 irqMask);
+
+extern HW_STATUS HW_MMU_EventEnable(const void __iomem *baseAddress,
+ u32 irqMask);
+
+extern HW_STATUS HW_MMU_EventStatus(const void __iomem *baseAddress,
+ u32 *irqMask);
+
+extern HW_STATUS HW_MMU_FaultAddrRead(const void __iomem *baseAddress,
+ u32 *addr);
+
+/* Set the TT base address */
+extern HW_STATUS HW_MMU_TTBSet(const void __iomem *baseAddress,
+ u32 TTBPhysAddr);
+
+extern HW_STATUS HW_MMU_TWLEnable(const void __iomem *baseAddress);
+
+extern HW_STATUS HW_MMU_TWLDisable(const void __iomem *baseAddress);
+
+extern HW_STATUS HW_MMU_TLBFlush(const void __iomem *baseAddress,
+ u32 virtualAddr,
+ u32 pageSize);
+
+extern HW_STATUS HW_MMU_TLBAdd(const void __iomem *baseAddress,
+ u32 physicalAddr,
+ u32 virtualAddr,
+ u32 pageSize,
+ u32 entryNum,
+ struct HW_MMUMapAttrs_t *mapAttrs,
+ enum HW_SetClear_t preservedBit,
+ enum HW_SetClear_t validBit);
+
+
+/* For PTEs */
+extern HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
+ u32 physicalAddr,
+ u32 virtualAddr,
+ u32 pageSize,
+ struct HW_MMUMapAttrs_t *mapAttrs);
+
+extern HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
+ u32 pgSize,
+ u32 virtualAddr);
+
+static inline u32 HW_MMU_PteAddrL1(u32 L1_base, u32 va)
+{
+ u32 pteAddr;
+ u32 VA_31_to_20;
+
+ VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
+ VA_31_to_20 &= 0xFFFFFFFCUL;
+ pteAddr = L1_base + VA_31_to_20;
+
+ return pteAddr;
+}
+
+static inline u32 HW_MMU_PteAddrL2(u32 L2_base, u32 va)
+{
+ u32 pteAddr;
+
+ pteAddr = (L2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
+
+ return pteAddr;
+}
+
+static inline u32 HW_MMU_PteCoarseL1(u32 pteVal)
+{
+ u32 pteCoarse;
+
+ pteCoarse = pteVal & 0xFFFFFC00;
+
+ return pteCoarse;
+}
+
+static inline u32 HW_MMU_PteSizeL1(u32 pteVal)
+{
+ u32 pteSize = 0;
+
+ if ((pteVal & 0x3) == 0x1) {
+ /* Points to L2 PT */
+ pteSize = HW_MMU_COARSE_PAGE_SIZE;
+ }
+
+ if ((pteVal & 0x3) == 0x2) {
+ if (pteVal & (1 << 18))
+ pteSize = HW_PAGE_SIZE_16MB;
+ else
+ pteSize = HW_PAGE_SIZE_1MB;
+ }
+
+ return pteSize;
+}
+
+static inline u32 HW_MMU_PteSizeL2(u32 pteVal)
+{
+ u32 pteSize = 0;
+
+ if (pteVal & 0x2)
+ pteSize = HW_PAGE_SIZE_4KB;
+ else if (pteVal & 0x1)
+ pteSize = HW_PAGE_SIZE_64KB;
+
+ return pteSize;
+}
+
+#endif /* __HW_MMU_H */
diff --git a/drivers/dsp/bridge/hw/hw_prcm.c b/drivers/dsp/bridge/hw/hw_prcm.c
new file mode 100644
index 000000000000..3a6279e967ab
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_prcm.c
@@ -0,0 +1,368 @@
+/*
+ * hw_prcm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * ======== hw_prcm.c ========
+ * Description:
+ * API definitions to configure PRCM (Power, Reset & Clocks Manager)
+ *
+ *! Revision History:
+ *! ================
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+#include <GlobalTypes.h>
+#include "PRCMRegAcM.h"
+#include <hw_defs.h>
+#include <hw_prcm.h>
+
+
+
+static HW_STATUS HW_RST_WriteVal(const void __iomem *baseAddress,
+ enum HW_RstModule_t r,
+ enum HW_SetClear_t val);
+
+HW_STATUS HW_RST_Reset(const void __iomem *baseAddress, enum HW_RstModule_t r)
+{
+ return HW_RST_WriteVal(baseAddress, r, HW_SET);
+}
+
+HW_STATUS HW_RST_UnReset(const void __iomem *baseAddress, enum HW_RstModule_t r)
+{
+ return HW_RST_WriteVal(baseAddress, r, HW_CLEAR);
+}
+
+static HW_STATUS HW_RST_WriteVal(const void __iomem *baseAddress,
+ enum HW_RstModule_t r,
+ enum HW_SetClear_t val)
+{
+ HW_STATUS status = RET_OK;
+
+ switch (r) {
+#ifdef OMAP44XX
+ case HW_RST1_TESLA:
+ PRM_TESLA_RSTCTRL_RST1_Write32(baseAddress, val);
+ break;
+ case HW_RST2_TESLA:
+ PRM_TESLA_RSTCTRL_RST2_Write32(baseAddress, val);
+ break;
+#else
+ case HW_RST1_IVA2:
+ PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress, val);
+ break;
+ case HW_RST2_IVA2:
+ PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress, val);
+ break;
+ case HW_RST3_IVA2:
+ PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress, val);
+ break;
+#endif
+ default:
+ status = RET_FAIL;
+ break;
+ }
+ return status;
+}
+
+#ifdef OMAP_3430
+HW_STATUS HW_PWR_IVA2StateGet(const void __iomem *baseAddress,
+ enum HW_PwrModule_t p, enum HW_PwrState_t *value)
+{
+ HW_STATUS status = RET_OK;
+ u32 temp;
+
+ switch (p) {
+ case HW_PWR_DOMAIN_DSP:
+ /* wait until Transition is complete */
+ do {
+ /* mdelay(1); */
+ temp = PRCMPM_PWSTST_IVA2InTransitionRead32
+ (baseAddress);
+
+ } while (temp);
+ temp = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
+ *value = PRCMPM_PWSTST_IVA2PowerStateStGet32(temp);
+ break;
+
+ default:
+ status = RET_FAIL;
+ break;
+ }
+ return status;
+}
+
+HW_STATUS HW_PWRST_IVA2RegGet(const void __iomem *baseAddress, u32 *value)
+{
+ HW_STATUS status = RET_OK;
+
+ *value = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
+
+ return status;
+}
+
+
+HW_STATUS HW_PWR_IVA2PowerStateSet(const void __iomem *baseAddress,
+ enum HW_PwrModule_t p,
+ enum HW_PwrState_t value)
+{
+ HW_STATUS status = RET_OK;
+
+ switch (p) {
+ case HW_PWR_DOMAIN_DSP:
+ switch (value) {
+ case HW_PWR_STATE_ON:
+ PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress);
+ break;
+ case HW_PWR_STATE_RET:
+ PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress);
+ break;
+ case HW_PWR_STATE_OFF:
+ PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress);
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+ break;
+
+ default:
+ status = RET_FAIL;
+ break;
+ }
+
+ return status;
+}
+
+HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const void __iomem *baseAddress,
+ enum HW_TransitionState_t val)
+{
+ HW_STATUS status = RET_OK;
+
+ PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, val);
+
+ return status;
+
+}
+#endif
+
+HW_STATUS HW_RSTST_RegGet(const void __iomem *baseAddress,
+ enum HW_RstModule_t m, u32 *value)
+{
+ HW_STATUS status = RET_OK;
+#ifdef OMAP44XX
+ *value = PRM_TESLA_RSTSTReadRegister32(baseAddress);
+
+#else
+ *value = PRCMRM_RSTST_DSPReadRegister32(baseAddress);
+#endif
+
+ return status;
+}
+
+HW_STATUS HW_RSTCTRL_RegGet(const void __iomem *baseAddress,
+ enum HW_RstModule_t m, u32 *value)
+{
+ HW_STATUS status = RET_OK;
+#ifdef OMAP44XX
+ *value = PRM_TESLA_RSTCTRLReadRegister32(baseAddress);
+#else
+ *value = PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress);
+#endif
+
+
+ return status;
+}
+
+#ifdef OMAP44XX
+
+static HW_STATUS HW_CLK_WriteVal (const u32 baseAddress, enum HW_ClkModule_t c, enum HW_SetClear_t val);
+
+
+HW_STATUS HW_CLK_Enable(const u32 baseAddress, enum HW_ClkModule_t c)
+{
+ return HW_CLK_WriteVal(baseAddress, c, HW_SET);
+}
+
+HW_STATUS HW_CLK_Disable(const u32 baseAddress, enum HW_ClkModule_t c)
+{
+ return HW_CLK_WriteVal(baseAddress, c, HW_CLEAR);
+}
+
+static HW_STATUS HW_CLK_WriteVal (const u32 baseAddress, enum HW_ClkModule_t c, enum HW_SetClear_t val)
+{
+ HW_STATUS status = RET_OK;
+ u32 val_clk = HW_CLEAR;
+
+ if (val == HW_SET)
+ val_clk = 0x2;
+
+ switch (c) {
+ case HW_CLK_TESLA:
+ CM_TESLA_TESLA_CLKCTRLWriteRegister32(baseAddress, val);
+ break;
+ case HW_CLK_MCBSP1:
+ CM_ABEEN_MCBSP1Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_MCBSP2:
+ CM_ABEEN_MCBSP2Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_MCBSP3:
+ CM_ABEEN_MCBSP3Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_MCBSP4:
+ CM_L4PEREN_MCBSP4Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_MCBSP5:
+ CM_L4PEREN_MCBSP5Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_TIMER5:
+ CM_ABEEN_TIMER5Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_TIMER6:
+ CM_ABEEN_TIMER6Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_TIMER7:
+ CM_ABEEN_TIMER7Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_TIMER8:
+ CM_ABEEN_TIMER8Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER2:
+ CM_L4PEREN_DMTIMER2Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER3:
+ CM_L4PEREN_DMTIMER3Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER4:
+ CM_L4PEREN_DMTIMER4Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER9:
+ CM_L4PEREN_DMTIMER9Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER10:
+ CM_L4PEREN_DMTIMER10Write32(baseAddress, val_clk);
+ break;
+ case HW_CLK_DMTIMER11:
+ CM_L4PEREN_DMTIMER11Write32(baseAddress, val_clk);
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+
+ return status;
+}
+
+
+HW_STATUS HW_PWRSTCTRL_RegGet(const u32 baseAddress, u32 *value)
+{
+ HW_STATUS status = RET_OK;
+
+ *value = PRM_TESLA_PWRSTCTRLReadRegister32(baseAddress);
+
+ return status;
+}
+
+
+HW_STATUS HW_PWR_PowerStateGet(const u32 baseAddress,
+ enum HW_PwrModule_t p, enum HW_PwrState_t *value)
+{
+ HW_STATUS status = RET_OK;
+ switch (p) {
+ case HW_PWR_DOMAIN_TESLA:
+ *value = (enum HW_PwrState_t)PRM_TESLA_PWRSTSTGet32(baseAddress);
+ break;
+
+ default:
+ status = RET_FAIL;
+ break;
+ }
+
+ return status;
+}
+
+HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
+ enum HW_PwrModule_t p, enum HW_PwrState_t value)
+{
+ HW_STATUS status = RET_OK;
+
+ switch (p) {
+ case HW_PWR_DOMAIN_TESLA:
+ switch (value) {
+ case HW_PWR_STATE_ON:
+ PRM_TESLA_PWRSTCTRLWriteON32(baseAddress);
+ break;
+ case HW_PWR_STATE_INACT:
+ PRM_TESLA_PWRSTCTRLWriteINACTIVE32(baseAddress);
+ break;
+ case HW_PWR_STATE_RET:
+ PRM_TESLA_PWRSTCTRLWriteRET32(baseAddress);
+ break;
+ case HW_PWR_STATE_OFF:
+ PRM_TESLA_PWRSTCTRLWriteOFF32(baseAddress);
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+ break;
+ case HW_PWR_DOMAIN_CORE:
+ switch (value) {
+ case HW_PWR_STATE_ON:
+ case HW_PWR_STATE_INACT:
+ case HW_PWR_STATE_RET:
+ case HW_PWR_STATE_OFF:
+ PRM_CORE_PWRSTCTRLWrite32(baseAddress, value);
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+
+ return status;
+}
+
+HW_STATUS HW_PWR_ForceStateSet(const u32 baseAddress, enum HW_PwrModule_t p,
+ enum HW_TransitionState_t value)
+{
+ HW_STATUS status = RET_OK;
+
+ switch (p) {
+ case HW_PWR_DOMAIN_TESLA:
+ CM_CLKSTCTRL_TESLAWriteRegister32(baseAddress, value);
+ break;
+ case HW_PWR_DOMAIN_ABE:
+ CM_CLKSTCTRL_ABEWriteRegister32(baseAddress, value);
+ break;
+ case HW_PWR_DOMAIN_L4PER:
+ CM_CLKSTCTRL_L4PERWriteRegister32(baseAddress, value);
+ break;
+ default:
+ status = RET_FAIL;
+ break;
+ }
+
+ return status;
+}
+
+
+#endif
+
diff --git a/drivers/dsp/bridge/hw/hw_prcm.h b/drivers/dsp/bridge/hw/hw_prcm.h
new file mode 100644
index 000000000000..61cace2b0355
--- /dev/null
+++ b/drivers/dsp/bridge/hw/hw_prcm.h
@@ -0,0 +1,284 @@
+/*
+ * hw_prcm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * ======== hw_prcm.h ========
+ * Description:
+ * PRCM types and API declarations
+ *
+ *! Revision History:
+ *! ================
+ *! 16 Feb 2003 sb: Initial version
+ */
+
+#ifndef __HW_PRCM_H
+#define __HW_PRCM_H
+
+/* HW_ClkModule: Enumerated Type used to specify the clock domain */
+
+enum HW_ClkModule_t {
+#ifdef OMAP44XX
+/*CM1 ABE*/
+ HW_CLK_TESLA,
+ HW_CLK_AESS,
+ HW_CLK_PDM,
+ HW_CLK_DMIC,
+ HW_CLK_MCASP,
+ HW_CLK_MCBSP1,
+ HW_CLK_MCBSP2,
+ HW_CLK_MCBSP3,
+ HW_CLK_SLIMBUS,
+ HW_CLK_TIMER5,
+ HW_CLK_TIMER6,
+ HW_CLK_TIMER7,
+ HW_CLK_TIMER8,
+ HW_CLK_WDT3,
+/*CM2 L4PER*/
+ HW_CLK_DMTIMER2,
+ HW_CLK_DMTIMER3,
+ HW_CLK_DMTIMER4,
+ HW_CLK_DMTIMER9,
+ HW_CLK_DMTIMER10,
+ HW_CLK_DMTIMER11,
+ HW_CLK_MCBSP4,
+ HW_CLK_MCBSP5,
+
+#else
+ /* DSP Domain */
+ HW_CLK_DSP_CPU,
+ HW_CLK_DSP_IPI_MMU,
+ HW_CLK_IVA_ARM,
+ HW_CLK_IVA_COP, /* IVA Coprocessor */
+
+ /* Core Domain */
+ HW_CLK_FN_WDT4, /* Functional Clock */
+ HW_CLK_FN_WDT3,
+ HW_CLK_FN_UART2,
+ HW_CLK_FN_UART1,
+ HW_CLK_GPT5,
+ HW_CLK_GPT6,
+ HW_CLK_GPT7,
+ HW_CLK_GPT8,
+
+ HW_CLK_IF_WDT4, /* Interface Clock */
+ HW_CLK_IF_WDT3,
+ HW_CLK_IF_UART2,
+ HW_CLK_IF_UART1,
+ HW_CLK_IF_MBOX
+#endif
+} ;
+
+enum HW_ClkSubsys_t {
+ HW_CLK_DSPSS,
+ HW_CLK_IVASS
+} ;
+
+/* HW_GPtimers: General purpose timers */
+enum HW_GPtimer_t {
+ HW_GPT5 = 5,
+ HW_GPT6 = 6,
+ HW_GPT7 = 7,
+ HW_GPT8 = 8
+} ;
+
+
+/* GP timers Input clock type: General purpose timers */
+enum HW_Clocktype_t {
+ HW_CLK_32KHz = 0,
+ HW_CLK_SYS = 1,
+ HW_CLK_EXT = 2
+} ;
+
+/* HW_ClkDiv: Clock divisors */
+enum HW_ClkDiv_t {
+ HW_CLK_DIV_1 = 0x1,
+ HW_CLK_DIV_2 = 0x2,
+ HW_CLK_DIV_3 = 0x3,
+ HW_CLK_DIV_4 = 0x4,
+ HW_CLK_DIV_6 = 0x6,
+ HW_CLK_DIV_8 = 0x8,
+ HW_CLK_DIV_12 = 0xC
+} ;
+
+/* HW_RstModule: Enumerated Type used to specify the module to be reset */
+enum HW_RstModule_t {
+#ifdef OMAP44XX
+ HW_RST1_TESLA, /*Reset the DSP*/
+ HW_RST2_TESLA, /* Reset MMU */
+#else
+ HW_RST1_IVA2, /* Reset the DSP */
+ HW_RST2_IVA2, /* Reset MMU and LEON HWa */
+ HW_RST3_IVA2 /* Reset LEON sequencer */
+#endif
+} ;
+
+/* HW_PwrModule: Enumerated Type used to specify the power domain */
+enum HW_PwrModule_t {
+/* Domains */
+ HW_PWR_DOMAIN_CORE,
+ HW_PWR_DOMAIN_MPU,
+ HW_PWR_DOMAIN_WAKEUP,
+#ifdef OMAP44XX
+ HW_PWR_DOMAIN_TESLA,
+ HW_PWR_DOMAIN_ABE,
+ HW_PWR_DOMAIN_L4PER,
+#else
+ HW_PWR_DOMAIN_DSP,
+#endif
+
+/* Sub-domains */
+ HW_PWR_DSP_IPI, /* IPI = Intrusive Port Interface */
+ HW_PWR_IVA_ISP /* ISP = Intrusive Slave Port */
+} ;
+
+enum HW_PwrState_t {
+ HW_PWR_STATE_OFF,
+ HW_PWR_STATE_RET,
+ HW_PWR_STATE_INACT,
+ HW_PWR_STATE_ON = 3
+} ;
+
+enum HW_ForceState_t {
+ HW_FORCE_OFF,
+ HW_FORCE_ON
+} ;
+
+enum HW_IdleState_t {
+ HW_ACTIVE,
+ HW_STANDBY
+} ;
+
+enum HW_TransitionState_t {
+ HW_AUTOTRANS_DIS,
+ HW_SW_SUP_SLEEP,
+ HW_SW_SUP_WAKEUP,
+ HW_AUTOTRANS_EN
+} ;
+
+#ifdef OMAP44XX
+enum HW_RetState_t {
+ HW_RETSTATE_LOGIC,
+ HW_RETSTATE_L1,
+ HW_RETSTATE_L2
+};
+
+enum HW_WeakUpDep_t {
+ HW_WKUP_IVA_MPU,
+ HW_WKUP_IVA_DUCATI
+};
+
+enum HW_IvaDVFS_t {
+ HW_DVFS_PERF_TESLA,
+ HW_DVFS_PERF_IVAHD,
+ HW_DVFS_PERF_ABE,
+ HW_DVFS_RESULT,
+ HW_DVFS_CURRENT
+};
+
+enum HW_IdleStatus_t {
+ HW_TESLA_FULLFUNC = 0x0, /* Module is fully functional, including OCP*/
+ HW_TESLA_TRANSITIONING, /* Transitioning (weakup, sleep or sleep abortion)*/
+ HW_TESLA_IDLE,/* Idle mode(only OCP)*/
+ HW_TESLA_DISABLED/*Module is disabled and cannot be accessed*/
+};
+#endif
+
+extern HW_STATUS HW_RST_Reset(const void __iomem *baseAddress,
+ enum HW_RstModule_t r);
+
+extern HW_STATUS HW_RST_UnReset(const void __iomem *baseAddress,
+ enum HW_RstModule_t r);
+
+extern HW_STATUS HW_RSTCTRL_RegGet(const void __iomem *baseAddress,
+ enum HW_RstModule_t p,
+ u32 *value);
+extern HW_STATUS HW_RSTST_RegGet(const void __iomem *baseAddress,
+ enum HW_RstModule_t p, u32 *value);
+
+extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
+ enum HW_PwrModule_t p,
+ enum HW_PwrState_t value);
+
+extern HW_STATUS HW_CLK_SetInputClock(const u32 baseAddress,
+ enum HW_GPtimer_t gpt,
+ enum HW_Clocktype_t c);
+
+#ifdef OMAP_3430
+extern HW_STATUS HW_PWR_IVA2StateGet(const void __iomem *baseAddress,
+ enum HW_PwrModule_t p,
+ enum HW_PwrState_t *value);
+
+extern HW_STATUS HW_PWRST_IVA2RegGet(const void __iomem *baseAddress,
+ u32 *value);
+
+extern HW_STATUS HW_PWR_IVA2PowerStateSet(const void __iomem *baseAddress,
+ enum HW_PwrModule_t p,
+ enum HW_PwrState_t value);
+
+extern HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const void __iomem *baseAddress,
+ enum HW_TransitionState_t val);
+#endif
+
+#ifdef OMAP44XX
+extern HW_STATUS HW_CLK_Enable(const u32 baseAddress,
+ enum HW_ClkModule_t c);
+
+extern HW_STATUS HW_CLK_Disable(const u32 baseAddress,
+ enum HW_ClkModule_t c);
+
+extern HW_STATUS HW_CLK_AutoIdleEnable(const u32 baseAddress,
+ enum HW_ClkModule_t c);
+
+extern HW_STATUS HW_CLK_AutoIdleDisable(const u32 baseAddress,
+ enum HW_ClkModule_t c);
+#if 0
+extern HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress, u32 *value);
+
+extern HW_STATUS HW_RSTST_RegGet(const u32 baseAddress, u32 *value);
+#endif
+
+extern HW_STATUS HW_RSTST_RegClear(const u32 baseAddress);
+
+extern HW_STATUS HW_PWRSTCTRL_RegGet(const u32 baseAddress, u32 *value);
+
+extern HW_STATUS HW_PWR_PowerStateGet(const u32 baseAddress,
+ enum HW_PwrModule_t p, enum HW_PwrState_t *value);
+
+extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress, enum HW_PwrModule_t p,
+ enum HW_PwrState_t value);
+#if 0
+
+extern HW_STATUS HW_PWR_RetentionStateSet(const u32 baseAddress,
+ enum HW_PwrModule_t p, enum HW_RetState_t src, enum HW_SetClear_t value);
+#endif
+
+extern HW_STATUS HW_PWRST_RegGet(const u32 baseAddress, enum HW_PwrModule_t p, u32 *value);
+
+
+extern HW_STATUS HW_PWR_ForceStateSet(const u32 baseAddress, enum HW_PwrModule_t p,
+ enum HW_TransitionState_t value);
+
+extern HW_STATUS HW_TESLA_RST_WriteVal(const u32 baseAddress, enum HW_RstModule_t p,
+ enum HW_SetClear_t value);
+#if 0
+extern HW_STATUS HW_TESLA_CONTEXT_RegGet(const u32 baseAddress, u32 *value);
+
+extern HW_STATUS HW_TESLA_CONTEXT_ClrSet(const u32 baseAddress);
+#endif
+
+#endif
+
+#endif /* __HW_PRCM_H */
diff --git a/drivers/dsp/bridge/pmgr/chnl.c b/drivers/dsp/bridge/pmgr/chnl.c
new file mode 100644
index 000000000000..6b5a0d9256a9
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/chnl.c
@@ -0,0 +1,260 @@
+/*
+ * chnl.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnl.c ========
+ * Description:
+ * WCD channel interface: multiplexes data streams through the single
+ * physical link managed by a 'Bridge mini-driver.
+ *
+ * Public Functions:
+ * CHNL_Close
+ * CHNL_CloseOrphans
+ * CHNL_Create
+ * CHNL_Destroy
+ * CHNL_Exit
+ * CHNL_GetHandle
+ * CHNL_GetProcessHandle
+ * CHNL_Init
+ * CHNL_Open
+ *
+ * Notes:
+ * This interface is basically a pass through to the WMD CHNL functions,
+ * except for the CHNL_Get() accessor functions which call
+ * WMD_CHNL_GetInfo().
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 07-Jan-2002 ag CHNL_CloseOrphans() now closes supported # of channels.
+ *! 17-Nov-2000 jeh Removed IRQ, shared memory stuff from CHNL_Create.
+ *! 28-Feb-2000 rr: New GT USage Implementation
+ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
+ *! SERVICES)
+ *! 21-Jan-2000 ag: Added code review comments.
+ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
+ *! 08-Dec-1999 ag: CHNL_[Alloc|Free]Buffer bufs taken from client process heap.
+ *! 02-Dec-1999 ag: Implemented CHNL_GetEventHandle().
+ *! 17-Nov-1999 ag: CHNL_AllocBuffer() allocs extra word for process mapping.
+ *! 28-Oct-1999 ag: WinCE port. Search for "WinCE" for changes(TBR).
+ *! 07-Jan-1998 gp: CHNL_[Alloc|Free]Buffer now call MEM_UMB functions.
+ *! 22-Oct-1997 gp: Removed requirement in CHNL_Open that hReserved1 != NULL.
+ *! 30-Aug-1997 cr: Renamed cfg.h wbwcd.h b/c of WINNT file name collision.
+ *! 10-Mar-1997 gp: Added GT trace.
+ *! 14-Jan-1997 gp: Updated based on code review feedback.
+ *! 03-Jan-1997 gp: Moved CHNL_AllocBuffer/CHNL_FreeBuffer code from udspsys.
+ *! 14-Dec-1996 gp: Added uChnlId parameter to CHNL_Open().
+ *! 09-Sep-1996 gp: Added CHNL_GetProcessHandle().
+ *! 15-Jul-1996 gp: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/dpc.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/proc.h>
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/chnlpriv.h>
+#include <chnlobj.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/chnl.h>
+
+/* ----------------------------------- Globals */
+static u32 cRefs;
+#if GT_TRACE
+static struct GT_Mask CHNL_DebugMask = { NULL, NULL }; /* WCD CHNL Mask */
+#endif
+
+
+
+/*
+ * ======== CHNL_Create ========
+ * Purpose:
+ * Create a channel manager object, responsible for opening new channels
+ * and closing old ones for a given 'Bridge board.
+ */
+DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
+{
+ DSP_STATUS status;
+ struct CHNL_MGR *hChnlMgr;
+ struct CHNL_MGR_ *pChnlMgr = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phChnlMgr != NULL);
+ DBC_Require(pMgrAttrs != NULL);
+
+ GT_3trace(CHNL_DebugMask, GT_ENTER,
+ "Entered CHNL_Create: phChnlMgr: 0x%x\t"
+ "hDevObject: 0x%x\tpMgrAttrs:0x%x\n",
+ phChnlMgr, hDevObject, pMgrAttrs);
+
+ *phChnlMgr = NULL;
+
+ /* Validate args: */
+ if ((0 < pMgrAttrs->cChannels) &&
+ (pMgrAttrs->cChannels <= CHNL_MAXCHANNELS)) {
+ status = DSP_SOK;
+ } else if (pMgrAttrs->cChannels == 0) {
+ status = DSP_EINVALIDARG;
+ GT_0trace(CHNL_DebugMask, GT_7CLASS,
+ "CHNL_Create:Invalid Args\n");
+ } else {
+ status = CHNL_E_MAXCHANNELS;
+ GT_0trace(CHNL_DebugMask, GT_7CLASS,
+ "CHNL_Create:Error Max Channels\n");
+ }
+ if (pMgrAttrs->uWordSize == 0) {
+ status = CHNL_E_INVALIDWORDSIZE;
+ GT_0trace(CHNL_DebugMask, GT_7CLASS,
+ "CHNL_Create:Invalid Word size\n");
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
+ if (DSP_SUCCEEDED(status) && hChnlMgr != NULL)
+ status = CHNL_E_MGREXISTS;
+
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+ /* Let WMD channel module finish the create: */
+ status = (*pIntfFxns->pfnChnlCreate)(&hChnlMgr, hDevObject,
+ pMgrAttrs);
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in WCD channel module's fields of the
+ * CHNL_MGR structure */
+ pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
+ pChnlMgr->pIntfFxns = pIntfFxns;
+ /* Finally, return the new channel manager handle: */
+ *phChnlMgr = hChnlMgr;
+ GT_1trace(CHNL_DebugMask, GT_1CLASS,
+ "CHNL_Create: Success pChnlMgr:"
+ "0x%x\n", pChnlMgr);
+ }
+ }
+
+ GT_2trace(CHNL_DebugMask, GT_ENTER,
+ "Exiting CHNL_Create: pChnlMgr: 0x%x,"
+ "status: 0x%x\n", pChnlMgr, status);
+ DBC_Ensure(DSP_FAILED(status) || CHNL_IsValidMgr(pChnlMgr));
+
+ return status;
+}
+
+/*
+ * ======== CHNL_Destroy ========
+ * Purpose:
+ * Close all open channels, and destroy the channel manager.
+ */
+DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
+{
+ struct CHNL_MGR_ *pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(CHNL_DebugMask, GT_ENTER,
+ "Entered CHNL_Destroy: hChnlMgr: 0x%x\n", hChnlMgr);
+ if (CHNL_IsValidMgr(pChnlMgr)) {
+ pIntfFxns = pChnlMgr->pIntfFxns;
+ /* Let WMD channel module destroy the CHNL_MGR: */
+ status = (*pIntfFxns->pfnChnlDestroy)(hChnlMgr);
+ } else {
+ GT_0trace(CHNL_DebugMask, GT_7CLASS,
+ "CHNL_Destroy:Invalid Handle\n");
+ status = DSP_EHANDLE;
+ }
+
+ GT_2trace(CHNL_DebugMask, GT_ENTER,
+ "Exiting CHNL_Destroy: pChnlMgr: 0x%x,"
+ " status:0x%x\n", pChnlMgr, status);
+ DBC_Ensure(DSP_FAILED(status) || !CHNL_IsValidMgr(pChnlMgr));
+
+ return status;
+}
+
+/*
+ * ======== CHNL_Exit ========
+ * Purpose:
+ * Discontinue usage of the CHNL module.
+ */
+void CHNL_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(CHNL_DebugMask, GT_5CLASS,
+ "Entered CHNL_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+
+/*
+ * ======== CHNL_Init ========
+ * Purpose:
+ * Initialize the CHNL module's private state.
+ */
+bool CHNL_Init(void)
+{
+ bool fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!CHNL_DebugMask.flags);
+ GT_create(&CHNL_DebugMask, "CH"); /* "CH" for CHannel */
+ }
+
+ if (fRetval)
+ cRefs++;
+
+ GT_1trace(CHNL_DebugMask, GT_5CLASS,
+ "Entered CHNL_Init, ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+
diff --git a/drivers/dsp/bridge/pmgr/chnlobj.h b/drivers/dsp/bridge/pmgr/chnlobj.h
new file mode 100644
index 000000000000..da74c9683a83
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/chnlobj.h
@@ -0,0 +1,71 @@
+/*
+ * chnlobj.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnlobj.h ========
+ * Description:
+ * Structure subcomponents of channel class library channel objects which
+ * are exposed to class driver from mini-driver.
+ *
+ * Public Functions:
+ * None.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 17-Nov-2000 jeh Removed some fields from CHNL_MGR_ to match CHNL_MGR
+ *! structure defined in _chnl_sm.h.
+ *! 16-Jan-1997 gp: Created from chnlpriv.h
+ */
+
+#ifndef CHNLOBJ_
+#define CHNLOBJ_
+
+#include <dspbridge/chnldefs.h>
+#include <dspbridge/wmd.h>
+
+/* Object validateion macros: */
+#define CHNL_IsValidMgr(h) \
+ ((h != NULL) && ((h)->dwSignature == CHNL_MGRSIGNATURE))
+
+#define CHNL_IsValidChnl(h)\
+ ((h != NULL) && ((h)->dwSignature == CHNL_SIGNATURE))
+
+/*
+ * This struct is the first field in a CHNL_MGR struct, as implemented in
+ * a WMD channel class library. Other, implementation specific fields
+ * follow this structure in memory.
+ */
+struct CHNL_MGR_ {
+ /* These must be the first fields in a CHNL_MGR struct: */
+ u32 dwSignature; /* Used for object validation. */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
+} ;
+
+/*
+ * This struct is the first field in a CHNL_OBJECT struct, as implemented in
+ * a WMD channel class library. Other, implementation specific fields
+ * follow this structure in memory.
+ */
+struct CHNL_OBJECT_ {
+ /* These must be the first fields in a CHNL_OBJECT struct: */
+ u32 dwSignature; /* Used for object validation. */
+ struct CHNL_MGR_ *pChnlMgr; /* Pointer back to channel manager. */
+} ;
+
+#endif /* CHNLOBJ_ */
+
diff --git a/drivers/dsp/bridge/pmgr/cmm.c b/drivers/dsp/bridge/pmgr/cmm.c
new file mode 100644
index 000000000000..99a2432a9b3d
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/cmm.c
@@ -0,0 +1,1291 @@
+/*
+ * cmm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cmm.c ========
+ * Purpose:
+ * The Communication(Shared) Memory Management(CMM) module provides
+ * shared memory management services for DSP/BIOS Bridge data streaming
+ * and messaging.
+ *
+ * Multiple shared memory segments can be registered with CMM.
+ * Each registered SM segment is represented by a SM "allocator" that
+ * describes a block of physically contiguous shared memory used for
+ * future allocations by CMM.
+ *
+ * Memory is coelesced back to the appropriate heap when a buffer is
+ * freed.
+ *
+ * Public Functions:
+ * CMM_CallocBuf
+ * CMM_Create
+ * CMM_Destroy
+ * CMM_Exit
+ * CMM_FreeBuf
+ * CMM_GetHandle
+ * CMM_GetInfo
+ * CMM_Init
+ * CMM_RegisterGPPSMSeg
+ * CMM_UnRegisterGPPSMSeg
+ *
+ * The CMM_Xlator[xxx] routines below are used by Node and Stream
+ * to perform SM address translation to the client process address space.
+ * A "translator" object is created by a node/stream for each SM seg used.
+ *
+ * Translator Routines:
+ * CMM_XlatorAllocBuf
+ * CMM_XlatorCreate
+ * CMM_XlatorDelete
+ * CMM_XlatorFreeBuf
+ * CMM_XlatorInfo
+ * CMM_XlatorTranslate
+ *
+ * Private Functions:
+ * AddToFreeList
+ * GetAllocator
+ * GetFreeBlock
+ * GetNode
+ * GetSlot
+ * UnRegisterGPPSMSeg
+ *
+ * Notes:
+ * Va: Virtual address.
+ * Pa: Physical or kernel system address.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 16-Feb-2002 ag Code review cleanup.
+ *! PreOMAP address translation no longner supported.
+ *! 30-Jan-2002 ag Updates to CMM_XlatorTranslate() per TII, ANSI C++
+ *! warnings.
+ *! 27-Jan-2002 ag Removed unused CMM_[Alloc][Free]Desc() & #ifdef USELOOKUP,
+ *! & unused VALIDATECMM and VaPaConvert().
+ *! Removed bFastXlate from CMM_XLATOR. Always fast lookup.
+ *! 03-Jan-2002 ag Clear SM in CMM_AllocBuf(). Renamed to CMM_CallocBuf().
+ *! 13-Nov-2001 ag Now delete pNodeFreeListHead and nodes in CMM_Destroy().
+ *! 28-Aug-2001 ag CMM_GetHandle() returns CMM Mgr hndle given HPROCESSOR.
+ *! Removed unused CMM_[Un]RegisterDSPSMSeg() &
+ * CMM_[Un}ReserveVirtSpace fxns. Some cleanup.
+ *! 12-Aug-2001 ag Exposed CMM_UnRegisterGPP[DSP]SMSeg.
+ *! 13-Feb-2001 kc DSP/BIOS Bridge name update.
+ *! 21-Dec-2000 rr GetFreeBlock checks for pAllocator.
+ *! 09-Dec-2000 ag Added GPPPA2DSPPA, DSPPA2GPPPA macros.
+ *! 05-Dec-2000 ag CMM_XlatorDelete() optionally frees SM bufs and descriptors.
+ *! 30-Oct-2000 ag Buf size bug fixed in CMM_AllocBuf() causing leak.
+ *! Revamped XlatorTranslate() routine.
+ *! 10-Oct-2000 ag Added CMM_Xlator[xxx] functions.
+ *! 02-Aug-2000 ag Created.
+ *!
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/util.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/proc.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/cmm.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+/* Object signatures */
+#define CMMSIGNATURE 0x004d4d43 /* "CMM" (in reverse) */
+#define SMEMSIGNATURE 0x4D454D53 /* "SMEM" SM space */
+#define CMMXLATESIGNATURE 0x584d4d43 /* "CMMX" CMM Xlator */
+
+#define NEXT_PA(pNode) (pNode->dwPA + pNode->ulSize)
+
+/* Other bus/platform translations */
+#define DSPPA2GPPPA(base, x, y) ((x)+(y))
+#define GPPPA2DSPPA(base, x, y) ((x)-(y))
+
+/*
+ * Allocators define a block of contiguous memory used for future allocations.
+ *
+ * sma - shared memory allocator.
+ * vma - virtual memory allocator.(not used).
+ */
+struct CMM_ALLOCATOR { /* sma */
+ u32 dwSignature; /* SMA allocator signature SMEMSIGNATURE */
+ unsigned int dwSmBase; /* Start of physical SM block */
+ u32 ulSmSize; /* Size of SM block in bytes */
+ unsigned int dwVmBase; /* Start of VM block. (Dev driver
+ * context for 'sma') */
+ u32 dwDSPPhysAddrOffset; /* DSP PA to GPP PA offset for this
+ * SM space */
+ /* CMM_ADDTO[SUBFROM]DSPPA, _POMAPEMIF2DSPBUS */
+ enum CMM_CNVTTYPE cFactor;
+ unsigned int dwDSPBase; /* DSP virt base byte address */
+ u32 ulDSPSize; /* DSP seg size in bytes */
+ struct CMM_OBJECT *hCmmMgr; /* back ref to parent mgr */
+ struct LST_LIST *pFreeListHead; /* node list of available memory */
+ struct LST_LIST *pInUseListHead; /* node list of memory in use */
+} ;
+
+struct CMM_XLATOR { /* Pa<->Va translator object */
+ u32 dwSignature; /* "CMMX" */
+ struct CMM_OBJECT *hCmmMgr; /* CMM object this translator associated */
+ /*
+ * Client process virtual base address that corresponds to phys SM
+ * base address for translator's ulSegId.
+ * Only 1 segment ID currently supported.
+ */
+ unsigned int dwVirtBase; /* virtual base address */
+ u32 ulVirtSize; /* size of virt space in bytes */
+ u32 ulSegId; /* Segment Id */
+} ;
+
+/* CMM Mgr */
+struct CMM_OBJECT {
+ u32 dwSignature; /* Used for object validation */
+ /*
+ * Cmm Lock is used to serialize access mem manager for multi-threads.
+ */
+ struct SYNC_CSOBJECT *hCmmLock; /* Lock to access cmm mgr */
+ struct LST_LIST *pNodeFreeListHead; /* Free list of memory nodes */
+ u32 ulMinBlockSize; /* Min SM block; default 16 bytes */
+ u32 dwPageSize; /* Memory Page size (1k/4k) */
+ /* GPP SM segment ptrs */
+ struct CMM_ALLOCATOR *paGPPSMSegTab[CMM_MAXGPPSEGS];
+} ;
+
+/* Default CMM Mgr attributes */
+static struct CMM_MGRATTRS CMM_DFLTMGRATTRS = {
+ 16 /* ulMinBlockSize, min block size(bytes) allocated by cmm mgr */
+};
+
+/* Default allocation attributes */
+static struct CMM_ATTRS CMM_DFLTALCTATTRS = {
+ 1 /* ulSegId, default segment Id for allocator */
+};
+
+/* Address translator default attrs */
+static struct CMM_XLATORATTRS CMM_DFLTXLATORATTRS = {
+ 1, /* ulSegId, does not have to match CMM_DFLTALCTATTRS ulSegId */
+ 0, /* dwDSPBufs */
+ 0, /* dwDSPBufSize */
+ NULL, /* pVmBase */
+ 0, /* dwVmSize */
+};
+
+/* SM node representing a block of memory. */
+struct CMM_MNODE {
+ struct LST_ELEM link; /* must be 1st element */
+ u32 dwPA; /* Phys addr */
+ u32 dwVA; /* Virtual address in device process context */
+ u32 ulSize; /* SM block size in bytes */
+ u32 hClientProc; /* Process that allocated this mem block */
+} ;
+
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask CMM_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+
+/* ----------------------------------- Function Prototypes */
+static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
+ struct CMM_MNODE *pNode);
+static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
+ u32 ulSegId);
+static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
+ u32 uSize);
+static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
+ u32 dwVA, u32 ulSize);
+/* get available slot for new allocator */
+static s32 GetSlot(struct CMM_OBJECT *hCmmMgr);
+static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA);
+
+/*
+ * ======== CMM_CallocBuf ========
+ * Purpose:
+ * Allocate a SM buffer, zero contents, and return the physical address
+ * and optional driver context virtual address(ppBufVA).
+ *
+ * The freelist is sorted in increasing size order. Get the first
+ * block that satifies the request and sort the remaining back on
+ * the freelist; if large enough. The kept block is placed on the
+ * inUseList.
+ */
+void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr, u32 uSize,
+ struct CMM_ATTRS *pAttrs, OUT void **ppBufVA)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ void *pBufPA = NULL;
+ struct CMM_MNODE *pNode = NULL;
+ struct CMM_MNODE *pNewNode = NULL;
+ struct CMM_ALLOCATOR *pAllocator = NULL;
+ u32 uDeltaSize;
+ u8 *pByte = NULL;
+ s32 cnt;
+
+ if (pAttrs == NULL)
+ pAttrs = &CMM_DFLTALCTATTRS;
+
+ if (ppBufVA != NULL)
+ *ppBufVA = NULL;
+
+ if ((MEM_IsValidHandle(pCmmMgr, CMMSIGNATURE)) && (uSize != 0)) {
+ if (pAttrs->ulSegId > 0) {
+ /* SegId > 0 is SM */
+ /* get the allocator object for this segment id */
+ pAllocator = GetAllocator(pCmmMgr, pAttrs->ulSegId);
+ /* keep block size a multiple of ulMinBlockSize */
+ uSize = ((uSize - 1) & ~(pCmmMgr->ulMinBlockSize - 1))
+ + pCmmMgr->ulMinBlockSize;
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ pNode = GetFreeBlock(pAllocator, uSize);
+ }
+ if (pNode) {
+ uDeltaSize = (pNode->ulSize - uSize);
+ if (uDeltaSize >= pCmmMgr->ulMinBlockSize) {
+ /* create a new block with the leftovers and
+ * add to freelist */
+ pNewNode = GetNode(pCmmMgr, pNode->dwPA + uSize,
+ pNode->dwVA + uSize,
+ (u32)uDeltaSize);
+ /* leftovers go free */
+ AddToFreeList(pAllocator, pNewNode);
+ /* adjust our node's size */
+ pNode->ulSize = uSize;
+ }
+ /* Tag node with client process requesting allocation
+ * We'll need to free up a process's alloc'd SM if the
+ * client process goes away.
+ */
+ /* Return PID instead of process handle */
+ pNode->hClientProc = current->pid;
+
+ /* put our node on InUse list */
+ LST_PutTail(pAllocator->pInUseListHead,
+ (struct LST_ELEM *)pNode);
+ pBufPA = (void *)pNode->dwPA; /* physical address */
+ /* clear mem */
+ pByte = (u8 *)pNode->dwVA;
+ for (cnt = 0; cnt < (s32) uSize; cnt++, pByte++)
+ *pByte = 0;
+
+ if (ppBufVA != NULL) {
+ /* Virtual address */
+ *ppBufVA = (void *)pNode->dwVA;
+ }
+ }
+ GT_3trace(CMM_debugMask, GT_3CLASS,
+ "CMM_CallocBuf dwPA %x, dwVA %x uSize"
+ "%x\n", pNode->dwPA, pNode->dwVA, uSize);
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ }
+ return pBufPA;
+}
+
+/*
+ * ======== CMM_Create ========
+ * Purpose:
+ * Create a communication memory manager object.
+ */
+DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CMM_MGRATTRS *pMgrAttrs)
+{
+ struct CMM_OBJECT *pCmmObject = NULL;
+ DSP_STATUS status = DSP_SOK;
+ struct UTIL_SYSINFO sysInfo;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phCmmMgr != NULL);
+
+ GT_3trace(CMM_debugMask, GT_ENTER,
+ "CMM_Create: phCmmMgr: 0x%x\thDevObject: "
+ "0x%x\tpMgrAttrs: 0x%x\n", phCmmMgr, hDevObject, pMgrAttrs);
+ *phCmmMgr = NULL;
+ /* create, zero, and tag a cmm mgr object */
+ MEM_AllocObject(pCmmObject, struct CMM_OBJECT, CMMSIGNATURE);
+ if (pCmmObject != NULL) {
+ if (pMgrAttrs == NULL)
+ pMgrAttrs = &CMM_DFLTMGRATTRS; /* set defaults */
+
+ /* 4 bytes minimum */
+ DBC_Assert(pMgrAttrs->ulMinBlockSize >= 4);
+ /* save away smallest block allocation for this cmm mgr */
+ pCmmObject->ulMinBlockSize = pMgrAttrs->ulMinBlockSize;
+ /* save away the systems memory page size */
+ sysInfo.dwPageSize = PAGE_SIZE;
+ sysInfo.dwAllocationGranularity = PAGE_SIZE;
+ sysInfo.dwNumberOfProcessors = 1;
+ if (DSP_SUCCEEDED(status)) {
+ GT_1trace(CMM_debugMask, GT_5CLASS,
+ "CMM_Create: Got system page size"
+ "= 0x%x\t\n", sysInfo.dwPageSize);
+ pCmmObject->dwPageSize = sysInfo.dwPageSize;
+ } else {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_Create: failed to get system"
+ "page size\n");
+ pCmmObject->dwPageSize = 0;
+ status = DSP_EFAIL;
+ }
+ /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
+ * MEM_AllocObject */
+ if (DSP_SUCCEEDED(status)) {
+ /* create node free list */
+ pCmmObject->pNodeFreeListHead = LST_Create();
+ if (pCmmObject->pNodeFreeListHead == NULL) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_Create: LST_Create() "
+ "failed \n");
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_InitializeCS(&pCmmObject->hCmmLock);
+
+ if (DSP_SUCCEEDED(status))
+ *phCmmMgr = pCmmObject;
+ else
+ CMM_Destroy(pCmmObject, true);
+
+ } else {
+ GT_0trace(CMM_debugMask, GT_6CLASS,
+ "CMM_Create: Object Allocation "
+ "Failure(CMM Object)\n");
+ status = DSP_EMEMORY;
+ }
+ return status;
+}
+
+/*
+ * ======== CMM_Destroy ========
+ * Purpose:
+ * Release the communication memory manager resources.
+ */
+DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ struct CMM_INFO tempInfo;
+ DSP_STATUS status = DSP_SOK;
+ s32 nSlot;
+ struct CMM_MNODE *pNode;
+
+ DBC_Require(cRefs > 0);
+ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ /* If not force then fail if outstanding allocations exist */
+ if (!bForce) {
+ /* Check for outstanding memory allocations */
+ status = CMM_GetInfo(hCmmMgr, &tempInfo);
+ if (DSP_SUCCEEDED(status)) {
+ if (tempInfo.ulTotalInUseCnt > 0) {
+ /* outstanding allocations */
+ status = DSP_EFAIL;
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* UnRegister SM allocator */
+ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
+ if (pCmmMgr->paGPPSMSegTab[nSlot] != NULL) {
+ UnRegisterGPPSMSeg(pCmmMgr->
+ paGPPSMSegTab[nSlot]);
+ /* Set slot to NULL for future reuse */
+ pCmmMgr->paGPPSMSegTab[nSlot] = NULL;
+ }
+ }
+ }
+ if (pCmmMgr->pNodeFreeListHead != NULL) {
+ /* Free the free nodes */
+ while (!LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
+ /* (struct LST_ELEM*) pNode =
+ * LST_GetHead(pCmmMgr->pNodeFreeListHead);*/
+ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
+ pNodeFreeListHead);
+ MEM_Free(pNode);
+ }
+ /* delete NodeFreeList list */
+ LST_Delete(pCmmMgr->pNodeFreeListHead);
+ }
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ if (DSP_SUCCEEDED(status)) {
+ /* delete CS & cmm mgr object */
+ SYNC_DeleteCS(pCmmMgr->hCmmLock);
+ MEM_FreeObject(pCmmMgr);
+ }
+ return status;
+}
+
+/*
+ * ======== CMM_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ */
+void CMM_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(CMM_debugMask, GT_ENTER,
+ "exiting CMM_Exit,ref count:0x%x\n", cRefs);
+}
+
+/*
+ * ======== CMM_FreeBuf ========
+ * Purpose:
+ * Free the given buffer.
+ */
+DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr, void *pBufPA, u32 ulSegId)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ DSP_STATUS status = DSP_EPOINTER;
+ struct CMM_MNODE *pCurNode = NULL;
+ struct CMM_ALLOCATOR *pAllocator = NULL;
+ struct CMM_ATTRS *pAttrs;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBufPA != NULL);
+ GT_1trace(CMM_debugMask, GT_ENTER, "CMM_FreeBuf pBufPA %x\n", pBufPA);
+ if (ulSegId == 0) {
+ pAttrs = &CMM_DFLTALCTATTRS;
+ ulSegId = pAttrs->ulSegId;
+ }
+ if (!(MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) || !(ulSegId > 0)) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ /* get the allocator for this segment id */
+ pAllocator = GetAllocator(pCmmMgr, ulSegId);
+ if (pAllocator != NULL) {
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->
+ pInUseListHead);
+ while (pCurNode) {
+ if ((u32)pBufPA == pCurNode->dwPA) {
+ /* Found it */
+ LST_RemoveElem(pAllocator->pInUseListHead,
+ (struct LST_ELEM *)pCurNode);
+ /* back to freelist */
+ AddToFreeList(pAllocator, pCurNode);
+ status = DSP_SOK; /* all right! */
+ break;
+ }
+ /* next node. */
+ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
+ pInUseListHead, (struct LST_ELEM *)pCurNode);
+ }
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ }
+ return status;
+}
+
+/*
+ * ======== CMM_GetHandle ========
+ * Purpose:
+ * Return the communication memory manager object for this device.
+ * This is typically called from the client process.
+ */
+DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
+ OUT struct CMM_OBJECT **phCmmMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phCmmMgr != NULL);
+ if (hProcessor != NULL)
+ status = PROC_GetDevObject(hProcessor, &hDevObject);
+ else
+ hDevObject = DEV_GetFirst(); /* default */
+
+ if (DSP_SUCCEEDED(status))
+ status = DEV_GetCmmMgr(hDevObject, phCmmMgr);
+
+ return status;
+}
+
+/*
+ * ======== CMM_GetInfo ========
+ * Purpose:
+ * Return the current memory utilization information.
+ */
+DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
+ OUT struct CMM_INFO *pCmmInfo)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ u32 ulSeg;
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_ALLOCATOR *pAltr;
+ struct CMM_MNODE *pCurNode = NULL;
+
+ DBC_Require(pCmmInfo != NULL);
+
+ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ pCmmInfo->ulNumGPPSMSegs = 0; /* # of SM segments */
+ pCmmInfo->ulTotalInUseCnt = 0; /* Total # of outstanding alloc */
+ pCmmInfo->ulMinBlockSize = pCmmMgr->ulMinBlockSize; /* min block size */
+ /* check SM memory segments */
+ for (ulSeg = 1; ulSeg <= CMM_MAXGPPSEGS; ulSeg++) {
+ /* get the allocator object for this segment id */
+ pAltr = GetAllocator(pCmmMgr, ulSeg);
+ if (pAltr != NULL) {
+ pCmmInfo->ulNumGPPSMSegs++;
+ pCmmInfo->segInfo[ulSeg - 1].dwSegBasePa =
+ pAltr->dwSmBase - pAltr->ulDSPSize;
+ pCmmInfo->segInfo[ulSeg - 1].ulTotalSegSize =
+ pAltr->ulDSPSize + pAltr->ulSmSize;
+ pCmmInfo->segInfo[ulSeg - 1].dwGPPBasePA =
+ pAltr->dwSmBase;
+ pCmmInfo->segInfo[ulSeg - 1].ulGPPSize =
+ pAltr->ulSmSize;
+ pCmmInfo->segInfo[ulSeg - 1].dwDSPBaseVA =
+ pAltr->dwDSPBase;
+ pCmmInfo->segInfo[ulSeg - 1].ulDSPSize =
+ pAltr->ulDSPSize;
+ pCmmInfo->segInfo[ulSeg - 1].dwSegBaseVa =
+ pAltr->dwVmBase - pAltr->ulDSPSize;
+ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt = 0;
+ pCurNode = (struct CMM_MNODE *)LST_First(pAltr->
+ pInUseListHead);
+ /* Count inUse blocks */
+ while (pCurNode) {
+ pCmmInfo->ulTotalInUseCnt++;
+ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt++;
+ /* next node. */
+ pCurNode = (struct CMM_MNODE *)LST_Next(pAltr->
+ pInUseListHead,
+ (struct LST_ELEM *)pCurNode);
+ }
+ }
+ } /* end for */
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ return status;
+}
+
+/*
+ * ======== CMM_Init ========
+ * Purpose:
+ * Initializes private state of CMM module.
+ */
+bool CMM_Init(void)
+{
+ bool fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+ if (cRefs == 0) {
+ /* Set the Trace mask */
+ /* "CM" for Comm Memory manager */
+ GT_create(&CMM_debugMask, "CM");
+ }
+ if (fRetval)
+ cRefs++;
+
+ GT_1trace(CMM_debugMask, GT_ENTER,
+ "Entered CMM_Init,ref count:0x%x\n", cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+/*
+ * ======== CMM_RegisterGPPSMSeg ========
+ * Purpose:
+ * Register a block of SM with the CMM to be used for later GPP SM
+ * allocations.
+ */
+DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 dwGPPBasePA,
+ u32 ulSize, u32 dwDSPAddrOffset,
+ enum CMM_CNVTTYPE cFactor, u32 dwDSPBase,
+ u32 ulDSPSize, u32 *pulSegId,
+ u32 dwGPPBaseVA)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ struct CMM_ALLOCATOR *pSMA = NULL;
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_MNODE *pNewNode;
+ s32 nSlot;
+
+ DBC_Require(ulSize > 0);
+ DBC_Require(pulSegId != NULL);
+ DBC_Require(dwGPPBasePA != 0);
+ DBC_Require(dwGPPBaseVA != 0);
+ DBC_Require((cFactor <= CMM_ADDTODSPPA) &&
+ (cFactor >= CMM_SUBFROMDSPPA));
+ GT_6trace(CMM_debugMask, GT_ENTER,
+ "CMM_RegisterGPPSMSeg dwGPPBasePA %x "
+ "ulSize %x dwDSPAddrOffset %x dwDSPBase %x ulDSPSize %x "
+ "dwGPPBaseVA %x\n", dwGPPBasePA, ulSize, dwDSPAddrOffset,
+ dwDSPBase, ulDSPSize, dwGPPBaseVA);
+ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ /* make sure we have room for another allocator */
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ nSlot = GetSlot(pCmmMgr);
+ if (nSlot < 0) {
+ /* get a slot number */
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ /* Check if input ulSize is big enough to alloc at least one block */
+ if (DSP_SUCCEEDED(status)) {
+ if (ulSize < pCmmMgr->ulMinBlockSize) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_RegisterGPPSMSeg: "
+ "ulSize too small\n");
+ status = DSP_EINVALIDARG;
+ goto func_end;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* create, zero, and tag an SM allocator object */
+ MEM_AllocObject(pSMA, struct CMM_ALLOCATOR, SMEMSIGNATURE);
+ }
+ if (pSMA != NULL) {
+ pSMA->hCmmMgr = hCmmMgr; /* ref to parent */
+ pSMA->dwSmBase = dwGPPBasePA; /* SM Base phys */
+ pSMA->ulSmSize = ulSize; /* SM segment size in bytes */
+ pSMA->dwVmBase = dwGPPBaseVA;
+ pSMA->dwDSPPhysAddrOffset = dwDSPAddrOffset;
+ pSMA->cFactor = cFactor;
+ pSMA->dwDSPBase = dwDSPBase;
+ pSMA->ulDSPSize = ulDSPSize;
+ if (pSMA->dwVmBase == 0) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_RegisterGPPSMSeg: Error"
+ "MEM_LinearAddress()\n");
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* return the actual segment identifier */
+ *pulSegId = (u32) nSlot + 1;
+ /* create memory free list */
+ pSMA->pFreeListHead = LST_Create();
+ if (pSMA->pFreeListHead == NULL) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_RegisterGPPSMSeg: "
+ "Out Of Memory \n");
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* create memory in-use list */
+ pSMA->pInUseListHead = LST_Create();
+ if (pSMA->pInUseListHead == NULL) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_RegisterGPPSMSeg: "
+ "LST_Create failed\n");
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get a mem node for this hunk-o-memory */
+ pNewNode = GetNode(pCmmMgr, dwGPPBasePA,
+ pSMA->dwVmBase, ulSize);
+ /* Place node on the SM allocator's free list */
+ if (pNewNode) {
+ LST_PutTail(pSMA->pFreeListHead,
+ (struct LST_ELEM *)pNewNode);
+ } else {
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ }
+ if (DSP_FAILED(status)) {
+ /* Cleanup allocator */
+ UnRegisterGPPSMSeg(pSMA);
+ }
+ } else {
+ GT_0trace(CMM_debugMask, GT_6CLASS,
+ "CMM_RegisterGPPSMSeg: SMA Object "
+ "Allocation Failure\n");
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ /* make entry */
+ if (DSP_SUCCEEDED(status))
+ pCmmMgr->paGPPSMSegTab[nSlot] = pSMA;
+
+func_end:
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ return status;
+}
+
+/*
+ * ======== CMM_UnRegisterGPPSMSeg ========
+ * Purpose:
+ * UnRegister GPP SM segments with the CMM.
+ */
+DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 ulSegId)
+{
+ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_ALLOCATOR *pSMA;
+ u32 ulId = ulSegId;
+
+ DBC_Require(ulSegId > 0);
+ if (MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
+ if (ulSegId == CMM_ALLSEGMENTS)
+ ulId = 1;
+
+ if ((ulId > 0) && (ulId <= CMM_MAXGPPSEGS)) {
+ while (ulId <= CMM_MAXGPPSEGS) {
+ SYNC_EnterCS(pCmmMgr->hCmmLock);
+ /* slot = segId-1 */
+ pSMA = pCmmMgr->paGPPSMSegTab[ulId - 1];
+ if (pSMA != NULL) {
+ UnRegisterGPPSMSeg(pSMA);
+ /* Set alctr ptr to NULL for future
+ * reuse */
+ pCmmMgr->paGPPSMSegTab[ulId - 1] = NULL;
+ } else if (ulSegId != CMM_ALLSEGMENTS) {
+ status = DSP_EFAIL;
+ }
+ SYNC_LeaveCS(pCmmMgr->hCmmLock);
+ if (ulSegId != CMM_ALLSEGMENTS)
+ break;
+
+ ulId++;
+ } /* end while */
+ } else {
+ status = DSP_EINVALIDARG;
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_UnRegisterGPPSMSeg: Bad "
+ "segment Id\n");
+ }
+ } else {
+ status = DSP_EHANDLE;
+ }
+ return status;
+}
+
+/*
+ * ======== UnRegisterGPPSMSeg ========
+ * Purpose:
+ * UnRegister the SM allocator by freeing all its resources and
+ * nulling cmm mgr table entry.
+ * Note:
+ * This routine is always called within cmm lock crit sect.
+ */
+static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA)
+{
+ struct CMM_MNODE *pCurNode = NULL;
+ struct CMM_MNODE *pNextNode = NULL;
+
+ DBC_Require(pSMA != NULL);
+ if (pSMA->pFreeListHead != NULL) {
+ /* free nodes on free list */
+ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pFreeListHead);
+ while (pCurNode) {
+ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
+ pFreeListHead,
+ (struct LST_ELEM *)pCurNode);
+ LST_RemoveElem(pSMA->pFreeListHead,
+ (struct LST_ELEM *)pCurNode);
+ MEM_Free((void *) pCurNode);
+ /* next node. */
+ pCurNode = pNextNode;
+ }
+ LST_Delete(pSMA->pFreeListHead); /* delete freelist */
+ /* free nodes on InUse list */
+ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pInUseListHead);
+ while (pCurNode) {
+ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
+ pInUseListHead,
+ (struct LST_ELEM *)pCurNode);
+ LST_RemoveElem(pSMA->pInUseListHead,
+ (struct LST_ELEM *)pCurNode);
+ MEM_Free((void *) pCurNode);
+ /* next node. */
+ pCurNode = pNextNode;
+ }
+ LST_Delete(pSMA->pInUseListHead); /* delete InUse list */
+ }
+ if ((void *) pSMA->dwVmBase != NULL)
+ MEM_UnmapLinearAddress((void *) pSMA->dwVmBase);
+
+ /* Free allocator itself */
+ MEM_FreeObject(pSMA);
+}
+
+/*
+ * ======== GetSlot ========
+ * Purpose:
+ * An available slot # is returned. Returns negative on failure.
+ */
+static s32 GetSlot(struct CMM_OBJECT *pCmmMgr)
+{
+ s32 nSlot = -1; /* neg on failure */
+ DBC_Require(pCmmMgr != NULL);
+ /* get first available slot in cmm mgr SMSegTab[] */
+ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
+ if (pCmmMgr->paGPPSMSegTab[nSlot] == NULL)
+ break;
+
+ }
+ if (nSlot == CMM_MAXGPPSEGS) {
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_RegisterGPPSMSeg: Allocator "
+ "entry failure, max exceeded\n");
+ nSlot = -1; /* failed */
+ }
+ return nSlot;
+}
+
+/*
+ * ======== GetNode ========
+ * Purpose:
+ * Get a memory node from freelist or create a new one.
+ */
+static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
+ u32 dwVA, u32 ulSize)
+{
+ struct CMM_MNODE *pNode = NULL;
+
+ DBC_Require(pCmmMgr != NULL);
+ DBC_Require(dwPA != 0);
+ DBC_Require(dwVA != 0);
+ DBC_Require(ulSize != 0);
+ /* Check cmm mgr's node freelist */
+ if (LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
+ pNode = (struct CMM_MNODE *)MEM_Calloc(sizeof(struct CMM_MNODE),
+ MEM_PAGED);
+ } else {
+ /* surely a valid element */
+ /* (struct LST_ELEM*) pNode = LST_GetHead(pCmmMgr->
+ * pNodeFreeListHead);*/
+ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
+ pNodeFreeListHead);
+ }
+ if (pNode == NULL) {
+ GT_0trace(CMM_debugMask, GT_7CLASS, "GetNode: Out Of Memory\n");
+ } else {
+ LST_InitElem((struct LST_ELEM *) pNode); /* set self */
+ pNode->dwPA = dwPA; /* Physical addr of start of block */
+ pNode->dwVA = dwVA; /* Virtual " " */
+ pNode->ulSize = ulSize; /* Size of block */
+ }
+ return pNode;
+}
+
+/*
+ * ======== DeleteNode ========
+ * Purpose:
+ * Put a memory node on the cmm nodelist for later use.
+ * Doesn't actually delete the node. Heap thrashing friendly.
+ */
+static void DeleteNode(struct CMM_OBJECT *pCmmMgr, struct CMM_MNODE *pNode)
+{
+ DBC_Require(pNode != NULL);
+ LST_InitElem((struct LST_ELEM *) pNode); /* init .self ptr */
+ LST_PutTail(pCmmMgr->pNodeFreeListHead, (struct LST_ELEM *) pNode);
+}
+
+/*
+ * ====== GetFreeBlock ========
+ * Purpose:
+ * Scan the free block list and return the first block that satisfies
+ * the size.
+ */
+static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
+ u32 uSize)
+{
+ if (pAllocator) {
+ struct CMM_MNODE *pCurNode = (struct CMM_MNODE *)
+ LST_First(pAllocator->pFreeListHead);
+ while (pCurNode) {
+ if (uSize <= (u32) pCurNode->ulSize) {
+ LST_RemoveElem(pAllocator->pFreeListHead,
+ (struct LST_ELEM *)pCurNode);
+ return pCurNode;
+ }
+ /* next node. */
+ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
+ pFreeListHead, (struct LST_ELEM *)pCurNode);
+ }
+ }
+ return NULL;
+}
+
+/*
+ * ======== AddToFreeList ========
+ * Purpose:
+ * Coelesce node into the freelist in ascending size order.
+ */
+static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
+ struct CMM_MNODE *pNode)
+{
+ struct CMM_MNODE *pNodePrev = NULL;
+ struct CMM_MNODE *pNodeNext = NULL;
+ struct CMM_MNODE *pCurNode;
+ u32 dwThisPA;
+ u32 dwNextPA;
+
+ DBC_Require(pNode != NULL);
+ DBC_Require(pAllocator != NULL);
+ dwThisPA = pNode->dwPA;
+ dwNextPA = NEXT_PA(pNode);
+ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
+ while (pCurNode) {
+ if (dwThisPA == NEXT_PA(pCurNode)) {
+ /* found the block ahead of this one */
+ pNodePrev = pCurNode;
+ } else if (dwNextPA == pCurNode->dwPA) {
+ pNodeNext = pCurNode;
+ }
+ if ((pNodePrev == NULL) || (pNodeNext == NULL)) {
+ /* next node. */
+ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
+ pFreeListHead, (struct LST_ELEM *)pCurNode);
+ } else {
+ /* got 'em */
+ break;
+ }
+ } /* while */
+ if (pNodePrev != NULL) {
+ /* combine with previous block */
+ LST_RemoveElem(pAllocator->pFreeListHead,
+ (struct LST_ELEM *)pNodePrev);
+ /* grow node to hold both */
+ pNode->ulSize += pNodePrev->ulSize;
+ pNode->dwPA = pNodePrev->dwPA;
+ pNode->dwVA = pNodePrev->dwVA;
+ /* place node on mgr nodeFreeList */
+ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodePrev);
+ }
+ if (pNodeNext != NULL) {
+ /* combine with next block */
+ LST_RemoveElem(pAllocator->pFreeListHead,
+ (struct LST_ELEM *)pNodeNext);
+ /* grow da node */
+ pNode->ulSize += pNodeNext->ulSize;
+ /* place node on mgr nodeFreeList */
+ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodeNext);
+ }
+ /* Now, let's add to freelist in increasing size order */
+ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
+ while (pCurNode) {
+ if (pNode->ulSize <= pCurNode->ulSize)
+ break;
+
+ /* next node. */
+ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
+ pFreeListHead, (struct LST_ELEM *)pCurNode);
+ }
+ /* if pCurNode is NULL then add our pNode to the end of the freelist */
+ if (pCurNode == NULL) {
+ LST_PutTail(pAllocator->pFreeListHead,
+ (struct LST_ELEM *)pNode);
+ } else {
+ /* insert our node before the current traversed node */
+ LST_InsertBefore(pAllocator->pFreeListHead,
+ (struct LST_ELEM *)pNode,
+ (struct LST_ELEM *)pCurNode);
+ }
+}
+
+/*
+ * ======== GetAllocator ========
+ * Purpose:
+ * Return the allocator for the given SM Segid.
+ * SegIds: 1,2,3..max.
+ */
+static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
+ u32 ulSegId)
+{
+ struct CMM_ALLOCATOR *pAllocator = NULL;
+
+ DBC_Require(pCmmMgr != NULL);
+ DBC_Require((ulSegId > 0) && (ulSegId <= CMM_MAXGPPSEGS));
+ pAllocator = pCmmMgr->paGPPSMSegTab[ulSegId - 1];
+ if (pAllocator != NULL) {
+ /* make sure it's for real */
+ if (!MEM_IsValidHandle(pAllocator, SMEMSIGNATURE)) {
+ pAllocator = NULL;
+ DBC_Assert(false);
+ }
+ }
+ return pAllocator;
+}
+
+/*
+ * ======== CMM_XlatorCreate ========
+ * Purpose:
+ * Create an address translator object.
+ */
+DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
+ struct CMM_OBJECT *hCmmMgr,
+ struct CMM_XLATORATTRS *pXlatorAttrs)
+{
+ struct CMM_XLATOR *pXlatorObject = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phXlator != NULL);
+ DBC_Require(hCmmMgr != NULL);
+ GT_3trace(CMM_debugMask, GT_ENTER,
+ "CMM_XlatorCreate: phXlator: 0x%x\t"
+ "phCmmMgr: 0x%x\tpXlAttrs: 0x%x\n", phXlator,
+ hCmmMgr, pXlatorAttrs);
+ *phXlator = NULL;
+ if (pXlatorAttrs == NULL)
+ pXlatorAttrs = &CMM_DFLTXLATORATTRS; /* set defaults */
+
+ MEM_AllocObject(pXlatorObject, struct CMM_XLATOR, CMMXLATESIGNATURE);
+ if (pXlatorObject != NULL) {
+ pXlatorObject->hCmmMgr = hCmmMgr; /* ref back to CMM */
+ pXlatorObject->ulSegId = pXlatorAttrs->ulSegId; /* SM segId */
+ } else {
+ GT_0trace(CMM_debugMask, GT_6CLASS,
+ "CMM_XlatorCreate: Object Allocation"
+ "Failure(CMM Xlator)\n");
+ status = DSP_EMEMORY;
+ }
+ if (DSP_SUCCEEDED(status))
+ *phXlator = (struct CMM_XLATOROBJECT *) pXlatorObject;
+
+ return status;
+}
+
+/*
+ * ======== CMM_XlatorDelete ========
+ * Purpose:
+ * Free the Xlator resources.
+ * VM gets freed later.
+ */
+DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator, bool bForce)
+{
+ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
+ MEM_FreeObject(pXlator);
+ } else {
+ status = DSP_EHANDLE;
+ }
+
+ return status;
+}
+
+/*
+ * ======== CMM_XlatorAllocBuf ========
+ */
+void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator, void *pVaBuf,
+ u32 uPaSize)
+{
+ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
+ void *pBuf = NULL;
+ struct CMM_ATTRS attrs;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hXlator != NULL);
+ DBC_Require(pXlator->hCmmMgr != NULL);
+ DBC_Require(pVaBuf != NULL);
+ DBC_Require(uPaSize > 0);
+ DBC_Require(pXlator->ulSegId > 0);
+
+ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
+ attrs.ulSegId = pXlator->ulSegId;
+ *(volatile u32 *)pVaBuf = 0;
+ /* Alloc SM */
+ pBuf = CMM_CallocBuf(pXlator->hCmmMgr, uPaSize, &attrs, NULL);
+ if (pBuf) {
+ /* convert to translator(node/strm) process Virtual
+ * address */
+ *(volatile u32 **)pVaBuf =
+ (u32 *)CMM_XlatorTranslate(hXlator,
+ pBuf, CMM_PA2VA);
+ }
+ }
+ return pBuf;
+}
+
+/*
+ * ======== CMM_XlatorFreeBuf ========
+ * Purpose:
+ * Free the given SM buffer and descriptor.
+ * Does not free virtual memory.
+ */
+DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator, void *pBufVa)
+{
+ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
+ DSP_STATUS status = DSP_EFAIL;
+ void *pBufPa = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBufVa != NULL);
+ DBC_Require(pXlator->ulSegId > 0);
+
+ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
+ /* convert Va to Pa so we can free it. */
+ pBufPa = CMM_XlatorTranslate(hXlator, pBufVa, CMM_VA2PA);
+ if (pBufPa) {
+ status = CMM_FreeBuf(pXlator->hCmmMgr, pBufPa,
+ pXlator->ulSegId);
+ if (DSP_FAILED(status)) {
+ /* Uh oh, this shouldn't happen. Descriptor
+ * gone! */
+ GT_2trace(CMM_debugMask, GT_7CLASS,
+ "Cannot free DMA/ZCPY buffer"
+ "not allocated by MPU. PA %x, VA %x\n",
+ pBufPa, pBufVa);
+ DBC_Assert(false); /* CMM is leaking mem! */
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== CMM_XlatorInfo ========
+ * Purpose:
+ * Set/Get translator info.
+ */
+DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator, IN OUT u8 **pAddr,
+ u32 ulSize, u32 uSegId, bool bSetInfo)
+{
+ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pAddr != NULL);
+ DBC_Require((uSegId > 0) && (uSegId <= CMM_MAXGPPSEGS));
+
+ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
+ if (bSetInfo) {
+ /* set translators virtual address range */
+ pXlator->dwVirtBase = (u32)*pAddr;
+ pXlator->ulVirtSize = ulSize;
+ GT_2trace(CMM_debugMask, GT_3CLASS,
+ "pXlator->dwVirtBase %x, "
+ "ulVirtSize %x\n", pXlator->dwVirtBase,
+ pXlator->ulVirtSize);
+ } else { /* return virt base address */
+ *pAddr = (u8 *)pXlator->dwVirtBase;
+ }
+ } else {
+ status = DSP_EHANDLE;
+ }
+ return status;
+}
+
+/*
+ * ======== CMM_XlatorTranslate ========
+ */
+void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator, void *pAddr,
+ enum CMM_XLATETYPE xType)
+{
+ u32 dwAddrXlate = 0;
+ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
+ struct CMM_OBJECT *pCmmMgr = NULL;
+ struct CMM_ALLOCATOR *pAlctr = NULL;
+ u32 dwOffset = 0;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pAddr != NULL);
+ DBC_Require((xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA));
+
+ if (!MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE))
+ goto loop_cont;
+
+ pCmmMgr = (struct CMM_OBJECT *)pXlator->hCmmMgr;
+ /* get this translator's default SM allocator */
+ DBC_Assert(pXlator->ulSegId > 0);
+ pAlctr = pCmmMgr->paGPPSMSegTab[pXlator->ulSegId - 1];
+ if (!MEM_IsValidHandle(pAlctr, SMEMSIGNATURE))
+ goto loop_cont;
+
+ if ((xType == CMM_VA2DSPPA) || (xType == CMM_VA2PA) ||
+ (xType == CMM_PA2VA)) {
+ if (xType == CMM_PA2VA) {
+ /* Gpp Va = Va Base + offset */
+ dwOffset = (u8 *)pAddr - (u8 *)(pAlctr->dwSmBase -
+ pAlctr->ulDSPSize);
+ dwAddrXlate = pXlator->dwVirtBase + dwOffset;
+ /* Check if translated Va base is in range */
+ if ((dwAddrXlate < pXlator->dwVirtBase) ||
+ (dwAddrXlate >=
+ (pXlator->dwVirtBase + pXlator->ulVirtSize))) {
+ dwAddrXlate = 0; /* bad address */
+ GT_0trace(CMM_debugMask, GT_7CLASS,
+ "CMM_XlatorTranslate: "
+ "Virt addr out of range\n");
+ }
+ } else {
+ /* Gpp PA = Gpp Base + offset */
+ dwOffset = (u8 *)pAddr - (u8 *)pXlator->dwVirtBase;
+ dwAddrXlate = pAlctr->dwSmBase - pAlctr->ulDSPSize +
+ dwOffset;
+ }
+ } else {
+ dwAddrXlate = (u32)pAddr;
+ }
+ /*Now convert address to proper target physical address if needed*/
+ if ((xType == CMM_VA2DSPPA) || (xType == CMM_PA2DSPPA)) {
+ /* Got Gpp Pa now, convert to DSP Pa */
+ dwAddrXlate = GPPPA2DSPPA((pAlctr->dwSmBase - pAlctr->
+ ulDSPSize), dwAddrXlate,
+ pAlctr->dwDSPPhysAddrOffset *
+ pAlctr->cFactor);
+ } else if (xType == CMM_DSPPA2PA) {
+ /* Got DSP Pa, convert to GPP Pa */
+ dwAddrXlate = DSPPA2GPPPA(pAlctr->dwSmBase - pAlctr->ulDSPSize,
+ dwAddrXlate,
+ pAlctr->dwDSPPhysAddrOffset *
+ pAlctr->cFactor);
+ }
+loop_cont:
+ if (!dwAddrXlate) {
+ GT_2trace(CMM_debugMask, GT_7CLASS,
+ "CMM_XlatorTranslate: Can't translate"
+ " address: 0x%x xType %x\n", pAddr, xType);
+ } else {
+ GT_3trace(CMM_debugMask, GT_3CLASS,
+ "CMM_XlatorTranslate: pAddr %x, xType"
+ " %x, dwAddrXlate %x\n", pAddr, xType, dwAddrXlate);
+ }
+ return (void *)dwAddrXlate;
+}
diff --git a/drivers/dsp/bridge/pmgr/cod.c b/drivers/dsp/bridge/pmgr/cod.c
new file mode 100644
index 000000000000..6363f1ec48eb
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/cod.c
@@ -0,0 +1,683 @@
+/*
+ * cod.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cod.c ========
+ * This module implements DSP code management for the DSP/BIOS Bridge
+ * environment. It is mostly a thin wrapper.
+ *
+ * This module provides an interface for loading both static and
+ * dynamic code objects onto DSP systems.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Apr-2003 map: Consolidated DBL to DBLL loader name
+ *! 24-Feb-2003 swa: PMGR Code review comments incorporated.
+ *! 18-Apr-2002 jeh: Added DBL function tables.
+ *! 20-Nov-2001 jeh: Removed call to ZL_loadArgs function.
+ *! 19-Oct-2001 jeh: Access DBL as a static library. Added COD_GetBaseLib,
+ *! COD_GetLoader, removed COD_LoadSection, COD_UnloadSection.
+ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
+ *! 07-Aug-2001 rr: hMgr->baseLib is updated after zlopen in COD_LoadBase.
+ *! 18-Apr-2001 jeh: Check for fLoaded flag before ZL_unload, to allow
+ *! COD_OpenBase to be used.
+ *! 11-Jan-2001 jeh: Added COD_OpenBase (not used yet, since there is an
+ *! occasional crash).
+ *! 02-Aug-2000 kc: Added COD_ReadSection to COD module. Incorporates use
+ *! of ZL_readSect (new function in ZL module).
+ *! 28-Feb-2000 rr: New GT Usage Implementation
+ *! 08-Dec-1999 ag: Removed x86 specific __asm int 3.
+ *! 02-Oct-1999 ag: Added #ifdef DEBUGINT3COD for debug.
+ *! 20-Sep-1999 ag: Removed call to GT_set().
+ *! 04-Jun-1997 cr: Added validation of argc/argv pair in COD_LoadBase, as it
+ *! is a requirement to ZL_loadArgs.
+ *! 31-May-1997 cr: Changed COD_LoadBase argc value from u32 to int, added
+ *! DSP_ENOTIMPL return value to COD_Create when attrs != NULL.
+ *! 29-May-1997 cr: Added debugging support.
+ *! 24-Oct-1996 gp: Added COD_GetSection().
+ *! 18-Jun-1996 gp: Updated GetSymValue() to check for lib; updated E_ codes.
+ *! 12-Jun-1996 gp: Imported CSL_ services for strcpyn(); Added ref counting.
+ *! 20-May-1996 mg: Adapted for new MEM and LDR modules.
+ *! 08-May-1996 mg: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/kfile.h>
+#include <dspbridge/ldr.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- Platform Manager */
+/* Include appropriate loader header file */
+#include <dspbridge/dbll.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/cod.h>
+
+/* magic number for handle validation */
+#define MAGIC 0xc001beef
+
+/* macro to validate COD manager handles */
+#define IsValid(h) ((h) != NULL && (h)->ulMagic == MAGIC)
+
+/*
+ * ======== COD_MANAGER ========
+ */
+struct COD_MANAGER {
+ struct DBLL_TarObj *target;
+ struct DBLL_LibraryObj *baseLib;
+ bool fLoaded; /* Base library loaded? */
+ u32 ulEntry;
+ struct LDR_MODULE *hDll;
+ struct DBLL_Fxns fxns;
+ struct DBLL_Attrs attrs;
+ char szZLFile[COD_MAXPATHLENGTH];
+ u32 ulMagic;
+} ;
+
+/*
+ * ======== COD_LIBRARYOBJ ========
+ */
+struct COD_LIBRARYOBJ {
+ struct DBLL_LibraryObj *dbllLib;
+ struct COD_MANAGER *hCodMgr;
+} ;
+
+static u32 cRefs = 0L;
+
+#if GT_TRACE
+static struct GT_Mask COD_debugMask = { NULL, NULL };
+#endif
+
+static struct DBLL_Fxns dbllFxns = {
+ (DBLL_CloseFxn) DBLL_close,
+ (DBLL_CreateFxn) DBLL_create,
+ (DBLL_DeleteFxn) DBLL_delete,
+ (DBLL_ExitFxn) DBLL_exit,
+ (DBLL_GetAttrsFxn) DBLL_getAttrs,
+ (DBLL_GetAddrFxn) DBLL_getAddr,
+ (DBLL_GetCAddrFxn) DBLL_getCAddr,
+ (DBLL_GetSectFxn) DBLL_getSect,
+ (DBLL_InitFxn) DBLL_init,
+ (DBLL_LoadFxn) DBLL_load,
+ (DBLL_LoadSectFxn) DBLL_loadSect,
+ (DBLL_OpenFxn) DBLL_open,
+ (DBLL_ReadSectFxn) DBLL_readSect,
+ (DBLL_SetAttrsFxn) DBLL_setAttrs,
+ (DBLL_UnloadFxn) DBLL_unload,
+ (DBLL_UnloadSectFxn) DBLL_unloadSect,
+};
+
+static bool NoOp(void);
+
+/*
+ * ======== COD_Close ========
+ */
+void COD_Close(struct COD_LIBRARYOBJ *lib)
+{
+ struct COD_MANAGER *hMgr;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(lib != NULL);
+ DBC_Require(IsValid(((struct COD_LIBRARYOBJ *)lib)->hCodMgr));
+
+ hMgr = lib->hCodMgr;
+ hMgr->fxns.closeFxn(lib->dbllLib);
+
+ MEM_Free(lib);
+}
+
+/*
+ * ======== COD_Create ========
+ * Purpose:
+ * Create an object to manage code on a DSP system.
+ * This object can be used to load an initial program image with
+ * arguments that can later be expanded with
+ * dynamically loaded object files.
+ *
+ */
+DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile,
+ IN OPTIONAL CONST struct COD_ATTRS *attrs)
+{
+ struct COD_MANAGER *hMgrNew;
+ struct DBLL_Attrs zlAttrs;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMgr != NULL);
+
+ GT_3trace(COD_debugMask, GT_ENTER,
+ "Entered COD_Create, Args: \t\nphMgr: "
+ "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n",
+ phMgr, pstrDummyFile, attrs);
+ /* assume failure */
+ *phMgr = NULL;
+
+ /* we don't support non-default attrs yet */
+ if (attrs != NULL)
+ return DSP_ENOTIMPL;
+
+ hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED);
+ if (hMgrNew == NULL) {
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_Create: Out Of Memory\n");
+ return DSP_EMEMORY;
+ }
+
+ hMgrNew->ulMagic = MAGIC;
+
+ /* Set up loader functions */
+ hMgrNew->fxns = dbllFxns;
+
+ /* initialize the ZL module */
+ hMgrNew->fxns.initFxn();
+
+ zlAttrs.alloc = (DBLL_AllocFxn)NoOp;
+ zlAttrs.free = (DBLL_FreeFxn)NoOp;
+ zlAttrs.fread = (DBLL_ReadFxn)KFILE_Read;
+ zlAttrs.fseek = (DBLL_SeekFxn)KFILE_Seek;
+ zlAttrs.ftell = (DBLL_TellFxn)KFILE_Tell;
+ zlAttrs.fclose = (DBLL_FCloseFxn)KFILE_Close;
+ zlAttrs.fopen = (DBLL_FOpenFxn)KFILE_Open;
+ zlAttrs.symLookup = NULL;
+ zlAttrs.baseImage = true;
+ zlAttrs.logWrite = NULL;
+ zlAttrs.logWriteHandle = NULL;
+ zlAttrs.write = NULL;
+ zlAttrs.rmmHandle = NULL;
+ zlAttrs.wHandle = NULL;
+ zlAttrs.symHandle = NULL;
+ zlAttrs.symArg = NULL;
+
+ hMgrNew->attrs = zlAttrs;
+
+ status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs);
+
+ if (DSP_FAILED(status)) {
+ COD_Delete(hMgrNew);
+ GT_1trace(COD_debugMask, GT_7CLASS,
+ "COD_Create:ZL Create Failed: 0x%x\n", status);
+ return COD_E_ZLCREATEFAILED;
+ }
+
+ /* return the new manager */
+ *phMgr = hMgrNew;
+ GT_1trace(COD_debugMask, GT_1CLASS,
+ "COD_Create: Success CodMgr: 0x%x\n", *phMgr);
+ return DSP_SOK;
+}
+
+/*
+ * ======== COD_Delete ========
+ * Purpose:
+ * Delete a code manager object.
+ */
+void COD_Delete(struct COD_MANAGER *hMgr)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hMgr));
+
+ GT_1trace(COD_debugMask, GT_ENTER, "COD_Delete:hMgr 0x%x\n", hMgr);
+ if (hMgr->baseLib) {
+ if (hMgr->fLoaded)
+ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
+
+ hMgr->fxns.closeFxn(hMgr->baseLib);
+ }
+ if (hMgr->target) {
+ hMgr->fxns.deleteFxn(hMgr->target);
+ hMgr->fxns.exitFxn();
+ }
+ hMgr->ulMagic = ~MAGIC;
+ MEM_Free(hMgr);
+}
+
+/*
+ * ======== COD_Exit ========
+ * Purpose:
+ * Discontinue usage of the COD module.
+ *
+ */
+void COD_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(COD_debugMask, GT_ENTER,
+ "Entered COD_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== COD_GetBaseLib ========
+ * Purpose:
+ * Get handle to the base image DBL library.
+ */
+DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
+ struct DBLL_LibraryObj **plib)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hManager));
+ DBC_Require(plib != NULL);
+
+ *plib = (struct DBLL_LibraryObj *) hManager->baseLib;
+
+ return status;
+}
+
+/*
+ * ======== COD_GetBaseName ========
+ */
+DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager, char *pszName,
+ u32 uSize)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hManager));
+ DBC_Require(pszName != NULL);
+
+ if (uSize <= COD_MAXPATHLENGTH)
+ strncpy(pszName, hManager->szZLFile, uSize);
+ else
+ status = DSP_EFAIL;
+
+ return status;
+}
+
+/*
+ * ======== COD_GetEntry ========
+ * Purpose:
+ * Retrieve the entry point of a loaded DSP program image
+ *
+ */
+DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager, u32 *pulEntry)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hManager));
+ DBC_Require(pulEntry != NULL);
+
+ *pulEntry = hManager->ulEntry;
+
+ GT_1trace(COD_debugMask, GT_ENTER, "COD_GetEntry:ulEntr 0x%x\n",
+ *pulEntry);
+
+ return DSP_SOK;
+}
+
+/*
+ * ======== COD_GetLoader ========
+ * Purpose:
+ * Get handle to the DBLL loader.
+ */
+DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
+ struct DBLL_TarObj **phLoader)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hManager));
+ DBC_Require(phLoader != NULL);
+
+ *phLoader = (struct DBLL_TarObj *)hManager->target;
+
+ return status;
+}
+
+/*
+ * ======== COD_GetSection ========
+ * Purpose:
+ * Retrieve the starting address and length of a section in the COFF file
+ * given the section name.
+ */
+DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
+ OUT u32 *puAddr, OUT u32 *puLen)
+{
+ struct COD_MANAGER *hManager;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(lib != NULL);
+ DBC_Require(IsValid(lib->hCodMgr));
+ DBC_Require(pstrSect != NULL);
+ DBC_Require(puAddr != NULL);
+ DBC_Require(puLen != NULL);
+
+ GT_4trace(COD_debugMask, GT_ENTER,
+ "Entered COD_GetSection Args \t\n lib: "
+ "0x%x\t\npstrsect: 0x%x\t\npuAddr: 0x%x\t\npuLen: 0x%x\n",
+ lib, pstrSect, puAddr, puLen);
+ *puAddr = 0;
+ *puLen = 0;
+ if (lib != NULL) {
+ hManager = lib->hCodMgr;
+ status = hManager->fxns.getSectFxn(lib->dbllLib, pstrSect,
+ puAddr, puLen);
+ if (DSP_FAILED(status)) {
+ GT_1trace(COD_debugMask, GT_7CLASS,
+ "COD_GetSection: Section %s not"
+ "found\n", pstrSect);
+ }
+ } else {
+ status = COD_E_NOSYMBOLSLOADED;
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_GetSection:No Symbols loaded\n");
+ }
+
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
+
+ return status;
+}
+
+/*
+ * ======== COD_GetSymValue ========
+ * Purpose:
+ * Retrieve the value for the specified symbol. The symbol is first
+ * searched for literally and then, if not found, searched for as a
+ * C symbol.
+ *
+ */
+DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hMgr, char *pstrSym,
+ u32 *pulValue)
+{
+ struct DBLL_Symbol *pSym;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hMgr));
+ DBC_Require(pstrSym != NULL);
+ DBC_Require(pulValue != NULL);
+
+ GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_GetSymValue Args \t\n"
+ "hMgr: 0x%x\t\npstrSym: 0x%x\t\npulValue: 0x%x\n",
+ hMgr, pstrSym, pulValue);
+ if (hMgr->baseLib) {
+ if (!hMgr->fxns.getAddrFxn(hMgr->baseLib, pstrSym, &pSym)) {
+ if (!hMgr->fxns.getCAddrFxn(hMgr->baseLib, pstrSym,
+ &pSym)) {
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_GetSymValue: "
+ "Symbols not found\n");
+ return COD_E_SYMBOLNOTFOUND;
+ }
+ }
+ } else {
+ GT_0trace(COD_debugMask, GT_7CLASS, "COD_GetSymValue: "
+ "No Symbols loaded\n");
+ return COD_E_NOSYMBOLSLOADED;
+ }
+
+ *pulValue = pSym->value;
+
+ return DSP_SOK;
+}
+
+/*
+ * ======== COD_Init ========
+ * Purpose:
+ * Initialize the COD module's private state.
+ *
+ */
+bool COD_Init(void)
+{
+ bool fRetVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!COD_debugMask.flags);
+ GT_create(&COD_debugMask, "CO");
+ }
+
+ if (fRetVal)
+ cRefs++;
+
+
+ GT_1trace(COD_debugMask, GT_1CLASS,
+ "Entered COD_Init, ref count: 0x%x\n", cRefs);
+ DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0));
+ return fRetVal;
+}
+
+/*
+ * ======== COD_LoadBase ========
+ * Purpose:
+ * Load the initial program image, optionally with command-line arguments,
+ * on the DSP system managed by the supplied handle. The program to be
+ * loaded must be the first element of the args array and must be a fully
+ * qualified pathname.
+ * Details:
+ * if nArgc doesn't match the number of arguments in the aArgs array, the
+ * aArgs array is searched for a NULL terminating entry, and argc is
+ * recalculated to reflect this. In this way, we can support NULL
+ * terminating aArgs arrays, if nArgc is very large.
+ */
+DSP_STATUS COD_LoadBase(struct COD_MANAGER *hMgr, u32 nArgc, char *aArgs[],
+ COD_WRITEFXN pfnWrite, void *pArb, char *envp[])
+{
+ DBLL_Flags flags;
+ struct DBLL_Attrs saveAttrs;
+ struct DBLL_Attrs newAttrs;
+ DSP_STATUS status;
+ u32 i;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hMgr));
+ DBC_Require(nArgc > 0);
+ DBC_Require(aArgs != NULL);
+ DBC_Require(aArgs[0] != NULL);
+ DBC_Require(pfnWrite != NULL);
+ DBC_Require(hMgr->baseLib != NULL);
+
+ GT_6trace(COD_debugMask, GT_ENTER,
+ "Entered COD_LoadBase, hMgr: 0x%x\n \t"
+ "nArgc: 0x%x\n\taArgs: 0x%x\n\tpfnWrite: 0x%x\n\tpArb:"
+ " 0x%x\n \tenvp: 0x%x\n", hMgr, nArgc, aArgs, pfnWrite,
+ pArb, envp);
+ /*
+ * Make sure every argv[] stated in argc has a value, or change argc to
+ * reflect true number in NULL terminated argv array.
+ */
+ for (i = 0; i < nArgc; i++) {
+ if (aArgs[i] == NULL) {
+ nArgc = i;
+ break;
+ }
+ }
+
+ /* set the write function for this operation */
+ hMgr->fxns.getAttrsFxn(hMgr->target, &saveAttrs);
+
+ newAttrs = saveAttrs;
+ newAttrs.write = (DBLL_WriteFxn)pfnWrite;
+ newAttrs.wHandle = pArb;
+ newAttrs.alloc = (DBLL_AllocFxn)NoOp;
+ newAttrs.free = (DBLL_FreeFxn)NoOp;
+ newAttrs.logWrite = NULL;
+ newAttrs.logWriteHandle = NULL;
+
+ /* Load the image */
+ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
+ status = hMgr->fxns.loadFxn(hMgr->baseLib, flags, &newAttrs,
+ &hMgr->ulEntry);
+ if (DSP_FAILED(status)) {
+ hMgr->fxns.closeFxn(hMgr->baseLib);
+ GT_1trace(COD_debugMask, GT_7CLASS,
+ "COD_LoadBase: COD Load failed: "
+ "0x%x\n", status);
+ }
+ if (DSP_SUCCEEDED(status))
+ hMgr->fLoaded = true;
+ else
+ hMgr->baseLib = NULL;
+
+ return status;
+}
+
+/*
+ * ======== COD_Open ========
+ * Open library for reading sections.
+ */
+DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
+ COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct COD_LIBRARYOBJ *lib = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hMgr));
+ DBC_Require(pszCoffPath != NULL);
+ DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB);
+ DBC_Require(pLib != NULL);
+
+ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t "
+ "pszCoffPath: 0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr,
+ pszCoffPath, flags, pLib);
+
+ *pLib = NULL;
+
+ lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED);
+ if (lib == NULL) {
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_Open: Out Of Memory\n");
+ status = DSP_EMEMORY;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ lib->hCodMgr = hMgr;
+ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags,
+ &lib->dbllLib);
+ if (DSP_FAILED(status)) {
+ GT_1trace(COD_debugMask, GT_7CLASS,
+ "COD_Open failed: 0x%x\n", status);
+ } else {
+ *pLib = lib;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== COD_OpenBase ========
+ * Purpose:
+ * Open base image for reading sections.
+ */
+DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
+ DBLL_Flags flags)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DBLL_LibraryObj *lib;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValid(hMgr));
+ DBC_Require(pszCoffPath != NULL);
+
+ GT_2trace(COD_debugMask, GT_ENTER,
+ "Entered COD_OpenBase, hMgr: 0x%x\n\t"
+ "pszCoffPath: 0x%x\n", hMgr, pszCoffPath);
+
+ /* if we previously opened a base image, close it now */
+ if (hMgr->baseLib) {
+ if (hMgr->fLoaded) {
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "Base Image is already loaded. "
+ "Unloading it...\n");
+ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
+ hMgr->fLoaded = false;
+ }
+ hMgr->fxns.closeFxn(hMgr->baseLib);
+ hMgr->baseLib = NULL;
+ } else {
+ GT_0trace(COD_debugMask, GT_1CLASS,
+ "COD_OpenBase: Opening the base image ...\n");
+ }
+ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib);
+ if (DSP_FAILED(status)) {
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_OpenBase: COD Open failed\n");
+ } else {
+ /* hang onto the library for subsequent sym table usage */
+ hMgr->baseLib = lib;
+ strncpy(hMgr->szZLFile, pszCoffPath, COD_MAXPATHLENGTH);
+ }
+
+ return status;
+}
+
+/*
+ * ======== COD_ReadSection ========
+ * Purpose:
+ * Retrieve the content of a code section given the section name.
+ */
+DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
+ OUT char *pstrContent, IN u32 cContentSize)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(lib != NULL);
+ DBC_Require(IsValid(lib->hCodMgr));
+ DBC_Require(pstrSect != NULL);
+ DBC_Require(pstrContent != NULL);
+
+ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_ReadSection Args: 0x%x,"
+ " 0x%x, 0x%x, 0x%x\n", lib, pstrSect, pstrContent,
+ cContentSize);
+
+ if (lib != NULL) {
+ status = lib->hCodMgr->fxns.readSectFxn(lib->dbllLib, pstrSect,
+ pstrContent,
+ cContentSize);
+ if (DSP_FAILED(status)) {
+ GT_1trace(COD_debugMask, GT_7CLASS,
+ "COD_ReadSection failed: 0x%lx\n", status);
+ }
+ } else {
+ status = COD_E_NOSYMBOLSLOADED;
+ GT_0trace(COD_debugMask, GT_7CLASS,
+ "COD_ReadSection: No Symbols loaded\n");
+ }
+ return status;
+}
+
+/*
+ * ======== NoOp ========
+ * Purpose:
+ * No Operation.
+ *
+ */
+static bool NoOp(void)
+{
+ return true;
+}
+
diff --git a/drivers/dsp/bridge/pmgr/dbl.c b/drivers/dsp/bridge/pmgr/dbl.c
new file mode 100644
index 000000000000..641b011cb6c0
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/dbl.c
@@ -0,0 +1,1385 @@
+/*
+ * dbl.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbl.c ========
+ * Dynamic BOF Loader library. Contains functions related to
+ * loading and unloading symbols/code/data on DSP.
+ * Also contains other support functions.
+ *
+ *! Revision History
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 24-May-2002 jeh Free DCD sects in DBL_close().
+ *! 19-Mar-2002 jeh Changes made to match dynamic loader (dbll.c): Pass
+ *! DBL_Library to DBL_getAddr() instead of DBL_Target,
+ *! eliminate scope param, use DBL_Symbol. Pass attrs to
+ *! DBL_load(), DBL_unload().
+ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
+ *! 07-Sep-2001 jeh Added overlay support.
+ *! 31-Jul-2001 jeh Include windows.h.
+ *! 06-Jun-2001 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/kfile.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dbof.h>
+#include <dspbridge/dbl.h>
+
+#define DBL_TARGSIGNATURE 0x544c4244 /* "TLBD" */
+#define DBL_LIBSIGNATURE 0x4c4c4244 /* "LLBD" */
+
+#define C54TARG 0
+#define C55TARG 1
+#define NUMTARGS 2
+
+#define C54MAGIC 0x98 /* Magic number for TI C54 COF */
+#define C55MAGIC 0x9c /* Magic number for LEAD3 (C55) COF */
+
+/* Three task phases */
+#define CREATEPHASE 0
+#define DELETEPHASE 1
+#define EXECUTEPHASE 2
+#define NONE 3 /* For overlay section with phase not specified */
+
+/* Default load buffer size */
+#define LOADBUFSIZE 0x800
+
+#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
+ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
+
+#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
+
+/*
+ * Macros for accessing the following types of overlay data within a
+ * structure of type OvlyData:
+ * - Overlay data not associated with a particular phase
+ * - Create phase overlay data
+ * - Delete phase overlay data
+ * - Execute phase overlay data
+ */
+#define numOtherSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
+#define numCreateSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numCreateSects)
+#define numDeleteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numDeleteSects)
+#define numExecuteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numExecuteSects)
+#define otherOffset(pOvlyData) 0
+#define createOffset(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
+#define deleteOffset(pOvlyData) (createOffset(pOvlyData) + \
+ (pOvlyData->hdr.dbofHdr.numCreateSects))
+#define executeOffset(pOvlyData) (deleteOffset(pOvlyData) + \
+ (pOvlyData->hdr.dbofHdr.numDeleteSects))
+/*
+ * ======== OvlyHdr ========
+ */
+struct OvlyHdr {
+ struct DBOF_OvlySectHdr dbofHdr;
+ char *pName; /* Name of overlay section */
+ u16 createRef; /* Reference count for create phase */
+ u16 deleteRef; /* Reference count for delete phase */
+ u16 executeRef; /* Execute phase ref count */
+ u16 otherRef; /* Unspecified phase ref count */
+} ;
+
+/*
+ * ======== OvlyData ========
+ */
+struct OvlyData {
+ struct OvlyHdr hdr;
+ struct DBOF_OvlySectData data[1];
+} ;
+
+/*
+ * ======== Symbol ========
+ */
+struct Symbol {
+ struct DBL_Symbol sym;
+ char *pSymName;
+};
+
+/*
+ * ======== DCDSect ========
+ */
+struct DCDSect {
+ struct DBOF_DCDSectHdr sectHdr;
+ char *pData;
+} ;
+
+/*
+ * ======== DBL_TargetObj ========
+ */
+struct DBL_TargetObj {
+ u32 dwSignature; /* For object validation */
+ struct DBL_Attrs dblAttrs; /* file read, write, etc. functions */
+ char *pBuf; /* Load buffer */
+};
+
+/*
+ * ======== TargetInfo ========
+ */
+struct TargetInfo {
+ u16 dspType; /* eg, C54TARG, C55TARG */
+ u32 magic; /* COFF magic number, identifies target type */
+ u16 wordSize; /* Size of a DSP word */
+ u16 mauSize; /* Size of minimum addressable unit */
+ u16 charSize; /* For C55x, mausize = 1, but charsize = 2 */
+} ;
+
+/*
+ * ======== DBL_LibraryObj ========
+ * Represents a library loaded on a target.
+ */
+struct DBL_LibraryObj {
+ u32 dwSignature; /* For object validation */
+ struct DBL_TargetObj *pTarget; /* Target for this library */
+ struct KFILE_FileObj *file; /* DBOF file handle */
+ bool byteSwapped; /* Are bytes swapped? */
+ struct DBOF_FileHdr fileHdr; /* Header of DBOF file */
+ u16 nSymbols; /* Number of DSP/Bridge symbols */
+ struct Symbol *symbols; /* Table of DSP/Bridge symbols */
+ u16 nDCDSects; /* Number of DCD sections */
+ u16 nOvlySects; /* Number of overlay nodes */
+ struct DCDSect *dcdSects; /* DCD section data */
+ struct OvlyData **ppOvlyData; /* Array of overlay section data */
+ struct TargetInfo *pTargetInfo; /* Entry in targetTab[] below */
+} ;
+
+#if GT_TRACE
+static struct GT_Mask DBL_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+
+static u32 magicTab[NUMTARGS] = { C54MAGIC, C55MAGIC };
+
+static struct TargetInfo targetTab[] = {
+ /* targ magic wordsize mausize charsize */
+ {C54TARG, C54MAGIC, 2, 2, 2}, /* C54 */
+ {C55TARG, C55MAGIC, 2, 1, 2}, /* C55 */
+};
+
+static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
+ s32 offset, s32 nSects);
+static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib);
+static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib);
+static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib);
+static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib);
+static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib);
+
+/*
+ * ======== DBL_close ========
+ * Purpose:
+ * Close library opened with DBL_open.
+ */
+void DBL_close(struct DBL_LibraryObj *lib)
+{
+ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
+ u16 i;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
+
+ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_close: lib: 0x%x\n", lib);
+
+ /* Free symbols */
+ if (pdblLib->symbols) {
+ for (i = 0; i < pdblLib->nSymbols; i++) {
+ if (pdblLib->symbols[i].pSymName)
+ MEM_Free(pdblLib->symbols[i].pSymName);
+
+ }
+ MEM_Free(pdblLib->symbols);
+ }
+
+ /* Free DCD sects */
+ if (pdblLib->dcdSects) {
+ for (i = 0; i < pdblLib->nDCDSects; i++) {
+ if (pdblLib->dcdSects[i].pData)
+ MEM_Free(pdblLib->dcdSects[i].pData);
+
+ }
+ MEM_Free(pdblLib->dcdSects);
+ }
+
+ /* Free overlay sects */
+ if (pdblLib->ppOvlyData) {
+ for (i = 0; i < pdblLib->nOvlySects; i++) {
+ if (pdblLib->ppOvlyData[i]) {
+ if (pdblLib->ppOvlyData[i]->hdr.pName) {
+ MEM_Free(pdblLib->ppOvlyData[i]->
+ hdr.pName);
+ }
+ MEM_Free(pdblLib->ppOvlyData[i]);
+ }
+ }
+ MEM_Free(pdblLib->ppOvlyData);
+ }
+
+ /* Close the file */
+ if (pdblLib->file)
+ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
+
+
+ MEM_FreeObject(pdblLib);
+}
+
+/*
+ * ======== DBL_create ========
+ * Purpose:
+ * Create a target object by specifying the alloc, free, and
+ * write functions for the target.
+ */
+DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget, struct DBL_Attrs *pAttrs)
+{
+ struct DBL_TargetObj *pdblTarget = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pAttrs != NULL);
+ DBC_Require(pTarget != NULL);
+
+ GT_2trace(DBL_debugMask, GT_ENTER,
+ "DBL_create: pTarget: 0x%x pAttrs: 0x%x\n",
+ pTarget, pAttrs);
+ /* Allocate DBL target object */
+ MEM_AllocObject(pdblTarget, struct DBL_TargetObj, DBL_TARGSIGNATURE);
+ if (pdblTarget == NULL) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "DBL_create: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ pdblTarget->dblAttrs = *pAttrs;
+ /* Allocate buffer for loading target */
+ pdblTarget->pBuf = MEM_Calloc(LOADBUFSIZE, MEM_PAGED);
+ if (pdblTarget->pBuf == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ *pTarget = pdblTarget;
+ } else {
+ *pTarget = NULL;
+ if (pdblTarget)
+ DBL_delete(pdblTarget);
+
+ }
+ DBC_Ensure(DSP_SUCCEEDED(status) &&
+ ((MEM_IsValidHandle((*pTarget), DBL_TARGSIGNATURE)) ||
+ (DSP_FAILED(status) && *pTarget == NULL)));
+ return status;
+}
+
+/*
+ * ======== DBL_delete ========
+ * Purpose:
+ * Delete target object and free resources for any loaded libraries.
+ */
+void DBL_delete(struct DBL_TargetObj *target)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
+
+ GT_1trace(DBL_debugMask, GT_ENTER,
+ "DBL_delete: target: 0x%x\n", target);
+
+ if (target->pBuf)
+ MEM_Free(target->pBuf);
+
+ MEM_FreeObject(target);
+}
+
+/*
+ * ======== DBL_exit ========
+ * Purpose
+ * Discontinue usage of DBL module.
+ */
+void DBL_exit()
+{
+ DBC_Require(cRefs > 0);
+ cRefs--;
+ GT_1trace(DBL_debugMask, GT_5CLASS,
+ "DBL_exit() ref count: 0x%x\n", cRefs);
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== DBL_getAddr ========
+ * Purpose:
+ * Get address of name in the specified library.
+ */
+bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
+ struct DBL_Symbol **ppSym)
+{
+ bool retVal = false;
+ struct Symbol *symbol;
+ u16 i;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
+ DBC_Require(name != NULL);
+ DBC_Require(ppSym != NULL);
+
+ GT_3trace(DBL_debugMask, GT_ENTER,
+ "DBL_getAddr: libt: 0x%x name: %s pAddr: "
+ "0x%x\n", lib, name, ppSym);
+ for (i = 0; i < lib->nSymbols; i++) {
+ symbol = &lib->symbols[i];
+ if (CSL_Strcmp(name, symbol->pSymName) == 0) {
+ /* Found it */
+ *ppSym = &lib->symbols[i].sym;
+ retVal = true;
+ break;
+ }
+ }
+ return retVal;
+}
+
+/*
+ * ======== DBL_getAttrs ========
+ * Purpose:
+ * Retrieve the attributes of the target.
+ */
+void DBL_getAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
+ DBC_Require(pAttrs != NULL);
+ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_getAttrs: target: 0x%x pAttrs: "
+ "0x%x\n", target, pAttrs);
+ *pAttrs = target->dblAttrs;
+}
+
+/*
+ * ======== DBL_getCAddr ========
+ * Purpose:
+ * Get address of "C" name in the specified library.
+ */
+bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
+ struct DBL_Symbol **ppSym)
+{
+ bool retVal = false;
+ struct Symbol *symbol;
+ u16 i;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
+ DBC_Require(name != NULL);
+ DBC_Require(ppSym != NULL);
+
+ GT_3trace(DBL_debugMask, GT_ENTER,
+ "DBL_getCAddr: target: 0x%x name:%s pAddr:"
+ " 0x%x\n", lib, name, ppSym);
+ for (i = 0; i < lib->nSymbols; i++) {
+ symbol = &lib->symbols[i];
+ if ((CSL_Strcmp(name, symbol->pSymName) == 0) ||
+ (CSL_Strcmp(name, symbol->pSymName + 1) == 0 &&
+ symbol->pSymName[0] == '_')) {
+ /* Found it */
+ *ppSym = &lib->symbols[i].sym;
+ retVal = true;
+ break;
+ }
+ }
+ return retVal;
+}
+
+/*
+ * ======== DBL_getEntry ========
+ * Purpose:
+ * Get program entry point.
+ *
+ */
+bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry)
+{
+ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
+ DBC_Require(pEntry != NULL);
+
+ GT_2trace(DBL_debugMask, GT_ENTER,
+ "DBL_getEntry: lib: 0x%x pEntry: 0x%x\n", lib, pEntry);
+ *pEntry = pdblLib->fileHdr.entry;
+
+ return true;
+}
+
+/*
+ * ======== DBL_getSect ========
+ * Purpose:
+ * Get address and size of a named section.
+ */
+DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name, u32 *pAddr,
+ u32 *pSize)
+{
+ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
+ u16 i;
+ DSP_STATUS status = DSP_ENOSECT;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(name != NULL);
+ DBC_Require(pAddr != NULL);
+ DBC_Require(pSize != NULL);
+ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
+
+ GT_4trace(DBL_debugMask, GT_ENTER,
+ "DBL_getSect: lib: 0x%x name: %s pAddr:"
+ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
+
+ /*
+ * Check for DCD and overlay sections. Overlay loader uses DBL_getSect
+ * to determine whether or not a node has overlay sections.
+ * DCD section names begin with '.'
+ */
+ if (name[0] == '.') {
+ /* Get DCD section size (address is 0, since it's a NOLOAD). */
+ for (i = 0; i < pdblLib->nDCDSects; i++) {
+ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name,
+ name) == 0) {
+ *pAddr = 0;
+ *pSize = pdblLib->dcdSects[i].sectHdr.size *
+ pdblLib->pTargetInfo->mauSize;
+ status = DSP_SOK;
+ break;
+ }
+ }
+ } else {
+ /* Check for overlay section */
+ for (i = 0; i < pdblLib->nOvlySects; i++) {
+ if (CSL_Strcmp(pdblLib->ppOvlyData[i]->hdr.pName,
+ name) == 0) {
+ /* Address and size are meaningless */
+ *pAddr = 0;
+ *pSize = 0;
+ status = DSP_SOK;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== DBL_init ========
+ * Purpose:
+ * Initialize DBL module.
+ */
+bool DBL_init(void)
+{
+ bool retVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!DBL_debugMask.flags);
+ GT_create(&DBL_debugMask, "BL"); /* "BL" for dBL */
+
+ }
+
+ if (retVal)
+ cRefs++;
+
+
+ GT_1trace(DBL_debugMask, GT_5CLASS, "DBL_init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
+
+ return retVal;
+}
+
+/*
+ * ======== DBL_load ========
+ * Purpose:
+ * Add symbols/code/data defined in file to that already present
+ * on the target.
+ */
+DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
+ struct DBL_Attrs *attrs, u32 *pEntry)
+{
+ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
+ struct DBL_TargetObj *dbl;
+ u16 i;
+ u16 nSects;
+ DSP_STATUS status = DSP_EFAIL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
+ DBC_Require(pEntry != NULL);
+ DBC_Require(attrs != NULL);
+
+ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_load: lib: 0x%x flags: "
+ "0x%x attrs: 0x%x pEntry: 0x%x\n", lib, flags, attrs, pEntry);
+
+ dbl = pdblLib->pTarget;
+ *pEntry = pdblLib->fileHdr.entry;
+ nSects = pdblLib->fileHdr.numSects;
+ dbl->dblAttrs = *attrs;
+
+ for (i = 0; i < nSects; i++) {
+ /* Load the section at the current file offset */
+ status = loadSect(dbl, lib);
+ if (DSP_FAILED(status))
+ break;
+
+ }
+
+ /* Done with file, we can close it */
+ if (pdblLib->file) {
+ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
+ pdblLib->file = NULL;
+ }
+ return status;
+}
+
+/*
+ * ======== DBL_loadSect ========
+ * Purpose:
+ * Load a named section from an library (for overlay support).
+ */
+DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib, char *sectName,
+ struct DBL_Attrs *attrs)
+{
+ struct DBL_TargetObj *dbl;
+ s32 i;
+ s32 phase;
+ s32 offset = -1;
+ s32 nSects = -1;
+ s32 allocdSects = 0;
+ u32 loadAddr;
+ u32 runAddr;
+ u32 size;
+ u32 space;
+ u32 ulBytes;
+ u16 mauSize;
+ u16 wordSize;
+ u16 *phaseRef = NULL;
+ u16 *otherRef = NULL;
+ char *name = NULL;
+ struct OvlyData *pOvlyData;
+ DSP_STATUS status = DSP_ENOSECT;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
+ DBC_Require(sectName != NULL);
+ DBC_Require(attrs != NULL);
+ DBC_Require(attrs->write != NULL);
+ GT_3trace(DBL_debugMask, GT_ENTER,
+ "DBL_loadSect: lib: 0x%x sectName: %s "
+ "attrs: 0x%x\n", lib, sectName, attrs);
+ dbl = lib->pTarget;
+ mauSize = lib->pTargetInfo->mauSize;
+ wordSize = lib->pTargetInfo->wordSize;
+ /* Check for match of sect name in overlay table */
+ for (i = 0; i < lib->nOvlySects; i++) {
+ name = lib->ppOvlyData[i]->hdr.pName;
+ if (!CSL_Strncmp(name, sectName, CSL_Strlen(name))) {
+ /* Match found */
+ status = DSP_SOK;
+ break;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(i < lib->nOvlySects);
+ pOvlyData = lib->ppOvlyData[i];
+ /*
+ * If node overlay, phase will be encoded in name. If not node
+ * overlay, set phase to NONE.
+ */
+ phase = (CSL_Strcmp(name, sectName)) ?
+ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
+ /* Get reference count of node phase to be loaded, offset into
+ * overlay data array, and number of sections to overlay. */
+ switch (phase) {
+ case NONE:
+ /* Not a node overlay */
+ phaseRef = &pOvlyData->hdr.otherRef;
+ nSects = numOtherSects(pOvlyData);
+ offset = otherOffset(pOvlyData);
+ break;
+ case CREATEPHASE:
+ phaseRef = &pOvlyData->hdr.createRef;
+ otherRef = &pOvlyData->hdr.otherRef;
+ if (*otherRef) {
+ /* The overlay sections where node phase was
+ * not specified, have already been loaded. */
+ nSects = numCreateSects(pOvlyData);
+ offset = createOffset(pOvlyData);
+ } else {
+ /* Overlay sections where node phase was not
+ * specified get loaded at create time, along
+ * with create sects. */
+ nSects = numCreateSects(pOvlyData) +
+ numOtherSects(pOvlyData);
+ offset = otherOffset(pOvlyData);
+ }
+ break;
+ case DELETEPHASE:
+ phaseRef = &pOvlyData->hdr.deleteRef;
+ nSects = numDeleteSects(pOvlyData);
+ offset = deleteOffset(pOvlyData);
+ break;
+ case EXECUTEPHASE:
+ phaseRef = &pOvlyData->hdr.executeRef;
+ nSects = numExecuteSects(pOvlyData);
+ offset = executeOffset(pOvlyData);
+ break;
+ default:
+ /* ERROR */
+ DBC_Assert(false);
+ break;
+ }
+ /* Do overlay if reference count is 0 */
+ if (!(*phaseRef)) {
+ /* "Allocate" all sections */
+ for (i = 0; i < nSects; i++) {
+ runAddr = pOvlyData->data[offset + i].runAddr;
+ size = pOvlyData->data[offset + i].size;
+ space = pOvlyData->data[offset + i].page;
+ status = (dbl->dblAttrs.alloc)(dbl->dblAttrs.
+ rmmHandle, space, size, 0,
+ &runAddr, true);
+ if (DSP_FAILED(status))
+ break;
+
+ allocdSects++;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Load sections */
+ for (i = 0; i < nSects; i++) {
+ loadAddr = pOvlyData->data[offset + i].
+ loadAddr;
+ runAddr = pOvlyData->data[offset + i].
+ runAddr;
+ size = pOvlyData->data[offset + i].
+ size;
+ space = pOvlyData->data[offset + i].
+ page;
+ /* Convert to word address, call
+ * write function */
+ loadAddr /= (wordSize / mauSize);
+ runAddr /= (wordSize / mauSize);
+ ulBytes = size * mauSize;
+ if ((*attrs->write)(attrs->wHandle,
+ runAddr, (void *)loadAddr, ulBytes,
+ space) != ulBytes) {
+ GT_0trace(DBL_debugMask,
+ GT_6CLASS,
+ "DBL_loadSect: write"
+ " failed\n");
+ status = DSP_EFWRITE;
+ break;
+ }
+ }
+ }
+ /* Free sections on failure */
+ if (DSP_FAILED(status))
+ freeSects(dbl, pOvlyData, offset, allocdSects);
+
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Increment reference counts */
+ if (otherRef)
+ *otherRef = *otherRef + 1;
+
+ *phaseRef = *phaseRef + 1;
+ }
+ return status;
+}
+
+/*
+ * ======== DBL_open ========
+ * Purpose:
+ * DBL_open() returns a library handle that can be used to
+ * load/unload the symbols/code/data via DBL_load()/DBL_unload().
+ */
+DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file, DBL_Flags flags,
+ struct DBL_LibraryObj **pLib)
+{
+ struct DBL_LibraryObj *pdblLib = NULL;
+ u16 nSymbols;
+ u16 nDCDSects;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
+ DBC_Require(target->dblAttrs.fopen != NULL);
+ DBC_Require(file != NULL);
+ DBC_Require(pLib != NULL);
+
+ GT_3trace(DBL_debugMask, GT_ENTER, "DBL_open: target: 0x%x file: %s "
+ "pLib: 0x%x\n", target, file, pLib);
+ /* Allocate DBL library object */
+ MEM_AllocObject(pdblLib, struct DBL_LibraryObj, DBL_LIBSIGNATURE);
+ if (pdblLib == NULL)
+ status = DSP_EMEMORY;
+
+ /* Open the file */
+ if (DSP_SUCCEEDED(status)) {
+ pdblLib->pTarget = target;
+ pdblLib->file = (*target->dblAttrs.fopen)(file, "rb");
+ if (pdblLib->file == NULL)
+ status = DSP_EFOPEN;
+
+ }
+ /* Read file header */
+ if (DSP_SUCCEEDED(status)) {
+ status = readHeader(target, pdblLib);
+ if (DSP_FAILED(status)) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "DBL_open(): Failed to read file header\n");
+ }
+ }
+ /* Allocate symbol table */
+ if (DSP_SUCCEEDED(status)) {
+ nSymbols = pdblLib->nSymbols = pdblLib->fileHdr.numSymbols;
+ pdblLib->symbols = MEM_Calloc(nSymbols * sizeof(struct Symbol),
+ MEM_PAGED);
+ if (pdblLib->symbols == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ /* Read all the symbols */
+ if (DSP_SUCCEEDED(status)) {
+ status = readSymbols(target, pdblLib);
+ if (DSP_FAILED(status)) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "DBL_open(): Failed to read symbols\n");
+ }
+ }
+ /* Allocate DCD sect table */
+ if (DSP_SUCCEEDED(status)) {
+ nDCDSects = pdblLib->nDCDSects = pdblLib->fileHdr.numDCDSects;
+ pdblLib->dcdSects = MEM_Calloc(nDCDSects *
+ sizeof(struct DCDSect), MEM_PAGED);
+ if (pdblLib->dcdSects == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ /* Read DCD sections */
+ if (DSP_SUCCEEDED(status)) {
+ status = readDCDSects(target, pdblLib);
+ if (DSP_FAILED(status)) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "DBL_open(): Failed to read DCD sections\n");
+ }
+ }
+ /* Read overlay sections */
+ if (DSP_SUCCEEDED(status)) {
+ status = readOvlySects(target, pdblLib);
+ if (DSP_FAILED(status)) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "DBL_open(): Failed to read "
+ "overlay sections\n");
+ }
+ }
+ if (DSP_FAILED(status)) {
+ *pLib = NULL;
+ if (pdblLib != NULL)
+ DBL_close((struct DBL_LibraryObj *) pdblLib);
+
+ } else {
+ *pLib = pdblLib;
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ (MEM_IsValidHandle((*pLib), DBL_LIBSIGNATURE))) ||
+ (DSP_FAILED(status) && *pLib == NULL));
+ return status;
+}
+
+/*
+ * ======== DBL_readSect ========
+ * Purpose:
+ * Read COFF section into a character buffer.
+ */
+DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name, char *pContent,
+ u32 size)
+{
+ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
+ u16 i;
+ u32 mauSize;
+ u32 max;
+ DSP_STATUS status = DSP_ENOSECT;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
+ DBC_Require(name != NULL);
+ DBC_Require(pContent != NULL);
+ DBC_Require(size != 0);
+ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_readSect: lib: 0x%x name: %s "
+ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
+
+ mauSize = pdblLib->pTargetInfo->mauSize;
+
+ /* Attempt to find match with DCD section names. */
+ for (i = 0; i < pdblLib->nDCDSects; i++) {
+ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name, name) == 0) {
+ /* Match found */
+ max = pdblLib->dcdSects[i].sectHdr.size * mauSize;
+ max = (max > size) ? size : max;
+ memcpy(pContent, pdblLib->dcdSects[i].pData, max);
+ status = DSP_SOK;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== DBL_setAttrs ========
+ * Purpose:
+ * Set the attributes of the target.
+ */
+void DBL_setAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
+ DBC_Require(pAttrs != NULL);
+
+ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_setAttrs: target: 0x%x pAttrs: "
+ "0x%x\n", target, pAttrs);
+
+ target->dblAttrs = *pAttrs;
+}
+
+/*
+ * ======== DBL_unload ========
+ * Purpose:
+ * Remove the symbols/code/data corresponding to the library lib.
+ */
+void DBL_unload(struct DBL_LibraryObj *lib, struct DBL_Attrs *attrs)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
+
+ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_unload: lib: 0x%x\n", lib);
+
+ /* Nothing to do for static loading */
+}
+
+/*
+ * ======== DBL_unloadSect ========
+ * Purpose:
+ * Unload a named section from an library (for overlay support).
+ */
+DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib, char *sectName,
+ struct DBL_Attrs *attrs)
+{
+ struct DBL_TargetObj *dbl;
+ s32 i;
+ s32 phase;
+ s32 offset = -1;
+ s32 nSects = -1;
+ u16 *phaseRef = NULL;
+ u16 *otherRef = NULL;
+ char *pName = NULL;
+ struct OvlyData *pOvlyData;
+ DSP_STATUS status = DSP_ENOSECT;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
+ DBC_Require(sectName != NULL);
+
+ GT_2trace(DBL_debugMask, GT_ENTER,
+ "DBL_unloadSect: lib: 0x%x sectName: %s\n", lib, sectName);
+ dbl = lib->pTarget;
+ /* Check for match of sect name in overlay table */
+ for (i = 0; i < lib->nOvlySects; i++) {
+ pName = lib->ppOvlyData[i]->hdr.pName;
+ if (!CSL_Strncmp(pName, sectName, CSL_Strlen(pName))) {
+ /* Match found */
+ status = DSP_SOK;
+ break;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(i < lib->nOvlySects);
+ pOvlyData = lib->ppOvlyData[i];
+ /* If node overlay, phase will be encoded in name. */
+ phase = (CSL_Strcmp(pName, sectName)) ?
+ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
+ switch (phase) {
+ case NONE:
+ nSects = numOtherSects(pOvlyData);
+ phaseRef = &pOvlyData->hdr.otherRef;
+ offset = otherOffset(pOvlyData);
+ break;
+ case CREATEPHASE:
+ nSects = numCreateSects(pOvlyData);
+ offset = createOffset(pOvlyData);
+ phaseRef = &pOvlyData->hdr.createRef;
+ break;
+ case DELETEPHASE:
+ nSects = numDeleteSects(pOvlyData);
+ offset = deleteOffset(pOvlyData);
+ phaseRef = &pOvlyData->hdr.deleteRef;
+ otherRef = &pOvlyData->hdr.otherRef;
+ break;
+ case EXECUTEPHASE:
+ nSects = numExecuteSects(pOvlyData);
+ offset = executeOffset(pOvlyData);
+ phaseRef = &pOvlyData->hdr.executeRef;
+ break;
+ default:
+ /* ERROR */
+ DBC_Assert(false);
+ break;
+ }
+ if (*phaseRef) {
+ *phaseRef = *phaseRef - 1;
+ if (*phaseRef == 0) {
+ /* Unload overlay sections for phase */
+ freeSects(dbl, pOvlyData, offset, nSects);
+ }
+ if (phase == DELETEPHASE) {
+ DBC_Assert(*otherRef);
+ *otherRef = *otherRef - 1;
+ if (*otherRef == 0) {
+ /* Unload other overlay sections */
+ nSects = numOtherSects(pOvlyData);
+ offset = otherOffset(pOvlyData);
+ freeSects(dbl, pOvlyData, offset,
+ nSects);
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== freeSects ========
+ * Purpose:
+ * Free section
+ */
+static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
+ s32 offset, s32 nSects)
+{
+ u32 runAddr;
+ u32 size;
+ u32 space;
+ s32 i;
+
+ for (i = 0; i < nSects; i++) {
+ runAddr = pOvlyData->data[offset + i].runAddr;
+ size = pOvlyData->data[offset + i].size;
+ space = pOvlyData->data[offset + i].page;
+ if (!(dbl->dblAttrs.free)
+ (dbl->dblAttrs.rmmHandle, space, runAddr, size, true)) {
+ /*
+ * Free function will not fail for overlay, unless
+ * address passed in is bad.
+ */
+ DBC_Assert(false);
+ }
+ }
+}
+
+/*
+ * ======== loadSect ========
+ * Purpose:
+ * Load section to target
+ */
+static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib)
+{
+ struct DBOF_SectHdr sectHdr;
+ char *pBuf;
+ struct KFILE_FileObj *file;
+ u32 space;
+ u32 addr;
+ u32 total;
+ u32 nWords = 0;
+ u32 nBytes = 0;
+ u16 mauSize;
+ u32 bufSize;
+ DSP_STATUS status = DSP_SOK;
+
+ file = pdblLib->file;
+ mauSize = pdblLib->pTargetInfo->mauSize;
+ bufSize = LOADBUFSIZE / mauSize;
+ pBuf = dbl->pBuf;
+
+ /* Read the section header */
+ if ((*dbl->dblAttrs.fread)(&sectHdr, sizeof(struct DBOF_SectHdr),
+ 1, file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read DCD sect header\n");
+ status = DSP_EFREAD;
+ } else {
+ if (pdblLib->byteSwapped) {
+ sectHdr.size = SWAPLONG(sectHdr.size);
+ sectHdr.addr = SWAPLONG(sectHdr.addr);
+ sectHdr.page = SWAPWORD(sectHdr.page);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ addr = sectHdr.addr;
+ space = sectHdr.page;
+ for (total = sectHdr.size; total > 0; total -= nWords) {
+ nWords = min(total, bufSize);
+ nBytes = nWords * mauSize;
+ /* Read section data */
+ if ((*dbl->dblAttrs.fread)(pBuf, nBytes, 1,
+ file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read DCD sect header\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ /* Write section to target */
+ if (!(*dbl->dblAttrs.write)(dbl->dblAttrs.wHandle,
+ addr, pBuf, nBytes, space)) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to write section data\n");
+ status = DSP_EFWRITE;
+ break;
+ }
+ addr += nWords;
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== readDCDSects ========
+ * Purpose:
+ * Read DCD sections.
+ */
+static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib)
+{
+ struct DBOF_DCDSectHdr *pSectHdr;
+ struct DCDSect *pSect;
+ struct KFILE_FileObj *file;
+ u16 nSects;
+ u16 i;
+ u16 mauSize;
+ DSP_STATUS status = DSP_SOK;
+
+ file = pdblLib->file;
+ mauSize = pdblLib->pTargetInfo->mauSize;
+ nSects = pdblLib->fileHdr.numDCDSects;
+ for (i = 0; i < nSects; i++) {
+ pSect = &pdblLib->dcdSects[i];
+ pSectHdr = &pdblLib->dcdSects[i].sectHdr;
+ /* Read sect header */
+ if ((*dbl->dblAttrs.fread)(pSectHdr,
+ sizeof(struct DBOF_DCDSectHdr), 1, file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read DCD sect header\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ if (pdblLib->byteSwapped)
+ pSectHdr->size = SWAPLONG(pSectHdr->size);
+
+ pSect->pData = (char *)MEM_Calloc(pSectHdr->size *
+ mauSize, MEM_PAGED);
+ if (pSect->pData == NULL) {
+ GT_2trace(DBL_debugMask, GT_6CLASS,
+ "Memory allocation for sect %s "
+ "data failed: Size: 0x%lx\n", pSectHdr->name,
+ pSectHdr->size);
+ status = DSP_EMEMORY;
+ break;
+ }
+ /* Read DCD sect data */
+ if ((*dbl->dblAttrs.fread)(pSect->pData, mauSize,
+ pSectHdr->size, file) != pSectHdr->size) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read DCD sect data\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== readHeader ========
+ * Purpose:
+ * Read Header.
+ */
+static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib)
+{
+ struct KFILE_FileObj *file;
+ s32 i;
+ struct DBOF_FileHdr *pHdr;
+ u32 swapMagic;
+ DSP_STATUS status = DSP_SOK;
+
+ pdblLib->byteSwapped = false;
+ file = pdblLib->file;
+ pHdr = &pdblLib->fileHdr;
+ if ((*dbl->dblAttrs.fread)(pHdr, sizeof(struct DBOF_FileHdr), 1,
+ file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "readHeader: Failed to read file header\n");
+ status = DSP_EFREAD;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Determine if byte swapped */
+ for (i = 0; i < NUMTARGS; i++) {
+ swapMagic = SWAPLONG(pHdr->magic);
+ if (pHdr->magic == magicTab[i] || swapMagic ==
+ magicTab[i]) {
+ if (swapMagic == magicTab[i]) {
+ pdblLib->byteSwapped = true;
+ pHdr->magic = SWAPLONG(pHdr->magic);
+ pHdr->entry = SWAPLONG(pHdr->entry);
+ pHdr->symOffset = SWAPLONG(pHdr->
+ symOffset);
+ pHdr->dcdSectOffset = SWAPLONG(pHdr->
+ dcdSectOffset);
+ pHdr->loadSectOffset = SWAPLONG(pHdr->
+ loadSectOffset);
+ pHdr->ovlySectOffset = SWAPLONG(pHdr->
+ ovlySectOffset);
+ pHdr->numSymbols = SWAPWORD(pHdr->
+ numSymbols);
+ pHdr->numDCDSects = SWAPWORD(pHdr->
+ numDCDSects);
+ pHdr->numSects = SWAPWORD(pHdr->
+ numSects);
+ pHdr->numOvlySects = SWAPWORD(pHdr->
+ numOvlySects);
+ }
+ break;
+ }
+ }
+ if (i == NUMTARGS) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "readHeader: Failed to determine"
+ " target type\n");
+ status = DSP_ECORRUPTFILE;
+ } else {
+ pdblLib->pTargetInfo = &targetTab[i];
+ GT_1trace(DBL_debugMask, GT_ENTER,
+ "COF type: 0x%lx\n", pHdr->magic);
+ GT_1trace(DBL_debugMask, GT_ENTER,
+ "Entry point:0x%lx\n", pHdr->entry);
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== readOvlySects ========
+ * Purpose:
+ * Read Overlay Sections
+ */
+static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib)
+{
+ struct DBOF_OvlySectHdr hdr;
+ struct DBOF_OvlySectData *pData;
+ struct OvlyData *pOvlyData;
+ char *pName;
+ struct KFILE_FileObj *file;
+ u16 i, j;
+ u16 nSects;
+ u16 n;
+ DSP_STATUS status = DSP_SOK;
+
+ pdblLib->nOvlySects = nSects = pdblLib->fileHdr.numOvlySects;
+ file = pdblLib->file;
+ if (nSects > 0) {
+ pdblLib->ppOvlyData = MEM_Calloc(nSects * sizeof(OvlyData *),
+ MEM_PAGED);
+ if (pdblLib->ppOvlyData == NULL) {
+ GT_0trace(DBL_debugMask, GT_7CLASS,
+ "Failed to allocatate overlay "
+ "data memory\n");
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Read overlay data for each node */
+ for (i = 0; i < nSects; i++) {
+ /* Read overlay section header */
+ if ((*dbl->dblAttrs.fread)(&hdr,
+ sizeof(struct DBOF_OvlySectHdr), 1, file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read overlay sect"
+ " header\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ if (pdblLib->byteSwapped) {
+ hdr.nameLen = SWAPWORD(hdr.nameLen);
+ hdr.numCreateSects =
+ SWAPWORD(hdr.numCreateSects);
+ hdr.numDeleteSects =
+ SWAPWORD(hdr.numDeleteSects);
+ hdr.numExecuteSects =
+ SWAPWORD(hdr.numExecuteSects);
+ hdr.numOtherSects =
+ SWAPWORD(hdr.numOtherSects);
+ hdr.resvd = SWAPWORD(hdr.resvd);
+ }
+ n = hdr.numCreateSects + hdr.numDeleteSects +
+ hdr.numExecuteSects + hdr.numOtherSects;
+
+ /* Allocate memory for node's overlay data */
+ pOvlyData = (struct OvlyData *)MEM_Calloc
+ (sizeof(struct OvlyHdr) +
+ n * sizeof(struct DBOF_OvlySectData),
+ MEM_PAGED);
+ if (pOvlyData == NULL) {
+ GT_0trace(DBL_debugMask, GT_7CLASS,
+ "Failed to allocatate ovlyay"
+ " data memory\n");
+ status = DSP_EMEMORY;
+ break;
+ }
+ pOvlyData->hdr.dbofHdr = hdr;
+ pdblLib->ppOvlyData[i] = pOvlyData;
+ /* Allocate memory for section name */
+ pName = (char *)MEM_Calloc(hdr.nameLen + 1, MEM_PAGED);
+ if (pName == NULL) {
+ GT_0trace(DBL_debugMask, GT_7CLASS,
+ "Failed to allocatate ovlyay"
+ " section name\n");
+ status = DSP_EMEMORY;
+ break;
+ }
+ pOvlyData->hdr.pName = pName;
+ /* Read the overlay section name */
+ if ((*dbl->dblAttrs.fread)(pName, sizeof(char),
+ hdr.nameLen, file) != hdr.nameLen) {
+ GT_0trace(DBL_debugMask, GT_7CLASS,
+ "readOvlySects: Unable to "
+ "read overlay name.\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ /* Read the overlay section data */
+ pData = pOvlyData->data;
+ if ((*dbl->dblAttrs.fread)(pData,
+ sizeof(struct DBOF_OvlySectData), n, file) != n) {
+ GT_0trace(DBL_debugMask, GT_7CLASS,
+ "readOvlySects: Unable to "
+ "read overlay data.\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ /* Swap overlay data, if necessary */
+ if (pdblLib->byteSwapped) {
+ for (j = 0; j < n; j++) {
+ pData[j].loadAddr =
+ SWAPLONG(pData[j].loadAddr);
+ pData[j].runAddr =
+ SWAPLONG(pData[j].runAddr);
+ pData[j].size =
+ SWAPLONG(pData[j].size);
+ pData[j].page =
+ SWAPWORD(pData[j].page);
+ }
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== readSymbols ========
+ * Purpose:
+ * Read Symbols
+ */
+static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
+ struct DBL_LibraryObj *pdblLib)
+{
+ struct DBOF_SymbolHdr symHdr;
+ struct KFILE_FileObj *file;
+ u16 i;
+ u16 nSymbols;
+ u16 len;
+ char *pName = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ file = pdblLib->file;
+
+ nSymbols = pdblLib->fileHdr.numSymbols;
+
+ for (i = 0; i < nSymbols; i++) {
+ /* Read symbol value */
+ if ((*dbl->dblAttrs.fread)(&symHdr,
+ sizeof(struct DBOF_SymbolHdr), 1, file) != 1) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read symbol value\n");
+ status = DSP_EFREAD;
+ break;
+ }
+ if (pdblLib->byteSwapped) {
+ symHdr.nameLen = SWAPWORD(symHdr.nameLen);
+ symHdr.value = SWAPLONG(symHdr.value);
+ }
+ /* Allocate buffer for symbol name */
+ len = symHdr.nameLen;
+ pName = (char *)MEM_Calloc(len + 1, MEM_PAGED);
+ if (pName == NULL) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ break;
+ }
+ pdblLib->symbols[i].pSymName = pName;
+ pdblLib->symbols[i].sym.value = symHdr.value;
+ /* Read symbol name */
+ if ((*dbl->dblAttrs.fread) (pName, sizeof(char), len, file) !=
+ len) {
+ GT_0trace(DBL_debugMask, GT_6CLASS,
+ "Failed to read symbol value\n");
+ status = DSP_EFREAD;
+ break;
+ } else {
+ pName[len] = '\0';
+ GT_2trace(DBL_debugMask, GT_ENTER,
+ "Symbol: %s Value: 0x%lx\n",
+ pName, symHdr.value);
+ }
+ }
+ return status;
+}
+
diff --git a/drivers/dsp/bridge/pmgr/dbll.c b/drivers/dsp/bridge/pmgr/dbll.c
new file mode 100644
index 000000000000..30a95f579c1b
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/dbll.c
@@ -0,0 +1,1587 @@
+/*
+ * dbll.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== dbll.c ========
+ *
+ *! Revision History
+ *! ================
+ *! 25-Apr-2030 map: Fixed symbol redefinition bug + unload and return error
+ *! 08-Apr-2003 map: Consolidated DBL with DBLL loader name
+ *! 24-Mar-2003 map: Updated findSymbol to support dllview update
+ *! 23-Jan-2003 map: Updated rmmAlloc to support memory granularity
+ *! 21-Nov-2002 map: Combine fopen and DLOAD_module_open to increase
+ *! performance on start.
+ *! 04-Oct-2002 map: Integrated new TIP dynamic loader w/ DOF api.
+ *! 27-Sep-2002 map: Changed handle passed to RemoteFree, instead of
+ *! RMM_free; added GT_trace to rmmDealloc
+ *! 20-Sep-2002 map: Updated from Code Review
+ *! 08-Aug-2002 jeh: Updated to support overlays.
+ *! 25-Jun-2002 jeh: Pass RMM_Addr object to alloc function in rmmAlloc().
+ *! 20-Mar-2002 jeh: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/gt.h>
+#include <dspbridge/dbc.h>
+#include <dspbridge/gh.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* Dynamic loader library interface */
+#include <dspbridge/dynamic_loader.h>
+#include <dspbridge/getsection.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dbll.h>
+#include <dspbridge/rmm.h>
+
+#define DBLL_TARGSIGNATURE 0x544c4c44 /* "TLLD" */
+#define DBLL_LIBSIGNATURE 0x4c4c4c44 /* "LLLD" */
+
+/* Number of buckets for symbol hash table */
+#define MAXBUCKETS 211
+
+/* Max buffer length */
+#define MAXEXPR 128
+
+#ifndef UINT32_C
+#define UINT32_C(zzz) ((uint32_t)zzz)
+#endif
+#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
+
+/*
+ * ======== struct DBLL_TarObj* ========
+ * A target may have one or more libraries of symbols/code/data loaded
+ * onto it, where a library is simply the symbols/code/data contained
+ * in a DOFF file.
+ */
+/*
+ * ======== DBLL_TarObj ========
+ */
+struct DBLL_TarObj {
+ u32 dwSignature; /* For object validation */
+ struct DBLL_Attrs attrs;
+ struct DBLL_LibraryObj *head; /* List of all opened libraries */
+} ;
+
+/*
+ * The following 4 typedefs are "super classes" of the dynamic loader
+ * library types used in dynamic loader functions (dynamic_loader.h).
+ */
+/*
+ * ======== DBLLStream ========
+ * Contains Dynamic_Loader_Stream
+ */
+struct DBLLStream {
+ struct Dynamic_Loader_Stream dlStream;
+ struct DBLL_LibraryObj *lib;
+} ;
+
+/*
+ * ======== DBLLSymbol ========
+ */
+struct DBLLSymbol {
+ struct Dynamic_Loader_Sym dlSymbol;
+ struct DBLL_LibraryObj *lib;
+} ;
+
+/*
+ * ======== DBLLAlloc ========
+ */
+ struct DBLLAlloc {
+ struct Dynamic_Loader_Allocate dlAlloc;
+ struct DBLL_LibraryObj *lib;
+} ;
+
+/*
+ * ======== DBLLInit ========
+ */
+struct DBLLInit {
+ struct Dynamic_Loader_Initialize dlInit;
+ struct DBLL_LibraryObj *lib;
+};
+
+/*
+ * ======== DBLL_Library ========
+ * A library handle is returned by DBLL_Open() and is passed to DBLL_load()
+ * to load symbols/code/data, and to DBLL_unload(), to remove the
+ * symbols/code/data loaded by DBLL_load().
+ */
+
+/*
+ * ======== DBLL_LibraryObj ========
+ */
+ struct DBLL_LibraryObj {
+ u32 dwSignature; /* For object validation */
+ struct DBLL_LibraryObj *next; /* Next library in target's list */
+ struct DBLL_LibraryObj *prev; /* Previous in the list */
+ struct DBLL_TarObj *pTarget; /* target for this library */
+
+ /* Objects needed by dynamic loader */
+ struct DBLLStream stream;
+ struct DBLLSymbol symbol;
+ struct DBLLAlloc allocate;
+ struct DBLLInit init;
+ DLOAD_mhandle mHandle;
+
+ char *fileName; /* COFF file name */
+ void *fp; /* Opaque file handle */
+ u32 entry; /* Entry point */
+ DLOAD_mhandle desc; /* desc of DOFF file loaded */
+ u32 openRef; /* Number of times opened */
+ u32 loadRef; /* Number of times loaded */
+ struct GH_THashTab *symTab; /* Hash table of symbols */
+ u32 ulPos;
+} ;
+
+/*
+ * ======== Symbol ========
+ */
+struct Symbol {
+ struct DBLL_Symbol value;
+ char *name;
+} ;
+extern bool bSymbolsReloaded;
+
+static void dofClose(struct DBLL_LibraryObj *zlLib);
+static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib);
+static s32 NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
+ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsiz);
+
+/*
+ * Functions called by dynamic loader
+ *
+ */
+/* Dynamic_Loader_Stream */
+static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
+ unsigned bufsize);
+static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos);
+/* Dynamic_Loader_Sym */
+static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
+ const char *name);
+static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
+ const char *name,
+ unsigned moduleId);
+static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
+ const char *name,
+ unsigned moduleid);
+static void purgeSymbolTable(struct Dynamic_Loader_Sym *this,
+ unsigned moduleId);
+static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize);
+static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr);
+static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
+ va_list args);
+/* Dynamic_Loader_Allocate */
+static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
+ struct LDR_SECTION_INFO *info, unsigned align);
+static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
+ struct LDR_SECTION_INFO *info);
+
+/* Dynamic_Loader_Initialize */
+static int connect(struct Dynamic_Loader_Initialize *this);
+static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
+ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
+ unsigned nbytes);
+static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
+ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
+ unsigned nbytes);
+static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
+ struct LDR_SECTION_INFO *info, unsigned nbytes,
+ unsigned val);
+static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start);
+static void release(struct Dynamic_Loader_Initialize *this);
+
+/* symbol table hash functions */
+static u16 nameHash(void *name, u16 maxBucket);
+static bool nameMatch(void *name, void *sp);
+static void symDelete(void *sp);
+
+#if GT_TRACE
+static struct GT_Mask DBLL_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+
+/* Symbol Redefinition */
+static int bRedefinedSymbol;
+static int bGblSearch = 1;
+
+/*
+ * ======== DBLL_close ========
+ */
+void DBLL_close(struct DBLL_LibraryObj *zlLib)
+{
+ struct DBLL_TarObj *zlTarget;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(zlLib->openRef > 0);
+ zlTarget = zlLib->pTarget;
+ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_close: lib: 0x%x\n", zlLib);
+ zlLib->openRef--;
+ if (zlLib->openRef == 0) {
+ /* Remove library from list */
+ if (zlTarget->head == zlLib)
+ zlTarget->head = zlLib->next;
+
+ if (zlLib->prev)
+ (zlLib->prev)->next = zlLib->next;
+
+ if (zlLib->next)
+ (zlLib->next)->prev = zlLib->prev;
+
+ /* Free DOF resources */
+ dofClose(zlLib);
+ if (zlLib->fileName)
+ MEM_Free(zlLib->fileName);
+
+ /* remove symbols from symbol table */
+ if (zlLib->symTab)
+ GH_delete(zlLib->symTab);
+
+ /* remove the library object itself */
+ MEM_FreeObject(zlLib);
+ zlLib = NULL;
+ }
+}
+
+/*
+ * ======== DBLL_create ========
+ */
+DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget, struct DBLL_Attrs *pAttrs)
+{
+ struct DBLL_TarObj *pzlTarget;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pAttrs != NULL);
+ DBC_Require(pTarget != NULL);
+
+ GT_2trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_create: pTarget: 0x%x pAttrs: "
+ "0x%x\n", pTarget, pAttrs);
+ /* Allocate DBL target object */
+ MEM_AllocObject(pzlTarget, struct DBLL_TarObj, DBLL_TARGSIGNATURE);
+ if (pTarget != NULL) {
+ if (pzlTarget == NULL) {
+ GT_0trace(DBLL_debugMask, GT_6CLASS,
+ "DBLL_create: Memory allocation"
+ " failed\n");
+ *pTarget = NULL;
+ status = DSP_EMEMORY;
+ } else {
+ pzlTarget->attrs = *pAttrs;
+ *pTarget = (struct DBLL_TarObj *)pzlTarget;
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle(((struct DBLL_TarObj *)(*pTarget)),
+ DBLL_TARGSIGNATURE)) || (DSP_FAILED(status) &&
+ *pTarget == NULL));
+ }
+
+ return status;
+}
+
+/*
+ * ======== DBLL_delete ========
+ */
+void DBLL_delete(struct DBLL_TarObj *target)
+{
+ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
+
+ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_delete: target: 0x%x\n",
+ target);
+
+ if (zlTarget != NULL)
+ MEM_FreeObject(zlTarget);
+
+}
+
+/*
+ * ======== DBLL_exit ========
+ * Discontinue usage of DBL module.
+ */
+void DBLL_exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_exit() ref count: 0x%x\n",
+ cRefs);
+
+ if (cRefs == 0) {
+ MEM_Exit();
+ CSL_Exit();
+ GH_exit();
+#if GT_TRACE
+ DBLL_debugMask.flags = NULL;
+#endif
+ }
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== DBLL_getAddr ========
+ * Get address of name in the specified library.
+ */
+bool DBLL_getAddr(struct DBLL_LibraryObj *zlLib, char *name,
+ struct DBLL_Symbol **ppSym)
+{
+ struct Symbol *sym;
+ bool status = false;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(name != NULL);
+ DBC_Require(ppSym != NULL);
+ DBC_Require(zlLib->symTab != NULL);
+
+ GT_3trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_getAddr: lib: 0x%x name: %s pAddr:"
+ " 0x%x\n", zlLib, name, ppSym);
+ sym = (struct Symbol *)GH_find(zlLib->symTab, name);
+ if (sym != NULL) {
+ *ppSym = &sym->value;
+ status = true;
+ }
+ return status;
+}
+
+/*
+ * ======== DBLL_getAttrs ========
+ * Retrieve the attributes of the target.
+ */
+void DBLL_getAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
+{
+ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
+ DBC_Require(pAttrs != NULL);
+
+ if ((pAttrs != NULL) && (zlTarget != NULL))
+ *pAttrs = zlTarget->attrs;
+
+}
+
+/*
+ * ======== DBLL_getCAddr ========
+ * Get address of a "C" name in the specified library.
+ */
+bool DBLL_getCAddr(struct DBLL_LibraryObj *zlLib, char *name,
+ struct DBLL_Symbol **ppSym)
+{
+ struct Symbol *sym;
+ char cname[MAXEXPR + 1];
+ bool status = false;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(ppSym != NULL);
+ DBC_Require(zlLib->symTab != NULL);
+ DBC_Require(name != NULL);
+
+ cname[0] = '_';
+
+ strncpy(cname + 1, name, sizeof(cname) - 2);
+ cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
+
+ /* Check for C name, if not found */
+ sym = (struct Symbol *)GH_find(zlLib->symTab, cname);
+
+ if (sym != NULL) {
+ *ppSym = &sym->value;
+ status = true;
+ }
+
+ return status;
+}
+
+/*
+ * ======== DBLL_getSect ========
+ * Get the base address and size (in bytes) of a COFF section.
+ */
+DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr,
+ u32 *pSize)
+{
+ u32 uByteSize;
+ bool fOpenedDoff = false;
+ const struct LDR_SECTION_INFO *sect = NULL;
+ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(name != NULL);
+ DBC_Require(pAddr != NULL);
+ DBC_Require(pSize != NULL);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+
+ GT_4trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_getSect: lib: 0x%x name: %s pAddr:"
+ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
+ /* If DOFF file is not open, we open it. */
+ if (zlLib != NULL) {
+ if (zlLib->fp == NULL) {
+ status = dofOpen(zlLib);
+ if (DSP_SUCCEEDED(status))
+ fOpenedDoff = true;
+
+ } else {
+ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
+ zlLib->ulPos, SEEK_SET);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ uByteSize = 1;
+ if (DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
+ *pAddr = sect->load_addr;
+ *pSize = sect->size * uByteSize;
+ /* Make sure size is even for good swap */
+ if (*pSize % 2)
+ (*pSize)++;
+
+ /* Align size */
+ *pSize = DOFF_ALIGN(*pSize);
+ } else {
+ status = DSP_ENOSECT;
+ }
+ }
+ if (fOpenedDoff) {
+ dofClose(zlLib);
+ fOpenedDoff = false;
+ }
+
+ return status;
+}
+
+/*
+ * ======== DBLL_init ========
+ */
+bool DBLL_init(void)
+{
+ bool retVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!DBLL_debugMask.flags);
+ GT_create(&DBLL_debugMask, "DL"); /* "DL" for dbDL */
+ GH_init();
+ CSL_Init();
+ retVal = MEM_Init();
+ if (!retVal)
+ MEM_Exit();
+
+ }
+
+ if (retVal)
+ cRefs++;
+
+
+ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
+
+ return retVal;
+}
+
+/*
+ * ======== DBLL_load ========
+ */
+DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib, DBLL_Flags flags,
+ struct DBLL_Attrs *attrs, u32 *pEntry)
+{
+ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
+ struct DBLL_TarObj *dbzl;
+ bool gotSymbols = true;
+ s32 err;
+ DSP_STATUS status = DSP_SOK;
+ bool fOpenedDoff = false;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(pEntry != NULL);
+ DBC_Require(attrs != NULL);
+
+ GT_4trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_load: lib: 0x%x flags: 0x%x pEntry:"
+ " 0x%x\n", lib, flags, attrs, pEntry);
+ /*
+ * Load if not already loaded.
+ */
+ if (zlLib->loadRef == 0 || !(flags & DBLL_DYNAMIC)) {
+ dbzl = zlLib->pTarget;
+ dbzl->attrs = *attrs;
+ /* Create a hash table for symbols if not already created */
+ if (zlLib->symTab == NULL) {
+ gotSymbols = false;
+ zlLib->symTab = GH_create(MAXBUCKETS,
+ sizeof(struct Symbol),
+ nameHash,
+ nameMatch, symDelete);
+ if (zlLib->symTab == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ /*
+ * Set up objects needed by the dynamic loader
+ */
+ /* Stream */
+ zlLib->stream.dlStream.read_buffer = readBuffer;
+ zlLib->stream.dlStream.set_file_posn = setFilePosn;
+ zlLib->stream.lib = zlLib;
+ /* Symbol */
+ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
+ if (gotSymbols) {
+ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
+ findInSymbolTable;
+ } else {
+ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
+ addToSymbolTable;
+ }
+ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
+ zlLib->symbol.dlSymbol.Allocate = allocate;
+ zlLib->symbol.dlSymbol.Deallocate = deallocate;
+ zlLib->symbol.dlSymbol.Error_Report = errorReport;
+ zlLib->symbol.lib = zlLib;
+ /* Allocate */
+ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
+ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
+ zlLib->allocate.lib = zlLib;
+ /* Init */
+ zlLib->init.dlInit.connect = connect;
+ zlLib->init.dlInit.readmem = readMem;
+ zlLib->init.dlInit.writemem = writeMem;
+ zlLib->init.dlInit.fillmem = fillMem;
+ zlLib->init.dlInit.execute = execute;
+ zlLib->init.dlInit.release = release;
+ zlLib->init.lib = zlLib;
+ /* If COFF file is not open, we open it. */
+ if (zlLib->fp == NULL) {
+ status = dofOpen(zlLib);
+ if (DSP_SUCCEEDED(status))
+ fOpenedDoff = true;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell))
+ (zlLib->fp);
+ /* Reset file cursor */
+ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0,
+ SEEK_SET);
+ bSymbolsReloaded = true;
+ /* The 5th argument, DLOAD_INITBSS, tells the DLL
+ * module to zero-init all BSS sections. In general,
+ * this is not necessary and also increases load time.
+ * We may want to make this configurable by the user */
+ err = Dynamic_Load_Module(&zlLib->stream.dlStream,
+ &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc,
+ &zlLib->init.dlInit, DLOAD_INITBSS,
+ &zlLib->mHandle);
+
+ if (err != 0) {
+ GT_1trace(DBLL_debugMask, GT_6CLASS,
+ "DBLL_load: "
+ "Dynamic_Load_Module failed: 0x%lx\n",
+ err);
+ status = DSP_EDYNLOAD;
+ } else if (bRedefinedSymbol) {
+ zlLib->loadRef++;
+ DBLL_unload(zlLib, (struct DBLL_Attrs *) attrs);
+ bRedefinedSymbol = false;
+ status = DSP_EDYNLOAD;
+ } else {
+ *pEntry = zlLib->entry;
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status))
+ zlLib->loadRef++;
+
+ /* Clean up DOFF resources */
+ if (fOpenedDoff)
+ dofClose(zlLib);
+
+ DBC_Ensure(DSP_FAILED(status) || zlLib->loadRef > 0);
+ return status;
+}
+
+/*
+ * ======== DBLL_loadSect ========
+ * Not supported for COFF.
+ */
+DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *zlLib, char *sectName,
+ struct DBLL_Attrs *attrs)
+{
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== DBLL_open ========
+ */
+DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags,
+ struct DBLL_LibraryObj **pLib)
+{
+ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
+ struct DBLL_LibraryObj *zlLib = NULL;
+ s32 err;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
+ DBC_Require(zlTarget->attrs.fopen != NULL);
+ DBC_Require(file != NULL);
+ DBC_Require(pLib != NULL);
+
+ GT_3trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_open: target: 0x%x file: %s pLib:"
+ " 0x%x\n", target, file, pLib);
+ zlLib = zlTarget->head;
+ while (zlLib != NULL) {
+ if (strcmp(zlLib->fileName, file) == 0) {
+ /* Library is already opened */
+ zlLib->openRef++;
+ break;
+ }
+ zlLib = zlLib->next;
+ }
+ if (zlLib == NULL) {
+ /* Allocate DBL library object */
+ MEM_AllocObject(zlLib, struct DBLL_LibraryObj,
+ DBLL_LIBSIGNATURE);
+ if (zlLib == NULL) {
+ GT_0trace(DBLL_debugMask, GT_6CLASS,
+ "DBLL_open: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ zlLib->ulPos = 0;
+ /* Increment ref count to allow close on failure
+ * later on */
+ zlLib->openRef++;
+ zlLib->pTarget = zlTarget;
+ /* Keep a copy of the file name */
+ zlLib->fileName = MEM_Calloc(strlen(file) + 1,
+ MEM_PAGED);
+ if (zlLib->fileName == NULL) {
+ GT_0trace(DBLL_debugMask, GT_6CLASS,
+ "DBLL_open: Memory "
+ "allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ strncpy(zlLib->fileName, file,
+ strlen(file) + 1);
+ }
+ zlLib->symTab = NULL;
+ }
+ }
+ /*
+ * Set up objects needed by the dynamic loader
+ */
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ /* Stream */
+ zlLib->stream.dlStream.read_buffer = readBuffer;
+ zlLib->stream.dlStream.set_file_posn = setFilePosn;
+ zlLib->stream.lib = zlLib;
+ /* Symbol */
+ zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable;
+ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
+ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
+ zlLib->symbol.dlSymbol.Allocate = allocate;
+ zlLib->symbol.dlSymbol.Deallocate = deallocate;
+ zlLib->symbol.dlSymbol.Error_Report = errorReport;
+ zlLib->symbol.lib = zlLib;
+ /* Allocate */
+ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
+ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
+ zlLib->allocate.lib = zlLib;
+ /* Init */
+ zlLib->init.dlInit.connect = connect;
+ zlLib->init.dlInit.readmem = readMem;
+ zlLib->init.dlInit.writemem = writeMem;
+ zlLib->init.dlInit.fillmem = fillMem;
+ zlLib->init.dlInit.execute = execute;
+ zlLib->init.dlInit.release = release;
+ zlLib->init.lib = zlLib;
+ if (DSP_SUCCEEDED(status) && zlLib->fp == NULL)
+ status = dofOpen(zlLib);
+
+ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp);
+ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET);
+ /* Create a hash table for symbols if flag is set */
+ if (zlLib->symTab != NULL || !(flags & DBLL_SYMB))
+ goto func_cont;
+
+ zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash,
+ nameMatch, symDelete);
+ if (zlLib->symTab == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Do a fake load to get symbols - set write function to NoOp */
+ zlLib->init.dlInit.writemem = NoOp;
+ err = Dynamic_Open_Module(&zlLib->stream.dlStream,
+ &zlLib->symbol.dlSymbol,
+ &zlLib->allocate.dlAlloc,
+ &zlLib->init.dlInit, 0,
+ &zlLib->mHandle);
+ if (err != 0) {
+ GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: "
+ "Dynamic_Load_Module failed: 0x%lx\n", err);
+ status = DSP_EDYNLOAD;
+ } else {
+ /* Now that we have the symbol table, we can unload */
+ err = Dynamic_Unload_Module(zlLib->mHandle,
+ &zlLib->symbol.dlSymbol,
+ &zlLib->allocate.dlAlloc,
+ &zlLib->init.dlInit);
+ if (err != 0) {
+ GT_1trace(DBLL_debugMask, GT_6CLASS,
+ "DBLL_open: "
+ "Dynamic_Unload_Module failed: 0x%lx\n",
+ err);
+ status = DSP_EDYNLOAD;
+ }
+ zlLib->mHandle = NULL;
+ }
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status)) {
+ if (zlLib->openRef == 1) {
+ /* First time opened - insert in list */
+ if (zlTarget->head)
+ (zlTarget->head)->prev = zlLib;
+
+ zlLib->prev = NULL;
+ zlLib->next = zlTarget->head;
+ zlTarget->head = zlLib;
+ }
+ *pLib = (struct DBLL_LibraryObj *)zlLib;
+ } else {
+ *pLib = NULL;
+ if (zlLib != NULL)
+ DBLL_close((struct DBLL_LibraryObj *)zlLib);
+
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) &&
+ MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)),
+ DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL));
+ return status;
+}
+
+/*
+ * ======== DBLL_readSect ========
+ * Get the content of a COFF section.
+ */
+DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib, char *name,
+ char *pContent, u32 size)
+{
+ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
+ bool fOpenedDoff = false;
+ u32 uByteSize; /* size of bytes */
+ u32 ulSectSize; /* size of section */
+ const struct LDR_SECTION_INFO *sect = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(name != NULL);
+ DBC_Require(pContent != NULL);
+ DBC_Require(size != 0);
+
+ GT_4trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_readSect: lib: 0x%x name: %s "
+ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
+ /* If DOFF file is not open, we open it. */
+ if (zlLib != NULL) {
+ if (zlLib->fp == NULL) {
+ status = dofOpen(zlLib);
+ if (DSP_SUCCEEDED(status))
+ fOpenedDoff = true;
+
+ } else {
+ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
+ zlLib->ulPos, SEEK_SET);
+ }
+ }
+
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ uByteSize = 1;
+ if (!DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
+ status = DSP_ENOSECT;
+ goto func_cont;
+ }
+ /*
+ * Ensure the supplied buffer size is sufficient to store
+ * the section content to be read.
+ */
+ ulSectSize = sect->size * uByteSize;
+ /* Make sure size is even for good swap */
+ if (ulSectSize % 2)
+ ulSectSize++;
+
+ /* Align size */
+ ulSectSize = DOFF_ALIGN(ulSectSize);
+ if (ulSectSize > size) {
+ status = DSP_EFAIL;
+ } else {
+ if (!DLOAD_GetSection(zlLib->desc, sect, pContent))
+ status = DSP_EFREAD;
+
+ }
+func_cont:
+ if (fOpenedDoff) {
+ dofClose(zlLib);
+ fOpenedDoff = false;
+ }
+ return status;
+}
+
+/*
+ * ======== DBLL_setAttrs ========
+ * Set the attributes of the target.
+ */
+void DBLL_setAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
+{
+ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
+ DBC_Require(pAttrs != NULL);
+ GT_2trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_setAttrs: target: 0x%x pAttrs: "
+ "0x%x\n", target, pAttrs);
+ if ((pAttrs != NULL) && (zlTarget != NULL))
+ zlTarget->attrs = *pAttrs;
+
+}
+
+/*
+ * ======== DBLL_unload ========
+ */
+void DBLL_unload(struct DBLL_LibraryObj *lib, struct DBLL_Attrs *attrs)
+{
+ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
+ s32 err = 0;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
+ DBC_Require(zlLib->loadRef > 0);
+ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_unload: lib: 0x%x\n", lib);
+ zlLib->loadRef--;
+ /* Unload only if reference count is 0 */
+ if (zlLib->loadRef != 0)
+ goto func_end;
+
+ zlLib->pTarget->attrs = *attrs;
+ if (zlLib != NULL) {
+ if (zlLib->mHandle) {
+ err = Dynamic_Unload_Module(zlLib->mHandle,
+ &zlLib->symbol.dlSymbol,
+ &zlLib->allocate.dlAlloc, &zlLib->init.dlInit);
+ if (err != 0) {
+ GT_1trace(DBLL_debugMask, GT_5CLASS,
+ "Dynamic_Unload_Module "
+ "failed: 0x%x\n", err);
+ }
+ }
+ /* remove symbols from symbol table */
+ if (zlLib->symTab != NULL) {
+ GH_delete(zlLib->symTab);
+ zlLib->symTab = NULL;
+ }
+ /* delete DOFF desc since it holds *lots* of host OS
+ * resources */
+ dofClose(zlLib);
+ }
+func_end:
+ DBC_Ensure(zlLib->loadRef >= 0);
+}
+
+/*
+ * ======== DBLL_unloadSect ========
+ * Not supported for COFF.
+ */
+DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib, char *sectName,
+ struct DBLL_Attrs *attrs)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(sectName != NULL);
+ GT_2trace(DBLL_debugMask, GT_ENTER,
+ "DBLL_unloadSect: lib: 0x%x sectName: "
+ "%s\n", lib, sectName);
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== dofClose ========
+ */
+static void dofClose(struct DBLL_LibraryObj *zlLib)
+{
+ if (zlLib->desc) {
+ DLOAD_module_close(zlLib->desc);
+ zlLib->desc = NULL;
+ }
+ /* close file */
+ if (zlLib->fp) {
+ (zlLib->pTarget->attrs.fclose) (zlLib->fp);
+ zlLib->fp = NULL;
+ }
+}
+
+/*
+ * ======== dofOpen ========
+ */
+static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib)
+{
+ void *open = *(zlLib->pTarget->attrs.fopen);
+ DSP_STATUS status = DSP_SOK;
+
+ /* First open the file for the dynamic loader, then open COF */
+ zlLib->fp = (void *)((DBLL_FOpenFxn)(open))(zlLib->fileName, "rb");
+
+ /* Open DOFF module */
+ if (zlLib->fp && zlLib->desc == NULL) {
+ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0, SEEK_SET);
+ zlLib->desc = DLOAD_module_open(&zlLib->stream.dlStream,
+ &zlLib->symbol.dlSymbol);
+ if (zlLib->desc == NULL) {
+ (zlLib->pTarget->attrs.fclose)(zlLib->fp);
+ zlLib->fp = NULL;
+ status = DSP_EFOPEN;
+ }
+ } else {
+ status = DSP_EFOPEN;
+ }
+
+ return status;
+}
+
+/*
+ * ======== nameHash ========
+ */
+static u16 nameHash(void *key, u16 maxBucket)
+{
+ u16 ret;
+ u16 hash;
+ char *name = (char *)key;
+
+ DBC_Require(name != NULL);
+
+ hash = 0;
+
+ while (*name) {
+ hash <<= 1;
+ hash ^= *name++;
+ }
+
+ ret = hash % maxBucket;
+
+ return ret;
+}
+
+/*
+ * ======== nameMatch ========
+ */
+static bool nameMatch(void *key, void *value)
+{
+ DBC_Require(key != NULL);
+ DBC_Require(value != NULL);
+
+ if ((key != NULL) && (value != NULL)) {
+ if (strcmp((char *)key, ((struct Symbol *)value)->name) == 0)
+ return true;
+ }
+ return false;
+}
+
+/*
+ * ======== NoOp ========
+ */
+static int NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
+ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsize)
+{
+ return 1;
+}
+
+/*
+ * ======== symDelete ========
+ */
+static void symDelete(void *value)
+{
+ struct Symbol *sp = (struct Symbol *)value;
+
+ MEM_Free(sp->name);
+}
+
+/*
+ * Dynamic Loader Functions
+ */
+
+/* Dynamic_Loader_Stream */
+/*
+ * ======== readBuffer ========
+ */
+static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
+ unsigned bufsize)
+{
+ struct DBLLStream *pStream = (struct DBLLStream *)this;
+ struct DBLL_LibraryObj *lib;
+ int bytesRead = 0;
+
+ DBC_Require(this != NULL);
+ lib = pStream->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ if (lib != NULL) {
+ bytesRead = (*(lib->pTarget->attrs.fread))(buffer, 1, bufsize,
+ lib->fp);
+ }
+ return bytesRead;
+}
+
+/*
+ * ======== setFilePosn ========
+ */
+static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos)
+{
+ struct DBLLStream *pStream = (struct DBLLStream *)this;
+ struct DBLL_LibraryObj *lib;
+ int status = 0; /* Success */
+
+ DBC_Require(this != NULL);
+ lib = pStream->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ if (lib != NULL) {
+ status = (*(lib->pTarget->attrs.fseek))(lib->fp, (long)pos,
+ SEEK_SET);
+ }
+
+ return status;
+}
+
+/* Dynamic_Loader_Sym */
+
+/*
+ * ======== findSymbol ========
+ */
+static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
+ const char *name)
+{
+ struct dynload_symbol *retSym;
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+ struct DBLL_Symbol *pSym = NULL;
+ bool status = false; /* Symbol not found yet */
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ if (lib != NULL) {
+ if (lib->pTarget->attrs.symLookup) {
+ /* Check current lib + base lib + dep lib +
+ * persistent lib */
+ status = (*(lib->pTarget->attrs.symLookup))
+ (lib->pTarget->attrs.symHandle,
+ lib->pTarget->attrs.symArg,
+ lib->pTarget->attrs.rmmHandle, name, &pSym);
+ } else {
+ /* Just check current lib for symbol */
+ status = DBLL_getAddr((struct DBLL_LibraryObj *)lib,
+ (char *)name, &pSym);
+ if (!status) {
+ status =
+ DBLL_getCAddr((struct DBLL_LibraryObj *)lib,
+ (char *)name, &pSym);
+ }
+ }
+ }
+
+ if (!status && bGblSearch) {
+ GT_1trace(DBLL_debugMask, GT_6CLASS,
+ "findSymbol: Symbol not found: %s\n", name);
+ }
+
+ DBC_Assert((status && (pSym != NULL)) || (!status && (pSym == NULL)));
+
+ retSym = (struct dynload_symbol *)pSym;
+ return retSym;
+}
+
+/*
+ * ======== findInSymbolTable ========
+ */
+static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
+ const char *name,
+ unsigned moduleid)
+{
+ struct dynload_symbol *retSym;
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+ struct Symbol *sym;
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+ DBC_Require(lib->symTab != NULL);
+
+ sym = (struct Symbol *)GH_find(lib->symTab, (char *) name);
+
+ retSym = (struct dynload_symbol *)&sym->value;
+ return retSym;
+}
+
+/*
+ * ======== addToSymbolTable ========
+ */
+static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
+ const char *name,
+ unsigned moduleId)
+{
+ struct Symbol *symPtr = NULL;
+ struct Symbol symbol;
+ struct dynload_symbol *pSym = NULL;
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+ struct dynload_symbol *retVal;
+
+ DBC_Require(this != NULL);
+ DBC_Require(name);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ /* Check to see if symbol is already defined in symbol table */
+ if (!(lib->pTarget->attrs.baseImage)) {
+ bGblSearch = false;
+ pSym = findSymbol(this, name);
+ bGblSearch = true;
+ if (pSym) {
+
+ #ifdef OMAP44XX
+ #define SQ_IGNORE_SYMBOLS 1
+ #endif
+ #if !SQ_IGNORE_SYMBOLS
+
+ bRedefinedSymbol = true;
+ GT_1trace(DBLL_debugMask, GT_6CLASS,
+ "Symbol already defined in "
+ "symbol table: %s\n", name);
+ return NULL;
+ #else
+ if ((strcmp(name, "___ASM__") == 0)
+ || (strcmp(name, "___TARG__") == 0)
+ || (strcmp(name, "___PLAT__") == 0)
+ || (strcmp(name, "___ISA__") == 0)
+ || (strcmp(name, "___TRDR__") == 0))
+ retVal = findSymbol(this, name);
+ else {
+ bRedefinedSymbol = true;
+ GT_1trace(DBLL_debugMask, GT_6CLASS,
+ "Symbol already defined in "
+ "symbol table: %s\n", name);
+ return NULL;
+ }
+ #endif
+
+
+ }
+ }
+ /* Allocate string to copy symbol name */
+ symbol.name = (char *)MEM_Calloc(strlen((char *const)name) + 1,
+ MEM_PAGED);
+ if (symbol.name == NULL)
+ return NULL;
+
+ if (symbol.name != NULL) {
+ /* Just copy name (value will be filled in by dynamic loader) */
+ strncpy(symbol.name, (char *const)name,
+ strlen((char *const)name) + 1);
+
+ /* Add symbol to symbol table */
+ symPtr = (struct Symbol *)GH_insert(lib->symTab, (void *)name,
+ (void *)&symbol);
+ if (symPtr == NULL)
+ MEM_Free(symbol.name);
+
+ }
+ if (symPtr != NULL)
+ retVal = (struct dynload_symbol *)&symPtr->value;
+ else
+ retVal = NULL;
+
+ return retVal;
+}
+
+/*
+ * ======== purgeSymbolTable ========
+ */
+static void purgeSymbolTable(struct Dynamic_Loader_Sym *this, unsigned moduleId)
+{
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ /* May not need to do anything */
+}
+
+/*
+ * ======== allocate ========
+ */
+static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize)
+{
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+ void *buf;
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ buf = MEM_Calloc(memsize, MEM_PAGED);
+
+ return buf;
+}
+
+/*
+ * ======== deallocate ========
+ */
+static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr)
+{
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ MEM_Free(memPtr);
+}
+
+/*
+ * ======== errorReport ========
+ */
+static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
+ va_list args)
+{
+ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
+ struct DBLL_LibraryObj *lib;
+ char tempBuf[MAXEXPR];
+
+ DBC_Require(this != NULL);
+ lib = pSymbol->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+ vsnprintf((char *)tempBuf, MAXEXPR, (char *)errstr, args);
+ GT_1trace(DBLL_debugMask, GT_5CLASS, "%s\n", tempBuf);
+}
+
+/* Dynamic_Loader_Allocate */
+
+/*
+ * ======== rmmAlloc ========
+ */
+static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
+ struct LDR_SECTION_INFO *info, unsigned align)
+{
+ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
+ struct DBLL_LibraryObj *lib;
+ DSP_STATUS status = DSP_SOK;
+ u32 memType;
+ struct RMM_Addr rmmAddr;
+ s32 retVal = TRUE;
+ unsigned stype = DLOAD_SECTION_TYPE(info->type);
+ char *pToken = NULL;
+ char *szSecLastToken = NULL;
+ char *szLastToken = NULL;
+ char *szSectName = NULL;
+ char *pszCur;
+ s32 tokenLen = 0;
+ s32 segId = -1;
+ s32 req = -1;
+ s32 count = 0;
+ u32 allocSize = 0;
+
+ DBC_Require(this != NULL);
+ lib = pAlloc->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
+ DBLL_BSS : DBLL_DATA;
+
+ /* Attempt to extract the segment ID and requirement information from
+ the name of the section */
+ DBC_Require(info->name);
+ tokenLen = strlen((char *)(info->name)) + 1;
+
+ szSectName = MEM_Calloc(tokenLen, MEM_PAGED);
+ szLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
+ szSecLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
+
+ if (szSectName == NULL || szSecLastToken == NULL ||
+ szLastToken == NULL) {
+ status = DSP_EMEMORY;
+ goto func_cont;
+ }
+ strncpy(szSectName, (char *)(info->name), tokenLen);
+ pszCur = szSectName;
+ while ((pToken = strsep(&pszCur, ":")) && *pToken != '\0') {
+ strncpy(szSecLastToken, szLastToken, strlen(szLastToken) + 1);
+ strncpy(szLastToken, pToken, strlen(pToken) + 1);
+ pToken = strsep(&pszCur, ":");
+ count++; /* optimizes processing*/
+ }
+ /* If pToken is 0 or 1, and szSecLastToken is DYN_DARAM or DYN_SARAM,
+ or DYN_EXTERNAL, then mem granularity information is present
+ within the section name - only process if there are at least three
+ tokens within the section name (just a minor optimization)*/
+ if (count >= 3)
+ strict_strtol(szLastToken, 10, (long *)&req);
+
+ if ((req == 0) || (req == 1)) {
+ if (strcmp(szSecLastToken, "DYN_DARAM") == 0) {
+ segId = 0;
+ } else {
+ if (strcmp(szSecLastToken, "DYN_SARAM") == 0) {
+ segId = 1;
+ } else {
+ if (strcmp(szSecLastToken,
+ "DYN_EXTERNAL") == 0) {
+ segId = 2;
+ }
+ }
+ }
+ if (segId != -1) {
+ GT_2trace(DBLL_debugMask, GT_5CLASS,
+ "Extracted values for memory"
+ " granularity req [%d] segId [%d]\n",
+ req, segId);
+ }
+ }
+ MEM_Free(szSectName);
+ szSectName = NULL;
+ MEM_Free(szLastToken);
+ szLastToken = NULL;
+ MEM_Free(szSecLastToken);
+ szSecLastToken = NULL;
+func_cont:
+ if (memType == DBLL_CODE)
+ allocSize = info->size + GEM_L1P_PREFETCH_SIZE;
+ else
+ allocSize = info->size;
+ /* TODO - ideally, we can pass the alignment requirement also
+ * from here */
+ if (lib != NULL) {
+ status = (lib->pTarget->attrs.alloc)(lib->pTarget->
+ attrs.rmmHandle, memType, allocSize, align,
+ (u32 *)&rmmAddr, segId, req, FALSE);
+ }
+ if (DSP_FAILED(status)) {
+ retVal = false;
+ } else {
+ /* RMM gives word address. Need to convert to byte address */
+ info->load_addr = rmmAddr.addr * DSPWORDSIZE;
+ info->run_addr = info->load_addr;
+ info->context = (u32)rmmAddr.segid;
+ GT_3trace(DBLL_debugMask, GT_5CLASS,
+ "Remote alloc: %s base = 0x%lx len"
+ "= 0x%lx\n", info->name, info->load_addr / DSPWORDSIZE,
+ info->size / DSPWORDSIZE);
+ }
+ return retVal;
+}
+
+/*
+ * ======== rmmDealloc ========
+ */
+static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
+ struct LDR_SECTION_INFO *info)
+{
+ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
+ struct DBLL_LibraryObj *lib;
+ u32 segid;
+ DSP_STATUS status = DSP_SOK;
+ unsigned stype = DLOAD_SECTION_TYPE(info->type);
+ u32 memType;
+ u32 freeSize = 0;
+
+ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
+ DBLL_BSS : DBLL_DATA;
+ DBC_Require(this != NULL);
+ lib = pAlloc->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+ /* segid was set by alloc function */
+ segid = (u32)info->context;
+ if (memType == DBLL_CODE)
+ freeSize = info->size + GEM_L1P_PREFETCH_SIZE;
+ else
+ freeSize = info->size;
+ if (lib != NULL) {
+ status = (lib->pTarget->attrs.free)(lib->pTarget->
+ attrs.symHandle, segid, info->load_addr / DSPWORDSIZE,
+ freeSize, false);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ GT_2trace(DBLL_debugMask, GT_5CLASS,
+ "Remote dealloc: base = 0x%lx len ="
+ "0x%lx\n", info->load_addr / DSPWORDSIZE,
+ freeSize / DSPWORDSIZE);
+ }
+}
+
+/* Dynamic_Loader_Initialize */
+/*
+ * ======== connect ========
+ */
+static int connect(struct Dynamic_Loader_Initialize *this)
+{
+ return true;
+}
+
+/*
+ * ======== readMem ========
+ * This function does not need to be implemented.
+ */
+static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
+ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
+ unsigned nbytes)
+{
+ struct DBLLInit *pInit = (struct DBLLInit *)this;
+ struct DBLL_LibraryObj *lib;
+ int bytesRead = 0;
+
+ DBC_Require(this != NULL);
+ lib = pInit->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+ /* Need WMD_BRD_Read function */
+ return bytesRead;
+}
+
+/*
+ * ======== writeMem ========
+ */
+static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
+ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
+ unsigned nBytes)
+{
+ struct DBLLInit *pInit = (struct DBLLInit *)this;
+ struct DBLL_LibraryObj *lib;
+ struct DBLL_SectInfo sectInfo;
+ u32 memType;
+ bool retVal = true;
+
+ DBC_Require(this != NULL);
+ lib = pInit->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+
+ memType = (DLOAD_SECTION_TYPE(info->type) == DLOAD_TEXT) ? DBLL_CODE :
+ DBLL_DATA;
+ if (lib != NULL) {
+ retVal = (*lib->pTarget->attrs.write)(lib->pTarget->
+ attrs.wHandle, addr, buf, nBytes, memType);
+ }
+ if (lib->pTarget->attrs.logWrite) {
+ sectInfo.name = info->name;
+ sectInfo.runAddr = info->run_addr;
+ sectInfo.loadAddr = info->load_addr;
+ sectInfo.size = info->size;
+ sectInfo.type = memType;
+ /* Pass the information about what we've written to
+ * another module */
+ (*lib->pTarget->attrs.logWrite)(lib->pTarget->
+ attrs.logWriteHandle, &sectInfo, addr, nBytes);
+ }
+ return retVal;
+}
+
+/*
+ * ======== fillMem ========
+ * Fill nBytes of memory at a given address with a given value by
+ * writing from a buffer containing the given value. Write in
+ * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
+ */
+static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
+ struct LDR_SECTION_INFO *info, unsigned nBytes,
+ unsigned val)
+{
+ bool retVal = true;
+ char *pBuf;
+ struct DBLL_LibraryObj *lib;
+ struct DBLLInit *pInit = (struct DBLLInit *)this;
+
+ DBC_Require(this != NULL);
+ lib = pInit->lib;
+ pBuf = NULL;
+ /* Pass the NULL pointer to writeMem to get the start address of Shared
+ memory. This is a trick to just get the start address, there is no
+ writing taking place with this Writemem
+ */
+ if ((lib->pTarget->attrs.write) != (DBLL_WriteFxn)NoOp)
+ writeMem(this, &pBuf, addr, info, 0);
+ if (pBuf)
+ memset(pBuf, val, nBytes);
+
+ return retVal;
+}
+
+/*
+ * ======== execute ========
+ */
+static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start)
+{
+ struct DBLLInit *pInit = (struct DBLLInit *)this;
+ struct DBLL_LibraryObj *lib;
+ bool retVal = true;
+
+ DBC_Require(this != NULL);
+ lib = pInit->lib;
+ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
+ /* Save entry point */
+ if (lib != NULL)
+ lib->entry = (u32)start;
+
+ return retVal;
+}
+
+/*
+ * ======== release ========
+ */
+static void release(struct Dynamic_Loader_Initialize *this)
+{
+}
+
diff --git a/drivers/dsp/bridge/pmgr/dev.c b/drivers/dsp/bridge/pmgr/dev.c
new file mode 100644
index 000000000000..1c2f7d5ae409
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/dev.c
@@ -0,0 +1,1476 @@
+/*
+ * dev.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dev.c ========
+ * Description:
+ * Implementation of 'Bridge Mini-driver device operations.
+ *
+ * Public Functions:
+ * DEV_BrdWriteFxn
+ * DEV_CreateDevice
+ * DEV_Create2
+ * DEV_Destroy2
+ * DEV_DestroyDevice
+ * DEV_GetChnlMgr
+ * DEV_GetCmmMgr
+ * DEV_GetCodMgr
+ * DEV_GetDehMgr
+ * DEV_GetDevNode
+ * DEV_GetDSPWordSize
+ * DEV_GetFirst
+ * DEV_GetIntfFxns
+ * DEV_GetIOMgr
+ * DEV_GetNext
+ * DEV_GetNodeManager
+ * DEV_GetSymbol
+ * DEV_GetWMDContext
+ * DEV_Exit
+ * DEV_Init
+ * DEV_InsertProcObject
+ * DEV_IsLocked
+ * DEV_NotifyClient
+ * DEV_RegisterNotify
+ * DEV_ReleaseCodMgr
+ * DEV_RemoveDevice
+ * DEV_RemoveProcObject
+ * DEV_SetChnlMgr
+ * DEV_SetMsgMgr
+ * DEV_SetLockOwner
+ * DEV_StartDevice
+ *
+ * Private Functions:
+ * FxnNotImplemented
+ * InitCodMgr
+ * InsertDevObject
+ * IsValidHandle
+ * RemoveDevObject
+ * StoreInterfaceFxns
+ *
+ *! Revision History:
+ *! ================
+ *! 03-Jan-2005 hn Support for IVA DEH
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
+ *! 09-Feb-2004 vp Updated to support IVA.
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 29-Nov-2001 jeh Check for DSP_ENOTIMPL status of DEH create function.
+ *! 05-Nov-2001 kc Added support for DEH module.
+ *! 05-Aug-2001 ag Shared memory registration moved to WMD_IO_OnLoaded().
+ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
+ *! 11-Apr-2001 rr: Removed CMM_RegisterGPPSMSeg.
+ *! 02-Apr-2001 rr: CHNL_Create failure is printed out.
+ *! 15-Jan-2001 jeh Removed call to IO_OnLoaded() from DEV_Create2().
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name update.
+ *! 15-Dec-2000 rr: Dev_Create2 returns error if NODE_CreateMgr fails.
+ *! 05-Dec-2000 jeh Moved IO_OnLoaded() to PROC_Load. Added DEV_SetMsgMgr.
+ *! 05-Dev-2000 ag SM Heap for messaging registered via CMM_RegisterGPPSMSeg().
+ *! SM heap base and size currently taken from registry.
+ *! 29-Nov-2000 rr: Incorporated code review changes.
+ *! 17-Nov-2000 jeh Added calls to get IO manager (IO_Create), IO_OnLoaded().
+ *! 06-Oct-2000 rr: DEV_Destroy2 and DEV_Create2 added.
+ *! 02-Oct-2000 rr: DEV_GetNodeManager added.
+ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr(), CMM_Init() & CMM_Exit().
+ *! Removed <dspbridge/std.h> & <stdwin.h>, added <dspbridge/dbtype.h>
+ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
+ *! DEV_Cleanup calls PROC_Detach if it is a matching process.
+ *! 27-Jul-2000 rr: DEV is in new directoy DEV and produces devlib.lib
+ *! 17-Jul-2000 rr: DRV Object holds the list of Dev Objects. DEV gets
+ *! the List and Next devices through DRV.
+ *! DEV object has a back pointer to DRV Object.
+ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
+ *! 09-May-2000 rr: dwMemBase has index for multiple windows need.
+ *! 28-Feb-2000 rr: New GT Usage implemented.
+ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
+ *! SERVICES)
+ *! 31-Jan-2000 rr: Comments changed after code review.
+ *! 21-Jan-2000 rr: windows.h, tchar.h, HMODULE removed. FreeLibrary replaced
+ *! with LDR_FreeModule
+ *! 17-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
+ *! StoreInterfaceFxns stores the new fxn WMD_BRD_SETSTATE.
+ *! 20-Nov-1999 ag: Actual uSMLength = total - monitor offset.
+ *! 12-Nov-1999 rr: bIRQ and IRQAttrib taken from the struct CFG_HOSTRES.
+ *! dMemBase is added with offset for monitor taken from
+ *! registry.
+ *! 31-Oct-1999 ag: Added CHNL support.
+ *! 10-Sep-1999 rr: GT Enabled. DEV_Create will Load the Mini Driver and will
+ *! find its fxn table. Right now lot of things are hardcoded
+ *! as the REG is not ready.
+ *! 10-Jun-1996 rr: Created from WSX
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/ldr.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/util.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/cod.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/proc.h>
+#include <dspbridge/dmm.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/mgr.h>
+#include <dspbridge/node.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbreg.h>
+#include <dspbridge/wcd.h> /* WCD version info. */
+
+#include <dspbridge/chnl.h>
+#include <dspbridge/io.h>
+#include <dspbridge/msg.h>
+#include <dspbridge/cmm.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+
+#define SIGNATURE 0x5f564544 /* "DEV_" (in reverse) */
+#define MAKEVERSION(major, minor) (major * 10 + minor)
+#define WCDVERSION MAKEVERSION(WCD_MAJOR_VERSION, WCD_MINOR_VERSION)
+
+/* The WMD device object: */
+struct DEV_OBJECT {
+ /* LST requires "link" to be first field! */
+ struct LST_ELEM link; /* Link to next DEV_OBJECT. */
+ u32 devType; /* Device Type */
+ u32 dwSignature; /* Used for object validation. */
+ struct CFG_DEVNODE *hDevNode; /* Platform specific device id */
+ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
+ struct WMD_DRV_INTERFACE intfFxns; /* Function interface to WMD. */
+ struct BRD_OBJECT *lockOwner; /* Client with exclusive access. */
+ struct COD_MANAGER *hCodMgr; /* Code manager handle. */
+ struct CHNL_MGR *hChnlMgr; /* Channel manager. */
+ struct DEH_MGR *hDehMgr; /* DEH manager. */
+ struct MSG_MGR *hMsgMgr; /* Message manager. */
+ struct IO_MGR *hIOMgr; /* IO manager (CHNL, MSG) */
+ struct CMM_OBJECT *hCmmMgr; /* SM memory manager. */
+ struct DMM_OBJECT *hDmmMgr; /* Dynamic memory manager. */
+ struct LDR_MODULE *hModule; /* WMD Module handle. */
+ u32 uWordSize; /* DSP word size: quick access. */
+ struct DRV_OBJECT *hDrvObject; /* Driver Object */
+ struct LST_LIST *procList; /* List of Proceeosr attached to
+ * this device */
+ struct NODE_MGR *hNodeMgr;
+} ;
+
+/* ----------------------------------- Globals */
+static u32 cRefs; /* Module reference count */
+#if GT_TRACE
+static struct GT_Mask debugMask = { NULL, NULL }; /* For debugging */
+#endif
+
+/* ----------------------------------- Function Prototypes */
+static DSP_STATUS FxnNotImplemented(int arg, ...);
+static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject);
+static bool IsValidHandle(struct DEV_OBJECT *hObj);
+static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
+ OUT struct WMD_DRV_INTERFACE *pIntfFxns);
+/*
+ * ======== DEV_BrdWriteFxn ========
+ * Purpose:
+ * Exported function to be used as the COD write function. This function
+ * is passed a handle to a DEV_hObject, then calls the
+ * device's WMD_BRD_Write() function.
+ */
+u32 DEV_BrdWriteFxn(void *pArb, u32 ulDspAddr, void *pHostBuf,
+ u32 ulNumBytes, u32 nMemSpace)
+{
+ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)pArb;
+ u32 ulWritten = 0;
+ DSP_STATUS status;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pHostBuf != NULL); /* Required of BrdWrite(). */
+ GT_5trace(debugMask, GT_ENTER,
+ "Entered DEV_BrdWriteFxn, pArb: 0x%x\n\t\t"
+ "ulDspAddr: 0x%x\n\t\tpHostBuf: 0x%x\n \t\tulNumBytes: 0x%x\n"
+ "\t\tnMemSpace: 0x%x\n", pArb, ulDspAddr, pHostBuf,
+ ulNumBytes, nMemSpace);
+ if (IsValidHandle(pDevObject)) {
+ /* Require of BrdWrite() */
+ DBC_Assert(pDevObject->hWmdContext != NULL);
+ status = (*pDevObject->intfFxns.pfnBrdWrite)(pDevObject->
+ hWmdContext, pHostBuf, ulDspAddr, ulNumBytes,
+ nMemSpace);
+ /* Special case of getting the address only */
+ if (ulNumBytes == 0)
+ ulNumBytes = 1;
+ if (DSP_SUCCEEDED(status))
+ ulWritten = ulNumBytes;
+
+ }
+ GT_1trace(debugMask, GT_ENTER, "Exit DEV_BrdWriteFxn ulWritten: 0x%x\n",
+ ulWritten);
+ return ulWritten;
+}
+
+/*
+ * ======== DEV_CreateDevice ========
+ * Purpose:
+ * Called by the operating system to load the PM Mini Driver for a
+ * PM board (device).
+ */
+DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT **phDevObject,
+ IN CONST char *pstrWMDFileName,
+ IN CONST struct CFG_HOSTRES *pHostConfig,
+ IN CONST struct CFG_DSPRES *pDspConfig,
+ struct CFG_DEVNODE *hDevNode)
+{
+ struct LDR_MODULE *hModule = NULL;
+ struct WMD_DRV_INTERFACE *pDrvFxns = NULL;
+ struct DEV_OBJECT *pDevObject = NULL;
+ struct CHNL_MGRATTRS mgrAttrs;
+ struct IO_ATTRS ioMgrAttrs;
+ u32 uNumWindows;
+ struct DRV_OBJECT *hDrvObject = NULL;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDevObject != NULL);
+ DBC_Require(pstrWMDFileName != NULL);
+ DBC_Require(pHostConfig != NULL);
+ DBC_Require(pDspConfig != NULL);
+
+ GT_5trace(debugMask, GT_ENTER,
+ "Entered DEV_CreateDevice, phDevObject: 0x%x\n"
+ "\t\tpstrWMDFileName: 0x%x\n\t\tpHostConfig:0x%x\n\t\t"
+ "pDspConfig: 0x%x\n\t\tnhDevNode: 0x%x\n", phDevObject,
+ pstrWMDFileName, pHostConfig, pDspConfig, hDevNode);
+ /* Get the WMD interface functions*/
+ WMD_DRV_Entry(&pDrvFxns, pstrWMDFileName);
+ if (DSP_FAILED(CFG_GetObject((u32 *) &hDrvObject, REG_DRV_OBJECT))) {
+ /* don't propogate CFG errors from this PROC function */
+ GT_0trace(debugMask, GT_7CLASS,
+ "Failed to get the DRV Object \n");
+ status = DSP_EFAIL;
+ }
+ /* Create the device object, and pass a handle to the WMD for
+ * storage. */
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(pDrvFxns);
+ MEM_AllocObject(pDevObject, struct DEV_OBJECT, SIGNATURE);
+ if (pDevObject) {
+ /* Fill out the rest of the Dev Object structure: */
+ pDevObject->hDevNode = hDevNode;
+ pDevObject->hModule = hModule;
+ pDevObject->hCodMgr = NULL;
+ pDevObject->hChnlMgr = NULL;
+ pDevObject->hDehMgr = NULL;
+ pDevObject->lockOwner = NULL;
+ pDevObject->uWordSize = pDspConfig->uWordSize;
+ pDevObject->hDrvObject = hDrvObject;
+ pDevObject->devType = DSP_UNIT;
+ /* Store this WMD's interface functions, based on its
+ * version. */
+ StoreInterfaceFxns(pDrvFxns, &pDevObject->intfFxns);
+ /* Call WMD_DEV_CREATE() to get the WMD's device
+ * context handle. */
+ status = (pDevObject->intfFxns.pfnDevCreate)
+ (&pDevObject->hWmdContext, pDevObject,
+ pHostConfig, pDspConfig);
+ /* Assert WMD_DEV_Create()'s ensure clause: */
+ DBC_Assert(DSP_FAILED(status) || (pDevObject->
+ hWmdContext != NULL));
+ } else {
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_Create: Out Of Memory");
+ status = DSP_EMEMORY;
+ }
+ }
+ /* Attempt to create the COD manager for this device: */
+ if (DSP_SUCCEEDED(status))
+ status = InitCodMgr(pDevObject);
+
+ /* Attempt to create the channel manager for this device: */
+ if (DSP_SUCCEEDED(status)) {
+ mgrAttrs.cChannels = CHNL_MAXCHANNELS;
+ ioMgrAttrs.bIRQ = pHostConfig->bIRQRegisters;
+ ioMgrAttrs.fShared = (pHostConfig->bIRQAttrib & CFG_IRQSHARED);
+ ioMgrAttrs.uWordSize = pDspConfig->uWordSize;
+ mgrAttrs.uWordSize = pDspConfig->uWordSize;
+ uNumWindows = pHostConfig->wNumMemWindows;
+ if (uNumWindows) {
+ /* Assume last memory window is for CHNL */
+ ioMgrAttrs.dwSMBase = pHostConfig->dwMemBase[1] +
+ pHostConfig->dwOffsetForMonitor;
+ ioMgrAttrs.uSMLength = pHostConfig->dwMemLength[1] -
+ pHostConfig->dwOffsetForMonitor;
+ } else {
+ ioMgrAttrs.dwSMBase = 0;
+ ioMgrAttrs.uSMLength = 0;
+ GT_0trace(debugMask, GT_7CLASS,
+ "**There is no memory reserved for "
+ "shared structures**\n");
+ }
+ status = CHNL_Create(&pDevObject->hChnlMgr, pDevObject,
+ &mgrAttrs);
+ if (status == DSP_ENOTIMPL) {
+ /* It's OK for a device not to have a channel
+ * manager: */
+ status = DSP_SOK;
+ }
+ /* Create CMM mgr even if Msg Mgr not impl. */
+ status = CMM_Create(&pDevObject->hCmmMgr,
+ (struct DEV_OBJECT *)pDevObject, NULL);
+ if (DSP_FAILED(status)) {
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_Create: Failed to Create SM "
+ "Manager\n");
+ }
+ /* Only create IO manager if we have a channel manager */
+ if (DSP_SUCCEEDED(status) && pDevObject->hChnlMgr) {
+ status = IO_Create(&pDevObject->hIOMgr, pDevObject,
+ &ioMgrAttrs);
+ }
+ /* Only create DEH manager if we have an IO manager */
+ if (DSP_SUCCEEDED(status)) {
+ /* Instantiate the DEH module */
+ status = (*pDevObject->intfFxns.pfnDehCreate)
+ (&pDevObject->hDehMgr, pDevObject);
+ }
+ /* Create DMM mgr . */
+ status = DMM_Create(&pDevObject->hDmmMgr,
+ (struct DEV_OBJECT *)pDevObject, NULL);
+ if (DSP_FAILED(status)) {
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_Create: Failed to Create DMM "
+ "Manager\n");
+ }
+ }
+ /* Add the new DEV_Object to the global list: */
+ if (DSP_SUCCEEDED(status)) {
+ LST_InitElem(&pDevObject->link);
+ status = DRV_InsertDevObject(hDrvObject, pDevObject);
+ }
+ /* Create the Processor List */
+ if (DSP_SUCCEEDED(status)) {
+ pDevObject->procList = LST_Create();
+ if (!(pDevObject->procList)) {
+ status = DSP_EFAIL;
+ GT_0trace(debugMask, GT_7CLASS, "DEV_Create: "
+ "Failed to Create Proc List");
+ }
+ }
+ /* If all went well, return a handle to the dev object;
+ * else, cleanup and return NULL in the OUT parameter. */
+ if (DSP_SUCCEEDED(status)) {
+ *phDevObject = pDevObject;
+ GT_1trace(debugMask, GT_1CLASS,
+ "DEV_CreateDevice Succeeded \nDevObject "
+ "0x%x\n", pDevObject);
+ } else {
+ if (pDevObject && pDevObject->procList)
+ LST_Delete(pDevObject->procList);
+
+ if (pDevObject && pDevObject->hCodMgr)
+ COD_Delete(pDevObject->hCodMgr);
+
+ if (pDevObject && pDevObject->hDmmMgr)
+ DMM_Destroy(pDevObject->hDmmMgr);
+
+ if (pDevObject)
+ MEM_FreeObject(pDevObject);
+
+ *phDevObject = NULL;
+ GT_0trace(debugMask, GT_7CLASS, "DEV_CreateDevice Failed\n");
+ }
+ GT_1trace(debugMask, GT_1CLASS, "Exiting DEV_Create: DevObject 0x%x\n",
+ *phDevObject);
+ DBC_Ensure((DSP_SUCCEEDED(status) && IsValidHandle(*phDevObject)) ||
+ (DSP_FAILED(status) && !*phDevObject));
+ return status;
+}
+
+/*
+ * ======== DEV_Create2 ========
+ * Purpose:
+ * After successful loading of the image from WCD_InitComplete2
+ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
+ * the Node Manager and updates the DEV Object.
+ */
+DSP_STATUS DEV_Create2(struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(hDevObject));
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Entered DEV_Create2, hDevObject: 0x%x\n", hDevObject);
+ /* There can be only one Node Manager per DEV object */
+ DBC_Assert(!pDevObject->hNodeMgr);
+ status = NODE_CreateMgr(&pDevObject->hNodeMgr, hDevObject);
+ if (DSP_FAILED(status)) {
+ GT_1trace(debugMask, GT_7CLASS,
+ "DEV_Create2: NODE_CreateMgr failed, "
+ "0x%x!\n", status);
+ pDevObject->hNodeMgr = NULL;
+ GT_0trace(debugMask, GT_7CLASS, "DEV_Create2: Failed!!\n");
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr != NULL)
+ || (DSP_FAILED(status) && pDevObject->hNodeMgr == NULL));
+ GT_2trace(debugMask, GT_ENTER,
+ "Exiting DEV_Create2, hNodeMgr: 0x%x, status:"
+ " 0x%x\n", pDevObject->hNodeMgr, status);
+ return status;
+}
+
+/*
+ * ======== DEV_Destroy2 ========
+ * Purpose:
+ * Destroys the Node manager for this device.
+ */
+DSP_STATUS DEV_Destroy2(struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(hDevObject));
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Entered DEV_Destroy2, hDevObject: 0x%x\n",
+ hDevObject);
+ if (pDevObject->hNodeMgr) {
+ if (DSP_FAILED(NODE_DeleteMgr(pDevObject->hNodeMgr)))
+ status = DSP_EFAIL;
+ else
+ pDevObject->hNodeMgr = NULL;
+
+ }
+ if (DSP_FAILED(status))
+ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy2 failed!!\n");
+
+ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr == NULL) ||
+ DSP_FAILED(status));
+ GT_2trace(debugMask, GT_ENTER,
+ "Exiting DEV_Destroy2, hNodeMgr: 0x%x, status"
+ " = 0x%x\n", pDevObject->hNodeMgr, status);
+ return status;
+}
+
+/*
+ * ======== DEV_DestroyDevice ========
+ * Purpose:
+ * Destroys the channel manager for this device, if any, calls
+ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
+ */
+DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(debugMask, GT_ENTER, "Entered DEV_DestroyDevice, hDevObject: "
+ "0x%x\n", hDevObject);
+ if (IsValidHandle(hDevObject)) {
+ if (pDevObject->hCodMgr)
+ COD_Delete(pDevObject->hCodMgr);
+
+ if (pDevObject->hNodeMgr)
+ NODE_DeleteMgr(pDevObject->hNodeMgr);
+
+ /* Free the io, channel, and message managers for this board: */
+ if (pDevObject->hIOMgr) {
+ IO_Destroy(pDevObject->hIOMgr);
+ pDevObject->hIOMgr = NULL;
+ }
+ if (pDevObject->hChnlMgr) {
+ CHNL_Destroy(pDevObject->hChnlMgr);
+ pDevObject->hChnlMgr = NULL;
+ }
+ if (pDevObject->hMsgMgr)
+ MSG_Delete(pDevObject->hMsgMgr);
+
+ if (pDevObject->hDehMgr) {
+ /* Uninitialize DEH module. */
+ (*pDevObject->intfFxns.pfnDehDestroy)
+ (pDevObject->hDehMgr);
+ }
+ if (pDevObject->hCmmMgr)
+ CMM_Destroy(pDevObject->hCmmMgr, true);
+
+ if (pDevObject->hDmmMgr)
+ DMM_Destroy(pDevObject->hDmmMgr);
+
+ /* Call the driver's WMD_DEV_Destroy() function: */
+ /* Require of DevDestroy */
+ DBC_Assert(pDevObject->hWmdContext != NULL);
+ status = (*pDevObject->intfFxns.pfnDevDestroy)
+ (pDevObject->hWmdContext);
+ if (DSP_SUCCEEDED(status)) {
+ if (pDevObject->procList)
+ LST_Delete(pDevObject->procList);
+
+ /* Remove this DEV_Object from the global list: */
+ DRV_RemoveDevObject(pDevObject->hDrvObject, pDevObject);
+ /* Free The library * LDR_FreeModule
+ * (pDevObject->hModule);*/
+ /* Free this dev object: */
+ MEM_FreeObject(pDevObject);
+ }
+ } else {
+ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy: Invlaid handle");
+ status = DSP_EHANDLE;
+ }
+ GT_1trace(debugMask, GT_ENTER, "Exit DEV_destroy: status 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== DEV_GetChnlMgr ========
+ * Purpose:
+ * Retrieve the handle to the channel manager handle created for this
+ * device.
+ */
+DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct CHNL_MGR **phMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMgr != NULL);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetChnlMgr, hDevObject: 0x%x\n\t"
+ "\tphMgr: 0x%x\n", hDevObject, phMgr);
+ if (IsValidHandle(hDevObject)) {
+ *phMgr = pDevObject->hChnlMgr;
+ } else {
+ *phMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetChnlMgr: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetChnlMgr: status 0x%x\t\n hMgr: "
+ "0x%x\n", status, *phMgr);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
+ (*phMgr == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_GetCmmMgr ========
+ * Purpose:
+ * Retrieve the handle to the shared memory manager created for this
+ * device.
+ */
+DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct CMM_OBJECT **phMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMgr != NULL);
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetCmmMgr, hDevObject: 0x%x\n\t"
+ "\tphMgr: 0x%x\n", hDevObject, phMgr);
+ if (IsValidHandle(hDevObject)) {
+ *phMgr = pDevObject->hCmmMgr;
+ } else {
+ *phMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetCmmMgr: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetCmmMgr: status 0x%x\t\nhMgr: "
+ "0x%x\n", status, *phMgr);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
+ (*phMgr == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_GetDmmMgr ========
+ * Purpose:
+ * Retrieve the handle to the dynamic memory manager created for this
+ * device.
+ */
+DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct DMM_OBJECT **phMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMgr != NULL);
+
+ GT_2trace(debugMask, GT_ENTER, "Entered DEV_GetDmmMgr, hDevObject: "
+ "0x%x\n\t\tphMgr: 0x%x\n", hDevObject, phMgr);
+ if (IsValidHandle(hDevObject)) {
+ *phMgr = pDevObject->hDmmMgr;
+ } else {
+ *phMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetDmmMgr: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetDmmMgr: status 0x%x\t\n hMgr: "
+ "0x%x\n", status, *phMgr);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
+ (*phMgr == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_GetCodMgr ========
+ * Purpose:
+ * Retrieve the COD manager create for this device.
+ */
+DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct COD_MANAGER **phCodMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phCodMgr != NULL);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetCodMgr, hDevObject: 0x%x\n\t\t"
+ "phCodMgr: 0x%x\n", hDevObject, phCodMgr);
+ if (IsValidHandle(hDevObject)) {
+ *phCodMgr = pDevObject->hCodMgr;
+ } else {
+ *phCodMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_1trace(debugMask, GT_7CLASS,
+ "DEV_GetCodMgr, invalid handle: 0x%x\n",
+ hDevObject);
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetCodMgr: status 0x%x\t\n hCodMgr:"
+ " 0x%x\n", status, *phCodMgr);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phCodMgr != NULL) &&
+ (*phCodMgr == NULL)));
+ return status;
+}
+
+/*
+ * ========= DEV_GetDehMgr ========
+ */
+DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct DEH_MGR **phDehMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDehMgr != NULL);
+ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
+ if (IsValidHandle(hDevObject)) {
+ *phDehMgr = hDevObject->hDehMgr;
+ } else {
+ *phDehMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetDehMgr: Invalid handle");
+ }
+ return status;
+}
+
+/*
+ * ======== DEV_GetDevNode ========
+ * Purpose:
+ * Retrieve the platform specific device ID for this device.
+ */
+DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
+ OUT struct CFG_DEVNODE **phDevNode)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDevNode != NULL);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetDevNode, hDevObject: 0x%x\n\t"
+ "\tphDevNode: 0x%x\n", hDevObject, phDevNode);
+ if (IsValidHandle(hDevObject)) {
+ *phDevNode = pDevObject->hDevNode;
+ } else {
+ *phDevNode = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetDevNode: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetDevNode: status 0x%x\t\nhDevNode:"
+ "0x%x\n", status, *phDevNode);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phDevNode != NULL) &&
+ (*phDevNode == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_GetFirst ========
+ * Purpose:
+ * Retrieve the first Device Object handle from an internal linked list
+ * DEV_OBJECTs maintained by DEV.
+ */
+struct DEV_OBJECT *DEV_GetFirst(void)
+{
+ struct DEV_OBJECT *pDevObject = NULL;
+
+ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+
+ DBC_Ensure((pDevObject == NULL) || IsValidHandle(pDevObject));
+
+ return pDevObject;
+}
+
+/*
+ * ======== DEV_GetIntfFxns ========
+ * Purpose:
+ * Retrieve the WMD interface function structure for the loaded WMD.
+ * ppIntfFxns != NULL.
+ */
+DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
+ OUT struct WMD_DRV_INTERFACE **ppIntfFxns)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(ppIntfFxns != NULL);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetIntfFxns, hDevObject: 0x%x\n\t"
+ "\tppIntfFxns: 0x%x\n", hDevObject, ppIntfFxns);
+ if (IsValidHandle(hDevObject)) {
+ *ppIntfFxns = &pDevObject->intfFxns;
+ } else {
+ *ppIntfFxns = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetIntDxns: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetIntFxns: status 0x%x\t\n"
+ "ppIntFxns: 0x%x\n", status, *ppIntfFxns);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((ppIntfFxns != NULL) &&
+ (*ppIntfFxns == NULL)));
+ return status;
+}
+
+/*
+ * ========= DEV_GetIOMgr ========
+ */
+DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct IO_MGR **phIOMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phIOMgr != NULL);
+ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
+
+ if (IsValidHandle(hDevObject)) {
+ *phIOMgr = hDevObject->hIOMgr;
+ } else {
+ *phIOMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS, "DEV_GetIOMgr: Invalid handle");
+ }
+
+ return status;
+}
+
+/*
+ * ======== DEV_GetNext ========
+ * Purpose:
+ * Retrieve the next Device Object handle from an internal linked list
+ * of DEV_OBJECTs maintained by DEV, after having previously called
+ * DEV_GetFirst() and zero or more DEV_GetNext
+ */
+struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT *hDevObject)
+{
+ struct DEV_OBJECT *pNextDevObject = NULL;
+
+ if (IsValidHandle(hDevObject)) {
+ pNextDevObject = (struct DEV_OBJECT *)
+ DRV_GetNextDevObject((u32)hDevObject);
+ }
+ DBC_Ensure((pNextDevObject == NULL) || IsValidHandle(pNextDevObject));
+ return pNextDevObject;
+}
+
+/*
+ * ========= DEV_GetMsgMgr ========
+ */
+void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
+ OUT struct MSG_MGR **phMsgMgr)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMsgMgr != NULL);
+ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
+
+ *phMsgMgr = hDevObject->hMsgMgr;
+}
+
+/*
+ * ======== DEV_GetNodeManager ========
+ * Purpose:
+ * Retrieve the Node Manager Handle
+ */
+DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT *hDevObject,
+ OUT struct NODE_MGR **phNodeMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phNodeMgr != NULL);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetNodeManager, hDevObject: 0x%x"
+ "\n\t\tphNodeMgr: 0x%x\n", hDevObject, phNodeMgr);
+ if (IsValidHandle(hDevObject)) {
+ *phNodeMgr = pDevObject->hNodeMgr;
+ } else {
+ *phNodeMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_1trace(debugMask, GT_7CLASS,
+ "DEV_GetNodeManager, invalid handle: 0x"
+ "%x\n", hDevObject);
+ }
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetNodeManager: status 0x%x\t\nhMgr:"
+ " 0x%x\n", status, *phNodeMgr);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNodeMgr != NULL) &&
+ (*phNodeMgr == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_GetSymbol ========
+ */
+DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
+ IN CONST char *pstrSym, OUT u32 *pulValue)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct COD_MANAGER *hCodMgr;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pstrSym != NULL && pulValue != NULL);
+
+ GT_3trace(debugMask, GT_ENTER,
+ "Entered DEV_GetSymbol, hDevObject: 0x%x\n\t\t"
+ "pstrSym: 0x%x\n\t\tpulValue: 0x%x\n", hDevObject, pstrSym,
+ pulValue);
+ if (IsValidHandle(hDevObject)) {
+ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(hCodMgr != NULL);
+ status = COD_GetSymValue(hCodMgr, (char *)pstrSym,
+ pulValue);
+ }
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetSymbol: Invalid handle");
+ }
+ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetSymbol: status 0x%x\t\n"
+ "hWmdContext: 0x%x\n", status, *pulValue);
+ return status;
+}
+
+/*
+ * ======== DEV_GetWMDContext ========
+ * Purpose:
+ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
+ */
+DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
+ OUT struct WMD_DEV_CONTEXT **phWmdContext)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phWmdContext != NULL);
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_GetWMDContext, hDevObject: 0x%x\n"
+ "\t\tphWmdContext: 0x%x\n", hDevObject, phWmdContext);
+ if (IsValidHandle(hDevObject)) {
+ *phWmdContext = pDevObject->hWmdContext;
+ } else {
+ *phWmdContext = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_GetWMDContext: Invalid handle");
+ }
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Exit DEV_GetWMDContext: status 0x%x\t\n"
+ "hWmdContext: 0x%x\n", status, *phWmdContext);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phWmdContext != NULL) &&
+ (*phWmdContext == NULL)));
+ return status;
+}
+
+/*
+ * ======== DEV_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ */
+void DEV_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ if (cRefs == 0) {
+ CMM_Exit();
+ DMM_Exit();
+ }
+
+ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Exit, ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== DEV_Init ========
+ * Purpose:
+ * Initialize DEV's private state, keeping a reference count on each call.
+ */
+bool DEV_Init(void)
+{
+ bool fCmm, fDmm, fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ /* Set the Trace mask */
+ DBC_Assert(!debugMask.flags);
+ GT_create(&debugMask, "DV"); /* "DV" for DeVice */
+ fCmm = CMM_Init();
+ fDmm = DMM_Init();
+
+ fRetval = fCmm && fDmm;
+
+ if (!fRetval) {
+ if (fCmm)
+ CMM_Exit();
+
+
+ if (fDmm)
+ DMM_Exit();
+
+ }
+ }
+
+ if (fRetval)
+ cRefs++;
+
+
+ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Init, ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+/*
+ * ======== DEV_NotifyClients ========
+ * Purpose:
+ * Notify all clients of this device of a change in device status.
+ */
+DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject, u32 ulStatus)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ struct DEV_OBJECT *pDevObject = hDevObject;
+ DSP_HPROCESSOR hProcObject;
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_NotifyClients, hDevObject: 0x%x\n"
+ "\t\tulStatus: 0x%x\n", hDevObject, ulStatus);
+ for (hProcObject = (DSP_HPROCESSOR)LST_First(pDevObject->procList);
+ hProcObject != NULL;
+ hProcObject = (DSP_HPROCESSOR)LST_Next(pDevObject->procList,
+ (struct LST_ELEM *)hProcObject))
+ PROC_NotifyClients(hProcObject, (u32) ulStatus);
+
+ return status;
+}
+
+/*
+ * ======== DEV_RemoveDevice ========
+ */
+DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode)
+{
+ struct DEV_OBJECT *hDevObject; /* handle to device object */
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject;
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Entered DEV_RemoveDevice, hDevNode: 0x%x\n", hDevNode);
+ /* Retrieve the device object handle originaly stored with
+ * the DevNode: */
+ status = CFG_GetDevObject(hDevNode, (u32 *)&hDevObject);
+ if (DSP_SUCCEEDED(status)) {
+ /* Remove the Processor List */
+ pDevObject = (struct DEV_OBJECT *)hDevObject;
+ /* Destroy the device object. */
+ status = DEV_DestroyDevice(hDevObject);
+ if (DSP_SUCCEEDED(status)) {
+ /* Null out the handle stored with the DevNode. */
+ GT_0trace(debugMask, GT_1CLASS,
+ "DEV_RemoveDevice, success");
+ }
+ }
+ GT_1trace(debugMask, GT_ENTER, "Exit DEV_RemoveDevice, status: 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== DEV_SetChnlMgr ========
+ * Purpose:
+ * Set the channel manager for this device.
+ */
+DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject, struct CHNL_MGR *hMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = hDevObject;
+
+ DBC_Require(cRefs > 0);
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_SetChnlMgr, hDevObject: 0x%x\n\t"
+ "\thMgr:0x%x\n", hDevObject, hMgr);
+ if (IsValidHandle(hDevObject)) {
+ pDevObject->hChnlMgr = hMgr;
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(debugMask, GT_7CLASS,
+ "DEV_SetChnlMgr, Invalid handle\n");
+ }
+ DBC_Ensure(DSP_FAILED(status) || (pDevObject->hChnlMgr == hMgr));
+ return status;
+}
+
+/*
+ * ======== DEV_SetMsgMgr ========
+ * Purpose:
+ * Set the message manager for this device.
+ */
+void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject, struct MSG_MGR *hMgr)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(hDevObject));
+ GT_2trace(debugMask, GT_ENTER,
+ "Entered DEV_SetMsgMgr, hDevObject: 0x%x\n\t\t"
+ "hMgr: 0x%x\n", hDevObject, hMgr);
+ hDevObject->hMsgMgr = hMgr;
+}
+
+/*
+ * ======== DEV_StartDevice ========
+ * Purpose:
+ * Initializes the new device with the BRIDGE environment.
+ */
+DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode)
+{
+ struct DEV_OBJECT *hDevObject = NULL; /* handle to 'Bridge Device */
+ struct CFG_HOSTRES hostRes; /* resources struct. */
+ struct CFG_DSPRES dspRes; /* DSP resources struct */
+ char szWMDFileName[CFG_MAXSEARCHPATHLEN] = "UMA"; /* wmd filename */
+ DSP_STATUS status;
+ struct MGR_OBJECT *hMgrObject = NULL;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Entered DEV_StartDevice, hDevObject: 0x%x\n", hDevNode);
+ status = CFG_GetHostResources(hDevNode, &hostRes);
+ if (DSP_SUCCEEDED(status)) {
+ /* Get DSP resources of device from Registry: */
+ status = CFG_GetDSPResources(hDevNode, &dspRes);
+ if (DSP_FAILED(status)) {
+ GT_1trace(debugMask, GT_7CLASS,
+ "Failed to get WMD DSP resources"
+ " from registry: 0x%x ", status);
+ }
+ } else {
+ GT_1trace(debugMask, GT_7CLASS,
+ "Failed to get WMD Host resources "
+ "from registry: 0x%x ", status);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Given all resources, create a device object. */
+ status = DEV_CreateDevice(&hDevObject, szWMDFileName, &hostRes,
+ &dspRes, hDevNode);
+ if (DSP_SUCCEEDED(status)) {
+ /* Store away the hDevObject with the DEVNODE */
+ status = CFG_SetDevObject(hDevNode, (u32)hDevObject);
+ if (DSP_FAILED(status)) {
+ /* Clean up */
+ GT_1trace(debugMask, GT_7CLASS,
+ "Failed to set DevObject in the "
+ "Registry: 0x%x", status);
+ DEV_DestroyDevice(hDevObject);
+ hDevObject = NULL;
+ }
+ } else {
+ GT_1trace(debugMask, GT_7CLASS,
+ "Failed to Create Device: 0x%x",
+ status);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Create the Manager Object */
+ status = MGR_Create(&hMgrObject, hDevNode);
+ }
+ if (DSP_FAILED(status)) {
+ GT_1trace(debugMask, GT_7CLASS, "Failed to MGR object: 0x%x",
+ status);
+ status = DSP_EFAIL;
+ }
+ if (DSP_FAILED(status)) {
+ if (hDevObject)
+ DEV_DestroyDevice(hDevObject);
+
+ /* Ensure the device extension is NULL */
+ CFG_SetDevObject(hDevNode, 0L);
+ }
+ GT_1trace(debugMask, GT_ENTER, "Exiting DEV_StartDevice status 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== FxnNotImplemented ========
+ * Purpose:
+ * Takes the place of a WMD Null Function.
+ * Parameters:
+ * Multiple, optional.
+ * Returns:
+ * DSP_ENOTIMPL: Always.
+ */
+static DSP_STATUS FxnNotImplemented(int arg, ...)
+{
+ DBG_Trace(DBG_LEVEL1,
+ "WARNING: Calling a non-implemented WMD function.\n");
+
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== IsValidHandle ========
+ * Purpose:
+ * Validate the device object handle.
+ * Parameters:
+ * hDevObject: Handle to device object created with
+ * DEV_CreateDevice().
+ * Returns:
+ * true if handle is valid; false otherwise.
+ * Requires:
+ * Ensures:
+ */
+static bool IsValidHandle(struct DEV_OBJECT *hObj)
+{
+ bool retVal;
+
+ retVal = (hObj != NULL) && (hObj->dwSignature == SIGNATURE);
+
+ return retVal;
+}
+
+/*
+ * ======== InitCodMgr ========
+ * Purpose:
+ * Create a COD manager for this device.
+ * Parameters:
+ * pDevObject: Pointer to device object created with
+ * DEV_CreateDevice()
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EHANDLE: Invalid hDevObject.
+ * Requires:
+ * Should only be called once by DEV_CreateDevice() for a given DevObject.
+ * Ensures:
+ */
+static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ char *szDummyFile = "dummy";
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(!IsValidHandle(pDevObject) ||
+ (pDevObject->hCodMgr == NULL));
+ GT_1trace(debugMask, GT_ENTER, "Entering InitCodMgr pDevObject: 0x%x",
+ pDevObject);
+ status = COD_Create(&pDevObject->hCodMgr, szDummyFile, NULL);
+ GT_1trace(debugMask, GT_ENTER, "Exiting InitCodMgr status 0x%x\n ",
+ status);
+ return status;
+}
+
+/*
+ * ======== DEV_InsertProcObject ========
+ * Purpose:
+ * Insert a ProcObject into the list maintained by DEV.
+ * Parameters:
+ * pProcObject: Ptr to ProcObject to insert.
+ * pDevObject: Ptr to Dev Object where the list is.
+ * pbAlreadyAttached: Ptr to return the bool
+ * Returns:
+ * DSP_SOK: If successful.
+ * Requires:
+ * List Exists
+ * hDevObject is Valid handle
+ * DEV Initialized
+ * pbAlreadyAttached != NULL
+ * hProcObject != 0
+ * Ensures:
+ * DSP_SOK and List is not Empty.
+ */
+DSP_STATUS DEV_InsertProcObject(struct DEV_OBJECT *hDevObject,
+ u32 hProcObject,
+ OUT bool *pbAlreadyAttached)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
+
+ GT_2trace(debugMask, GT_ENTER,
+ "Entering DEV_InsetProcObject pProcObject 0x%x"
+ "pDevObject 0x%x\n", hProcObject, hDevObject);
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(pDevObject));
+ DBC_Require(hProcObject != 0);
+ DBC_Require(pDevObject->procList != NULL);
+ DBC_Require(pbAlreadyAttached != NULL);
+ if (!LST_IsEmpty(pDevObject->procList))
+ *pbAlreadyAttached = true;
+
+ /* Add DevObject to tail. */
+ LST_PutTail(pDevObject->procList, (struct LST_ELEM *)hProcObject);
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Exiting DEV_InsetProcObject status 0x%x\n", status);
+ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDevObject->procList));
+
+ return status;
+}
+
+/*
+ * ======== DEV_RemoveProcObject ========
+ * Purpose:
+ * Search for and remove a Proc object from the given list maintained
+ * by the DEV
+ * Parameters:
+ * pProcObject: Ptr to ProcObject to insert.
+ * pDevObject Ptr to Dev Object where the list is.
+ * Returns:
+ * DSP_SOK: If successful.
+ * Requires:
+ * List exists and is not empty
+ * hProcObject != 0
+ * hDevObject is a valid Dev handle.
+ * Ensures:
+ * Details:
+ * List will be deleted when the DEV is destroyed.
+ */
+DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT *hDevObject,
+ u32 hProcObject)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct LST_ELEM *pCurElem;
+ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
+
+ DBC_Require(IsValidHandle(pDevObject));
+ DBC_Require(hProcObject != 0);
+ DBC_Require(pDevObject->procList != NULL);
+ DBC_Require(!LST_IsEmpty(pDevObject->procList));
+
+ GT_1trace(debugMask, GT_ENTER,
+ "Entering DEV_RemoveProcObject hDevObject "
+ "0x%x\n", hDevObject);
+ /* Search list for pDevObject: */
+ for (pCurElem = LST_First(pDevObject->procList); pCurElem != NULL;
+ pCurElem = LST_Next(pDevObject->procList, pCurElem)) {
+ /* If found, remove it. */
+ if ((u32)pCurElem == hProcObject) {
+ LST_RemoveElem(pDevObject->procList, pCurElem);
+ status = DSP_SOK;
+ break;
+ }
+ }
+ GT_1trace(debugMask, GT_ENTER, "DEV_RemoveProcObject returning 0x%x\n",
+ status);
+ return status;
+}
+
+DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject, u32 *devType)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hdevObject;
+
+ *devType = pDevObject->devType;
+
+ return status;
+}
+
+/*
+ * ======== StoreInterfaceFxns ========
+ * Purpose:
+ * Copy the WMD's interface functions into the device object,
+ * ensuring that FxnNotImplemented() is set for:
+ *
+ * 1. All WMD function pointers which are NULL; and
+ * 2. All function slots in the struct DEV_OBJECT structure which have no
+ * corresponding slots in the the WMD's interface, because the WMD
+ * is of an *older* version.
+ * Parameters:
+ * pIntfFxns: Interface Fxn Structure of the WCD's Dev Object.
+ * pDrvFxns: Interface Fxns offered by the WMD during DEV_Create().
+ * Returns:
+ * Requires:
+ * Input pointers are valid.
+ * WMD is *not* written for a newer WCD.
+ * Ensures:
+ * All function pointers in the dev object's Fxn interface are not NULL.
+ */
+static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
+ OUT struct WMD_DRV_INTERFACE *pIntfFxns)
+{
+ u32 dwWMDVersion;
+
+ /* Local helper macro: */
+#define StoreFxn(cast, pfn) \
+ (pIntfFxns->pfn = ((pDrvFxns->pfn != NULL) ? pDrvFxns->pfn : \
+ (cast)FxnNotImplemented))
+
+ DBC_Require(pIntfFxns != NULL);
+ DBC_Require(pDrvFxns != NULL);
+ DBC_Require(MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
+ pDrvFxns->dwWCDMinorVersion) <= WCDVERSION);
+ dwWMDVersion = MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
+ pDrvFxns->dwWCDMinorVersion);
+ pIntfFxns->dwWCDMajorVersion = pDrvFxns->dwWCDMajorVersion;
+ pIntfFxns->dwWCDMinorVersion = pDrvFxns->dwWCDMinorVersion;
+ /* Install functions up to WCD version .80 (first alpha): */
+ if (dwWMDVersion > 0) {
+ StoreFxn(WMD_DEV_CREATE, pfnDevCreate);
+ StoreFxn(WMD_DEV_DESTROY, pfnDevDestroy);
+ StoreFxn(WMD_DEV_CTRL, pfnDevCntrl);
+ StoreFxn(WMD_BRD_MONITOR, pfnBrdMonitor);
+ StoreFxn(WMD_BRD_START, pfnBrdStart);
+ StoreFxn(WMD_BRD_STOP, pfnBrdStop);
+ StoreFxn(WMD_BRD_STATUS, pfnBrdStatus);
+ StoreFxn(WMD_BRD_READ, pfnBrdRead);
+ StoreFxn(WMD_BRD_WRITE, pfnBrdWrite);
+ StoreFxn(WMD_BRD_SETSTATE, pfnBrdSetState);
+ StoreFxn(WMD_BRD_MEMCOPY, pfnBrdMemCopy);
+ StoreFxn(WMD_BRD_MEMWRITE, pfnBrdMemWrite);
+ StoreFxn(WMD_BRD_MEMMAP, pfnBrdMemMap);
+ StoreFxn(WMD_BRD_MEMUNMAP, pfnBrdMemUnMap);
+ StoreFxn(WMD_CHNL_CREATE, pfnChnlCreate);
+ StoreFxn(WMD_CHNL_DESTROY, pfnChnlDestroy);
+ StoreFxn(WMD_CHNL_OPEN, pfnChnlOpen);
+ StoreFxn(WMD_CHNL_CLOSE, pfnChnlClose);
+ StoreFxn(WMD_CHNL_ADDIOREQ, pfnChnlAddIOReq);
+ StoreFxn(WMD_CHNL_GETIOC, pfnChnlGetIOC);
+ StoreFxn(WMD_CHNL_CANCELIO, pfnChnlCancelIO);
+ StoreFxn(WMD_CHNL_FLUSHIO, pfnChnlFlushIO);
+ StoreFxn(WMD_CHNL_GETINFO, pfnChnlGetInfo);
+ StoreFxn(WMD_CHNL_GETMGRINFO, pfnChnlGetMgrInfo);
+ StoreFxn(WMD_CHNL_IDLE, pfnChnlIdle);
+ StoreFxn(WMD_CHNL_REGISTERNOTIFY, pfnChnlRegisterNotify);
+ StoreFxn(WMD_DEH_CREATE, pfnDehCreate);
+ StoreFxn(WMD_DEH_DESTROY, pfnDehDestroy);
+ StoreFxn(WMD_DEH_NOTIFY, pfnDehNotify);
+ StoreFxn(WMD_DEH_REGISTERNOTIFY, pfnDehRegisterNotify);
+ StoreFxn(WMD_DEH_GETINFO, pfnDehGetInfo);
+ StoreFxn(WMD_IO_CREATE, pfnIOCreate);
+ StoreFxn(WMD_IO_DESTROY, pfnIODestroy);
+ StoreFxn(WMD_IO_ONLOADED, pfnIOOnLoaded);
+ StoreFxn(WMD_IO_GETPROCLOAD, pfnIOGetProcLoad);
+ StoreFxn(WMD_MSG_CREATE, pfnMsgCreate);
+ StoreFxn(WMD_MSG_CREATEQUEUE, pfnMsgCreateQueue);
+ StoreFxn(WMD_MSG_DELETE, pfnMsgDelete);
+ StoreFxn(WMD_MSG_DELETEQUEUE, pfnMsgDeleteQueue);
+ StoreFxn(WMD_MSG_GET, pfnMsgGet);
+ StoreFxn(WMD_MSG_PUT, pfnMsgPut);
+ StoreFxn(WMD_MSG_REGISTERNOTIFY, pfnMsgRegisterNotify);
+ StoreFxn(WMD_MSG_SETQUEUEID, pfnMsgSetQueueId);
+ }
+ /* Add code for any additional functions in newer WMD versions here: */
+ /* Ensure postcondition: */
+ DBC_Ensure(pIntfFxns->pfnDevCreate != NULL);
+ DBC_Ensure(pIntfFxns->pfnDevDestroy != NULL);
+ DBC_Ensure(pIntfFxns->pfnDevCntrl != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdMonitor != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdStart != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdStop != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdStatus != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdRead != NULL);
+ DBC_Ensure(pIntfFxns->pfnBrdWrite != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlCreate != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlDestroy != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlOpen != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlClose != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlAddIOReq != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlGetIOC != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlCancelIO != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlFlushIO != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlGetInfo != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlGetMgrInfo != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlIdle != NULL);
+ DBC_Ensure(pIntfFxns->pfnChnlRegisterNotify != NULL);
+ DBC_Ensure(pIntfFxns->pfnDehCreate != NULL);
+ DBC_Ensure(pIntfFxns->pfnDehDestroy != NULL);
+ DBC_Ensure(pIntfFxns->pfnDehNotify != NULL);
+ DBC_Ensure(pIntfFxns->pfnDehRegisterNotify != NULL);
+ DBC_Ensure(pIntfFxns->pfnDehGetInfo != NULL);
+ DBC_Ensure(pIntfFxns->pfnIOCreate != NULL);
+ DBC_Ensure(pIntfFxns->pfnIODestroy != NULL);
+ DBC_Ensure(pIntfFxns->pfnIOOnLoaded != NULL);
+ DBC_Ensure(pIntfFxns->pfnIOGetProcLoad != NULL);
+ DBC_Ensure(pIntfFxns->pfnMsgSetQueueId != NULL);
+
+#undef StoreFxn
+}
+
diff --git a/drivers/dsp/bridge/pmgr/dmm.c b/drivers/dsp/bridge/pmgr/dmm.c
new file mode 100644
index 000000000000..803de93ef478
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/dmm.c
@@ -0,0 +1,692 @@
+/*
+ * dmm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== dmm.c ========
+ * Purpose:
+ * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
+ * space that can be directly mapped to any MPU buffer or memory region
+ *
+ * Public Functions:
+ * DMM_CreateTables
+ * DMM_Create
+ * DMM_Destroy
+ * DMM_Exit
+ * DMM_Init
+ * DMM_MapMemory
+ * DMM_Reset
+ * DMM_ReserveMemory
+ * DMM_UnMapMemory
+ * DMM_UnReserveMemory
+ *
+ * Private Functions:
+ * AddRegion
+ * CreateRegion
+ * GetRegion
+ * GetFreeRegion
+ * GetMappedRegion
+ *
+ * Notes:
+ * Region: Generic memory entitiy having a start address and a size
+ * Chunk: Reserved region
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 04-Jun-2008 Hari K : Optimized DMM implementation. Removed linked list
+ *! and instead used Table approach.
+ *! 19-Apr-2004 sb: Integrated Alan's code review updates.
+ *! 17-Mar-2004 ap: Fixed GetRegion for size=0 using tighter bound.
+ *! 20-Feb-2004 sb: Created.
+ *!
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/proc.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dmm.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+/* Object signatures */
+#define DMMSIGNATURE 0x004d4d44 /* "DMM" (in reverse) */
+
+#define DMM_ADDR_VIRTUAL(a) \
+ (((struct MapPage *)(a) - pVirtualMappingTable) * PG_SIZE_4K +\
+ dynMemMapBeg)
+#define DMM_ADDR_TO_INDEX(a) (((a) - dynMemMapBeg) / PG_SIZE_4K)
+
+/* DMM Mgr */
+struct DMM_OBJECT {
+ u32 dwSignature; /* Used for object validation */
+ /* Dmm Lock is used to serialize access mem manager for
+ * multi-threads. */
+ struct SYNC_CSOBJECT *hDmmLock; /* Lock to access dmm mgr */
+};
+
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask DMM_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+struct MapPage {
+ u32 RegionSize:15;
+ u32 MappedSize:15;
+ u32 bReserved:1;
+ u32 bMapped:1;
+};
+
+/* Create the free list */
+static struct MapPage *pVirtualMappingTable;
+static u32 iFreeRegion; /* The index of free region */
+static u32 iFreeSize;
+static u32 *pPhysicalAddrTable; /* Physical address of MPU buffer */
+static u32 dynMemMapBeg; /* The Beginning of dynamic memory mapping */
+static u32 TableSize;/* The size of virtual and physical pages tables */
+
+/* ----------------------------------- Function Prototypes */
+static struct MapPage *GetRegion(u32 addr);
+static struct MapPage *GetFreeRegion(u32 aSize);
+static struct MapPage *GetMappedRegion(u32 aAddr);
+#ifdef DSP_DMM_DEBUG
+u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
+#endif
+
+/* ======== DMM_CreateTables ========
+ * Purpose:
+ * Create table to hold the information of physical address
+ * the buffer pages that is passed by the user, and the table
+ * to hold the information of the virtual memory that is reserved
+ * for DSP.
+ */
+DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_CreateTables () hDmmMgr %x, addr"
+ " %x, size %x\n", hDmmMgr, addr, size);
+ status = DMM_DeleteTables(pDmmObj);
+ if (DSP_SUCCEEDED(status)) {
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+ dynMemMapBeg = addr;
+ TableSize = (size/PG_SIZE_4K) + 1;
+ /* Create the free list */
+ pVirtualMappingTable = (struct MapPage *) MEM_Calloc
+ (TableSize*sizeof(struct MapPage), MEM_NONPAGED);
+ if (pVirtualMappingTable == NULL)
+ status = DSP_EMEMORY;
+ else {
+ /* This table will be used
+ * to store the virtual to physical
+ * address translations
+ */
+ pPhysicalAddrTable = (u32 *)MEM_Calloc
+ (TableSize*sizeof(u32), MEM_NONPAGED);
+ GT_1trace(DMM_debugMask, GT_4CLASS,
+ "DMM_CreateTables: Allocate"
+ "memory for pPhysicalAddrTable=%d entries\n",
+ TableSize);
+ if (pPhysicalAddrTable == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(DMM_debugMask, GT_7CLASS,
+ "DMM_CreateTables: Memory allocation for "
+ "pPhysicalAddrTable failed\n");
+ } else {
+ /* On successful allocation,
+ * all entries are zero ('free') */
+ iFreeRegion = 0;
+ iFreeSize = TableSize*PG_SIZE_4K;
+ pVirtualMappingTable[0].RegionSize = TableSize;
+ }
+ }
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ } else
+ GT_0trace(DMM_debugMask, GT_7CLASS,
+ "DMM_CreateTables: DMM_DeleteTables"
+ "Failure\n");
+
+ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status"
+ "0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== DMM_Create ========
+ * Purpose:
+ * Create a dynamic memory manager object.
+ */
+DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct DMM_MGRATTRS *pMgrAttrs)
+{
+ struct DMM_OBJECT *pDmmObject = NULL;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDmmMgr != NULL);
+
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "DMM_Create: phDmmMgr: 0x%x hDevObject: "
+ "0x%x pMgrAttrs: 0x%x\n", phDmmMgr, hDevObject, pMgrAttrs);
+ *phDmmMgr = NULL;
+ /* create, zero, and tag a cmm mgr object */
+ MEM_AllocObject(pDmmObject, struct DMM_OBJECT, DMMSIGNATURE);
+ if (pDmmObject != NULL) {
+ status = SYNC_InitializeCS(&pDmmObject->hDmmLock);
+ if (DSP_SUCCEEDED(status))
+ *phDmmMgr = pDmmObject;
+ else
+ DMM_Destroy(pDmmObject);
+ } else {
+ GT_0trace(DMM_debugMask, GT_7CLASS,
+ "DMM_Create: Object Allocation "
+ "Failure(DMM Object)\n");
+ status = DSP_EMEMORY;
+ }
+ GT_2trace(DMM_debugMask, GT_4CLASS,
+ "Leaving DMM_Create status %x pDmmObject %x\n",
+ status, pDmmObject);
+
+ return status;
+}
+
+/*
+ * ======== DMM_Destroy ========
+ * Purpose:
+ * Release the communication memory manager resources.
+ */
+DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_1trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_Destroy () hDmmMgr %x\n", hDmmMgr);
+ DBC_Require(cRefs > 0);
+ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
+ status = DMM_DeleteTables(pDmmObj);
+ if (DSP_SUCCEEDED(status)) {
+ /* Delete CS & dmm mgr object */
+ SYNC_DeleteCS(pDmmObj->hDmmLock);
+ MEM_FreeObject(pDmmObj);
+ } else
+ GT_0trace(DMM_debugMask, GT_7CLASS,
+ "DMM_Destroy: DMM_DeleteTables "
+ "Failure\n");
+ } else
+ status = DSP_EHANDLE;
+ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_Destroy status %x\n",
+ status);
+ return status;
+}
+
+
+/*
+ * ======== DMM_DeleteTables ========
+ * Purpose:
+ * Delete DMM Tables.
+ */
+DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_1trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_DeleteTables () hDmmMgr %x\n", hDmmMgr);
+ DBC_Require(cRefs > 0);
+ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
+ /* Delete all DMM tables */
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+
+ if (pVirtualMappingTable != NULL)
+ MEM_Free(pVirtualMappingTable);
+
+ if (pPhysicalAddrTable != NULL)
+ MEM_Free(pPhysicalAddrTable);
+
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ } else
+ status = DSP_EHANDLE;
+ GT_1trace(DMM_debugMask, GT_4CLASS,
+ "Leaving DMM_DeleteTables status %x\n", status);
+ return status;
+}
+
+
+
+
+/*
+ * ======== DMM_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ */
+void DMM_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(DMM_debugMask, GT_ENTER,
+ "exiting DMM_Exit, ref count:0x%x\n", cRefs);
+}
+
+/*
+ * ======== DMM_GetHandle ========
+ * Purpose:
+ * Return the dynamic memory manager object for this device.
+ * This is typically called from the client process.
+ */
+DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
+ OUT struct DMM_OBJECT **phDmmMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *hDevObject;
+
+ GT_2trace(DMM_debugMask, GT_ENTER,
+ "DMM_GetHandle: hProcessor %x, phDmmMgr"
+ "%x\n", hProcessor, phDmmMgr);
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDmmMgr != NULL);
+ if (hProcessor != NULL)
+ status = PROC_GetDevObject(hProcessor, &hDevObject);
+ else
+ hDevObject = DEV_GetFirst(); /* default */
+
+ if (DSP_SUCCEEDED(status))
+ status = DEV_GetDmmMgr(hDevObject, phDmmMgr);
+
+ GT_2trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_GetHandle status %x, "
+ "*phDmmMgr %x\n", status, phDmmMgr ? *phDmmMgr : NULL);
+ return status;
+}
+
+/*
+ * ======== DMM_Init ========
+ * Purpose:
+ * Initializes private state of DMM module.
+ */
+bool DMM_Init(void)
+{
+ bool fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ /* Set the Trace mask */
+ /*"DM" for Dymanic Memory Manager */
+ GT_create(&DMM_debugMask, "DM");
+ }
+
+ if (fRetval)
+ cRefs++;
+
+ GT_1trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_Init, ref count:0x%x\n", cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ pVirtualMappingTable = NULL ;
+ pPhysicalAddrTable = NULL ;
+ TableSize = 0;
+
+ return fRetval;
+}
+
+/*
+ * ======== DMM_MapMemory ========
+ * Purpose:
+ * Add a mapping block to the reserved chunk. DMM assumes that this block
+ * will be mapped in the DSP/IVA's address space. DMM returns an error if a
+ * mapping overlaps another one. This function stores the info that will be
+ * required later while unmapping the block.
+ */
+DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ struct MapPage *chunk;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_MapMemory () hDmmMgr %x, "
+ "addr %x, size %x\n", hDmmMgr, addr, size);
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+ /* Find the Reserved memory chunk containing the DSP block to
+ * be mapped */
+ chunk = (struct MapPage *)GetRegion(addr);
+ if (chunk != NULL) {
+ /* Mark the region 'mapped', leave the 'reserved' info as-is */
+ chunk->bMapped = true;
+ chunk->MappedSize = (size/PG_SIZE_4K);
+ } else
+ status = DSP_ENOTFOUND;
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ GT_2trace(DMM_debugMask, GT_4CLASS,
+ "Leaving DMM_MapMemory status %x, chunk %x\n",
+ status, chunk);
+ return status;
+}
+
+/*
+ * ======== DMM_ReserveMemory ========
+ * Purpose:
+ * Reserve a chunk of virtually contiguous DSP/IVA address space.
+ */
+DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
+ u32 *pRsvAddr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ struct MapPage *node;
+ u32 rsvAddr = 0;
+ u32 rsvSize = 0;
+
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_ReserveMemory () hDmmMgr %x, "
+ "size %x, pRsvAddr %x\n", hDmmMgr, size, pRsvAddr);
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+
+ /* Try to get a DSP chunk from the free list */
+ node = GetFreeRegion(size);
+ if (node != NULL) {
+ /* DSP chunk of given size is available. */
+ rsvAddr = DMM_ADDR_VIRTUAL(node);
+ /* Calculate the number entries to use */
+ rsvSize = size/PG_SIZE_4K;
+ if (rsvSize < node->RegionSize) {
+ /* Mark remainder of free region */
+ node[rsvSize].bMapped = false;
+ node[rsvSize].bReserved = false;
+ node[rsvSize].RegionSize = node->RegionSize - rsvSize;
+ node[rsvSize].MappedSize = 0;
+ }
+ /* GetRegion will return first fit chunk. But we only use what
+ is requested. */
+ node->bMapped = false;
+ node->bReserved = true;
+ node->RegionSize = rsvSize;
+ node->MappedSize = 0;
+ /* Return the chunk's starting address */
+ *pRsvAddr = rsvAddr;
+ } else
+ /*dSP chunk of given size is not available */
+ status = DSP_EMEMORY;
+
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ GT_3trace(DMM_debugMask, GT_4CLASS,
+ "Leaving ReserveMemory status %x, rsvAddr"
+ " %x, rsvSize %x\n", status, rsvAddr, rsvSize);
+ return status;
+}
+
+
+/*
+ * ======== DMM_UnMapMemory ========
+ * Purpose:
+ * Remove the mapped block from the reserved chunk.
+ */
+DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 *pSize)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ struct MapPage *chunk;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_UnMapMemory () hDmmMgr %x, "
+ "addr %x, pSize %x\n", hDmmMgr, addr, pSize);
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+ chunk = GetMappedRegion(addr) ;
+ if (chunk == NULL)
+ status = DSP_ENOTFOUND ;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Unmap the region */
+ *pSize = chunk->MappedSize * PG_SIZE_4K;
+ chunk->bMapped = false;
+ chunk->MappedSize = 0;
+ }
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ GT_3trace(DMM_debugMask, GT_ENTER,
+ "Leaving DMM_UnMapMemory status %x, chunk"
+ " %x, *pSize %x\n", status, chunk, *pSize);
+
+ return status;
+}
+
+/*
+ * ======== DMM_UnReserveMemory ========
+ * Purpose:
+ * Free a chunk of reserved DSP/IVA address space.
+ */
+DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 rsvAddr)
+{
+ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
+ struct MapPage *chunk;
+ u32 i;
+ DSP_STATUS status = DSP_SOK;
+ u32 chunkSize;
+
+ GT_2trace(DMM_debugMask, GT_ENTER,
+ "Entered DMM_UnReserveMemory () hDmmMgr "
+ "%x, rsvAddr %x\n", hDmmMgr, rsvAddr);
+
+ SYNC_EnterCS(pDmmObj->hDmmLock);
+
+ /* Find the chunk containing the reserved address */
+ chunk = GetMappedRegion(rsvAddr);
+ if (chunk == NULL)
+ status = DSP_ENOTFOUND;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Free all the mapped pages for this reserved region */
+ i = 0;
+ while (i < chunk->RegionSize) {
+ if (chunk[i].bMapped) {
+ /* Remove mapping from the page tables. */
+ chunkSize = chunk[i].MappedSize;
+ /* Clear the mapping flags */
+ chunk[i].bMapped = false;
+ chunk[i].MappedSize = 0;
+ i += chunkSize;
+ } else
+ i++;
+ }
+ /* Clear the flags (mark the region 'free') */
+ chunk->bReserved = false;
+ /* NOTE: We do NOT coalesce free regions here.
+ * Free regions are coalesced in GetRegion(), as it traverses
+ *the whole mapping table
+ */
+ }
+ SYNC_LeaveCS(pDmmObj->hDmmLock);
+ GT_2trace(DMM_debugMask, GT_ENTER,
+ "Leaving DMM_UnReserveMemory status %x"
+ " chunk %x\n", status, chunk);
+ return status;
+}
+
+
+/*
+ * ======== GetRegion ========
+ * Purpose:
+ * Returns a region containing the specified memory region
+ */
+static struct MapPage *GetRegion(u32 aAddr)
+{
+ struct MapPage *currRegion = NULL;
+ u32 i = 0;
+
+ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetRegion () "
+ " aAddr %x\n", aAddr);
+
+ if (pVirtualMappingTable != NULL) {
+ /* find page mapped by this address */
+ i = DMM_ADDR_TO_INDEX(aAddr);
+ if (i < TableSize)
+ currRegion = pVirtualMappingTable + i;
+ }
+ GT_3trace(DMM_debugMask, GT_4CLASS,
+ "Leaving GetRegion currRegion %x, iFreeRegion %d\n,"
+ "iFreeSize %d\n", currRegion, iFreeRegion, iFreeSize) ;
+ return currRegion;
+}
+
+/*
+ * ======== GetFreeRegion ========
+ * Purpose:
+ * Returns the requested free region
+ */
+static struct MapPage *GetFreeRegion(u32 aSize)
+{
+ struct MapPage *currRegion = NULL;
+ u32 i = 0;
+ u32 RegionSize = 0;
+ u32 nextI = 0;
+ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetFreeRegion () "
+ "aSize 0x%x\n", aSize);
+
+ if (pVirtualMappingTable == NULL)
+ return currRegion;
+ if (aSize > iFreeSize) {
+ /* Find the largest free region
+ * (coalesce during the traversal) */
+ while (i < TableSize) {
+ RegionSize = pVirtualMappingTable[i].RegionSize;
+ nextI = i+RegionSize;
+ if (pVirtualMappingTable[i].bReserved == false) {
+ /* Coalesce, if possible */
+ if (nextI < TableSize &&
+ pVirtualMappingTable[nextI].bReserved
+ == false) {
+ pVirtualMappingTable[i].RegionSize +=
+ pVirtualMappingTable[nextI].RegionSize;
+ continue;
+ }
+ RegionSize *= PG_SIZE_4K;
+ if (RegionSize > iFreeSize) {
+ iFreeRegion = i;
+ iFreeSize = RegionSize;
+ }
+ }
+ i = nextI;
+ }
+ }
+ if (aSize <= iFreeSize) {
+ currRegion = pVirtualMappingTable + iFreeRegion;
+ iFreeRegion += (aSize / PG_SIZE_4K);
+ iFreeSize -= aSize;
+ }
+ return currRegion;
+}
+
+/*
+ * ======== GetMappedRegion ========
+ * Purpose:
+ * Returns the requestedmapped region
+ */
+static struct MapPage *GetMappedRegion(u32 aAddr)
+{
+ u32 i = 0;
+ struct MapPage *currRegion = NULL;
+ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetMappedRegion () "
+ "aAddr 0x%x\n", aAddr);
+
+ if (pVirtualMappingTable == NULL)
+ return currRegion;
+
+ i = DMM_ADDR_TO_INDEX(aAddr);
+ if (i < TableSize && (pVirtualMappingTable[i].bMapped ||
+ pVirtualMappingTable[i].bReserved))
+ currRegion = pVirtualMappingTable + i;
+ return currRegion;
+}
+
+/*
+ * ======== DMM_GetPhysicalAddrTable ========
+ * Purpose:
+ * Returns the physical table address
+ */
+u32 *DMM_GetPhysicalAddrTable(void)
+{
+ GT_1trace(DMM_debugMask, GT_ENTER, "Entered "
+ "DMM_GetPhysicalAddrTable()- pPhysicalAddrTable 0x%x\n",
+ pPhysicalAddrTable);
+ return pPhysicalAddrTable;
+}
+
+#ifdef DSP_DMM_DEBUG
+u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr)
+{
+ struct MapPage *curNode = NULL;
+ u32 i;
+ u32 freemem = 0;
+ u32 bigsize = 0;
+
+ SYNC_EnterCS(hDmmMgr->hDmmLock);
+
+ if (pVirtualMappingTable != NULL) {
+ for (i = 0; i < TableSize; i +=
+ pVirtualMappingTable[i].RegionSize) {
+ curNode = pVirtualMappingTable + i;
+ if (curNode->bReserved == TRUE) {
+ /*printk("RESERVED size = 0x%x, "
+ "Map size = 0x%x\n",
+ (curNode->RegionSize * PG_SIZE_4K),
+ (curNode->bMapped == false) ? 0 :
+ (curNode->MappedSize * PG_SIZE_4K));
+*/
+ } else {
+/* printk("UNRESERVED size = 0x%x\n",
+ (curNode->RegionSize * PG_SIZE_4K));
+*/
+ freemem += (curNode->RegionSize * PG_SIZE_4K);
+ if (curNode->RegionSize > bigsize)
+ bigsize = curNode->RegionSize;
+ }
+ }
+ }
+ printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
+ freemem/(1024*1024));
+ printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
+ (((TableSize * PG_SIZE_4K)-freemem))/(1024*1024));
+ printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
+ (bigsize*PG_SIZE_4K/(1024*1024)));
+ SYNC_LeaveCS(hDmmMgr->hDmmLock);
+
+ return 0;
+}
+#endif
diff --git a/drivers/dsp/bridge/pmgr/io.c b/drivers/dsp/bridge/pmgr/io.c
new file mode 100644
index 000000000000..cdfe0dcb01b6
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/io.c
@@ -0,0 +1,205 @@
+/*
+ * io.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== io.c ========
+ * Description:
+ * IO manager interface: Manages IO between CHNL and MSG.
+ *
+ * Public Functions:
+ * IO_Create
+ * IO_Destroy
+ * IO_Exit
+ * IO_Init
+ * IO_OnLoaded
+ *
+ * Notes:
+ * This interface is basically a pass through to the WMD IO functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 04-Apr-2001 rr WSX_STATUS initialized in IO_Create.
+ *! 07-Nov-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- This */
+#include <ioobj.h>
+#include <dspbridge/iodefs.h>
+#include <dspbridge/io.h>
+
+/* ----------------------------------- Globals */
+static u32 cRefs;
+
+#if GT_TRACE
+static struct GT_Mask IO_DebugMask = { NULL, NULL }; /* WCD IO Mask */
+#endif
+
+/*
+ * ======== IO_Create ========
+ * Purpose:
+ * Create an IO manager object, responsible for managing IO between
+ * CHNL and MSG
+ */
+DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr, struct DEV_OBJECT *hDevObject,
+ IN CONST struct IO_ATTRS *pMgrAttrs)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct IO_MGR *hIOMgr = NULL;
+ struct IO_MGR_ *pIOMgr = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phIOMgr != NULL);
+ DBC_Require(pMgrAttrs != NULL);
+
+ GT_3trace(IO_DebugMask, GT_ENTER, "Entered IO_Create: phIOMgr: 0x%x\t "
+ "hDevObject: 0x%x\tpMgrAttrs: 0x%x\n",
+ phIOMgr, hDevObject, pMgrAttrs);
+
+ *phIOMgr = NULL;
+
+ /* A memory base of 0 implies no memory base: */
+ if ((pMgrAttrs->dwSMBase != 0) && (pMgrAttrs->uSMLength == 0)) {
+ status = CHNL_E_INVALIDMEMBASE;
+ GT_0trace(IO_DebugMask, GT_7CLASS,
+ "IO_Create:Invalid Mem Base\n");
+ }
+
+ if (pMgrAttrs->uWordSize == 0) {
+ status = CHNL_E_INVALIDWORDSIZE;
+ GT_0trace(IO_DebugMask, GT_7CLASS,
+ "IO_Create:Invalid Word size\n");
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+
+ /* Let WMD channel module finish the create: */
+ status = (*pIntfFxns->pfnIOCreate)(&hIOMgr, hDevObject,
+ pMgrAttrs);
+
+ if (DSP_SUCCEEDED(status)) {
+ pIOMgr = (struct IO_MGR_ *) hIOMgr;
+ pIOMgr->pIntfFxns = pIntfFxns;
+ pIOMgr->hDevObject = hDevObject;
+
+ /* Return the new channel manager handle: */
+ *phIOMgr = hIOMgr;
+ GT_1trace(IO_DebugMask, GT_1CLASS,
+ "IO_Create: Success hIOMgr: 0x%x\n",
+ hIOMgr);
+ }
+ }
+
+ GT_2trace(IO_DebugMask, GT_ENTER,
+ "Exiting IO_Create: hIOMgr: 0x%x, status:"
+ " 0x%x\n", hIOMgr, status);
+
+ return status;
+}
+
+/*
+ * ======== IO_Destroy ========
+ * Purpose:
+ * Delete IO manager.
+ */
+DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct IO_MGR_ *pIOMgr = (struct IO_MGR_ *)hIOMgr;
+ DSP_STATUS status;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(IO_DebugMask, GT_ENTER, "Entered IO_Destroy: hIOMgr: 0x%x\n",
+ hIOMgr);
+
+ pIntfFxns = pIOMgr->pIntfFxns;
+
+ /* Let WMD channel module destroy the IO_MGR: */
+ status = (*pIntfFxns->pfnIODestroy) (hIOMgr);
+
+ GT_2trace(IO_DebugMask, GT_ENTER,
+ "Exiting IO_Destroy: pIOMgr: 0x%x, status:"
+ " 0x%x\n", pIOMgr, status);
+ return status;
+}
+
+/*
+ * ======== IO_Exit ========
+ * Purpose:
+ * Discontinue usage of the IO module.
+ */
+void IO_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(IO_DebugMask, GT_5CLASS,
+ "Entered IO_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== IO_Init ========
+ * Purpose:
+ * Initialize the IO module's private state.
+ */
+bool IO_Init(void)
+{
+ bool fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!IO_DebugMask.flags);
+ GT_create(&IO_DebugMask, "IO"); /* "IO" for IO */
+ }
+
+ if (fRetval)
+ cRefs++;
+
+
+ GT_1trace(IO_DebugMask, GT_5CLASS,
+ "Entered IO_Init, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
diff --git a/drivers/dsp/bridge/pmgr/ioobj.h b/drivers/dsp/bridge/pmgr/ioobj.h
new file mode 100644
index 000000000000..f473a631b1ab
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/ioobj.h
@@ -0,0 +1,52 @@
+/*
+ * ioobj.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== ioobj.h ========
+ * Description:
+ * Structure subcomponents of channel class library IO objects which
+ * are exposed to class driver from mini-driver.
+ *
+ * Public Functions:
+ * None.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 01/16/97 gp: Created from chnlpriv.h
+ */
+
+#ifndef IOOBJ_
+#define IOOBJ_
+
+#include <dspbridge/devdefs.h>
+#include <dspbridge/wmd.h>
+
+/*
+ * This struct is the first field in a IO_MGR struct, as implemented in
+ * a WMD channel class library. Other, implementation specific fields
+ * follow this structure in memory.
+ */
+struct IO_MGR_ {
+ /* These must be the first fields in a IO_MGR struct: */
+ u32 dwSignature; /* Used for object validation. */
+ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
+ struct DEV_OBJECT *hDevObject; /* Device this board represents. */
+} ;
+
+#endif /* IOOBJ_ */
diff --git a/drivers/dsp/bridge/pmgr/msg.c b/drivers/dsp/bridge/pmgr/msg.c
new file mode 100644
index 000000000000..be4acdb55210
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/msg.c
@@ -0,0 +1,173 @@
+/*
+ * msg.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== msg.c ========
+ * Description:
+ * DSP/BIOS Bridge MSG Module.
+ *
+ * Public Functions:
+ * MSG_Create
+ * MSG_Delete
+ * MSG_Exit
+ * MSG_Init
+ *
+ *! Revision History:
+ *! =================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 15-May-2001 ag Changed SUCCEEDED to DSP_SUCCEEDED.
+ *! 16-Feb-2001 jeh Fixed some comments.
+ *! 15-Dec-2000 rr MSG_Create returns DSP_EFAIL if pfnMsgCreate fails.
+ *! 12-Sep-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- Mini Driver */
+#include <dspbridge/wmd.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- This */
+#include <msgobj.h>
+#include <dspbridge/msg.h>
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask MSG_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+static u32 cRefs; /* module reference count */
+
+/*
+ * ======== MSG_Create ========
+ * Purpose:
+ * Create an object to manage message queues. Only one of these objects
+ * can exist per device object.
+ */
+DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
+ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct MSG_MGR_ *pMsgMgr;
+ struct MSG_MGR *hMsgMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phMsgMgr != NULL);
+ DBC_Require(msgCallback != NULL);
+ DBC_Require(hDevObject != NULL);
+
+ GT_3trace(MSG_debugMask, GT_ENTER, "MSG_Create: phMsgMgr: 0x%x\t"
+ "hDevObject: 0x%x\tmsgCallback: 0x%x\n",
+ phMsgMgr, hDevObject, msgCallback);
+
+ *phMsgMgr = NULL;
+
+ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+
+ /* Let WMD message module finish the create: */
+ status = (*pIntfFxns->pfnMsgCreate)(&hMsgMgr, hDevObject, msgCallback);
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in WCD message module's fields of the MSG_MGR
+ * structure */
+ pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
+ pMsgMgr->pIntfFxns = pIntfFxns;
+
+ /* Finally, return the new message manager handle: */
+ *phMsgMgr = hMsgMgr;
+ GT_1trace(MSG_debugMask, GT_1CLASS,
+ "MSG_Create: Success pMsgMgr: 0x%x\n", pMsgMgr);
+ } else {
+ status = DSP_EFAIL;
+ }
+ return status;
+}
+
+/*
+ * ======== MSG_Delete ========
+ * Purpose:
+ * Delete a MSG manager allocated in MSG_Create().
+ */
+void MSG_Delete(struct MSG_MGR *hMsgMgr)
+{
+ struct MSG_MGR_ *pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
+
+ GT_1trace(MSG_debugMask, GT_ENTER, "MSG_Delete: hMsgMgr: 0x%x\n",
+ hMsgMgr);
+
+ pIntfFxns = pMsgMgr->pIntfFxns;
+
+ /* Let WMD message module destroy the MSG_MGR: */
+ (*pIntfFxns->pfnMsgDelete)(hMsgMgr);
+
+ DBC_Ensure(!MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
+}
+
+/*
+ * ======== MSG_Exit ========
+ */
+void MSG_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+ cRefs--;
+ GT_1trace(MSG_debugMask, GT_5CLASS,
+ "Entered MSG_Exit, ref count: 0x%x\n", cRefs);
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== MSG_Init ========
+ */
+bool MSG_Init(void)
+{
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!MSG_debugMask.flags);
+ GT_create(&MSG_debugMask, "MS"); /* "MS" for MSg */
+ }
+
+ cRefs++;
+
+ GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+
+ return true;
+}
+
diff --git a/drivers/dsp/bridge/pmgr/msgobj.h b/drivers/dsp/bridge/pmgr/msgobj.h
new file mode 100644
index 000000000000..63d025bf9e8f
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/msgobj.h
@@ -0,0 +1,52 @@
+/*
+ * msgobj.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== msgobj.h ========
+ * Description:
+ * Structure subcomponents of channel class library MSG objects which
+ * are exposed to class driver from mini-driver.
+ *
+ * Public Functions:
+ * None.
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 17-Nov-2000 jeh Created.
+ */
+
+#ifndef MSGOBJ_
+#define MSGOBJ_
+
+#include <dspbridge/wmd.h>
+
+#include <dspbridge/msgdefs.h>
+
+/*
+ * This struct is the first field in a MSG_MGR struct, as implemented in
+ * a WMD channel class library. Other, implementation specific fields
+ * follow this structure in memory.
+ */
+struct MSG_MGR_ {
+ /* The first two fields must match those in msgobj.h */
+ u32 dwSignature;
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
+};
+
+#endif /* MSGOBJ_ */
+
diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c
new file mode 100644
index 000000000000..08d0854908b7
--- /dev/null
+++ b/drivers/dsp/bridge/pmgr/wcd.c
@@ -0,0 +1,1651 @@
+/*
+ * wcd.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== wcd.c ========
+ * Description:
+ * Common WCD functions, also includes the wrapper
+ * functions called directly by the DeviceIOControl interface.
+ *
+ * Public Functions:
+ * WCD_CallDevIOCtl
+ * WCD_Init
+ * WCD_InitComplete2
+ * WCD_Exit
+ * <MOD>WRAP_*
+ *
+ *! Revision History:
+ *! ================
+ *! 29-Apr-2004 hp Call PROC_AutoStart only for DSP device
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
+ *! 03-Apr-2003 sb Process environment pointer in PROCWRAP_Load
+ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
+ *! 30-Jan-2002 ag CMMWRAP_AllocBuf name changed to CMMWRAP_CallocBuf
+ *! 15-Jan-2002 ag Added actual bufSize param to STRMWRAP_Reclaim[issue].
+ *! 14-Dec-2001 rr ARGS_NODE_CONNECT maps the pAttr.
+ *! 03-Oct-2001 rr ARGS_NODE_ALLOCMSGBUF/FREEMSGBUF maps the pAttr.
+ *! 10-Sep-2001 ag Added CMD_CMM_GETHANDLE.
+ *! 23-Apr-2001 jeh Pass pStatus to NODE_Terminate.
+ *! 11-Apr-2001 jeh STRMWRAP_Reclaim embedded pointer is mapped and unmapped.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 06-Dec-2000 jeh WRAP_MAP2CALLER pointers in RegisterNotify calls.
+ *! 05-Dec-2000 ag: Removed MAP2CALLER in NODEWRAP_FreeMsgBuf().
+ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data().
+ *! 20-Nov-2000 jeh Added MSG_Init()/MSG_Exit(), IO_Init()/IO_Exit().
+ *! WRAP pointers to handles for PROC_Attach, NODE_Allocate.
+ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
+ *! NODEWRAP_GetMessageStream.
+ *! 12-Oct-2000 ag: Added user CMM wrappers.
+ *! 05-Oct-2000 rr: WcdInitComplete2 will fail even if one BRD or PROC
+ *! AutoStart fails.
+ *! 25-Sep-2000 rr: Updated to Version 0.9
+ *! 13-Sep-2000 jeh Pass ARGS_NODE_CONNECT.pAttrs to NODE_Connect().
+ *! 11-Aug-2000 rr: Part of node enabled.
+ *! 31-Jul-2000 rr: UTIL_Wrap and MEM_Wrap added to RM.
+ *! 27-Jul-2000 rr: PROCWRAP, NODEWRAP and STRMWRAP implemented.
+ *! STRM and some NODE Wrappers are not implemented.
+ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
+ *! 08-Feb-2000 rr File name changed to wcd.c
+ *! 03-Feb-2000 rr: Module initialization are done by SERVICES init. GT Class
+ *! changes for module init/exit fxns.
+ *! 24-Jan-2000 rr: Merged with Scott's code.
+ *! 21-Jan-1999 sg: Changed ARGS_CHNL_GETMODE field name from pdwMode to pMode.
+ *! 17-Jan-2000 rr: BRD_GetStatus does WRAP_MAP2CALLER for state.
+ *! 14-Dec-1999 ag: Removed _MAP2CALLER in CHNL_GetMgr().
+ *! 13-Dec-1999 rr: BRDWRAP_GetSymbol, BRDWRAP_GetTrace uses WRAP_MAP2CALLER
+ *! macros.BRDWRAP_Load maps and unmaps embedded pointers.
+ *! 10-Dec-1999 ag: User CHNL bufs mapped in _AddIOReq & _GetIOCompletion.
+ *! 09-Dec-1999 rr: BRDWRAP_Open and CHNLWRAP_GetMgr does not map
+ *! pointer as there was a change in config.c
+ *! 06-Dec-1999 rr: BRD_Read and Write Maps the buf pointers.
+ *! 03-Dec-1999 rr: CHNLWRAP_GetMgr and BRDWRAP_Open maps hDevNode pointer.
+ *! WCD_InitComplete2 Included for BRD_AutoStart.
+ *! 16-Nov-1999 ag: Map buf to process in CHNLWRAP_AllocBuffer().
+ *! CHNL_GetMgr() Mapping Fix.
+ *! 10-Nov-1999 ag: Removed unnecessary calls to WRAP_MAP2CALLER.
+ *! 08-Nov-1999 kc: Added MEMRY & enabled BRD_IOCtl for tests.
+ *! 29-Oct-1999 ag: Added CHNL.
+ *! 29-Oct-1999 kc: Added trace statements; added ptr mapping; updated
+ *! use of UTIL module API.
+ *! 29-Oct-1999 rr: Wrapper functions does the Mapping of the Pointers.
+ *! in WinCE all the explicit pointers will be converted
+ *! by the OS during interprocess but not the embedded pointers.
+ *! 16-Oct-1999 kc: Code review cleanup.
+ *! 07-Oct-1999 kc: Added UTILWRAP_TestDll() to run PM test harness. See
+ *! /src/doc/pmtest.doc for more detail.
+ *! 09-Sep-1999 rr: After exactly two years(!). Adopted for WinCE. GT Enabled.
+ *! 09-Sep-1997 gp: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/services.h>
+#include <dspbridge/util.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/chnl.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/drv.h>
+
+#include <dspbridge/proc.h>
+#include <dspbridge/strm.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/disp.h>
+#include <dspbridge/mgr.h>
+#include <dspbridge/node.h>
+#include <dspbridge/rmm.h>
+
+
+/* ----------------------------------- Others */
+#include <dspbridge/msg.h>
+#include <dspbridge/cmm.h>
+#include <dspbridge/io.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/_dcd.h>
+#include <dspbridge/dbdcd.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/resourcecleanup.h>
+#endif
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define MAX_TRACEBUFLEN 255
+#define MAX_LOADARGS 16
+#define MAX_NODES 64
+#define MAX_STREAMS 16
+#define MAX_BUFS 64
+
+/* Following two macros should ideally have do{}while(0) */
+
+#define cp_fm_usr(dest, src, status, elements) \
+ if (DSP_SUCCEEDED(status)) {\
+ if (unlikely(src == NULL) || \
+ unlikely(copy_from_user(dest, src, elements * sizeof(*(dest))))) { \
+ GT_1trace(WCD_debugMask, GT_7CLASS, \
+ "copy_from_user failed, src=0x%x\n", src); \
+ status = DSP_EPOINTER ; \
+ } \
+ }
+
+#define cp_to_usr(dest, src, status, elements) \
+ if (DSP_SUCCEEDED(status)) {\
+ if (unlikely(dest == NULL) || \
+ unlikely(copy_to_user(dest, src, elements * sizeof(*(src))))) { \
+ GT_1trace(WCD_debugMask, GT_7CLASS, \
+ "copy_to_user failed, dest=0x%x\n", dest); \
+ status = DSP_EPOINTER ;\
+ } \
+ }
+
+/* Device IOCtl function pointer */
+struct WCD_Cmd {
+ u32(*fxn)(union Trapped_Args *args);
+ u32 dwIndex;
+} ;
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask WCD_debugMask = { NULL, NULL }; /* Core VxD Mask */
+#endif
+static u32 WCD_cRefs;
+
+/*
+ * Function table.
+ * The order of these functions MUST be the same as the order of the command
+ * numbers defined in wcdioctl.h This is how an IOCTL number in user mode
+ * turns into a function call in kernel mode.
+ */
+static struct WCD_Cmd WCD_cmdTable[] = {
+ /* MGR module */
+ {MGRWRAP_EnumNode_Info, CMD_MGR_ENUMNODE_INFO_OFFSET},
+ {MGRWRAP_EnumProc_Info, CMD_MGR_ENUMPROC_INFO_OFFSET},
+ {MGRWRAP_RegisterObject, CMD_MGR_REGISTEROBJECT_OFFSET},
+ {MGRWRAP_UnregisterObject, CMD_MGR_UNREGISTEROBJECT_OFFSET},
+ {MGRWRAP_WaitForBridgeEvents, CMD_MGR_WAIT_OFFSET},
+#ifndef RES_CLEANUP_DISABLE
+ {MGRWRAP_GetProcessResourcesInfo, CMD_MGR_RESOUCES_OFFSET},
+#endif
+ /* PROC Module */
+ {PROCWRAP_Attach, CMD_PROC_ATTACH_OFFSET},
+ {PROCWRAP_Ctrl, CMD_PROC_CTRL_OFFSET},
+ {PROCWRAP_Detach, CMD_PROC_DETACH_OFFSET},
+ {PROCWRAP_EnumNode_Info, CMD_PROC_ENUMNODE_OFFSET},
+ {PROCWRAP_EnumResources, CMD_PROC_ENUMRESOURCES_OFFSET},
+ {PROCWRAP_GetState, CMD_PROC_GETSTATE_OFFSET},
+ {PROCWRAP_GetTrace, CMD_PROC_GETTRACE_OFFSET},
+ {PROCWRAP_Load, CMD_PROC_LOAD_OFFSET},
+ {PROCWRAP_RegisterNotify, CMD_PROC_REGISTERNOTIFY_OFFSET},
+ {PROCWRAP_Start, CMD_PROC_START_OFFSET},
+ {PROCWRAP_ReserveMemory, CMD_PROC_RSVMEM_OFFSET},
+ {PROCWRAP_UnReserveMemory, CMD_PROC_UNRSVMEM_OFFSET},
+ {PROCWRAP_Map, CMD_PROC_MAPMEM_OFFSET},
+ {PROCWRAP_UnMap, CMD_PROC_UNMAPMEM_OFFSET},
+ {PROCWRAP_FlushMemory, CMD_PROC_FLUSHMEMORY_OFFSET},
+ {PROCWRAP_Stop, CMD_PROC_STOP_OFFSET},
+ {PROCWRAP_InvalidateMemory, CMD_PROC_INVALIDATEMEMORY_OFFSET},
+ /* NODE Module */
+ {NODEWRAP_Allocate, CMD_NODE_ALLOCATE_OFFSET},
+ {NODEWRAP_AllocMsgBuf, CMD_NODE_ALLOCMSGBUF_OFFSET},
+ {NODEWRAP_ChangePriority, CMD_NODE_CHANGEPRIORITY_OFFSET},
+ {NODEWRAP_Connect, CMD_NODE_CONNECT_OFFSET},
+ {NODEWRAP_Create, CMD_NODE_CREATE_OFFSET},
+ {NODEWRAP_Delete, CMD_NODE_DELETE_OFFSET},
+ {NODEWRAP_FreeMsgBuf, CMD_NODE_FREEMSGBUF_OFFSET},
+ {NODEWRAP_GetAttr, CMD_NODE_GETATTR_OFFSET},
+ {NODEWRAP_GetMessage, CMD_NODE_GETMESSAGE_OFFSET},
+ {NODEWRAP_Pause, CMD_NODE_PAUSE_OFFSET},
+ {NODEWRAP_PutMessage, CMD_NODE_PUTMESSAGE_OFFSET},
+ {NODEWRAP_RegisterNotify, CMD_NODE_REGISTERNOTIFY_OFFSET},
+ {NODEWRAP_Run, CMD_NODE_RUN_OFFSET},
+ {NODEWRAP_Terminate, CMD_NODE_TERMINATE_OFFSET},
+ {NODEWRAP_GetUUIDProps, CMD_NODE_GETUUIDPROPS_OFFSET},
+ /* STRM wrapper functions */
+ {STRMWRAP_AllocateBuffer, CMD_STRM_ALLOCATEBUFFER_OFFSET},
+ {STRMWRAP_Close, CMD_STRM_CLOSE_OFFSET},
+ {STRMWRAP_FreeBuffer, CMD_STRM_FREEBUFFER_OFFSET},
+ {STRMWRAP_GetEventHandle, CMD_STRM_GETEVENTHANDLE_OFFSET},
+ {STRMWRAP_GetInfo, CMD_STRM_GETINFO_OFFSET},
+ {STRMWRAP_Idle, CMD_STRM_IDLE_OFFSET},
+ {STRMWRAP_Issue, CMD_STRM_ISSUE_OFFSET},
+ {STRMWRAP_Open, CMD_STRM_OPEN_OFFSET},
+ {STRMWRAP_Reclaim, CMD_STRM_RECLAIM_OFFSET},
+ {STRMWRAP_RegisterNotify, CMD_STRM_REGISTERNOTIFY_OFFSET},
+ {STRMWRAP_Select, CMD_STRM_SELECT_OFFSET},
+ /* CMM module */
+ {CMMWRAP_CallocBuf, CMD_CMM_ALLOCBUF_OFFSET},
+ {CMMWRAP_FreeBuf, CMD_CMM_FREEBUF_OFFSET},
+ {CMMWRAP_GetHandle, CMD_CMM_GETHANDLE_OFFSET},
+ {CMMWRAP_GetInfo, CMD_CMM_GETINFO_OFFSET}
+};
+
+/*
+ * ======== WCD_CallDevIOCtl ========
+ * Purpose:
+ * Call the (wrapper) function for the corresponding WCD IOCTL.
+ */
+inline DSP_STATUS WCD_CallDevIOCtl(u32 cmd, union Trapped_Args *args,
+ u32 *pResult)
+{
+ int cmdtable = sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd);
+ cmd -= CMD_BASE;
+
+ if (cmd < cmdtable) {
+ /* make the fxn call via the cmd table */
+ *pResult = (*WCD_cmdTable[cmd].fxn) (args);
+ return DSP_SOK;
+ } else {
+ return DSP_EINVALIDARG;
+ }
+}
+
+/*
+ * ======== WCD_Exit ========
+ */
+void WCD_Exit(void)
+{
+ DBC_Require(WCD_cRefs > 0);
+ WCD_cRefs--;
+ GT_1trace(WCD_debugMask, GT_5CLASS,
+ "Entered WCD_Exit, ref count: 0x%x\n", WCD_cRefs);
+ if (WCD_cRefs == 0) {
+ /* Release all WCD modules initialized in WCD_Init(). */
+ COD_Exit();
+ DEV_Exit();
+ CHNL_Exit();
+ MSG_Exit();
+ IO_Exit();
+ STRM_Exit();
+ NTFY_Exit();
+ DISP_Exit();
+ NODE_Exit();
+ PROC_Exit();
+ MGR_Exit();
+ RMM_exit();
+ DRV_Exit();
+ SERVICES_Exit();
+ }
+ DBC_Ensure(WCD_cRefs >= 0);
+}
+
+/*
+ * ======== WCD_Init ========
+ * Purpose:
+ * Module initialization is done by SERVICES Init.
+ */
+bool WCD_Init(void)
+{
+ bool fInit = true;
+ bool fDRV, fDEV, fCOD, fSERVICES, fCHNL, fMSG, fIO;
+ bool fMGR, fPROC, fNODE, fDISP, fNTFY, fSTRM, fRMM;
+#ifdef DEBUG
+ /* runtime check of Device IOCtl array. */
+ u32 i;
+ int cmdtable = sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd);
+
+ for (i = 0; i < cmdtable; i++)
+ DBC_Assert(WCD_cmdTable[i].dwIndex == i + CMD_BASE);
+#endif
+ if (WCD_cRefs == 0) {
+ /* initialize all SERVICES modules */
+ fSERVICES = SERVICES_Init();
+ /* initialize debugging module */
+ DBC_Assert(!WCD_debugMask.flags);
+ GT_create(&WCD_debugMask, "CD"); /* CD for class driver */
+ /* initialize class driver and other modules */
+ fDRV = DRV_Init();
+ fMGR = MGR_Init();
+ fPROC = PROC_Init();
+ fNODE = NODE_Init();
+ fDISP = DISP_Init();
+ fNTFY = NTFY_Init();
+ fSTRM = STRM_Init();
+ fRMM = RMM_init();
+ fCHNL = CHNL_Init();
+ fMSG = MSG_Init();
+ fIO = IO_Init();
+ fDEV = DEV_Init();
+ fCOD = COD_Init();
+ fInit = fSERVICES && fDRV && fDEV && fCHNL && fCOD &&
+ fMSG && fIO;
+ fInit = fInit && fMGR && fPROC && fRMM;
+ if (!fInit) {
+ if (fSERVICES)
+ SERVICES_Exit();
+
+ if (fDRV)
+ DRV_Exit();
+
+ if (fMGR)
+ MGR_Exit();
+
+ if (fSTRM)
+ STRM_Exit();
+
+ if (fPROC)
+ PROC_Exit();
+
+ if (fNODE)
+ NODE_Exit();
+
+ if (fDISP)
+ DISP_Exit();
+
+ if (fNTFY)
+ NTFY_Exit();
+
+ if (fCHNL)
+ CHNL_Exit();
+
+ if (fMSG)
+ MSG_Exit();
+
+ if (fIO)
+ IO_Exit();
+
+ if (fDEV)
+ DEV_Exit();
+
+ if (fCOD)
+ COD_Exit();
+
+ if (fRMM)
+ RMM_exit();
+
+ }
+ }
+ if (fInit)
+ WCD_cRefs++;
+
+ GT_1trace(WCD_debugMask, GT_5CLASS,
+ "Entered WCD_Init, ref count: 0x%x\n", WCD_cRefs);
+ return fInit;
+}
+
+/*
+ * ======== WCD_InitComplete2 ========
+ * Purpose:
+ * Perform any required WCD, and WMD initialization which
+ * cannot not be performed in WCD_Init() or DEV_StartDevice() due
+ * to the fact that some services are not yet
+ * completely initialized.
+ * Parameters:
+ * Returns:
+ * DSP_SOK: Allow this device to load
+ * DSP_EFAIL: Failure.
+ * Requires:
+ * WCD initialized.
+ * Ensures:
+ */
+DSP_STATUS WCD_InitComplete2(void)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CFG_DEVNODE *DevNode;
+ struct DEV_OBJECT *hDevObject;
+ u32 devType;
+
+ DBC_Require(WCD_cRefs > 0);
+ GT_0trace(WCD_debugMask, GT_ENTER, "Entered WCD_InitComplete\n");
+ /* Walk the list of DevObjects, get each devnode, and attempting to
+ * autostart the board. Note that this requires COF loading, which
+ * requires KFILE. */
+ for (hDevObject = DEV_GetFirst(); hDevObject != NULL;
+ hDevObject = DEV_GetNext(hDevObject)) {
+ if (DSP_FAILED(DEV_GetDevNode(hDevObject, &DevNode)))
+ continue;
+
+ if (DSP_FAILED(DEV_GetDevType(hDevObject, &devType)))
+ continue;
+
+ if ((devType == DSP_UNIT) || (devType == IVA_UNIT)) {
+ if (DSP_FAILED(PROC_AutoStart(DevNode, hDevObject))) {
+ GT_0trace(WCD_debugMask, GT_1CLASS,
+ "WCD_InitComplete2 Failed\n");
+ status = DSP_EFAIL;
+ /* break; */
+ }
+ } else
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "Ignoring PROC_AutoStart "
+ "for Device Type = 0x%x \n", devType);
+ } /* End For Loop */
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "Exiting WCD_InitComplete status 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== MGRWRAP_EnumNode_Info ========
+ */
+u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args)
+{
+ u8 *pNDBProps;
+ u32 uNumNodes;
+ DSP_STATUS status = DSP_SOK;
+ u32 size = args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize;
+
+ GT_4trace(WCD_debugMask, GT_ENTER,
+ "MGR_EnumNodeInfo: entered args:\n0x%x"
+ " uNode: 0x%x\tpNDBProps: 0x%x\tuNDBPropsSize: "
+ "0x%x\tpuNumNodes\n", args->ARGS_MGR_ENUMNODE_INFO.uNode,
+ args->ARGS_MGR_ENUMNODE_INFO.pNDBProps,
+ args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize,
+ args->ARGS_MGR_ENUMNODE_INFO.puNumNodes);
+ pNDBProps = MEM_Alloc(size, MEM_NONPAGED);
+ if (pNDBProps == NULL)
+ status = DSP_EMEMORY;
+
+ if (DSP_SUCCEEDED(status)) {
+ status = MGR_EnumNodeInfo(args->ARGS_MGR_ENUMNODE_INFO.uNode,
+ (struct DSP_NDBPROPS *)pNDBProps,
+ size, &uNumNodes);
+ }
+ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.pNDBProps, pNDBProps, status,
+ size);
+ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.puNumNodes, &uNumNodes, status,
+ 1);
+ if (pNDBProps)
+ MEM_Free(pNDBProps);
+
+ return status;
+}
+
+/*
+ * ======== MGRWRAP_EnumProc_Info ========
+ */
+u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args)
+{
+ u8 *pProcessorInfo;
+ u32 uNumProcs;
+ DSP_STATUS status = DSP_SOK;
+ u32 size = args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize;
+
+ GT_4trace(WCD_debugMask, GT_ENTER,
+ "MGRWRAP_EnumProc_Info: entered args:\n"
+ "0x%x uProcessor: 0x%x\tpProcessorInfo: 0x%x\t"
+ "uProcessorInfoSize: 0x%x\tpuNumProcs \n",
+ args->ARGS_MGR_ENUMPROC_INFO.uProcessor,
+ args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo,
+ args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize,
+ args->ARGS_MGR_ENUMPROC_INFO.puNumProcs);
+ pProcessorInfo = MEM_Alloc(size, MEM_NONPAGED);
+ if (pProcessorInfo == NULL)
+ status = DSP_EMEMORY;
+
+ if (DSP_SUCCEEDED(status)) {
+ status = MGR_EnumProcessorInfo(args->
+ ARGS_MGR_ENUMPROC_INFO.uProcessor,
+ (struct DSP_PROCESSORINFO *)pProcessorInfo,
+ size, &uNumProcs);
+ }
+ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo, pProcessorInfo,
+ status, size);
+ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.puNumProcs, &uNumProcs,
+ status, 1);
+ if (pProcessorInfo)
+ MEM_Free(pProcessorInfo);
+
+ return status;
+}
+
+#define WRAP_MAP2CALLER(x) x
+/*
+ * ======== MGRWRAP_RegisterObject ========
+ */
+u32 MGRWRAP_RegisterObject(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "MGRWRAP_RegisterObject: entered pg2hMsg "
+ "0x%x\n", args->ARGS_MGR_REGISTEROBJECT.pUuid);
+ retVal = DCD_RegisterObject(WRAP_MAP2CALLER
+ (args->ARGS_MGR_REGISTEROBJECT.pUuid),
+ args->ARGS_MGR_REGISTEROBJECT.objType,
+ WRAP_MAP2CALLER(args->ARGS_MGR_REGISTEROBJECT.pszPathName));
+ return retVal;
+}
+
+/*
+ * ======== MGRWRAP_UnregisterObject ========
+ */
+u32 MGRWRAP_UnregisterObject(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "MGRWRAP_UnregisterObject: entered pg2hMsg"
+ " 0x%x\n", args->ARGS_MGR_UNREGISTEROBJECT.pUuid);
+ retVal = DCD_UnregisterObject(WRAP_MAP2CALLER
+ (args->ARGS_MGR_UNREGISTEROBJECT.pUuid),
+ args->ARGS_MGR_UNREGISTEROBJECT.objType);
+
+ return retVal;
+}
+
+/*
+ * ======== MGRWRAP_WaitForBridgeEvents ========
+ */
+u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS];
+ struct DSP_NOTIFICATION notifications[MAX_EVENTS];
+ u32 uIndex, i;
+ u32 uCount = args->ARGS_MGR_WAIT.uCount;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "MGRWRAP_WaitForBridgeEvents: entered\n");
+
+ if (uCount > MAX_EVENTS)
+ status = DSP_EINVALIDARG;
+
+ /* get the array of pointers to user structures */
+ cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications,
+ status, uCount);
+ /* get the events */
+ for (i = 0; i < uCount; i++) {
+ cp_fm_usr(&notifications[i], aNotifications[i], status, 1);
+ if (DSP_SUCCEEDED(status)) {
+ /* set the array of pointers to kernel structures*/
+ aNotifications[i] = &notifications[i];
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = MGR_WaitForBridgeEvents(aNotifications, uCount,
+ &uIndex, args->ARGS_MGR_WAIT.uTimeout);
+ }
+ cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1);
+ return status;
+}
+
+
+#ifndef RES_CLEANUP_DISABLE
+/*
+ * ======== MGRWRAP_GetProcessResourceInfo ========
+ */
+u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 uSize = 0;
+ u8 *pBuf = MEM_Alloc(8092, MEM_NONPAGED);
+ status = DRV_ProcDisplayResInfo(pBuf, &uSize);
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "MGRWRAP_GetProcessResourcesInfo:uSize=%d :\n", uSize);
+ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, uSize);
+ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
+ "123MGRWRAP_GetProcessResourcesInfo:**************\n");
+ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
+ "456MGRWRAP_GetProcessResourcesInfo:**************\n");
+ cp_to_usr(args->ARGS_PROC_GETTRACE.pSize, &uSize, status, 1);
+ MEM_Free(pBuf);
+ return status;
+}
+#endif
+
+
+/*
+ * ======== PROCWRAP_Attach ========
+ */
+u32 PROCWRAP_Attach(union Trapped_Args *args)
+{
+ DSP_HPROCESSOR processor;
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_PROCESSORATTRIN attrIn, *pAttrIn = NULL;
+
+ GT_3trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_Attach: entered args:\n" "0x%x"
+ " uProcessor: 0x%x\tpAttrIn: 0x%x\tphProcessor \n",
+ args->ARGS_PROC_ATTACH.uProcessor,
+ args->ARGS_PROC_ATTACH.pAttrIn,
+ args->ARGS_PROC_ATTACH.phProcessor);
+ /* Optional argument */
+ if (args->ARGS_PROC_ATTACH.pAttrIn) {
+ cp_fm_usr(&attrIn, args->ARGS_PROC_ATTACH.pAttrIn, status, 1);
+ if (DSP_SUCCEEDED(status))
+ pAttrIn = &attrIn;
+
+ }
+ status = PROC_Attach(args->ARGS_PROC_ATTACH.uProcessor, pAttrIn,
+ &processor);
+ cp_to_usr(args->ARGS_PROC_ATTACH.phProcessor, &processor, status, 1);
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Ctrl ========
+ */
+u32 PROCWRAP_Ctrl(union Trapped_Args *args)
+{
+ u32 cbDataSize, __user *pSize = (u32 __user *)
+ args->ARGS_PROC_CTRL.pArgs;
+ u8 *pArgs = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ GT_3trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_Ctrl: entered args:\n 0x%x"
+ " uProcessor: 0x%x\tdwCmd: 0x%x\tpArgs \n",
+ args->ARGS_PROC_CTRL.hProcessor,
+ args->ARGS_PROC_CTRL.dwCmd,
+ args->ARGS_PROC_CTRL.pArgs);
+ if (pSize) {
+ if (get_user(cbDataSize, pSize))
+ status = DSP_EFAIL;
+
+ cbDataSize += sizeof(u32);
+ if (DSP_SUCCEEDED(status)) {
+ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
+ if (pArgs == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ cp_fm_usr(pArgs, args->ARGS_PROC_CTRL.pArgs, status,
+ cbDataSize);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_Ctrl(args->ARGS_PROC_CTRL.hProcessor,
+ args->ARGS_PROC_CTRL.dwCmd,
+ (struct DSP_CBDATA *)pArgs);
+ }
+
+ /* cp_to_usr(args->ARGS_PROC_CTRL.pArgs, pArgs, status, 1);*/
+ if (pArgs)
+ MEM_Free(pArgs);
+
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Detach ========
+ */
+u32 PROCWRAP_Detach(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_1trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_Detach: entered args\n0x%x "
+ "hProceesor \n", args->ARGS_PROC_DETACH.hProcessor);
+ retVal = PROC_Detach(args->ARGS_PROC_DETACH.hProcessor);
+
+ return retVal;
+}
+
+/*
+ * ======== PROCWRAP_EnumNode_Info ========
+ */
+u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ DSP_HNODE aNodeTab[MAX_NODES];
+ u32 uNumNodes;
+ u32 uAllocated;
+
+ GT_5trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_EnumNode_Info:entered args:\n0x"
+ "%xhProcessor:0x%x\taNodeTab:0x%x\tuNodeTabSize:"
+ "%0x%x\tpuNumNodes%\n0x%x puAllocated: \n",
+ args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
+ args->ARGS_PROC_ENUMNODE_INFO.aNodeTab,
+ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
+ args->ARGS_PROC_ENUMNODE_INFO.puNumNodes,
+ args->ARGS_PROC_ENUMNODE_INFO.puAllocated);
+ DBC_Require(args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize <= MAX_NODES);
+ status = PROC_EnumNodes(args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
+ aNodeTab,
+ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
+ &uNumNodes, &uAllocated);
+ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.aNodeTab, aNodeTab, status,
+ uNumNodes);
+ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puNumNodes, &uNumNodes,
+ status, 1);
+ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puAllocated, &uAllocated,
+ status, 1);
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_FlushMemory ========
+ */
+u32 PROCWRAP_FlushMemory(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_FlushMemory: entered\n");
+
+ status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
+ args->ARGS_PROC_FLUSHMEMORY.pMpuAddr,
+ args->ARGS_PROC_FLUSHMEMORY.ulSize,
+ args->ARGS_PROC_FLUSHMEMORY.ulFlags);
+ return status;
+}
+
+
+/*
+ * ======== PROCWRAP_InvalidateMemory ========
+ */
+u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_InvalidateMemory:entered\n");
+
+ status = PROC_InvalidateMemory(
+ args->ARGS_PROC_INVALIDATEMEMORY.hProcessor,
+ args->ARGS_PROC_INVALIDATEMEMORY.pMpuAddr,
+ args->ARGS_PROC_INVALIDATEMEMORY.ulSize);
+ return status;
+}
+
+
+/*
+ * ======== PROCWRAP_EnumResources ========
+ */
+u32 PROCWRAP_EnumResources(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_4trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_EnumResources: entered args:\n"
+ "0x%x hProcessor: 0x%x\tuResourceMask: 0x%x\tpResourceInfo"
+ " 0x%x\tuResourceInfoSixe \n",
+ args->ARGS_PROC_ENUMRESOURCES.hProcessor,
+ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
+ args->ARGS_PROC_ENUMRESOURCES.pResourceInfo,
+ args->ARGS_PROC_ENUMRESOURCES.uResourceInfoSize);
+ retVal = PROC_GetResourceInfo(args->ARGS_PROC_ENUMRESOURCES.hProcessor,
+ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
+ WRAP_MAP2CALLER(args->ARGS_PROC_ENUMRESOURCES.
+ pResourceInfo), args->ARGS_PROC_ENUMRESOURCES.
+ uResourceInfoSize);
+
+ return retVal;
+}
+
+/*
+ * ======== PROCWRAP_GetState ========
+ */
+u32 PROCWRAP_GetState(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ struct DSP_PROCESSORSTATE procStatus;
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetState: entered\n");
+ status = PROC_GetState(args->ARGS_PROC_GETSTATE.hProcessor, &procStatus,
+ args->ARGS_PROC_GETSTATE.uStateInfoSize);
+ cp_to_usr(args->ARGS_PROC_GETSTATE.pProcStatus, &procStatus, status, 1);
+ return status;
+
+}
+
+/*
+ * ======== PROCWRAP_GetTrace ========
+ */
+u32 PROCWRAP_GetTrace(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ u8 *pBuf;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n");
+
+ DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN);
+
+ pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED);
+ if (pBuf != NULL) {
+ status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor,
+ pBuf, args->ARGS_PROC_GETTRACE.uMaxSize);
+ } else {
+ status = DSP_EMEMORY;
+ }
+ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status,
+ args->ARGS_PROC_GETTRACE.uMaxSize);
+ if (pBuf)
+ MEM_Free(pBuf);
+
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Load ========
+ */
+u32 PROCWRAP_Load(union Trapped_Args *args)
+{
+ s32 i, len;
+ DSP_STATUS status = DSP_SOK;
+ char *temp;
+ s32 argc = args->ARGS_PROC_LOAD.iArgc;
+ u8 **argv, **envp = NULL;
+
+
+ DBC_Require(argc > 0);
+ DBC_Require(argc <= MAX_LOADARGS);
+
+ argv = MEM_Alloc(argc * sizeof(u8 *), MEM_NONPAGED);
+ if (argv == NULL)
+ status = DSP_EMEMORY;
+
+ cp_fm_usr(argv, args->ARGS_PROC_LOAD.aArgv, status, argc);
+ for (i = 0; DSP_SUCCEEDED(status) && (i < argc); i++) {
+ if (argv[i] != NULL) {
+ /* User space pointer to argument */
+ temp = (char *) argv[i];
+ len = strlen_user((char *)temp);
+ /* Kernel space pointer to argument */
+ argv[i] = MEM_Alloc(len, MEM_NONPAGED);
+ if (argv[i] == NULL) {
+ status = DSP_EMEMORY;
+ break;
+ }
+ cp_fm_usr(argv[i], temp, status, len);
+ }
+ }
+ /* TODO: validate this */
+ if (args->ARGS_PROC_LOAD.aEnvp != NULL) {
+ /* number of elements in the envp array including NULL */
+ len = 0;
+ do {
+ len++;
+ get_user(temp, args->ARGS_PROC_LOAD.aEnvp);
+ } while (temp);
+ envp = MEM_Alloc(len * sizeof(u8 *), MEM_NONPAGED);
+ if (envp == NULL)
+ status = DSP_EMEMORY;
+
+ cp_fm_usr(envp, args->ARGS_PROC_LOAD.aEnvp, status, len);
+ for (i = 0; DSP_SUCCEEDED(status) && (envp[i] != NULL); i++) {
+ /* User space pointer to argument */
+ temp = (char *)envp[i];
+ len = strlen_user((char *)temp);
+ /* Kernel space pointer to argument */
+ envp[i] = MEM_Alloc(len, MEM_NONPAGED);
+ if (envp[i] == NULL) {
+ status = DSP_EMEMORY;
+ break;
+ }
+ cp_fm_usr(envp[i], temp, status, len);
+ }
+ }
+ GT_5trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_Load, hProcessor: 0x%x\n\tiArgc:"
+ "0x%x\n\taArgv: 0x%x\n\taArgv[0]: %s\n\taEnvp: 0x%0x\n",
+ args->ARGS_PROC_LOAD.hProcessor,
+ args->ARGS_PROC_LOAD.iArgc, args->ARGS_PROC_LOAD.aArgv,
+ argv[0], args->ARGS_PROC_LOAD.aEnvp);
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_Load(args->ARGS_PROC_LOAD.hProcessor,
+ args->ARGS_PROC_LOAD.iArgc,
+ (CONST char **)argv, (CONST char **)envp);
+ }
+ if (envp != NULL) {
+ i = 0;
+ while (envp[i] != NULL)
+ MEM_Free(envp[i++]);
+
+ MEM_Free(envp);
+ }
+ if (argv != NULL) {
+ for (i = 0; i < argc; i++) {
+ if (argv[i] != NULL)
+ MEM_Free(argv[i]);
+
+ }
+ MEM_Free(argv);
+ }
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Map ========
+ */
+u32 PROCWRAP_Map(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ void *pMapAddr;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Map: entered\n");
+ status = PROC_Map(args->ARGS_PROC_MAPMEM.hProcessor,
+ args->ARGS_PROC_MAPMEM.pMpuAddr,
+ args->ARGS_PROC_MAPMEM.ulSize,
+ args->ARGS_PROC_MAPMEM.pReqAddr, &pMapAddr,
+ args->ARGS_PROC_MAPMEM.ulMapAttr);
+ if (DSP_SUCCEEDED(status)) {
+ if (put_user(pMapAddr, args->ARGS_PROC_MAPMEM.ppMapAddr))
+ status = DSP_EINVALIDARG;
+
+ }
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_RegisterNotify ========
+ */
+u32 PROCWRAP_RegisterNotify(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ struct DSP_NOTIFICATION notification;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_RegisterNotify: entered\n");
+
+ /* Initialize the notification data structure */
+ notification.psName = NULL;
+ notification.handle = NULL;
+
+ status = PROC_RegisterNotify(args->ARGS_PROC_REGISTER_NOTIFY.hProcessor,
+ args->ARGS_PROC_REGISTER_NOTIFY.uEventMask,
+ args->ARGS_PROC_REGISTER_NOTIFY.uNotifyType,
+ &notification);
+ cp_to_usr(args->ARGS_PROC_REGISTER_NOTIFY.hNotification, &notification,
+ status, 1);
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_ReserveMemory ========
+ */
+u32 PROCWRAP_ReserveMemory(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ void *pRsvAddr;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
+ status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
+ args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
+ if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr))
+ status = DSP_EINVALIDARG;
+
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Start ========
+ */
+u32 PROCWRAP_Start(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Start: entered\n");
+ retVal = PROC_Start(args->ARGS_PROC_START.hProcessor);
+ return retVal;
+}
+
+/*
+ * ======== PROCWRAP_UnMap ========
+ */
+u32 PROCWRAP_UnMap(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_UnMap: entered\n");
+ status = PROC_UnMap(args->ARGS_PROC_UNMAPMEM.hProcessor,
+ args->ARGS_PROC_UNMAPMEM.pMapAddr);
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_UnReserveMemory ========
+ */
+u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "PROCWRAP_UnReserveMemory: entered\n");
+ status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
+ args->ARGS_PROC_UNRSVMEM.pRsvAddr);
+ return status;
+}
+
+/*
+ * ======== PROCWRAP_Stop ========
+ */
+u32 PROCWRAP_Stop(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Stop: entered\n");
+ retVal = PROC_Stop(args->ARGS_PROC_STOP.hProcessor);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_Allocate ========
+ */
+u32 NODEWRAP_Allocate(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_UUID nodeId;
+ u32 cbDataSize;
+ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs;
+ u8 *pArgs = NULL;
+ struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL;
+ struct NODE_OBJECT *hNode;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n");
+
+ /* Optional argument */
+ if (pSize) {
+ if (get_user(cbDataSize, pSize))
+ status = DSP_EFAIL;
+
+ cbDataSize += sizeof(u32);
+ if (DSP_SUCCEEDED(status)) {
+ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
+ if (pArgs == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status,
+ cbDataSize);
+ }
+ cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1);
+ /* Optional argument */
+ if (args->ARGS_NODE_ALLOCATE.pAttrIn) {
+ cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1);
+ if (DSP_SUCCEEDED(status))
+ pAttrIn = &attrIn;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor,
+ &nodeId, (struct DSP_CBDATA *)pArgs,
+ pAttrIn, &hNode);
+ }
+ cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1);
+ if (pArgs)
+ MEM_Free(pArgs);
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_AllocMsgBuf ========
+ */
+u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_BUFFERATTR *pAttr = NULL;
+ struct DSP_BUFFERATTR attr;
+ u8 *pBuffer = NULL;
+
+ if (args->ARGS_NODE_ALLOCMSGBUF.pAttr) { /* Optional argument */
+ cp_fm_usr(&attr, args->ARGS_NODE_ALLOCMSGBUF.pAttr, status, 1);
+ if (DSP_SUCCEEDED(status))
+ pAttr = &attr;
+
+ }
+ /* IN OUT argument */
+ cp_fm_usr(&pBuffer, args->ARGS_NODE_ALLOCMSGBUF.pBuffer, status, 1);
+ if (DSP_SUCCEEDED(status)) {
+ status = NODE_AllocMsgBuf(args->ARGS_NODE_ALLOCMSGBUF.hNode,
+ args->ARGS_NODE_ALLOCMSGBUF.uSize,
+ pAttr, &pBuffer);
+ }
+ cp_to_usr(args->ARGS_NODE_ALLOCMSGBUF.pBuffer, &pBuffer, status, 1)
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_ChangePriority ========
+ */
+u32 NODEWRAP_ChangePriority(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "NODEWRAP_ChangePriority: entered\n");
+ retVal = NODE_ChangePriority(args->ARGS_NODE_CHANGEPRIORITY.hNode,
+ args->ARGS_NODE_CHANGEPRIORITY.iPriority);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_Connect ========
+ */
+u32 NODEWRAP_Connect(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_STRMATTR attrs;
+ struct DSP_STRMATTR *pAttrs = NULL;
+ u32 cbDataSize;
+ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam;
+ u8 *pArgs = NULL;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n");
+
+ /* Optional argument */
+ if (pSize) {
+ if (get_user(cbDataSize, pSize))
+ status = DSP_EFAIL;
+
+ cbDataSize += sizeof(u32);
+ if (DSP_SUCCEEDED(status)) {
+ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
+ if (pArgs == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status,
+ cbDataSize);
+ }
+ if (args->ARGS_NODE_CONNECT.pAttrs) { /* Optional argument */
+ cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1);
+ if (DSP_SUCCEEDED(status))
+ pAttrs = &attrs;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode,
+ args->ARGS_NODE_CONNECT.uStream,
+ args->ARGS_NODE_CONNECT.hOtherNode,
+ args->ARGS_NODE_CONNECT.uOtherStream,
+ pAttrs, (struct DSP_CBDATA *)pArgs);
+ }
+ if (pArgs)
+ MEM_Free(pArgs);
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_Create ========
+ */
+u32 NODEWRAP_Create(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Create: entered\n");
+ retVal = NODE_Create(args->ARGS_NODE_CREATE.hNode);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_Delete ========
+ */
+u32 NODEWRAP_Delete(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Delete: entered\n");
+ retVal = NODE_Delete(args->ARGS_NODE_DELETE.hNode);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_FreeMsgBuf ========
+ */
+u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_BUFFERATTR *pAttr = NULL;
+ struct DSP_BUFFERATTR attr;
+ if (args->ARGS_NODE_FREEMSGBUF.pAttr) { /* Optional argument */
+ cp_fm_usr(&attr, args->ARGS_NODE_FREEMSGBUF.pAttr, status, 1);
+ if (DSP_SUCCEEDED(status))
+ pAttr = &attr;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = NODE_FreeMsgBuf(args->ARGS_NODE_FREEMSGBUF.hNode,
+ args->ARGS_NODE_FREEMSGBUF.pBuffer,
+ pAttr);
+ }
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_GetAttr ========
+ */
+u32 NODEWRAP_GetAttr(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_NODEATTR attr;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetAttr: entered\n");
+
+ status = NODE_GetAttr(args->ARGS_NODE_GETATTR.hNode, &attr,
+ args->ARGS_NODE_GETATTR.uAttrSize);
+ cp_to_usr(args->ARGS_NODE_GETATTR.pAttr, &attr, status, 1);
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_GetMessage ========
+ */
+u32 NODEWRAP_GetMessage(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ struct DSP_MSG msg;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetMessage: entered\n");
+
+ status = NODE_GetMessage(args->ARGS_NODE_GETMESSAGE.hNode, &msg,
+ args->ARGS_NODE_GETMESSAGE.uTimeout);
+
+ cp_to_usr(args->ARGS_NODE_GETMESSAGE.pMessage, &msg, status, 1);
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_Pause ========
+ */
+u32 NODEWRAP_Pause(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Pause: entered\n");
+ retVal = NODE_Pause(args->ARGS_NODE_PAUSE.hNode);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_PutMessage ========
+ */
+u32 NODEWRAP_PutMessage(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_MSG msg;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_PutMessage: entered\n");
+
+ cp_fm_usr(&msg, args->ARGS_NODE_PUTMESSAGE.pMessage, status, 1);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = NODE_PutMessage(args->ARGS_NODE_PUTMESSAGE.hNode, &msg,
+ args->ARGS_NODE_PUTMESSAGE.uTimeout);
+ }
+
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_RegisterNotify ========
+ */
+u32 NODEWRAP_RegisterNotify(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_NOTIFICATION notification;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "NODEWRAP_RegisterNotify: entered\n");
+
+ /* Initialize the notification data structure */
+ notification.psName = NULL;
+ notification.handle = NULL;
+
+ status = NODE_RegisterNotify(args->ARGS_NODE_REGISTERNOTIFY.hNode,
+ args->ARGS_NODE_REGISTERNOTIFY.uEventMask,
+ args->ARGS_NODE_REGISTERNOTIFY.uNotifyType,
+ &notification);
+ cp_to_usr(args->ARGS_NODE_REGISTERNOTIFY.hNotification, &notification,
+ status, 1);
+ return status;
+}
+
+/*
+ * ======== NODEWRAP_Run ========
+ */
+u32 NODEWRAP_Run(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Run: entered\n");
+ retVal = NODE_Run(args->ARGS_NODE_RUN.hNode);
+
+ return retVal;
+}
+
+/*
+ * ======== NODEWRAP_Terminate ========
+ */
+u32 NODEWRAP_Terminate(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ DSP_STATUS tempstatus;
+
+ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Terminate: entered\n");
+
+ status = NODE_Terminate(args->ARGS_NODE_TERMINATE.hNode, &tempstatus);
+
+ cp_to_usr(args->ARGS_NODE_TERMINATE.pStatus, &tempstatus, status, 1);
+
+ return status;
+}
+
+
+/*
+ * ======== NODEWRAP_GetUUIDProps ========
+ */
+u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_UUID nodeId;
+ struct DSP_NDBPROPS *pnodeProps = NULL;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "NODEWRAP_GetUUIDPropste: entered\n");
+
+
+ cp_fm_usr(&nodeId, args->ARGS_NODE_GETUUIDPROPS.pNodeID, status, 1);
+ pnodeProps = MEM_Alloc(sizeof(struct DSP_NDBPROPS), MEM_NONPAGED);
+ if (pnodeProps != NULL) {
+ status = NODE_GetUUIDProps(args->
+ ARGS_NODE_GETUUIDPROPS.hProcessor,
+ &nodeId, pnodeProps);
+ cp_to_usr(args->ARGS_NODE_GETUUIDPROPS.pNodeProps, pnodeProps,
+ status, 1);
+ } else
+ status = DSP_EMEMORY;
+ if (pnodeProps)
+ MEM_Free(pnodeProps);
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_AllocateBuffer ========
+ */
+u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args)
+{
+ DSP_STATUS status;
+ u8 **apBuffer = NULL;
+ u32 uNumBufs = args->ARGS_STRM_ALLOCATEBUFFER.uNumBufs;
+
+ DBC_Require(uNumBufs <= MAX_BUFS);
+
+ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
+
+ status = STRM_AllocateBuffer(args->ARGS_STRM_ALLOCATEBUFFER.hStream,
+ args->ARGS_STRM_ALLOCATEBUFFER.uSize,
+ apBuffer, uNumBufs);
+ cp_to_usr(args->ARGS_STRM_ALLOCATEBUFFER.apBuffer, apBuffer, status,
+ uNumBufs);
+ if (apBuffer)
+ MEM_Free(apBuffer);
+
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_Close ========
+ */
+u32 STRMWRAP_Close(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ retVal = STRM_Close(args->ARGS_STRM_CLOSE.hStream);
+
+ return retVal;
+}
+
+/*
+ * ======== STRMWRAP_FreeBuffer ========
+ */
+u32 STRMWRAP_FreeBuffer(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ u8 **apBuffer = NULL;
+ u32 uNumBufs = args->ARGS_STRM_FREEBUFFER.uNumBufs;
+
+ DBC_Require(uNumBufs <= MAX_BUFS);
+
+ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
+
+ cp_fm_usr(apBuffer, args->ARGS_STRM_FREEBUFFER.apBuffer, status,
+ uNumBufs);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = STRM_FreeBuffer(args->ARGS_STRM_FREEBUFFER.hStream,
+ apBuffer, uNumBufs);
+ }
+ cp_to_usr(args->ARGS_STRM_FREEBUFFER.apBuffer, apBuffer, status,
+ uNumBufs);
+ if (apBuffer)
+ MEM_Free(apBuffer);
+
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_GetEventHandle ========
+ */
+u32 STRMWRAP_GetEventHandle(union Trapped_Args *args)
+{
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== STRMWRAP_GetInfo ========
+ */
+u32 STRMWRAP_GetInfo(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_INFO strmInfo;
+ struct DSP_STREAMINFO user;
+ struct DSP_STREAMINFO *temp;
+
+ cp_fm_usr(&strmInfo, args->ARGS_STRM_GETINFO.pStreamInfo, status, 1);
+ temp = strmInfo.pUser;
+
+ strmInfo.pUser = &user;
+
+ if (DSP_SUCCEEDED(status)) {
+ status = STRM_GetInfo(args->ARGS_STRM_GETINFO.hStream,
+ &strmInfo, args->ARGS_STRM_GETINFO.uStreamInfoSize);
+ }
+ cp_to_usr(temp, strmInfo.pUser, status, 1);
+ strmInfo.pUser = temp;
+ cp_to_usr(args->ARGS_STRM_GETINFO.pStreamInfo, &strmInfo, status, 1);
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_Idle ========
+ */
+u32 STRMWRAP_Idle(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ retVal = STRM_Idle(args->ARGS_STRM_IDLE.hStream,
+ args->ARGS_STRM_IDLE.bFlush);
+
+ return retVal;
+}
+
+/*
+ * ======== STRMWRAP_Issue ========
+ */
+u32 STRMWRAP_Issue(union Trapped_Args *args)
+{
+ u32 retVal;
+
+ retVal = STRM_Issue(args->ARGS_STRM_ISSUE.hStream,
+ args->ARGS_STRM_ISSUE.pBuffer,
+ args->ARGS_STRM_ISSUE.dwBytes,
+ args->ARGS_STRM_ISSUE.dwBufSize,
+ args->ARGS_STRM_ISSUE.dwArg);
+
+ /* This is a user space pointer */
+ return retVal;
+}
+
+/*
+ * ======== STRMWRAP_Open ========
+ */
+u32 STRMWRAP_Open(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_ATTR attr;
+ struct STRM_OBJECT *pStrm;
+ struct DSP_STREAMATTRIN strmAttrIn;
+
+ cp_fm_usr(&attr, args->ARGS_STRM_OPEN.pAttrIn, status, 1);
+
+ if (attr.pStreamAttrIn != NULL) { /* Optional argument */
+ cp_fm_usr(&strmAttrIn, attr.pStreamAttrIn, status, 1);
+ if (DSP_SUCCEEDED(status))
+ attr.pStreamAttrIn = &strmAttrIn;
+
+ }
+ status = STRM_Open(args->ARGS_STRM_OPEN.hNode,
+ args->ARGS_STRM_OPEN.uDirection,
+ args->ARGS_STRM_OPEN.uIndex, &attr, &pStrm);
+ cp_to_usr(args->ARGS_STRM_OPEN.phStream, &pStrm, status, 1);
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_Reclaim ========
+ */
+u32 STRMWRAP_Reclaim(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ u8 *pBufPtr;
+ u32 ulBytes;
+ u32 dwArg;
+ u32 ulBufSize;
+
+ status = STRM_Reclaim(args->ARGS_STRM_RECLAIM.hStream, &pBufPtr,
+ &ulBytes, &ulBufSize, &dwArg);
+ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufPtr, &pBufPtr, status, 1);
+ cp_to_usr(args->ARGS_STRM_RECLAIM.pBytes, &ulBytes, status, 1);
+ cp_to_usr(args->ARGS_STRM_RECLAIM.pdwArg, &dwArg, status, 1);
+
+ if (args->ARGS_STRM_RECLAIM.pBufSize != NULL) {
+ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufSize, &ulBufSize,
+ status, 1);
+ }
+
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_RegisterNotify ========
+ */
+u32 STRMWRAP_RegisterNotify(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_NOTIFICATION notification;
+
+ GT_0trace(WCD_debugMask, GT_ENTER,
+ "NODEWRAP_RegisterNotify: entered\n");
+
+ /* Initialize the notification data structure */
+ notification.psName = NULL;
+ notification.handle = NULL;
+
+ status = STRM_RegisterNotify(args->ARGS_STRM_REGISTERNOTIFY.hStream,
+ args->ARGS_STRM_REGISTERNOTIFY.uEventMask,
+ args->ARGS_STRM_REGISTERNOTIFY.uNotifyType,
+ &notification);
+ cp_to_usr(args->ARGS_STRM_REGISTERNOTIFY.hNotification, &notification,
+ status, 1);
+
+ return status;
+}
+
+/*
+ * ======== STRMWRAP_Select ========
+ */
+u32 STRMWRAP_Select(union Trapped_Args *args)
+{
+ u32 mask;
+ struct STRM_OBJECT *aStrmTab[MAX_STREAMS];
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(args->ARGS_STRM_SELECT.nStreams <= MAX_STREAMS);
+
+ cp_fm_usr(aStrmTab, args->ARGS_STRM_SELECT.aStreamTab, status,
+ args->ARGS_STRM_SELECT.nStreams);
+ if (DSP_SUCCEEDED(status)) {
+ status = STRM_Select(aStrmTab, args->ARGS_STRM_SELECT.nStreams,
+ &mask, args->ARGS_STRM_SELECT.uTimeout);
+ }
+ cp_to_usr(args->ARGS_STRM_SELECT.pMask, &mask, status, 1);
+ return status;
+}
+
+/* CMM */
+
+/*
+ * ======== CMMWRAP_CallocBuf ========
+ */
+u32 CMMWRAP_CallocBuf(union Trapped_Args *args)
+{
+ /* This operation is done in kernel */
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== CMMWRAP_FreeBuf ========
+ */
+u32 CMMWRAP_FreeBuf(union Trapped_Args *args)
+{
+ /* This operation is done in kernel */
+ return DSP_ENOTIMPL;
+}
+
+/*
+ * ======== CMMWRAP_GetHandle ========
+ */
+u32 CMMWRAP_GetHandle(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_OBJECT *hCmmMgr;
+
+ status = CMM_GetHandle(args->ARGS_CMM_GETHANDLE.hProcessor, &hCmmMgr);
+
+ cp_to_usr(args->ARGS_CMM_GETHANDLE.phCmmMgr, &hCmmMgr, status, 1);
+
+ return status;
+}
+
+/*
+ * ======== CMMWRAP_GetInfo ========
+ */
+u32 CMMWRAP_GetInfo(union Trapped_Args *args)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_INFO cmmInfo;
+
+ status = CMM_GetInfo(args->ARGS_CMM_GETINFO.hCmmMgr, &cmmInfo);
+
+ cp_to_usr(args->ARGS_CMM_GETINFO.pCmmInfo, &cmmInfo, status, 1);
+
+ return status;
+}
diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
new file mode 100644
index 000000000000..c5ec8f905c99
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/dbdcd.c
@@ -0,0 +1,1573 @@
+/*
+ * dbdcd.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbdcd.c ========
+ * Description:
+ * This file contains the implementation of the DSP/BIOS Bridge
+ * Configuration Database (DCD).
+ *
+ * Notes:
+ * The fxn DCD_GetObjects can apply a callback fxn to each DCD object
+ * that is located in a specified COFF file. At the moment,
+ * DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
+ * DCD_GetObjects.
+ *
+ *! Revision History
+ *! ================
+ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
+ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
+ *! to include phase information
+ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
+ *! libraries
+ *! 26-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
+ *! DCD implementation.
+ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
+ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
+ *! 18-Feb-2003 vp Code review updates
+ *! 18-Oct-2002 vp Ported to Linux platform
+ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
+ *! data. Added DCD_GetLibraryName().
+ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
+ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
+ *! DSP-MMU setup. These are private attributes.
+ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
+ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
+ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
+ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
+ *! GetAttrsFromBuf
+ *! 22-Nov-2000 kc: Replaced sprintf() calls with strncat.
+ *! 09-Nov-2000 kc: Optimized DCD module.
+ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
+ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
+ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
+ *! to replace atoi(), until cdb generation can output in
+ *! decimal format.
+ *! 26-Jul-2000 kc: Created.
+ *!
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/reg.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/cod.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/uuidutil.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dbdcd.h>
+
+/* ----------------------------------- Global defines. */
+#define SIGNATURE 0x5f444344 /* "DCD_" (in reverse). */
+
+#define IsValidHandle(h) (((h) != NULL) && (h->dwSignature == SIGNATURE))
+
+#define MAX_INT2CHAR_LENGTH 16 /* Maximum int2char len of 32 bit int. */
+
+/* Name of section containing dependent libraries */
+#define DEPLIBSECT ".dspbridge_deplibs"
+
+/* DCD specific structures. */
+struct DCD_MANAGER {
+ u32 dwSignature; /* Used for object validation. */
+ struct COD_MANAGER *hCodMgr; /* Handle to COD manager object. */
+};
+
+/* Global reference variables. */
+static u32 cRefs;
+static u32 cEnumRefs;
+
+extern struct GT_Mask curTrace;
+
+/* helper function prototypes. */
+static s32 Atoi(char *pszBuf);
+
+static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
+ enum DSP_DCDOBJTYPE objType,
+ struct DCD_GENERICOBJ *pGenObj);
+
+static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
+
+static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
+
+static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ IN OUT u16 *pNumLibs,
+ OPTIONAL OUT u16 *pNumPersLibs,
+ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
+ OPTIONAL OUT bool *pPersistentDepLibs,
+ IN enum NLDR_PHASE phase);
+
+/*
+ * ======== DCD_AutoRegister ========
+ * Purpose:
+ * Parses the supplied image and resigsters with DCD.
+ */
+
+DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
+ IN char *pszCoffPath)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ if (IsValidHandle(hDcdMgr)) {
+ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
+ (DCD_REGISTERFXN)DCD_RegisterObject,
+ (void *)pszCoffPath);
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_AutoRegister: invalid DCD manager handle.\n");
+ }
+
+ return status;
+}
+
+/*
+ * ======== DCD_AutoUnregister ========
+ * Purpose:
+ * Parses the supplied DSP image and unresiters from DCD.
+ */
+DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
+ IN char *pszCoffPath)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ if (IsValidHandle(hDcdMgr)) {
+ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
+ (DCD_REGISTERFXN)DCD_RegisterObject,
+ NULL);
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_AutoUnregister: invalid DCD manager"
+ " handle.\n");
+ }
+
+ return status;
+}
+
+/*
+ * ======== DCD_CreateManager ========
+ * Purpose:
+ * Creates DCD manager.
+ */
+DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
+ OUT struct DCD_MANAGER **phDcdMgr)
+{
+ struct COD_MANAGER *hCodMgr; /* COD manager handle */
+ struct DCD_MANAGER *pDcdMgr = NULL; /* DCD Manager pointer */
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs >= 0);
+ DBC_Require(phDcdMgr);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
+ phDcdMgr);
+
+ status = COD_Create(&hCodMgr, pszZlDllName, NULL);
+ if (DSP_SUCCEEDED(status)) {
+
+ /* Create a DCD object. */
+ MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
+ if (pDcdMgr != NULL) {
+
+ /* Fill out the object. */
+ pDcdMgr->hCodMgr = hCodMgr;
+
+ /* Return handle to this DCD interface. */
+ *phDcdMgr = pDcdMgr;
+
+ GT_2trace(curTrace, GT_5CLASS,
+ "DCD_CreateManager: pDcdMgr 0x%x, "
+ " hCodMgr 0x%x", pDcdMgr, hCodMgr);
+ } else {
+ status = DSP_EMEMORY;
+
+ /*
+ * If allocation of DcdManager object failed, delete the
+ * COD manager.
+ */
+ COD_Delete(hCodMgr);
+
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_CreateManager: MEM_AllocObject failed\n");
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_CreateManager: COD_Create failed\n");
+ }
+
+ DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
+ (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
+ (status == DSP_EMEMORY)));
+
+ return status;
+}
+
+/*
+ * ======== DCD_DestroyManager ========
+ * Purpose:
+ * Frees DCD Manager object.
+ */
+DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
+{
+ struct DCD_MANAGER *pDcdMgr = hDcdMgr;
+ DSP_STATUS status = DSP_EHANDLE;
+
+ DBC_Require(cRefs >= 0);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ if (IsValidHandle(hDcdMgr)) {
+
+ /* Delete the COD manager. */
+ COD_Delete(pDcdMgr->hCodMgr);
+
+ /* Deallocate a DCD manager object. */
+ MEM_FreeObject(pDcdMgr);
+
+ status = DSP_SOK;
+ } else {
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_DestroyManager: invalid DCD manager handle.\n");
+ }
+
+ return status;
+}
+
+/*
+ * ======== DCD_EnumerateObject ========
+ * Purpose:
+ * Enumerates objects in the DCD.
+ */
+DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
+ OUT struct DSP_UUID *pUuid)
+{
+ DSP_STATUS status = DSP_SOK;
+ char szRegKey[REG_MAXREGPATHLENGTH];
+ char szValue[REG_MAXREGPATHLENGTH];
+ char szData[REG_MAXREGPATHLENGTH];
+ u32 dwValueSize;
+ u32 dwDataSize;
+ struct DSP_UUID dspUuid;
+ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
+ u32 dwKeyLen = 0;
+
+ DBC_Require(cRefs >= 0);
+ DBC_Require(cIndex >= 0);
+ DBC_Require(pUuid != NULL);
+
+ GT_3trace(curTrace, GT_ENTER,
+ "DCD_EnumerateObject: cIndex %d, objType %d, "
+ " pUuid 0x%x\n", cIndex, objType, pUuid);
+
+ if ((cIndex != 0) && (cEnumRefs == 0)) {
+ /*
+ * If an enumeration is being performed on an index greater
+ * than zero, then the current cEnumRefs must have been
+ * incremented to greater than zero.
+ */
+ status = DSP_ECHANGEDURINGENUM;
+ } else {
+ /* Enumerate a specific key in the registry by index. */
+ dwValueSize = REG_MAXREGPATHLENGTH;
+ dwDataSize = REG_MAXREGPATHLENGTH;
+
+ /*
+ * Pre-determine final key length. It's length of DCD_REGKEY +
+ * "_\0" + length of szObjType string + terminating NULL.
+ */
+ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+
+ /* Create proper REG key; concatenate DCD_REGKEY with
+ * objType. */
+ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
+ if ((strlen(szRegKey) + strlen("_\0")) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, "_\0", 2);
+ } else {
+ status = DSP_EFAIL;
+ }
+
+ /* This snprintf is guaranteed not to exceed max size of an
+ * integer. */
+ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
+ objType);
+
+ if (status == -1) {
+ status = DSP_EFAIL;
+ } else {
+ status = DSP_SOK;
+ if ((strlen(szRegKey) + strlen(szObjType)) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szObjType,
+ strlen(szObjType) + 1);
+ } else {
+ status = DSP_EFAIL;
+ }
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
+ &dwValueSize, szData,
+ &dwDataSize);
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Create UUID value using string retrieved from
+ * registry. */
+ UUID_UuidFromString(szValue, &dspUuid);
+
+ *pUuid = dspUuid;
+
+ /* Increment cEnumRefs to update reference count. */
+ cEnumRefs++;
+
+ status = DSP_SOK;
+ } else if (status == REG_E_NOMOREITEMS) {
+ /* At the end of enumeration. Reset cEnumRefs. */
+ cEnumRefs = 0;
+
+ status = DSP_SENUMCOMPLETE;
+ } else {
+ status = DSP_EFAIL;
+ GT_1trace(curTrace, GT_6CLASS,
+ "DCD_EnumerateObject: REG_EnumValue"
+ " failed, status = 0x%x\n", status);
+ }
+ }
+
+ DBC_Ensure(pUuid || (status == DSP_EFAIL));
+
+ return status;
+}
+
+/*
+ * ======== DCD_Exit ========
+ * Purpose:
+ * Discontinue usage of the DCD module.
+ */
+void DCD_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
+
+ cRefs--;
+ if (cRefs == 0) {
+ REG_Exit();
+ COD_Exit();
+ MEM_Exit();
+ }
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== DCD_GetDepLibs ========
+ */
+DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
+ OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(hDcdMgr));
+ DBC_Require(pUuid != NULL);
+ DBC_Require(pDepLibUuids != NULL);
+ DBC_Require(pPersistentDepLibs != NULL);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
+ pPersistentDepLibs, phase);
+
+ return status;
+}
+
+/*
+ * ======== DCD_GetNumDepLibs ========
+ */
+DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
+ OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(IsValidHandle(hDcdMgr));
+ DBC_Require(pNumLibs != NULL);
+ DBC_Require(pNumPersLibs != NULL);
+ DBC_Require(pUuid != NULL);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
+ NULL, NULL, phase);
+
+ return status;
+}
+
+/*
+ * ======== DCD_GetObjectDef ========
+ * Purpose:
+ * Retrieves the properties of a node or processor based on the UUID and
+ * object type.
+ */
+DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pObjUuid,
+ IN enum DSP_DCDOBJTYPE objType,
+ OUT struct DCD_GENERICOBJ *pObjDef)
+{
+ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
+ struct COD_LIBRARYOBJ *lib = NULL;
+ DSP_STATUS status = DSP_SOK;
+ u32 ulAddr = 0; /* Used by COD_GetSection */
+ u32 ulLen = 0; /* Used by COD_GetSection */
+ u32 dwBufSize; /* Used by REG functions */
+ char szRegKey[REG_MAXREGPATHLENGTH];
+ char *szUuid; /*[MAXUUIDLEN];*/
+ char szRegData[REG_MAXREGPATHLENGTH];
+ char szSectName[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
+ char *pszCoffBuf;
+ u32 dwKeyLen; /* Len of REG key. */
+ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pObjDef != NULL);
+ DBC_Require(pObjUuid != NULL);
+
+ GT_4trace(curTrace, GT_ENTER,
+ "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
+ " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
+ objType, pObjDef);
+ szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
+ if (!szUuid)
+ return status = DSP_EMEMORY;
+
+ if (!IsValidHandle(hDcdMgr)) {
+ status = DSP_EHANDLE;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
+ "DCD manager handle.\n");
+ goto func_end;
+ }
+ /* Pre-determine final key length. It's length of DCD_REGKEY +
+ * "_\0" + length of szObjType string + terminating NULL */
+ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
+ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
+
+ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, "_\0", 2);
+ else
+ status = DSP_EFAIL;
+
+ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
+ if (status == -1) {
+ status = DSP_EFAIL;
+ } else {
+ status = DSP_SOK;
+
+ if ((strlen(szRegKey) + strlen(szObjType)) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
+ } else {
+ status = DSP_EFAIL;
+ }
+ /* Create UUID value to set in registry. */
+ UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
+
+ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, szUuid, MAXUUIDLEN);
+ else
+ status = DSP_EFAIL;
+
+ /* Retrieve paths from the registry based on struct DSP_UUID */
+ dwBufSize = REG_MAXREGPATHLENGTH;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
+ &dwBufSize);
+ }
+ if (DSP_FAILED(status)) {
+ status = DSP_EUUID;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+ "REG_GetValue() failed\n");
+ goto func_end;
+ }
+ /* Open COFF file. */
+ status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
+ if (DSP_FAILED(status)) {
+ status = DSP_EDCDLOADBASE;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+ "COD_OpenBase() failed\n");
+ goto func_end;
+ }
+ /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
+ DBC_Assert((strlen(szUuid) + 1) < sizeof(szSectName));
+ /* Create section name based on node UUID. A period is
+ * pre-pended to the UUID string to form the section name.
+ * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
+ strncpy(szSectName, ".", 2);
+ strncat(szSectName, szUuid, strlen(szUuid));
+ /* Get section information. */
+ status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
+ if (DSP_FAILED(status)) {
+ status = DSP_EDCDGETSECT;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
+ " COD_GetSection() failed\n");
+ goto func_end;
+ }
+ /* Allocate zeroed buffer. */
+ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+#ifdef _DB_TIOMAP
+ if (strstr(szRegData, "iva") == NULL) {
+ /* Locate section by objectID and read its content. */
+ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+ } else {
+ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+ GT_0trace(curTrace, GT_4CLASS,
+ "Skipped Byte swap for IVA !!\n");
+ }
+#else
+ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+#endif
+ if (DSP_SUCCEEDED(status)) {
+ /* Compres DSP buffer to conform to PC format. */
+ if (strstr(szRegData, "iva") == NULL) {
+ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+ } else {
+ CompressBuf(pszCoffBuf, ulLen, 1);
+ GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
+ "COFF buffer by 1 for IVA !!\n");
+ }
+ /* Parse the content of the COFF buffer. */
+ status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
+ if (DSP_FAILED(status)) {
+ status = DSP_EDCDPARSESECT;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+ "GetAttrsFromBuf() failed\n");
+ }
+ } else {
+ status = DSP_EDCDREADSECT;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+ "COD_ReadSection() failed\n");
+ }
+ /* Free the previously allocated dynamic buffer. */
+ MEM_Free(pszCoffBuf);
+func_end:
+ if (lib)
+ COD_Close(lib);
+
+ if (szUuid)
+ MEM_Free(szUuid);
+ return status;
+}
+
+/*
+ * ======== DCD_GetObjects ========
+ */
+DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
+ DCD_REGISTERFXN registerFxn, void *handle)
+{
+ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
+ DSP_STATUS status = DSP_SOK;
+ char *pszCoffBuf;
+ char *pszCur;
+ struct COD_LIBRARYOBJ *lib = NULL;
+ u32 ulAddr = 0; /* Used by COD_GetSection */
+ u32 ulLen = 0; /* Used by COD_GetSection */
+ char seps[] = ":, ";
+ char *pToken = NULL;
+ struct DSP_UUID dspUuid;
+ s32 cObjectType;
+
+ DBC_Require(cRefs > 0);
+ GT_1trace(curTrace, GT_ENTER,
+ "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
+ if (!IsValidHandle(hDcdMgr)) {
+ status = DSP_EHANDLE;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_GetObjects: invalid DCD manager handle.\n");
+ goto func_end;
+ }
+ /* Open DSP coff file, don't load symbols. */
+ status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
+ if (DSP_FAILED(status)) {
+ status = DSP_EDCDLOADBASE;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_AutoRegister: COD_Open() failed\n");
+ goto func_cont;
+ }
+ /* Get DCD_RESIGER_SECTION section information. */
+ status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
+ if (DSP_FAILED(status) || !(ulLen > 0)) {
+ status = DSP_EDCDNOAUTOREGISTER;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_GetObjects: COD_GetSection() "
+ "- no auto register section\n");
+ goto func_cont;
+ }
+ /* Allocate zeroed buffer. */
+ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+#ifdef _DB_TIOMAP
+ if (strstr(pszCoffPath, "iva") == NULL) {
+ /* Locate section by objectID and read its content. */
+ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
+ pszCoffBuf, ulLen);
+ } else {
+ GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
+ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
+ pszCoffBuf, ulLen);
+ }
+#else
+ status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
+#endif
+ if (DSP_SUCCEEDED(status)) {
+ /* Compress DSP buffer to conform to PC format. */
+ GT_0trace(curTrace, GT_4CLASS,
+ "Successfully read section !!\n");
+ if (strstr(pszCoffPath, "iva") == NULL) {
+ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+ } else {
+ CompressBuf(pszCoffBuf, ulLen, 1);
+ GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
+ "with 1 word for IVA !!\n");
+ }
+ /* Read from buffer and register object in buffer. */
+ pszCur = pszCoffBuf;
+ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
+ /* Retrieve UUID string. */
+ UUID_UuidFromString(pToken, &dspUuid);
+ /* Retrieve object type */
+ pToken = strsep(&pszCur, seps);
+ /* Retrieve object type */
+ cObjectType = Atoi(pToken);
+ /*
+ * Apply registerFxn to the found DCD object.
+ * Possible actions include:
+ *
+ * 1) Register found DCD object.
+ * 2) Unregister found DCD object (when handle == NULL)
+ * 3) Add overlay node.
+ */
+ GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
+ "%d \n", cObjectType);
+ status = registerFxn(&dspUuid, cObjectType, handle);
+ if (DSP_SUCCEEDED(status)) {
+ GT_1trace(curTrace, GT_5CLASS,
+ "DCD_GetObjects: status 0x%x\n",
+ status);
+ } else {
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_GetObjects: "
+ "registration() failed\n");
+ /* if error occurs, break from while loop. */
+ break;
+ }
+ }
+ } else {
+ status = DSP_EDCDREADSECT;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
+ "COD_ReadSection() failed\n");
+ }
+ /* Free the previously allocated dynamic buffer. */
+ MEM_Free(pszCoffBuf);
+func_cont:
+ if (lib)
+ COD_Close(lib);
+
+func_end:
+ return status;
+}
+
+/*
+ * ======== DCD_GetLibraryName ========
+ * Purpose:
+ * Retrieves the library name for the given UUID.
+ *
+ */
+DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
+ enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
+{
+ char szRegKey[REG_MAXREGPATHLENGTH];
+ char szUuid[MAXUUIDLEN];
+ u32 dwKeyLen; /* Len of REG key. */
+ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(pUuid != NULL);
+ DBC_Require(pstrLibName != NULL);
+ DBC_Require(pdwSize != NULL);
+ DBC_Require(IsValidHandle(hDcdMgr));
+
+ GT_4trace(curTrace, GT_ENTER,
+ "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
+ " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
+ pstrLibName, pdwSize);
+ /*
+ * Pre-determine final key length. It's length of DCD_REGKEY +
+ * "_\0" + length of szObjType string + terminating NULL.
+ */
+ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
+ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
+ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, "_\0", 2);
+ else
+ status = DSP_EFAIL;
+
+ switch (phase) {
+ case NLDR_CREATE:
+ /* create phase type */
+ sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
+ break;
+ case NLDR_EXECUTE:
+ /* execute phase type */
+ sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
+ break;
+ case NLDR_DELETE:
+ /* delete phase type */
+ sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
+ break;
+ case NLDR_NOPHASE:
+ /* known to be a dependent library */
+ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
+ break;
+ default:
+ status = -1;
+ DBC_Assert(false);
+ }
+ if (status == -1) {
+ status = DSP_EFAIL;
+ } else {
+ status = DSP_SOK;
+ if ((strlen(szRegKey) + strlen(szObjType))
+ < REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
+ } else {
+ status = DSP_EFAIL;
+ }
+ /* Create UUID value to find match in registry. */
+ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+ if ((strlen(szRegKey) + MAXUUIDLEN) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szUuid, MAXUUIDLEN);
+ } else {
+ status = DSP_EFAIL;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Retrieve path from the registry based on DSP_UUID */
+ status = REG_GetValue(NULL, szRegKey, szRegKey,
+ (u8 *)pstrLibName, pdwSize);
+ }
+ /* If can't find, phases might be registered as generic LIBRARYTYPE */
+ if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
+ if (fPhaseSplit)
+ *fPhaseSplit = false;
+
+ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
+ if ((strlen(szRegKey) + strlen("_\0")) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, "_\0", 2);
+ } else {
+ status = DSP_EFAIL;
+ }
+ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
+ if ((strlen(szRegKey) + strlen(szObjType))
+ < REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
+ } else {
+ status = DSP_EFAIL;
+ }
+ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, szUuid, MAXUUIDLEN);
+ else
+ status = DSP_EFAIL;
+
+ status = REG_GetValue(NULL, szRegKey, szRegKey,
+ (u8 *)pstrLibName, pdwSize);
+ }
+
+ return status;
+}
+
+/*
+ * ======== DCD_Init ========
+ * Purpose:
+ * Initialize the DCD module.
+ */
+bool DCD_Init(void)
+{
+ bool fInitMEM;
+ bool fInitREG;
+ bool fInitCOD;
+ bool fInit = true;
+
+ DBC_Require(cRefs >= 0);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
+ cRefs);
+
+ if (cRefs == 0) {
+
+ /* Initialize required modules. */
+ fInitMEM = MEM_Init();
+ fInitCOD = COD_Init();
+ fInitREG = REG_Init();
+ if (!fInitMEM || !fInitCOD || !fInitREG) {
+ fInit = false;
+ GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
+ /* Exit initialized modules. */
+ if (fInitMEM)
+ MEM_Exit();
+
+ if (fInitCOD)
+ COD_Exit();
+
+ if (fInitREG)
+ REG_Exit();
+
+ }
+ }
+
+ if (fInit)
+ cRefs++;
+
+
+ GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
+
+ return fInit;
+}
+
+/*
+ * ======== DCD_RegisterObject ========
+ * Purpose:
+ * Registers a node or a processor with the DCD.
+ * If pszPathName == NULL, unregister the specified DCD object.
+ */
+DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
+ IN enum DSP_DCDOBJTYPE objType,
+ IN char *pszPathName)
+{
+ DSP_STATUS status = DSP_SOK;
+ char szRegKey[REG_MAXREGPATHLENGTH];
+ char szUuid[MAXUUIDLEN + 1];
+ u32 dwPathSize = 0;
+ u32 dwKeyLen; /* Len of REG key. */
+ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pUuid != NULL);
+ DBC_Require((objType == DSP_DCDNODETYPE) ||
+ (objType == DSP_DCDPROCESSORTYPE) ||
+ (objType == DSP_DCDLIBRARYTYPE) ||
+ (objType == DSP_DCDCREATELIBTYPE) ||
+ (objType == DSP_DCDEXECUTELIBTYPE) ||
+ (objType == DSP_DCDDELETELIBTYPE));
+
+ GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
+ "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
+ /*
+ * Pre-determine final key length. It's length of DCD_REGKEY +
+ * "_\0" + length of szObjType string + terminating NULL.
+ */
+ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
+ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
+ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, "_\0", 2);
+ else
+ status = DSP_EFAIL;
+
+ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
+ if (status == -1) {
+ status = DSP_EFAIL;
+ } else {
+ status = DSP_SOK;
+ if ((strlen(szRegKey) + strlen(szObjType)) <
+ REG_MAXREGPATHLENGTH) {
+ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
+ } else {
+ status = DSP_EFAIL;
+ }
+ /* Create UUID value to set in registry. */
+ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
+ strncat(szRegKey, szUuid, MAXUUIDLEN);
+ else
+ status = DSP_EFAIL;
+
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /*
+ * If pszPathName != NULL, perform registration, otherwise,
+ * perform unregistration.
+ */
+ if (pszPathName) {
+ /* Add new reg value (UUID+objType) with COFF path
+ * info. */
+ dwPathSize = strlen(pszPathName) + 1;
+ status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
+ (u8 *)pszPathName, dwPathSize);
+ GT_3trace(curTrace, GT_6CLASS,
+ "REG_SetValue REG_SZ=%d, "
+ "(u8 *)pszPathName=%s, dwPathSize=%d\n",
+ REG_SZ, pszPathName, dwPathSize);
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_RegisterObject: REG_SetValue failed!\n");
+ }
+ } else {
+ /* Deregister an existing object. */
+ status = REG_DeleteValue(NULL, szRegKey, szRegKey);
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_6CLASS,
+ "DCD_UnregisterObject: "
+ "REG_DeleteValue failed!\n");
+ }
+ }
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /*
+ * Because the node database has been updated through a
+ * successful object registration/de-registration operation,
+ * we need to reset the object enumeration counter to allow
+ * current enumerations to reflect this update in the node
+ * database.
+ */
+
+ cEnumRefs = 0;
+ }
+
+ return status;
+}
+
+/*
+ * ======== DCD_UnregisterObject ========
+ * Call DCD_Register object with pszPathName set to NULL to
+ * perform actual object de-registration.
+ */
+DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
+ IN enum DSP_DCDOBJTYPE objType)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pUuid != NULL);
+ DBC_Require((objType == DSP_DCDNODETYPE) ||
+ (objType == DSP_DCDPROCESSORTYPE) ||
+ (objType == DSP_DCDLIBRARYTYPE) ||
+ (objType == DSP_DCDCREATELIBTYPE) ||
+ (objType == DSP_DCDEXECUTELIBTYPE) ||
+ (objType == DSP_DCDDELETELIBTYPE));
+
+ GT_2trace(curTrace, GT_ENTER,
+ "DCD_UnregisterObject: object UUID 0x%x, "
+ "objType %d\n", pUuid, objType);
+
+ /*
+ * When DCD_RegisterObject is called with NULL as pathname,
+ * it indicates an unregister object operation.
+ */
+ status = DCD_RegisterObject(pUuid, objType, NULL);
+
+ return status;
+}
+
+/*
+ **********************************************************************
+ * DCD Helper Functions
+ **********************************************************************
+ */
+
+/*
+ * ======== Atoi ========
+ * Purpose:
+ * This function converts strings in decimal or hex format to integers.
+ */
+static s32 Atoi(char *pszBuf)
+{
+ s32 result = 0;
+ char *pch = pszBuf;
+ char c;
+ char first;
+ s32 base = 10;
+ s32 len;
+
+ while (isspace(*pch))
+ pch++;
+
+ first = *pch;
+ if (first == '-' || first == '+') {
+ pch++;
+ } else {
+ /* Determine if base 10 or base 16 */
+ len = strlen(pch);
+ if (len > 1) {
+ c = pch[1];
+ if ((*pch == '0' && (c == 'x' || c == 'X'))) {
+ base = 16;
+ pch += 2;
+ }
+ c = pch[len - 1];
+ if (c == 'h' || c == 'H')
+ base = 16;
+
+ }
+ }
+
+ while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
+ result *= base;
+ if ('A' <= c && c <= 'F') {
+ c = c - 'A' + 10;
+ } else {
+ if ('a' <= c && c <= 'f')
+ c = c - 'a' + 10;
+ else
+ c -= '0';
+
+ }
+ result += c;
+ ++pch;
+ }
+
+ return result;
+}
+
+/*
+ * ======== GetAttrsFromBuf ========
+ * Purpose:
+ * Parse the content of a buffer filled with DSP-side data and
+ * retrieve an object's attributes from it. IMPORTANT: Assume the
+ * buffer has been converted from DSP format to GPP format.
+ */
+static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
+ enum DSP_DCDOBJTYPE objType,
+ struct DCD_GENERICOBJ *pGenObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ char seps[] = ", ";
+ char *pszCur;
+ char *token;
+ s32 cLen = 0;
+ u32 i = 0;
+#ifdef _DB_TIOMAP
+ s32 iEntry;
+#endif
+
+ DBC_Require(pszBuf != NULL);
+ DBC_Require(ulBufSize != 0);
+ DBC_Require((objType == DSP_DCDNODETYPE)
+ || (objType == DSP_DCDPROCESSORTYPE));
+ DBC_Require(pGenObj != NULL);
+
+
+ switch (objType) {
+ case DSP_DCDNODETYPE:
+ /*
+ * Parse COFF sect buffer to retrieve individual tokens used
+ * to fill in object attrs.
+ */
+ pszCur = pszBuf;
+ token = strsep(&pszCur, seps);
+
+ /* u32 cbStruct */
+ pGenObj->objData.nodeObj.ndbProps.cbStruct =
+ (u32) Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* DSP_UUID uiNodeID */
+ UUID_UuidFromString(token,
+ &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
+ token = strsep(&pszCur, seps);
+
+ /* acName */
+ DBC_Require(token);
+ cLen = strlen(token);
+ if (cLen > DSP_MAXNAMELEN - 1)
+ cLen = DSP_MAXNAMELEN - 1;
+
+ strncpy(pGenObj->objData.nodeObj.ndbProps.acName,
+ token, cLen);
+ pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
+ token = strsep(&pszCur, seps);
+ /* u32 uNodeType */
+ pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
+ token = strsep(&pszCur, seps);
+ /* u32 bCacheOnGPP */
+ pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
+ token = strsep(&pszCur, seps);
+ /* DSP_RESOURCEREQMTS dspResourceReqmts */
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
+ (u32) Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uStaticDataSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uGlobalDataSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uProgramMemSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uWCExecutionTime = Atoi(token);
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uWCPeriod = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uWCDeadline = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uAvgExectionTime = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+ uMinimumPeriod = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* s32 iPriority */
+ pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uStackSize */
+ pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uSysStackSize */
+ pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uStackSeg */
+ pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uMessageDepth */
+ pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uNumInputStreams */
+ pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
+ Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uNumOutputStreams */
+ pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
+ Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* u32 uTimeout */
+ pGenObj->objData.nodeObj.ndbProps.uTimeout =
+ Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* char * pstrCreatePhaseFxn */
+ DBC_Require(token);
+ cLen = strlen(token);
+ pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
+ MEM_Calloc(cLen + 1, MEM_PAGED);
+ strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
+ token, cLen);
+ pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
+ token = strsep(&pszCur, seps);
+
+ /* char * pstrExecutePhaseFxn */
+ DBC_Require(token);
+ cLen = strlen(token);
+ pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
+ MEM_Calloc(cLen + 1, MEM_PAGED);
+ strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
+ token, cLen);
+ pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
+ token = strsep(&pszCur, seps);
+
+ /* char * pstrDeletePhaseFxn */
+ DBC_Require(token);
+ cLen = strlen(token);
+ pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
+ MEM_Calloc(cLen + 1, MEM_PAGED);
+ strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
+ token, cLen);
+ pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
+ token = strsep(&pszCur, seps);
+
+ /* Segment id for message buffers */
+ pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* Message notification type */
+ pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ /* char * pstrIAlgName */
+ if (token) {
+ cLen = strlen(token);
+ pGenObj->objData.nodeObj.pstrIAlgName =
+ MEM_Calloc(cLen + 1, MEM_PAGED);
+ strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
+ token, cLen);
+ pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
+ token = strsep(&pszCur, seps);
+ }
+
+ /* Load type (static, dynamic, or overlay) */
+ if (token) {
+ pGenObj->objData.nodeObj.usLoadType = Atoi(token);
+ token = strsep(&pszCur, seps);
+ }
+
+ /* Dynamic load data requirements */
+ if (token) {
+ pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
+ token = strsep(&pszCur, seps);
+ }
+
+ /* Dynamic load code requirements */
+ if (token) {
+ pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
+ token = strsep(&pszCur, seps);
+ }
+
+ /* Extract node profiles into node properties */
+ if (token) {
+
+ pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
+ Atoi(token);
+ for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
+ uCountProfiles; i++) {
+ token = strsep(&pszCur, seps);
+ if (token) {
+ /* Heap Size for the node */
+ pGenObj->objData.nodeObj.ndbProps.
+ aProfiles[i].ulHeapSize =
+ Atoi(token);
+ }
+ }
+ }
+ token = strsep(&pszCur, seps);
+ if (token) {
+ pGenObj->objData.nodeObj.ndbProps.uStackSegName =
+ (u32)(token);
+ }
+
+ break;
+
+ case DSP_DCDPROCESSORTYPE:
+ /*
+ * Parse COFF sect buffer to retrieve individual tokens used
+ * to fill in object attrs.
+ */
+ pszCur = pszBuf;
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.cbStruct = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.uProcessorType = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.uClockRate = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.uProcessorID = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
+ token = strsep(&pszCur, seps);
+
+ pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
+
+#ifdef _DB_TIOMAP
+ /* Proc object may contain additional(extended) attributes. */
+ /* attr must match proc.hxx */
+ for (iEntry = 0; iEntry < 7; iEntry++) {
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
+ Atoi(token);
+
+ token = strsep(&pszCur, seps);
+ pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
+ Atoi(token);
+ }
+#endif
+
+ break;
+
+ default:
+ status = DSP_EFAIL;
+ break;
+ }
+
+ return status;
+}
+
+/*
+ * ======== CompressBuffer ========
+ * Purpose:
+ * Compress the DSP buffer, if necessary, to conform to PC format.
+ */
+static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
+{
+ char *p;
+ char ch;
+ char *q;
+
+ p = pszBuf;
+ if (p == NULL)
+ return;
+
+ for (q = pszBuf; q < (pszBuf + ulBufSize);) {
+
+ ch = DspChar2GppChar(q, cCharSize);
+ if (ch == '\\') {
+ q += cCharSize;
+ ch = DspChar2GppChar(q, cCharSize);
+ switch (ch) {
+ case 't':
+ *p = '\t';
+ break;
+
+ case 'n':
+ *p = '\n';
+ break;
+
+ case 'r':
+ *p = '\r';
+ break;
+
+ case '0':
+ *p = '\0';
+ break;
+
+ default:
+ *p = ch;
+ break;
+ }
+ } else {
+ *p = ch;
+ }
+ p++;
+ q += cCharSize;
+ }
+
+ /* NULL out remainder of buffer. */
+ while (p < q)
+ *p++ = '\0';
+
+}
+
+/*
+ * ======== DspChar2GppChar ========
+ * Purpose:
+ * Convert DSP char to host GPP char in a portable manner
+ */
+static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
+{
+ char ch = '\0';
+ char *chSrc;
+ s32 i;
+
+ for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
+ ch |= *chSrc++;
+
+ return ch;
+}
+
+/*
+ * ======== GetDepLibInfo ========
+ */
+static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
+ IN struct DSP_UUID *pUuid,
+ IN OUT u16 *pNumLibs,
+ OPTIONAL OUT u16 *pNumPersLibs,
+ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
+ OPTIONAL OUT bool *pPersistentDepLibs,
+ enum NLDR_PHASE phase)
+{
+ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
+ char *pszCoffBuf = NULL;
+ char *pszCur;
+ char *pszFileName = NULL;
+ struct COD_LIBRARYOBJ *lib = NULL;
+ u32 ulAddr = 0; /* Used by COD_GetSection */
+ u32 ulLen = 0; /* Used by COD_GetSection */
+ u32 dwDataSize = COD_MAXPATHLENGTH;
+ char seps[] = ", ";
+ char *pToken = NULL;
+ bool fGetUuids = (pDepLibUuids != NULL);
+ u16 nDepLibs = 0;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ DBC_Require(IsValidHandle(hDcdMgr));
+ DBC_Require(pNumLibs != NULL);
+ DBC_Require(pUuid != NULL);
+
+ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
+ hDcdMgr);
+
+ /* Initialize to 0 dependent libraries, if only counting number of
+ * dependent libraries */
+ if (!fGetUuids) {
+ *pNumLibs = 0;
+ *pNumPersLibs = 0;
+ }
+
+ /* Allocate a buffer for file name */
+ pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
+ if (pszFileName == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Get the name of the library */
+ status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
+ &dwDataSize, phase, NULL);
+ }
+ /* Open the library */
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
+ COD_NOLOAD, &lib);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get dependent library section information. */
+ status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
+
+ if (DSP_FAILED(status)) {
+ /* Ok, no dependent libraries */
+ ulLen = 0;
+ status = DSP_SNODEPENDENTLIBS;
+ }
+ }
+
+ if (DSP_FAILED(status) || !(ulLen > 0))
+ goto func_cont;
+
+ /* Allocate zeroed buffer. */
+ pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
+ if (pszCoffBuf == NULL)
+ status = DSP_EMEMORY;
+
+ /* Read section contents. */
+ status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ /* Compress and format DSP buffer to conform to PC format. */
+ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+ /* Read from buffer */
+ pszCur = pszCoffBuf;
+ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
+ if (fGetUuids) {
+ if (nDepLibs >= *pNumLibs) {
+ /* Gone beyond the limit */
+ break;
+ } else {
+ /* Retrieve UUID string. */
+ UUID_UuidFromString(pToken,
+ &(pDepLibUuids[nDepLibs]));
+ /* Is this library persistent? */
+ pToken = strsep(&pszCur, seps);
+ pPersistentDepLibs[nDepLibs] = Atoi(pToken);
+ nDepLibs++;
+ }
+ } else {
+ /* Advanc to next token */
+ pToken = strsep(&pszCur, seps);
+ if (Atoi(pToken))
+ (*pNumPersLibs)++;
+
+ /* Just counting number of dependent libraries */
+ (*pNumLibs)++;
+ }
+ }
+func_cont:
+ if (lib)
+ COD_Close(lib);
+
+ /* Free previously allocated dynamic buffers. */
+ if (pszFileName)
+ MEM_Free(pszFileName);
+
+ if (pszCoffBuf)
+ MEM_Free(pszCoffBuf);
+
+ return status;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
new file mode 100644
index 000000000000..3fbbf0199e33
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/disp.c
@@ -0,0 +1,916 @@
+/*
+ * disp.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== disp.c ========
+ *
+ * Description:
+ * Node Dispatcher interface. Communicates with Resource Manager Server
+ * (RMS) on DSP. Access to RMS is synchronized in NODE.
+ *
+ * Public Functions:
+ * DISP_Create
+ * DISP_Delete
+ * DISP_Exit
+ * DISP_Init
+ * DISP_NodeChangePriority
+ * DISP_NodeCreate
+ * DISP_NodeDelete
+ * DISP_NodePause
+ * DISP_NodeRun
+ *
+ *! Revision History:
+ *! =================
+ *! 18-Feb-2003 vp Code review updates
+ *! 18-Oct-2002 vp Ported to Linux platform
+ *! 16-May-2002 jeh Added DISP_DoCinit().
+ *! 24-Apr-2002 jeh Added DISP_MemWrite().
+ *! 13-Feb-2002 jeh Pass system stack size to RMS.
+ *! 16-Jan-2002 ag Added bufsize param to _ChnlAddIOReq() fxn
+ *! 10-May-2001 jeh Code Review cleanup.
+ *! 26-Sep-2000 jeh Fixed status values in SendMessage().
+ *! 19-Jun-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/gt.h>
+#include <dspbridge/dbc.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/dev.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/csl.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmd.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/chnldefs.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/nodedefs.h>
+#include <dspbridge/nodepriv.h>
+#include <dspbridge/rms_sh.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/disp.h>
+
+#define DISP_SIGNATURE 0x50534944 /* "PSID" */
+
+/* Size of a reply from RMS */
+#define REPLYSIZE (3 * sizeof(RMS_WORD))
+
+/* Reserved channel offsets for communication with RMS */
+#define CHNLTORMSOFFSET 0
+#define CHNLFROMRMSOFFSET 1
+
+#define CHNLIOREQS 1
+
+#define SwapWord(x) (((u32)(x) >> 16) | ((u32)(x) << 16))
+
+/*
+ * ======== DISP_OBJECT ========
+ */
+struct DISP_OBJECT {
+ u32 dwSignature; /* Used for object validation */
+ struct DEV_OBJECT *hDevObject; /* Device for this processor */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+ struct CHNL_MGR *hChnlMgr; /* Channel manager */
+ struct CHNL_OBJECT *hChnlToDsp; /* Channel for commands to RMS */
+ struct CHNL_OBJECT *hChnlFromDsp; /* Channel for replies from RMS */
+ u8 *pBuf; /* Buffer for commands, replies */
+ u32 ulBufsize; /* pBuf size in bytes */
+ u32 ulBufsizeRMS; /* pBuf size in RMS words */
+ u32 uCharSize; /* Size of DSP character */
+ u32 uWordSize; /* Size of DSP word */
+ u32 uDataMauSize; /* Size of DSP Data MAU */
+};
+
+static u32 cRefs;
+
+/* Debug msgs: */
+#if GT_TRACE
+static struct GT_Mask DISP_DebugMask = { NULL, NULL };
+#endif
+
+static void DeleteDisp(struct DISP_OBJECT *hDisp);
+static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
+ struct NODE_STRMDEF strmDef, u32 max,
+ u32 uCharsInRMSWord);
+static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
+ u32 ulBytes, OUT u32 *pdwArg);
+
+/*
+ * ======== DISP_Create ========
+ * Create a NODE Dispatcher object.
+ */
+DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct DISP_ATTRS *pDispAttrs)
+{
+ struct DISP_OBJECT *pDisp;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ u32 ulChnlId;
+ struct CHNL_ATTRS chnlAttrs;
+ DSP_STATUS status = DSP_SOK;
+ u32 devType;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDispObject != NULL);
+ DBC_Require(pDispAttrs != NULL);
+ DBC_Require(hDevObject != NULL);
+
+ GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
+ "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
+ hDevObject, pDispAttrs);
+
+ *phDispObject = NULL;
+
+ /* Allocate Node Dispatcher object */
+ MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
+ if (pDisp == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: MEM_AllocObject() failed!\n");
+ } else {
+ pDisp->hDevObject = hDevObject;
+ }
+
+ /* Get Channel manager and WMD function interface */
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
+ if (DSP_SUCCEEDED(status)) {
+ (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+ pDisp->pIntfFxns = pIntfFxns;
+ } else {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: Failed to get "
+ "channel manager! status = 0x%x\n", status);
+ }
+ }
+
+ /* check device type and decide if streams or messag'ing is used for
+ * RMS/EDS */
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ status = DEV_GetDevType(hDevObject, &devType);
+ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
+ "device = 0x%x\n", devType);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ if (devType != DSP_UNIT) {
+ GT_0trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: Unkown device "
+ "type in Device object !! \n");
+ status = DSP_EFAIL;
+ goto func_cont;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pDisp->uCharSize = DSPWORDSIZE;
+ pDisp->uWordSize = DSPWORDSIZE;
+ pDisp->uDataMauSize = DSPWORDSIZE;
+ /* Open channels for communicating with the RMS */
+ chnlAttrs.uIOReqs = CHNLIOREQS;
+ chnlAttrs.hEvent = NULL;
+ ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
+ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
+ pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
+ if (DSP_FAILED(status)) {
+ GT_2trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: Channel to RMS "
+ "open failed, chnl id = %d, status = 0x%x\n",
+ ulChnlId, status);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
+ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
+ pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
+ &chnlAttrs);
+ if (DSP_FAILED(status)) {
+ GT_2trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: Channel from RMS "
+ "open failed, chnl id = %d, status = 0x%x\n",
+ ulChnlId, status);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Allocate buffer for commands, replies */
+ pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
+ pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
+ pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
+ if (pDisp->pBuf == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Create: Failed "
+ "to allocate channel buffer!\n");
+ }
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status))
+ *phDispObject = pDisp;
+ else
+ DeleteDisp(pDisp);
+
+ DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
+ ((DSP_SUCCEEDED(status)) &&
+ (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
+ return status;
+}
+
+/*
+ * ======== DISP_Delete ========
+ * Delete the NODE Dispatcher.
+ */
+void DISP_Delete(struct DISP_OBJECT *hDisp)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+
+ GT_1trace(DISP_DebugMask, GT_ENTER,
+ "DISP_Delete: hDisp: 0x%x\n", hDisp);
+
+ DeleteDisp(hDisp);
+
+ DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+}
+
+/*
+ * ======== DISP_Exit ========
+ * Discontinue usage of DISP module.
+ */
+void DISP_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(DISP_DebugMask, GT_5CLASS,
+ "Entered DISP_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== DISP_Init ========
+ * Initialize the DISP module.
+ */
+bool DISP_Init(void)
+{
+ bool fRetVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!DISP_DebugMask.flags);
+ GT_create(&DISP_DebugMask, "DI"); /* "DI" for DIspatcher */
+ }
+
+ if (fRetVal)
+ cRefs++;
+
+ GT_1trace(DISP_DebugMask, GT_5CLASS,
+ "DISP_Init(), ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+ return fRetVal;
+}
+
+/*
+ * ======== DISP_NodeChangePriority ========
+ * Change the priority of a node currently running on the target.
+ */
+DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
+ struct NODE_OBJECT *hNode,
+ u32 ulRMSFxn, NODE_ENV nodeEnv,
+ s32 nPriority)
+{
+ u32 dwArg;
+ struct RMS_Command *pCommand;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+ DBC_Require(hNode != NULL);
+
+ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
+ "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
+ hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
+
+ /* Send message to RMS to change priority */
+ pCommand = (struct RMS_Command *)(hDisp->pBuf);
+ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+ pCommand->arg1 = (RMS_WORD)nodeEnv;
+ pCommand->arg2 = nPriority;
+ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+ sizeof(struct RMS_Command), &dwArg);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeChangePriority failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== DISP_NodeCreate ========
+ * Create a node on the DSP by remotely calling the node's create function.
+ */
+DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+ u32 ulRMSFxn, u32 ulCreateFxn,
+ IN CONST struct NODE_CREATEARGS *pArgs,
+ OUT NODE_ENV *pNodeEnv)
+{
+ struct NODE_MSGARGS msgArgs;
+ struct NODE_TASKARGS taskArgs;
+ struct RMS_Command *pCommand;
+ struct RMS_MsgArgs *pMsgArgs;
+ struct RMS_MoreTaskArgs *pMoreTaskArgs;
+ enum NODE_TYPE nodeType;
+ u32 dwLength;
+ RMS_WORD *pdwBuf = NULL;
+ u32 ulBytes;
+ u32 i;
+ u32 total;
+ u32 uCharsInRMSWord;
+ s32 taskArgsOffset;
+ s32 sioInDefOffset;
+ s32 sioOutDefOffset;
+ s32 sioDefsOffset;
+ s32 argsOffset = -1;
+ s32 offset;
+ struct NODE_STRMDEF strmDef;
+ u32 max;
+ DSP_STATUS status = DSP_SOK;
+ struct DSP_NODEINFO nodeInfo;
+ u32 devType;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+ DBC_Require(hNode != NULL);
+ DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
+ DBC_Require(pNodeEnv != NULL);
+
+ GT_6trace(DISP_DebugMask, GT_ENTER,
+ "DISP_NodeCreate: hDisp: 0x%x\thNode:"
+ " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
+ " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
+
+ status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
+ "for device = 0x%x\n", devType);
+
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ if (devType != DSP_UNIT) {
+ GT_1trace(DISP_DebugMask, GT_7CLASS,
+ "DISP_NodeCreate unknown device "
+ "type = 0x%x\n", devType);
+ goto func_end;
+ }
+ DBC_Require(pArgs != NULL);
+ nodeType = NODE_GetType(hNode);
+ msgArgs = pArgs->asa.msgArgs;
+ max = hDisp->ulBufsizeRMS; /*Max # of RMS words that can be sent */
+ DBC_Assert(max == RMS_COMMANDBUFSIZE);
+ uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
+ /* Number of RMS words needed to hold arg data */
+ dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
+ /* Make sure msg args and command fit in buffer */
+ total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
+ sizeof(struct RMS_MsgArgs)
+ / sizeof(RMS_WORD) - 1 + dwLength;
+ if (total >= max) {
+ status = DSP_EFAIL;
+ GT_2trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeCreate: Message args too"
+ " large for buffer! Message args size = %d, max = %d\n",
+ total, max);
+ }
+ /*
+ * Fill in buffer to send to RMS.
+ * The buffer will have the following format:
+ *
+ * RMS command:
+ * Address of RMS_CreateNode()
+ * Address of node's create function
+ * dummy argument
+ * node type
+ *
+ * Message Args:
+ * max number of messages
+ * segid for message buffer allocation
+ * notification type to use when message is received
+ * length of message arg data
+ * message args data
+ *
+ * Task Args (if task or socket node):
+ * priority
+ * stack size
+ * system stack size
+ * stack segment
+ * misc
+ * number of input streams
+ * pSTRMInDef[] - offsets of STRM definitions for input streams
+ * number of output streams
+ * pSTRMOutDef[] - offsets of STRM definitions for output
+ * streams
+ * STRMInDef[] - array of STRM definitions for input streams
+ * STRMOutDef[] - array of STRM definitions for output streams
+ *
+ * Socket Args (if DAIS socket node):
+ *
+ */
+ if (DSP_SUCCEEDED(status)) {
+ total = 0; /* Total number of words in buffer so far */
+ pdwBuf = (RMS_WORD *)hDisp->pBuf;
+ pCommand = (struct RMS_Command *)pdwBuf;
+ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+ pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
+ if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
+ /* Flush ICACHE on Load */
+ pCommand->arg2 = 1; /* dummy argument */
+ } else {
+ /* Do not flush ICACHE */
+ pCommand->arg2 = 0; /* dummy argument */
+ }
+ pCommand->data = NODE_GetType(hNode);
+ /*
+ * argsOffset is the offset of the data field in struct
+ * RMS_Command structure. We need this to calculate stream
+ * definition offsets.
+ */
+ argsOffset = 3;
+ total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
+ /* Message args */
+ pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
+ pMsgArgs->maxMessages = msgArgs.uMaxMessages;
+ pMsgArgs->segid = msgArgs.uSegid;
+ pMsgArgs->notifyType = msgArgs.uNotifyType;
+ pMsgArgs->argLength = msgArgs.uArgLength;
+ total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
+ memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
+ total += dwLength;
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* If node is a task node, copy task create arguments into buffer */
+ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
+ taskArgs = pArgs->asa.taskArgs;
+ taskArgsOffset = total;
+ total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
+ 1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
+ /* Copy task arguments */
+ if (total < max) {
+ total = taskArgsOffset;
+ pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
+ total);
+ /*
+ * Get some important info about the node. Note that we
+ * don't just reach into the hNode struct because
+ * that would break the node object's abstraction.
+ */
+ GetNodeInfo(hNode, &nodeInfo);
+ GT_2trace(DISP_DebugMask, GT_ENTER,
+ "uExecutionPriority %x, nPriority %x\n",
+ nodeInfo.uExecutionPriority,
+ taskArgs.nPriority);
+ pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
+ pMoreTaskArgs->stackSize = taskArgs.uStackSize;
+ pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
+ pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
+ pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
+ pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
+ pMoreTaskArgs->misc = taskArgs.ulDaisArg;
+ pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
+ total +=
+ sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
+ GT_2trace(DISP_DebugMask, GT_7CLASS,
+ "DISP::::uDSPHeapAddr %x, "
+ "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
+ taskArgs.uHeapSize);
+ /* Keep track of pSIOInDef[] and pSIOOutDef[]
+ * positions in the buffer, since this needs to be
+ * filled in later. */
+ sioInDefOffset = total;
+ total += taskArgs.uNumInputs;
+ pdwBuf[total++] = taskArgs.uNumOutputs;
+ sioOutDefOffset = total;
+ total += taskArgs.uNumOutputs;
+ sioDefsOffset = total;
+ /* Fill SIO defs and offsets */
+ offset = sioDefsOffset;
+ for (i = 0; i < taskArgs.uNumInputs; i++) {
+ if (DSP_FAILED(status))
+ break;
+
+ pdwBuf[sioInDefOffset + i] =
+ (offset - argsOffset)
+ * (sizeof(RMS_WORD) / DSPWORDSIZE);
+ strmDef = taskArgs.strmInDef[i];
+ status = FillStreamDef(pdwBuf, &total, offset,
+ strmDef, max, uCharsInRMSWord);
+ offset = total;
+ }
+ for (i = 0; (i < taskArgs.uNumOutputs) &&
+ (DSP_SUCCEEDED(status)); i++) {
+ pdwBuf[sioOutDefOffset + i] =
+ (offset - argsOffset)
+ * (sizeof(RMS_WORD) / DSPWORDSIZE);
+ strmDef = taskArgs.strmOutDef[i];
+ status = FillStreamDef(pdwBuf, &total, offset,
+ strmDef, max, uCharsInRMSWord);
+ offset = total;
+ }
+ if (DSP_FAILED(status)) {
+ GT_2trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeCreate: Message"
+ " args to large for buffer! Message args"
+ " size = %d, max = %d\n", total, max);
+ }
+ } else {
+ /* Args won't fit */
+ status = DSP_EFAIL;
+ GT_2trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeCreate: Message args "
+ " too large for buffer! Message args size = %d"
+ ", max = %d\n", total, max);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ ulBytes = total * sizeof(RMS_WORD);
+ DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
+ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+ ulBytes, pNodeEnv);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeCreate failed! "
+ "status = 0x%x\n", status);
+ } else {
+ /*
+ * Message successfully received from RMS.
+ * Return the status of the Node's create function
+ * on the DSP-side
+ */
+ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeCreate, "
+ "DSP-side Node Create failed: 0x%x\n",
+ status);
+ }
+
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== DISP_NodeDelete ========
+ * purpose:
+ * Delete a node on the DSP by remotely calling the node's delete function.
+ *
+ */
+DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+ u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
+{
+ u32 dwArg;
+ struct RMS_Command *pCommand;
+ DSP_STATUS status = DSP_SOK;
+ u32 devType;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+ DBC_Require(hNode != NULL);
+
+ GT_5trace(DISP_DebugMask, GT_ENTER,
+ "DISP_NodeDelete: hDisp: 0x%xthNode: "
+ "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
+ hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
+
+ status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+ if (DSP_SUCCEEDED(status)) {
+
+ if (devType == DSP_UNIT) {
+
+ /*
+ * Fill in buffer to send to RMS
+ */
+ pCommand = (struct RMS_Command *)hDisp->pBuf;
+ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+ pCommand->arg1 = (RMS_WORD)nodeEnv;
+ pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
+ pCommand->data = NODE_GetType(hNode);
+
+ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+ sizeof(struct RMS_Command), &dwArg);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeDelete failed!"
+ "status = 0x%x\n", status);
+ } else {
+ /*
+ * Message successfully received from RMS.
+ * Return the status of the Node's delete
+ * function on the DSP-side
+ */
+ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeDelete, "
+ "DSP-side Node Delete failed: 0x%x\n",
+ status);
+ }
+ }
+
+
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== DISP_NodeRun ========
+ * purpose:
+ * Start execution of a node's execute phase, or resume execution of a node
+ * that has been suspended (via DISP_NodePause()) on the DSP.
+ */
+DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+ u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
+{
+ u32 dwArg;
+ struct RMS_Command *pCommand;
+ DSP_STATUS status = DSP_SOK;
+ u32 devType;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+ DBC_Require(hNode != NULL);
+
+ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
+ 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
+ hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
+
+ status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+ if (DSP_SUCCEEDED(status)) {
+
+ if (devType == DSP_UNIT) {
+
+ /*
+ * Fill in buffer to send to RMS.
+ */
+ pCommand = (struct RMS_Command *) hDisp->pBuf;
+ pCommand->fxn = (RMS_WORD) (ulRMSFxn);
+ pCommand->arg1 = (RMS_WORD) nodeEnv;
+ pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
+ pCommand->data = NODE_GetType(hNode);
+
+ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+ sizeof(struct RMS_Command), &dwArg);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeRun failed!"
+ "status = 0x%x\n", status);
+ } else {
+ /*
+ * Message successfully received from RMS.
+ * Return the status of the Node's execute
+ * function on the DSP-side
+ */
+ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_NodeRun, DSP-side Node "
+ "Execute failed: 0x%x\n",
+ status);
+ }
+ }
+
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== DeleteDisp ========
+ * purpose:
+ * Frees the resources allocated for the dispatcher.
+ */
+static void DeleteDisp(struct DISP_OBJECT *hDisp)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+
+ if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
+ pIntfFxns = hDisp->pIntfFxns;
+
+ /* Free Node Dispatcher resources */
+ if (hDisp->hChnlFromDsp) {
+ /* Channel close can fail only if the channel handle
+ * is invalid. */
+ status = (*pIntfFxns->pfnChnlClose)
+ (hDisp->hChnlFromDsp);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Delete: Failed to "
+ "close channel from RMS: 0x%x\n",
+ status);
+ }
+ }
+ if (hDisp->hChnlToDsp) {
+ status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "DISP_Delete: Failed to "
+ "close channel to RMS: 0x%x\n",
+ status);
+ }
+ }
+ if (hDisp->pBuf)
+ MEM_Free(hDisp->pBuf);
+
+ MEM_FreeObject(hDisp);
+ }
+}
+
+/*
+ * ======== FillStreamDef ========
+ * purpose:
+ * Fills stream definitions.
+ */
+static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
+ struct NODE_STRMDEF strmDef, u32 max,
+ u32 uCharsInRMSWord)
+{
+ struct RMS_StrmDef *pStrmDef;
+ u32 total = *ptotal;
+ u32 uNameLen;
+ u32 dwLength;
+ DSP_STATUS status = DSP_SOK;
+
+ if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
+ status = DSP_EFAIL;
+ } else {
+ pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
+ pStrmDef->bufsize = strmDef.uBufsize;
+ pStrmDef->nbufs = strmDef.uNumBufs;
+ pStrmDef->segid = strmDef.uSegid;
+ pStrmDef->align = strmDef.uAlignment;
+ pStrmDef->timeout = strmDef.uTimeout;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /*
+ * Since we haven't added the device name yet, subtract
+ * 1 from total.
+ */
+ total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
+ DBC_Require(strmDef.szDevice);
+ dwLength = strlen(strmDef.szDevice) + 1;
+
+ /* Number of RMS_WORDS needed to hold device name */
+ uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
+
+ if (total + uNameLen >= max) {
+ status = DSP_EFAIL;
+ } else {
+ /*
+ * Zero out last word, since the device name may not
+ * extend to completely fill this word.
+ */
+ pdwBuf[total + uNameLen - 1] = 0;
+ /** TODO USE SERVICES **/
+ memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
+ total += uNameLen;
+ *ptotal = total;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== SendMessage ======
+ * Send command message to RMS, get reply from RMS.
+ */
+static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
+ u32 ulBytes, u32 *pdwArg)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct CHNL_OBJECT *hChnl;
+ u32 dwArg = 0;
+ u8 *pBuf;
+ struct CHNL_IOC chnlIOC;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(pdwArg != NULL);
+
+ *pdwArg = (u32) NULL;
+ pIntfFxns = hDisp->pIntfFxns;
+ hChnl = hDisp->hChnlToDsp;
+ pBuf = hDisp->pBuf;
+
+ /* Send the command */
+ status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
+ 0L, dwArg);
+
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage: Channel AddIOReq to"
+ " RMS failed! Status = 0x%x\n", status);
+ goto func_cont;
+ }
+ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
+ if (DSP_SUCCEEDED(status)) {
+ if (!CHNL_IsIOComplete(chnlIOC)) {
+ if (CHNL_IsTimedOut(chnlIOC)) {
+ status = DSP_ETIMEOUT;
+ } else {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage failed! "
+ "Channel IOC status = 0x%x\n",
+ chnlIOC.status);
+ status = DSP_EFAIL;
+ }
+ }
+ } else {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage: Channel GetIOC to"
+ " RMS failed! Status = 0x%x\n", status);
+ }
+func_cont:
+ /* Get the reply */
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ hChnl = hDisp->hChnlFromDsp;
+ ulBytes = REPLYSIZE;
+ status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
+ 0, 0L, dwArg);
+ if (DSP_FAILED(status)) {
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage: Channel AddIOReq "
+ "from RMS failed! Status = 0x%x\n", status);
+ goto func_end;
+ }
+ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
+ if (DSP_SUCCEEDED(status)) {
+ if (CHNL_IsTimedOut(chnlIOC)) {
+ status = DSP_ETIMEOUT;
+ } else if (chnlIOC.cBytes < ulBytes) {
+ /* Did not get all of the reply from the RMS */
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage: Did not get all"
+ "of reply from RMS! Bytes received: %d\n",
+ chnlIOC.cBytes);
+ status = DSP_EFAIL;
+ } else {
+ if (CHNL_IsIOComplete(chnlIOC)) {
+ DBC_Assert(chnlIOC.pBuf == pBuf);
+ status = (*((RMS_WORD *)chnlIOC.pBuf));
+ *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
+ } else {
+ status = DSP_EFAIL;
+ }
+ }
+ } else {
+ /* GetIOC failed */
+ GT_1trace(DISP_DebugMask, GT_6CLASS,
+ "SendMessage: Failed to get "
+ "reply from RMS! Status = 0x%x\n", status);
+ }
+func_end:
+ return status;
+}
diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
new file mode 100755
index 000000000000..8690f08b0288
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv.c
@@ -0,0 +1,1936 @@
+/*
+ * drv.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== drv.c ========
+ * Description:
+ * DSP/BIOS Bridge resource allocation module.
+ *
+ * Public Functions:
+ * DRV_Create
+ * DRV_Destroy
+ * DRV_Exit
+ * DRV_GetDevObject
+ * DRV_GetDevExtension
+ * DRV_GetFirstDevObject
+ * DRV_GetNextDevObject
+ * DRV_GetNextDevExtension
+ * DRV_Init
+ * DRV_InsertDevObject
+ * DRV_RemoveDevObject
+ * DRV_RequestResources
+ * DRV_ReleaseResources
+ *
+ *! Revision History
+ *! ======== ========
+ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
+ MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
+ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
+ *! 05-Jan-2004 vp: Updated for 24xx platform
+ *! 21-Mar-2003 sb: Get SHM size from registry
+ *! 10-Feb-2003 vp: Code review updates
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
+ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
+ *! RequestISAResources()
+ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
+ *! RequestISAResources.
+ *! 07-Aug-2000 rr: static list of dev objects removed.
+ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
+ *! Device extension created to hold the DevNodeString.
+ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
+ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
+ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
+ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
+ *! instead of MEM_Alloc.
+ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
+ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
+ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
+ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
+ *! struct CFG_HOSTRES Structure.
+ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
+ *! DBC_Ensure checks for sucess and pDevice != NULL
+ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
+ *! 09-Dec-1999 rr: windows.h included to remove warnings.
+ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
+ *! status while making call to Reg functions.
+ *! 23-Nov-1999 rr: windows.h included
+ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
+ *! fixed.
+ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
+ *! Hardcoded bIRQRegister define removed.
+ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
+ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
+ *! Resource structure directly.
+ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
+ *! dwBusType taken from the registry.Hard coded
+ *! registry entries removed.
+ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
+ *! MiniDriver has been renamed to DRV_RequestResources.
+ *! DRV_UnRegisterMiniDriver fxn removed.
+ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
+ *! Now it is simpler. IT stores the dev node in the
+ *! registry, assign resources and calls the DEV_Start.
+ *! 10-Sep-1999 rr: Register Minidriver modified.
+ *! - Resource structure follows the NT model
+ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/reg.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/drv.h>
+#include <dspbridge/dev.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/node.h>
+#include <dspbridge/proc.h>
+#include <dspbridge/strm.h>
+#include <dspbridge/nodepriv.h>
+#include <dspbridge/wmdchnl.h>
+#include <dspbridge/resourcecleanup.h>
+#endif
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define SIGNATURE 0x5f52474d /* "DRV_" (in reverse) */
+
+struct DRV_OBJECT {
+ u32 dwSignature;
+ struct LST_LIST *devList;
+ struct LST_LIST *devNodeString;
+#ifndef RES_CLEANUP_DISABLE
+ struct PROCESS_CONTEXT *procCtxtList;
+#endif
+};
+
+/*
+ * This is the Device Extension. Named with the Prefix
+ * DRV_ since it is living in this module
+ */
+struct DRV_EXT {
+ struct LST_ELEM link;
+ char szString[MAXREGPATHLENGTH];
+};
+
+/* ----------------------------------- Globals */
+static s32 cRefs;
+
+#if GT_TRACE
+extern struct GT_Mask curTrace;
+#endif
+
+/* ----------------------------------- Function Prototypes */
+static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
+static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
+
+#ifndef RES_CLEANUP_DISABLE
+/* GPP PROCESS CLEANUP CODE */
+
+static DSP_STATUS PrintProcessInformation(void);
+static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt);
+static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt);
+extern enum NODE_STATE NODE_GetState(HANDLE hNode);
+
+/* Get the process context list from driver object */
+
+/* Set the Process ID */
+DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Assert(hPCtxt != NULL);
+
+ pCtxt->pid = hProcess;
+ return status;
+}
+
+
+/* Getting the head of the process context list */
+DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
+ struct DRV_OBJECT *hDrvObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+
+ DBC_Assert(hDrvObject != NULL);
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
+ ":%x", *pPctxt, pDrvObject);
+ *pPctxt = pDrvObject->procCtxtList;
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
+ ":%x", *pPctxt, pDrvObject);
+ return status;
+}
+
+
+
+/* Get a particular process context based on process handle (phProcess) */
+DSP_STATUS DRV_GetProcContext(u32 phProcess,
+ struct DRV_OBJECT *hDrvObject,
+ HANDLE hPCtxt, DSP_HNODE hNode,
+ u32 pMapAddr)
+{
+ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct PROCESS_CONTEXT *pCtxtList = NULL;
+ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+ struct NODE_RES_OBJECT *pTempNode2 = NULL;
+ struct NODE_RES_OBJECT *pTempNode = NULL;
+ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
+ struct DMM_RES_OBJECT *pTempDMM = NULL;
+ s32 pCtxtFound = 0;
+
+ DBC_Assert(pDrvObject != NULL);
+ pCtxtList = pDrvObject->procCtxtList;
+ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
+ while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
+ pCtxtList = pCtxtList->next;
+ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
+ }
+ if (pCtxtList == NULL) {
+ if (hNode != NULL) {
+ pCtxtList = pDrvObject->procCtxtList;
+ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
+ pTempNode = pCtxtList->pNodeList;
+ while ((pTempNode != NULL) &&
+ (pTempNode->hNode != hNode)) {
+ pTempNode2 = pTempNode;
+ pTempNode = pTempNode->next;
+ }
+ if (pTempNode != NULL) {
+ pCtxtFound = 1;
+ status = DSP_SOK;
+ } else {
+ pCtxtList = pCtxtList->next;
+ }
+ }
+ } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
+ pCtxtList = pDrvObject->procCtxtList;
+ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
+ pTempDMM = pCtxtList->pDMMList;
+ while ((pTempDMM != NULL) &&
+ (pTempDMM->ulDSPAddr != pMapAddr)) {
+ pTempDMM2 = pTempDMM;
+ pTempDMM = pTempDMM->next;
+ }
+ if (pTempDMM != NULL) {
+ pCtxtFound = 1;
+ status = DSP_SOK;
+ } else {
+ pCtxtList = pCtxtList->next;
+ }
+ }
+ if (pCtxtList == NULL)
+ status = DSP_ENOTFOUND;
+
+ }
+ } else{
+ status = DSP_SOK;
+ }
+ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
+ *pCtxt = pCtxtList;
+ return status;
+}
+
+
+/* Add a new process context to process context list */
+DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct PROCESS_CONTEXT *pCtxtList = NULL;
+ struct DRV_OBJECT *hDRVObject;
+
+ GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
+ status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+ DBC_Assert(hDRVObject != NULL);
+ *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
+ GT_0trace(curTrace, GT_ENTER,
+ "\n In DRV_InsertProcContext Calling "
+ "DRV_GetProcCtxtList\n");
+ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
+ GT_0trace(curTrace, GT_ENTER,
+ "\n In DRV_InsertProcContext After Calling "
+ "DRV_GetProcCtxtList\n");
+ if (pCtxtList != NULL) {
+ GT_0trace(curTrace, GT_ENTER,
+ "\n In DRV_InsertProcContext and pCtxt is "
+ "not Null\n");
+ while (pCtxtList->next != NULL)
+ pCtxtList = pCtxtList->next;
+
+ pCtxtList->next = *pCtxt;
+ } else {
+ GT_0trace(curTrace, GT_ENTER,
+ "\n In DRV_InsertProcContext and "
+ "pCtxt is Null\n");
+ hDRVObject->procCtxtList = *pCtxt;
+ }
+ return status;
+}
+
+/* Delete a process context from process resource context list */
+DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
+ HANDLE hPCtxt, HANDLE hProcess)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROCESS_CONTEXT *pCtxt2 = NULL;
+ struct PROCESS_CONTEXT *pTmp = NULL;
+ struct PROCESS_CONTEXT *pCtxtList = NULL;
+
+ DBC_Assert(hDRVObject != NULL);
+ DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
+
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
+ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
+ pTmp = pCtxtList;
+ while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
+ pTmp = pCtxtList;
+ pCtxtList = pCtxtList->next;
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_RemoveProcContext: 2");
+ }
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
+ if (hDRVObject->procCtxtList == pCtxt2)
+ hDRVObject->procCtxtList = pCtxt2->next;
+
+ if (pCtxtList == NULL)
+ return DSP_ENOTFOUND;
+ else if (pTmp->next != NULL)
+ pTmp->next = pTmp->next->next;
+
+ MEM_Free(pCtxt2);
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
+
+ return status;
+}
+
+/* Update the state of process context */
+DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status1 = DSP_SOK;
+ if (pCtxt != NULL) {
+ pCtxt->resState = status;
+ } else {
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_ProcUpdatestate: Failed to update "
+ "process state");
+ }
+ return status1;
+}
+
+/* Allocate and add a node resource element
+* This function is called from .Node_Allocate. */
+DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
+ HANDLE hPCtxt)
+{
+ struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_RES_OBJECT *pTempNodeRes = NULL;
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
+ *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
+ (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
+ DBC_Assert(hPCtxt != NULL);
+ if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
+ status = DSP_EHANDLE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ (*pNodeRes)->hNode = hNode;
+ if (pCtxt->pNodeList != NULL) {
+ pTempNodeRes = pCtxt->pNodeList;
+ while (pTempNodeRes->next != NULL)
+ pTempNodeRes = pTempNodeRes->next;
+
+ pTempNodeRes->next = *pNodeRes;
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_InsertNodeResElement: 2");
+ } else {
+ pCtxt->pNodeList = *pNodeRes;
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_InsertNodeResElement: 3");
+ }
+ }
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
+ return status;
+}
+
+/* Release all Node resources and its context
+* This is called from .Node_Delete. */
+DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
+{
+ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
+ struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
+
+ DBC_Assert(hPCtxt != NULL);
+ GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
+ while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
+ pTempNode2 = pTempNode;
+ pTempNode = pTempNode->next;
+ }
+ if (pCtxt->pNodeList == pNodeRes)
+ pCtxt->pNodeList = pNodeRes->next;
+
+ if (pTempNode == NULL)
+ return DSP_ENOTFOUND;
+ else if (pTempNode2->next != NULL)
+ pTempNode2->next = pTempNode2->next->next;
+
+ MEM_Free(pTempNode);
+ return status;
+}
+
+/* Actual Node De-Allocation */
+static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_RES_OBJECT *pNodeList = NULL;
+ struct NODE_RES_OBJECT *pNodeRes = NULL;
+ u32 nState;
+
+ DBC_Assert(hPCtxt != NULL);
+ pNodeList = pCtxt->pNodeList;
+ while (pNodeList != NULL) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
+ pNodeRes = pNodeList;
+ pNodeList = pNodeList->next;
+ if (pNodeRes->nodeAllocated) {
+ nState = NODE_GetState(pNodeRes->hNode) ;
+ GT_1trace(curTrace, GT_5CLASS,
+ "DRV_ProcFreeNodeRes: Node state %x\n", nState);
+ if (nState <= NODE_DELETING) {
+ if ((nState == NODE_RUNNING) ||
+ (nState == NODE_PAUSED) ||
+ (nState == NODE_TERMINATING)) {
+ GT_1trace(curTrace, GT_5CLASS,
+ "Calling Node_Terminate for Node:"
+ " 0x%x\n", pNodeRes->hNode);
+ status = NODE_Terminate
+ (pNodeRes->hNode, &status);
+ GT_1trace(curTrace, GT_5CLASS,
+ "Calling Node_Delete for Node:"
+ " 0x%x\n", pNodeRes->hNode);
+ status = NODE_Delete(pNodeRes->hNode);
+ GT_1trace(curTrace, GT_5CLASS,
+ "the status after the NodeDelete %x\n",
+ status);
+ } else if ((nState == NODE_ALLOCATED)
+ || (nState == NODE_CREATED))
+ status = NODE_Delete(pNodeRes->hNode);
+ }
+ }
+ pNodeRes->nodeAllocated = 0;
+ }
+ return status;
+}
+
+/* Allocate the DMM resource element
+* This is called from Proc_Map. after the actual resource is allocated */
+DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+ *pDMMRes = (struct DMM_RES_OBJECT *)
+ MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
+ DBC_Assert(hPCtxt != NULL);
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
+ if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
+ GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
+ status = DSP_EHANDLE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ if (pCtxt->pDMMList != NULL) {
+ GT_0trace(curTrace, GT_5CLASS,
+ "DRV_InsertDMMResElement: 3");
+ pTempDMMRes = pCtxt->pDMMList;
+ while (pTempDMMRes->next != NULL)
+ pTempDMMRes = pTempDMMRes->next;
+
+ pTempDMMRes->next = *pDMMRes;
+ } else {
+ pCtxt->pDMMList = *pDMMRes;
+ GT_0trace(curTrace, GT_5CLASS,
+ "DRV_InsertDMMResElement: 4");
+ }
+ }
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
+ return status;
+}
+
+
+
+/* Release DMM resource element context
+* This is called from Proc_UnMap. after the actual resource is freed */
+DSP_STATUS DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
+ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ pTempDMMRes2 = pCtxt->pDMMList;
+ pTempDMMRes = pCtxt->pDMMList;
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
+ while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
+ pTempDMMRes2 = pTempDMMRes;
+ pTempDMMRes = pTempDMMRes->next;
+ }
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
+ if (pCtxt->pDMMList == pTempDMMRes)
+ pCtxt->pDMMList = pTempDMMRes->next;
+
+ if (pTempDMMRes == NULL)
+ return DSP_ENOTFOUND;
+ else if (pTempDMMRes2->next != NULL)
+ pTempDMMRes2->next = pTempDMMRes2->next->next;
+
+ MEM_Free(pDMMRes);
+ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
+ return status;
+}
+
+/* Update DMM resource status */
+DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
+ u32 pReqAddr, u32 pMapAddr,
+ HANDLE hProcessor)
+{
+ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Assert(hDMMRes != NULL);
+ pDMMRes->ulMpuAddr = pMpuAddr;
+ pDMMRes->ulDSPAddr = pMapAddr;
+ pDMMRes->ulDSPResAddr = pReqAddr;
+ pDMMRes->dmmSize = ulSize;
+ pDMMRes->hProcessor = hProcessor;
+ pDMMRes->dmmAllocated = 1;
+
+ return status;
+}
+
+/* Actual DMM De-Allocation */
+DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
+ struct DMM_RES_OBJECT *pDMMRes = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
+ while (pDMMList != NULL) {
+ pDMMRes = pDMMList;
+ pDMMList = pDMMList->next;
+ if (pDMMRes->dmmAllocated) {
+ status = PROC_UnMap(pDMMRes->hProcessor,
+ (void *)pDMMRes->ulDSPResAddr);
+ status = PROC_UnReserveMemory(pDMMRes->hProcessor,
+ (void *)pDMMRes->ulDSPResAddr);
+ pDMMRes->dmmAllocated = 0;
+ }
+ }
+ return status;
+}
+
+
+/* Release all DMM resources and its context
+* This is called from .bridge_release. */
+DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
+ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+ DBC_Assert(pCtxt != NULL);
+ DRV_ProcFreeDMMRes(pCtxt);
+ pTempDMMRes = pCtxt->pDMMList;
+ while (pTempDMMRes != NULL) {
+ pTempDMMRes2 = pTempDMMRes;
+ pTempDMMRes = pTempDMMRes->next;
+ MEM_Free(pTempDMMRes2);
+ }
+ pCtxt->pDMMList = NULL;
+ return status;
+}
+
+DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
+ DSP_STATUS status = DSP_SOK;
+ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
+ struct DMM_RES_OBJECT *pTempDMM = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ pTempDMM = pCtxt->pDMMList;
+ while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
+ GT_3trace(curTrace, GT_ENTER,
+ "DRV_GetDMMResElement: 2 pTempDMM:%x "
+ "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
+ pTempDMM->ulDSPAddr, pMapAddr);
+ pTempDMM2 = pTempDMM;
+ pTempDMM = pTempDMM->next;
+ }
+ if (pTempDMM != NULL) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
+ *pDMMRes = pTempDMM;
+ } else {
+ status = DSP_ENOTFOUND;
+ } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
+ return status;
+}
+
+/* Update Node allocation status */
+void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
+{
+ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+ DBC_Assert(hNodeRes != NULL);
+ pNodeRes->nodeAllocated = status;
+}
+
+/* Update Node Heap status */
+void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
+{
+ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+ DBC_Assert(hNodeRes != NULL);
+ pNodeRes->heapAllocated = status;
+}
+
+/* Release all Node resources and its context
+* This is called from .bridge_release.
+*/
+DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_RES_OBJECT *pTempNode2 = NULL;
+ struct NODE_RES_OBJECT *pTempNode = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ DRV_ProcFreeNodeRes(pCtxt);
+ pTempNode = pCtxt->pNodeList;
+ while (pTempNode != NULL) {
+ pTempNode2 = pTempNode;
+ pTempNode = pTempNode->next;
+ MEM_Free(pTempNode2);
+ }
+ pCtxt->pNodeList = NULL;
+ return status;
+}
+
+/* Getting the node resource element */
+
+DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
+{
+ struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_RES_OBJECT *pTempNode2 = NULL;
+ struct NODE_RES_OBJECT *pTempNode = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ pTempNode = pCtxt->pNodeList;
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
+ while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
+ pTempNode2 = pTempNode;
+ pTempNode = pTempNode->next;
+ }
+ if (pTempNode != NULL)
+ *nodeRes = pTempNode;
+ else
+ status = DSP_ENOTFOUND;
+
+ return status;
+}
+
+
+
+/* Allocate the STRM resource element
+* This is called after the actual resource is allocated
+*/
+DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
+ HANDLE hPCtxt)
+{
+ struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
+ DBC_Assert(hPCtxt != NULL);
+
+ *pSTRMRes = (struct STRM_RES_OBJECT *)
+ MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
+ if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
+ status = DSP_EHANDLE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ (*pSTRMRes)->hStream = hStreamHandle;
+ if (pCtxt->pSTRMList != NULL) {
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_InsertiSTRMResElement: 3");
+ pTempSTRMRes = pCtxt->pSTRMList;
+ while (pTempSTRMRes->next != NULL)
+ pTempSTRMRes = pTempSTRMRes->next;
+
+ pTempSTRMRes->next = *pSTRMRes;
+ } else {
+ pCtxt->pSTRMList = *pSTRMRes;
+ GT_0trace(curTrace, GT_ENTER,
+ "DRV_InsertSTRMResElement: 4");
+ }
+ }
+ return status;
+}
+
+
+
+/* Release Stream resource element context
+* This function called after the actual resource is freed
+*/
+DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+ struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
+ struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
+
+ DBC_Assert(hPCtxt != NULL);
+ while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
+ pTempSTRMRes2 = pTempSTRMRes;
+ pTempSTRMRes = pTempSTRMRes->next;
+ }
+ if (pCtxt->pSTRMList == pTempSTRMRes)
+ pCtxt->pSTRMList = pTempSTRMRes->next;
+
+ if (pTempSTRMRes == NULL)
+ status = DSP_ENOTFOUND;
+ else if (pTempSTRMRes2->next != NULL)
+ pTempSTRMRes2->next = pTempSTRMRes2->next->next;
+
+ MEM_Free(pSTRMRes);
+ return status;
+}
+
+
+/* Actual Stream De-Allocation */
+static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+ u8 **apBuffer = NULL;
+ struct STRM_RES_OBJECT *pSTRMList = NULL;
+ struct STRM_RES_OBJECT *pSTRMRes = NULL;
+ u8 *pBufPtr;
+ u32 ulBytes;
+ u32 dwArg;
+ s32 ulBufSize;
+
+
+ DBC_Assert(hPCtxt != NULL);
+ pSTRMList = pCtxt->pSTRMList;
+ while (pSTRMList != NULL) {
+ pSTRMRes = pSTRMList;
+ pSTRMList = pSTRMList->next;
+ if (pSTRMRes->uNumBufs != 0) {
+ apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
+ sizeof(u8 *)), MEM_NONPAGED);
+ status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
+ pSTRMRes->uNumBufs);
+ MEM_Free(apBuffer);
+ }
+ status = STRM_Close(pSTRMRes->hStream);
+ if (DSP_FAILED(status)) {
+ if (status == DSP_EPENDING) {
+ status = STRM_Reclaim(pSTRMRes->hStream,
+ &pBufPtr, &ulBytes,
+ (u32 *)&ulBufSize, &dwArg);
+ if (DSP_SUCCEEDED(status))
+ status = STRM_Close(pSTRMRes->hStream);
+
+ }
+ }
+ }
+ return status1;
+}
+
+/* Release all Stream resources and its context
+* This is called from .bridge_release.
+*/
+DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
+{
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
+ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
+
+ DBC_Assert(hPCtxt != NULL);
+ DRV_ProcFreeSTRMRes(pCtxt);
+ pTempSTRMRes = pCtxt->pSTRMList;
+ while (pTempSTRMRes != NULL) {
+ pTempSTRMRes2 = pTempSTRMRes;
+ pTempSTRMRes = pTempSTRMRes->next;
+ MEM_Free(pTempSTRMRes2);
+ }
+ pCtxt->pSTRMList = NULL;
+ return status;
+}
+
+
+/* Getting the stream resource element */
+DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
+ struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
+
+ DBC_Assert(hPCtxt != NULL);
+ while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
+ pTempSTRM2 = pTempSTRM;
+ pTempSTRM = pTempSTRM->next;
+ }
+ if (pTempSTRM != NULL) {
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
+ *STRMRes = pTempSTRM;
+ } else {
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
+ status = DSP_ENOTFOUND;
+ }
+ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
+ return status;
+}
+
+/* Updating the stream resource element */
+DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+
+ DBC_Assert(hPCtxt != NULL);
+ (*STRMRes)->uNumBufs = uNumBufs;
+ return status;
+}
+
+/* Displaying the resources allocated by a process */
+DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
+{
+ struct PROCESS_CONTEXT *pCtxt = NULL;
+ struct NODE_RES_OBJECT *pNodeRes = NULL;
+ struct DMM_RES_OBJECT *pDMMRes = NULL;
+ struct STRM_RES_OBJECT *pSTRMRes = NULL;
+ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
+ u32 tempCount = 1;
+ HANDLE hDrvObject = NULL;
+ void *pBuf = pBuf1;
+ u8 pTempBuf[250];
+ u32 tempStrLen = 0, tempStrLen2 = 0;
+ DSP_STATUS status = DSP_SOK;
+
+ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ DRV_GetProcCtxtList(&pCtxt, (struct DRV_OBJECT *)hDrvObject);
+ GT_0trace(curTrace, GT_ENTER, "*********************"
+ "DRV_ProcDisplayResourceInfo:*\n");
+ while (pCtxt != NULL) {
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "-------------------------------------"
+ "-----------------------------------\n");
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ if (pCtxt->resState == PROC_RES_ALLOCATED) {
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "GPP Process Resource State: "
+ "pCtxt->resState = PROC_RES_ALLOCATED, "
+ " Process ID: %d\n", pCtxt->pid);
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ } else {
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "GPP Resource State: pCtxt->resState"
+ " = PROC_RES_DEALLOCATED, Process ID:%d\n",
+ pCtxt->pid);
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ }
+ pNodeRes = pCtxt->pNodeList;
+ tempCount = 1;
+ while (pNodeRes != NULL) {
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_ProcDisplayResourceInfo: #:%d "
+ "pCtxt->pNodeList->hNode:%x\n",
+ tempCount, pNodeRes->hNode);
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "Node Resource Information: Node #"
+ " %d Node Handle hNode:0X%x\n",
+ tempCount, (u32)pNodeRes->hNode);
+ pNodeRes = pNodeRes->next;
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ tempCount++;
+ }
+ tempCount = 1;
+ pDSPHEAPRes = pCtxt->pDSPHEAPList;
+ while (pDSPHEAPRes != NULL) {
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_ProcDisplayResourceInfo: #:%d "
+ "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
+ tempCount, pDSPHEAPRes->ulMpuAddr);
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "DSP Heap Resource Info: HEAP # %d"
+ " Mapped GPP Address: 0x%x, size: 0x%x\n",
+ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
+ (u32)pDSPHEAPRes->heapSize);
+ pDSPHEAPRes = pDSPHEAPRes->next;
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ tempCount++;
+ }
+ tempCount = 1;
+ pDMMRes = pCtxt->pDMMList;
+ while (pDMMRes != NULL) {
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_ProcDisplayResourceInfo: #:%d "
+ " pCtxt->pDMMList->ulMpuAddr:%x\n",
+ tempCount,
+ pDMMRes->ulMpuAddr);
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "DMM Resource Info: DMM # %d Mapped"
+ " GPP Address: 0x%x, size: 0x%x\n",
+ tempCount, (u32)pDMMRes->ulMpuAddr,
+ (u32)pDMMRes->dmmSize);
+ pDMMRes = pDMMRes->next;
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ tempCount++;
+ }
+ tempCount = 1;
+ pSTRMRes = pCtxt->pSTRMList;
+ while (pSTRMRes != NULL) {
+ GT_2trace(curTrace, GT_ENTER,
+ "DRV_ProcDisplayResourceInfo: #:%d "
+ "pCtxt->pSTRMList->hStream:%x\n", tempCount,
+ pSTRMRes->hStream);
+ tempStrLen2 = sprintf((char *)pTempBuf,
+ "Stream Resource info: STRM # %d "
+ "Stream Handle: 0x%x \n",
+ tempCount, (u32)pSTRMRes->hStream);
+ pSTRMRes = pSTRMRes->next;
+ tempStrLen2 += 2;
+ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+ tempStrLen += tempStrLen2;
+ tempCount++;
+ }
+ pCtxt = pCtxt->next;
+ }
+ *pSize = tempStrLen;
+ status = PrintProcessInformation();
+ GT_0trace(curTrace, GT_ENTER, "*********************"
+ "DRV_ProcDisplayResourceInfo:**\n");
+ return status;
+}
+
+/*
+ * ======== PrintProcessInformation ========
+ * Purpose:
+ * This function prints the Process's information stored in
+ * the process context list. Some of the information that
+ * it displays is Process's state, Node, Stream, DMM, and
+ * Heap information.
+ */
+static DSP_STATUS PrintProcessInformation(void)
+{
+ struct DRV_OBJECT *hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pCtxtList = NULL;
+ struct NODE_RES_OBJECT *pNodeRes = NULL;
+ struct DMM_RES_OBJECT *pDMMRes = NULL;
+ struct STRM_RES_OBJECT *pSTRMRes = NULL;
+ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
+ DSP_STATUS status = DSP_SOK;
+ u32 tempCount;
+ u32 procID;
+
+ /* Get the Process context list */
+ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
+ GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
+ " for DSP bridge ##\n");
+ GT_0trace(curTrace, GT_4CLASS, " \n ###The processes"
+ " information is as follows ### \n") ;
+ GT_0trace(curTrace, GT_4CLASS, " ====================="
+ "============ \n");
+ /* Go through the entries in the Process context list */
+ while (pCtxtList != NULL) {
+ GT_1trace(curTrace, GT_4CLASS, "\nThe process"
+ " id is %d\n", pCtxtList->pid);
+ GT_0trace(curTrace, GT_4CLASS, " -------------------"
+ "---------\n");
+ if (pCtxtList->resState == PROC_RES_ALLOCATED) {
+ GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
+ " is in Allocated state\n");
+ } else {
+ GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
+ " is in DeAllocated state\n");
+ }
+ GT_1trace(curTrace, GT_4CLASS, "\nThe hProcessor"
+ " handle is: 0X%x\n",
+ (u32)pCtxtList->hProcessor);
+ if (pCtxtList->hProcessor != NULL) {
+ PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
+ if (procID == DSP_UNIT) {
+ GT_0trace(curTrace, GT_4CLASS,
+ "\nProcess connected to"
+ " DSP Processor\n");
+ } else if (procID == IVA_UNIT) {
+ GT_0trace(curTrace, GT_4CLASS,
+ "\nProcess connected to"
+ " IVA Processor\n");
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ "\n***ERROR:Invalid Processor Id***\n");
+ }
+ }
+ pNodeRes = pCtxtList->pNodeList;
+ tempCount = 1;
+ while (pNodeRes != NULL) {
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n***The Nodes allocated by"
+ " this Process are***\n");
+ GT_2trace(curTrace, GT_4CLASS,
+ "Node # %d Node Handle hNode:0x%x\n",
+ tempCount, (u32)pNodeRes->hNode);
+ pNodeRes = pNodeRes->next;
+ tempCount++;
+ }
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n ***There are no Nodes"
+ " allocated by this Process***\n");
+ tempCount = 1;
+ pDSPHEAPRes = pCtxtList->pDSPHEAPList;
+ while (pDSPHEAPRes != NULL) {
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n***The Heaps allocated by"
+ " this Process are***\n");
+ GT_3trace(curTrace, GT_4CLASS,
+ "DSP Heap Resource Info: HEAP # %d "
+ "Mapped GPP Address:0x%x, Size: 0x%lx\n",
+ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
+ pDSPHEAPRes->heapSize);
+ pDSPHEAPRes = pDSPHEAPRes->next;
+ tempCount++;
+ }
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n ***There are no Heaps allocated"
+ " by this Process***\n");
+ tempCount = 1;
+ pDMMRes = pCtxtList->pDMMList;
+ while (pDMMRes != NULL) {
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n ***The DMM resources allocated by"
+ " this Process are***\n");
+ GT_3trace(curTrace, GT_4CLASS,
+ "DMM Resource Info: DMM # %d "
+ "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
+ tempCount, pDMMRes->ulMpuAddr,
+ pDMMRes->dmmSize);
+ pDMMRes = pDMMRes->next;
+ tempCount++;
+ }
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n ***There are no DMM resources"
+ " allocated by this Process***\n");
+ tempCount = 1;
+ pSTRMRes = pCtxtList->pSTRMList;
+ while (pSTRMRes != NULL) {
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n***The Stream resources allocated by"
+ " this Process are***\n");
+ GT_2trace(curTrace, GT_4CLASS,
+ "Stream Resource info: STRM # %d"
+ "Stream Handle:0X%x\n", tempCount,
+ (u32)pSTRMRes->hStream);
+ pSTRMRes = pSTRMRes->next;
+ tempCount++;
+ }
+ if (tempCount == 1)
+ GT_0trace(curTrace, GT_4CLASS,
+ "\n ***There are no Stream resources"
+ "allocated by this Process***\n");
+ pCtxtList = pCtxtList->next;
+ }
+ return status;
+}
+
+/* GPP PROCESS CLEANUP CODE END */
+#endif
+
+/*
+ * ======== = DRV_Create ======== =
+ * Purpose:
+ * DRV Object gets created only once during Driver Loading.
+ */
+DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDRVObject = NULL;
+
+ DBC_Require(phDRVObject != NULL);
+ DBC_Require(cRefs > 0);
+ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
+ " phDRVObject 0x%x\n", phDRVObject);
+ MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
+ if (pDRVObject) {
+ /* Create and Initialize List of device objects */
+ pDRVObject->devList = LST_Create();
+ if (pDRVObject->devList) {
+ /* Create and Initialize List of device Extension */
+ pDRVObject->devNodeString = LST_Create();
+ if (!(pDRVObject->devNodeString)) {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to Create DRV_EXT list ");
+ MEM_FreeObject(pDRVObject);
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to Create Dev List ");
+ MEM_FreeObject(pDRVObject);
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to Allocate Memory for DRV Obj");
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Store the DRV Object in the Registry */
+ if (DSP_SUCCEEDED
+ (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
+ GT_1trace(curTrace, GT_1CLASS,
+ "DRV Obj Created pDrvObject 0x%x\n ",
+ pDRVObject);
+ *phDRVObject = pDRVObject;
+ } else {
+ /* Free the DRV Object */
+ status = DSP_EFAIL;
+ MEM_Free(pDRVObject);
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to update the Registry with "
+ "DRV Object ");
+ }
+ }
+ GT_2trace(curTrace, GT_ENTER,
+ "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
+ "0x%x\n", phDRVObject, status);
+ DBC_Ensure(DSP_FAILED(status) ||
+ MEM_IsValidHandle(pDRVObject, SIGNATURE));
+ return status;
+}
+
+/*
+ * ======== DRV_Exit ========
+ * Purpose:
+ * Discontinue usage of the DRV module.
+ */
+void DRV_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
+
+ cRefs--;
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== = DRV_Destroy ======== =
+ * purpose:
+ * Invoked during bridge de-initialization
+ */
+DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+
+ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
+ " hDRVObject 0x%x\n", hDRVObject);
+ /*
+ * Delete the List if it exists.Should not come here
+ * as the DRV_RemoveDevObject and the Last DRV_RequestResources
+ * removes the list if the lists are empty.
+ */
+ if (pDRVObject->devList) {
+ /* Could assert if the list is not empty */
+ LST_Delete(pDRVObject->devList);
+ }
+ if (pDRVObject->devNodeString) {
+ /* Could assert if the list is not empty */
+ LST_Delete(pDRVObject->devNodeString);
+ }
+ MEM_FreeObject(pDRVObject);
+ /* Update the DRV Object in Registry to be 0 */
+ (void)CFG_SetObject(0, REG_DRV_OBJECT);
+ GT_2trace(curTrace, GT_ENTER,
+ "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
+ "0x%x\n", hDRVObject, status);
+ DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
+ return status;
+}
+
+/*
+ * ======== DRV_GetDevObject ========
+ * Purpose:
+ * Given a index, returns a handle to DevObject from the list.
+ */
+DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
+ struct DEV_OBJECT **phDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+#if GT_TRACE /* pDrvObject is used only for Assertions and debug messages.*/
+ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+#endif
+ struct DEV_OBJECT *pDevObject;
+ u32 i;
+ DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
+ DBC_Require(phDevObject != NULL);
+ DBC_Require(uIndex >= 0);
+ DBC_Require(cRefs > 0);
+ DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
+ GT_3trace(curTrace, GT_ENTER,
+ "Entered DRV_GetDevObject, args:\n\tuIndex: "
+ "0x%x\n\thDrvObject: 0x%x\n\tphDevObject: 0x%x\n",
+ uIndex, hDrvObject, phDevObject);
+ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+ for (i = 0; i < uIndex; i++) {
+ pDevObject =
+ (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
+ }
+ if (pDevObject) {
+ *phDevObject = (struct DEV_OBJECT *) pDevObject;
+ status = DSP_SOK;
+ } else {
+ *phDevObject = NULL;
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS,
+ "DRV: Could not get the DevObject\n");
+ }
+ GT_2trace(curTrace, GT_ENTER,
+ "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
+ "hDevObject: 0x%x\n", status, *phDevObject);
+ return status;
+}
+
+/*
+ * ======== DRV_GetFirstDevObject ========
+ * Purpose:
+ * Retrieve the first Device Object handle from an internal linked list of
+ * of DEV_OBJECTs maintained by DRV.
+ */
+u32 DRV_GetFirstDevObject(void)
+{
+ u32 dwDevObject = 0;
+ struct DRV_OBJECT *pDrvObject;
+
+ if (DSP_SUCCEEDED
+ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+ if ((pDrvObject->devList != NULL) &&
+ !LST_IsEmpty(pDrvObject->devList))
+ dwDevObject = (u32) LST_First(pDrvObject->devList);
+ }
+
+ return dwDevObject;
+}
+
+/*
+ * ======== DRV_GetFirstDevNodeString ========
+ * Purpose:
+ * Retrieve the first Device Extension from an internal linked list of
+ * of Pointer to DevNode Strings maintained by DRV.
+ */
+u32 DRV_GetFirstDevExtension(void)
+{
+ u32 dwDevExtension = 0;
+ struct DRV_OBJECT *pDrvObject;
+
+ if (DSP_SUCCEEDED
+ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+
+ if ((pDrvObject->devNodeString != NULL) &&
+ !LST_IsEmpty(pDrvObject->devNodeString)) {
+ dwDevExtension = (u32)LST_First(pDrvObject->
+ devNodeString);
+ }
+ }
+
+ return dwDevExtension;
+}
+
+/*
+ * ======== DRV_GetNextDevObject ========
+ * Purpose:
+ * Retrieve the next Device Object handle from an internal linked list of
+ * of DEV_OBJECTs maintained by DRV, after having previously called
+ * DRV_GetFirstDevObject() and zero or more DRV_GetNext.
+ */
+u32 DRV_GetNextDevObject(u32 hDevObject)
+{
+ u32 dwNextDevObject = 0;
+ struct DRV_OBJECT *pDrvObject;
+
+ DBC_Require(hDevObject != 0);
+
+ if (DSP_SUCCEEDED
+ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+
+ if ((pDrvObject->devList != NULL) &&
+ !LST_IsEmpty(pDrvObject->devList)) {
+ dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
+ (struct LST_ELEM *)hDevObject);
+ }
+ }
+ return dwNextDevObject;
+}
+
+/*
+ * ======== DRV_GetNextDevExtension ========
+ * Purpose:
+ * Retrieve the next Device Extension from an internal linked list of
+ * of pointer to DevNodeString maintained by DRV, after having previously
+ * called DRV_GetFirstDevExtension() and zero or more
+ * DRV_GetNextDevExtension().
+ */
+u32 DRV_GetNextDevExtension(u32 hDevExtension)
+{
+ u32 dwDevExtension = 0;
+ struct DRV_OBJECT *pDrvObject;
+
+ DBC_Require(hDevExtension != 0);
+
+ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
+ REG_DRV_OBJECT))) {
+ if ((pDrvObject->devNodeString != NULL) &&
+ !LST_IsEmpty(pDrvObject->devNodeString)) {
+ dwDevExtension = (u32)LST_Next(pDrvObject->
+ devNodeString,
+ (struct LST_ELEM *)hDevExtension);
+ }
+ }
+
+ return dwDevExtension;
+}
+
+/*
+ * ======== DRV_Init ========
+ * Purpose:
+ * Initialize DRV module private state.
+ */
+DSP_STATUS DRV_Init(void)
+{
+ s32 fRetval = 1; /* function return value */
+
+ DBC_Require(cRefs >= 0);
+
+ if (fRetval)
+ cRefs++;
+
+ GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry crefs 0x%x \n",
+ cRefs);
+
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+/*
+ * ======== DRV_InsertDevObject ========
+ * Purpose:
+ * Insert a DevObject into the list of Manager object.
+ */
+DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
+ struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hDevObject != NULL);
+ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+ DBC_Assert(pDRVObject->devList);
+
+ GT_2trace(curTrace, GT_ENTER,
+ "Entering DRV_InsertProcObject hDRVObject "
+ "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
+
+ LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
+
+ GT_1trace(curTrace, GT_ENTER,
+ "Exiting InsertDevObject status 0x%x\n", status);
+
+ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
+
+ return status;
+}
+
+/*
+ * ======== DRV_RemoveDevObject ========
+ * Purpose:
+ * Search for and remove a DeviceObject from the given list of DRV
+ * objects.
+ */
+DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
+ struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+ struct LST_ELEM *pCurElem;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+ DBC_Require(hDevObject != NULL);
+
+ DBC_Require(pDRVObject->devList != NULL);
+ DBC_Require(!LST_IsEmpty(pDRVObject->devList));
+
+ GT_2trace(curTrace, GT_ENTER,
+ "Entering DRV_RemoveDevObject hDevObject "
+ "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
+ /* Search list for pProcObject: */
+ for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
+ pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
+ /* If found, remove it. */
+ if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
+ LST_RemoveElem(pDRVObject->devList, pCurElem);
+ status = DSP_SOK;
+ break;
+ }
+ }
+ /* Remove list if empty. */
+ if (LST_IsEmpty(pDRVObject->devList)) {
+ LST_Delete(pDRVObject->devList);
+ pDRVObject->devList = NULL;
+ }
+ DBC_Ensure((pDRVObject->devList == NULL) ||
+ !LST_IsEmpty(pDRVObject->devList));
+ GT_1trace(curTrace, GT_ENTER,
+ "DRV_RemoveDevObject returning 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== DRV_RequestResources ========
+ * Purpose:
+ * Requests resources from the OS.
+ */
+DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDRVObject;
+ struct DRV_EXT *pszdevNode;
+
+ DBC_Require(dwContext != 0);
+ DBC_Require(pDevNodeString != NULL);
+ GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
+ /*
+ * Allocate memory to hold the string. This will live untill
+ * it is freed in the Release resources. Update the driver object
+ * list.
+ */
+ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
+ REG_DRV_OBJECT))) {
+ pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
+ if (pszdevNode) {
+ LST_InitElem(&pszdevNode->link);
+ strncpy((char *) pszdevNode->szString,
+ (char *)dwContext, MAXREGPATHLENGTH);
+ /* Update the Driver Object List */
+ *pDevNodeString = (u32)pszdevNode->szString;
+ LST_PutTail(pDRVObject->devNodeString,
+ (struct LST_ELEM *)pszdevNode);
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to Allocate Memory devNodeString ");
+ status = DSP_EFAIL;
+ *pDevNodeString = 0;
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to get Driver Object from Registry");
+ *pDevNodeString = 0;
+ }
+
+ if (!(strcmp((char *) dwContext, "TIOMAP1510"))) {
+ GT_0trace(curTrace, GT_1CLASS,
+ " Allocating resources for UMA \n");
+ status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
+ }
+
+ if (DSP_FAILED(status)) {
+ GT_0trace(curTrace, GT_7CLASS,
+ "Failed to reserve bridge resources ");
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != NULL &&
+ !LST_IsEmpty(pDRVObject->devNodeString)) ||
+ (DSP_FAILED(status) && *pDevNodeString == 0));
+
+ return status;
+}
+
+/*
+ * ======== DRV_ReleaseResources ========
+ * Purpose:
+ * Releases resources from the OS.
+ */
+DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
+ struct DRV_EXT *pszdevNode;
+
+ GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
+
+ if (!(strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
+ "TIOMAP1510"))) {
+ GT_0trace(curTrace, GT_1CLASS,
+ " Releasing DSP-Bridge resources \n");
+ status = RequestBridgeResources(dwContext, DRV_RELEASE);
+ } else {
+ GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(curTrace, GT_1CLASS,
+ "Failed to relese bridge resources\n");
+ }
+
+ /*
+ * Irrespective of the status go ahead and clean it
+ * The following will over write the status.
+ */
+ for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
+ pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
+ DRV_GetNextDevExtension((u32)pszdevNode)) {
+ if ((u32)pszdevNode == dwContext) {
+ /* Found it */
+ /* Delete from the Driver object list */
+ LST_RemoveElem(pDRVObject->devNodeString,
+ (struct LST_ELEM *)pszdevNode);
+ MEM_Free((void *) pszdevNode);
+ break;
+ }
+ /* Delete the List if it is empty */
+ if (LST_IsEmpty(pDRVObject->devNodeString)) {
+ LST_Delete(pDRVObject->devNodeString);
+ pDRVObject->devNodeString = NULL;
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== RequestBridgeResources ========
+ * Purpose:
+ * Reserves shared memory for bridge.
+ */
+static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CFG_HOSTRES *pResources;
+ u32 dwBuffSize;
+
+ struct DRV_EXT *driverExt;
+ u32 shm_size;
+
+ DBC_Require(dwContext != 0);
+
+ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
+
+ if (!bRequest) {
+ driverExt = (struct DRV_EXT *)dwContext;
+ /* Releasing resources by deleting the registry key */
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+ if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
+ CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
+ status = CFG_E_RESOURCENOTAVAIL;
+ GT_0trace(curTrace, GT_1CLASS,
+ "REG_GetValue Failed \n");
+ } else {
+ GT_0trace(curTrace, GT_1CLASS,
+ "REG_GetValue Succeeded \n");
+ }
+
+ if (pResources != NULL) {
+ dwBuffSize = sizeof(shm_size);
+ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
+ (u8 *)&shm_size, &dwBuffSize);
+ if (DSP_SUCCEEDED(status)) {
+ if ((pResources->dwMemBase[1]) &&
+ (pResources->dwMemPhys[1])) {
+ MEM_FreePhysMem((void *)pResources->
+ dwMemBase[1], pResources->dwMemPhys[1],
+ shm_size);
+ }
+ } else {
+ GT_1trace(curTrace, GT_7CLASS,
+ "Error getting SHM size from registry: "
+ "%x. Not calling MEM_FreePhysMem\n",
+ status);
+ }
+ pResources->dwMemBase[1] = 0;
+ pResources->dwMemPhys[1] = 0;
+
+ if (pResources->dwPrmBase)
+ iounmap(pResources->dwPrmBase);
+#ifdef OMAP_3430
+ if (pResources->dwCmBase)
+ iounmap((void *)pResources->dwCmBase);
+#endif
+#ifdef OMAP_44XX
+ if (pResources->dwCm1Base)
+ iounmap((void *)pResources->dwCm1Base);
+ if (pResources->dwCm2Base)
+ iounmap((void *)pResources->dwCm2Base);
+#endif
+ if (pResources->dwMboxBase)
+ iounmap(pResources->dwMboxBase);
+ if (pResources->dwMemBase[0])
+ iounmap((void *)pResources->dwMemBase[0]);
+ if (pResources->dwMemBase[2])
+ iounmap((void *)pResources->dwMemBase[2]);
+ if (pResources->dwMemBase[3])
+ iounmap((void *)pResources->dwMemBase[3]);
+ if (pResources->dwMemBase[4])
+ iounmap((void *)pResources->dwMemBase[4]);
+ if (pResources->dwWdTimerDspBase)
+ iounmap(pResources->dwWdTimerDspBase);
+ if (pResources->dwDmmuBase)
+ iounmap(pResources->dwDmmuBase);
+ if (pResources->dwPerBase)
+ iounmap(pResources->dwPerBase);
+ if (pResources->dwPerPmBase)
+ iounmap((void *)pResources->dwPerPmBase);
+ if (pResources->dwCorePmBase)
+ iounmap((void *)pResources->dwCorePmBase);
+ if (pResources->dwSysCtrlBase) {
+ iounmap(pResources->dwSysCtrlBase);
+ /* don't set pResources->dwSysCtrlBase to null
+ * as it is used in BOARD_Stop */
+ }
+ pResources->dwPrmBase = NULL;
+#ifdef OMAP_3430
+ pResources->dwCmBase = NULL;
+#endif
+#ifdef OMAP_44XX
+ pResources->dwCm1Base = (u32) NULL;
+ pResources->dwCm2Base = (u32) NULL;
+#endif
+ pResources->dwMboxBase = NULL;
+ pResources->dwMemBase[0] = (u32) NULL;
+ pResources->dwMemBase[2] = (u32) NULL;
+ pResources->dwMemBase[3] = (u32) NULL;
+ pResources->dwMemBase[4] = (u32) NULL;
+ pResources->dwWdTimerDspBase = NULL;
+ pResources->dwDmmuBase = NULL;
+
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+ status = REG_SetValue(NULL, (char *)driverExt->szString,
+ CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
+ (u32)dwBuffSize);
+ /* Set all the other entries to NULL */
+ MEM_Free(pResources);
+ }
+ GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
+ return status;
+ }
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+ if (pResources != NULL) {
+ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
+ pResources->wNumMemWindows = 2;
+ /* First window is for DSP internal memory */
+
+ pResources->dwPrmBase = ioremap(OMAP_IVA2_PRM_BASE,
+ OMAP_IVA2_PRM_SIZE);
+
+#ifdef OMAP44XX
+ pResources->dwCm1Base = (u32)ioremap(OMAP_IVA2_CM1_BASE,
+ OMAP_IVA2_CM1_SIZE);
+ pResources->dwCm2Base = (u32)ioremap(OMAP_IVA2_CM2_BASE,
+ OMAP_IVA2_CM2_SIZE);
+#else
+ pResources->dwCmBase = ioremap(OMAP_IVA2_CM_BASE,
+ OMAP_IVA2_CM_SIZE);
+#endif
+
+ pResources->dwMboxBase = ioremap(OMAP_MBOX_BASE,
+ OMAP_MBOX_SIZE);
+ pResources->dwSysCtrlBase = ioremap(OMAP_SYSC_BASE,
+ OMAP_SYSC_SIZE);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
+ pResources->dwMemBase[0]);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
+ pResources->dwMemBase[3]);
+ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
+ pResources->dwPrmBase);
+#ifdef OMAP44XX
+ GT_1trace(curTrace, GT_2CLASS, "dwCm1Base 0x%x\n",
+ pResources->dwCm1Base);
+ GT_1trace(curTrace, GT_2CLASS, "dwCm2Base 0x%x\n",
+ pResources->dwCm2Base);
+#else
+ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
+ pResources->dwCmBase);
+#endif
+ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
+ pResources->dwWdTimerDspBase);
+ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
+ pResources->dwMboxBase);
+ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
+ pResources->dwDmmuBase);
+
+ /* for 24xx base port is not mapping the mamory for DSP
+ * internal memory TODO Do a ioremap here */
+ /* Second window is for DSP external memory shared with MPU */
+ if (DSP_SUCCEEDED(status)) {
+ /* for Linux, these are hard-coded values */
+ pResources->bIRQRegisters = 0;
+ pResources->bIRQAttrib = 0;
+ pResources->dwOffsetForMonitor = 0;
+ pResources->dwChnlOffset = 0;
+ /* CHNL_MAXCHANNELS */
+ pResources->dwNumChnls = CHNL_MAXCHANNELS;
+ pResources->dwChnlBufSize = 0x400;
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+ status = REG_SetValue(NULL, (char *) dwContext,
+ CURRENTCONFIG, REG_BINARY,
+ (u8 *)pResources,
+ sizeof(struct CFG_HOSTRES));
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(curTrace, GT_1CLASS,
+ " Successfully set the registry "
+ "value for CURRENTCONFIG\n");
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ " Failed to set the registry "
+ "value for CURRENTCONFIG\n");
+ }
+ }
+ MEM_Free(pResources);
+ }
+ /* End Mem alloc */
+ return status;
+}
+
+/*
+ * ======== RequestBridgeResourcesDSP ========
+ * Purpose:
+ * Reserves shared memory for bridge.
+ */
+static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CFG_HOSTRES *pResources;
+ u32 dwBuffSize;
+ u32 dmaAddr;
+ u32 shm_size;
+
+ DBC_Require(dwContext != 0);
+
+ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
+
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+
+ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+
+ if (pResources != NULL) {
+ if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
+ dwContext, pResources))) {
+ /* Call CFG_GetHostResources to get reserve resouces */
+ status = RequestBridgeResources(dwContext, bRequest);
+ if (DSP_SUCCEEDED(status)) {
+ status = CFG_GetHostResources
+ ((struct CFG_DEVNODE *) dwContext,
+ pResources);
+ }
+ }
+ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
+ pResources->wNumMemWindows = 4;
+
+ pResources->dwMemBase[0] = 0;
+ pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
+ OMAP_DSP_MEM1_SIZE);
+ pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
+ OMAP_DSP_MEM2_SIZE);
+ pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
+ OMAP_DSP_MEM3_SIZE);
+#ifdef OMAP_3430
+ pResources->dwPerBase = ioremap(OMAP_PER_CM_BASE,
+ OMAP_PER_CM_SIZE);
+ pResources->dwPerPmBase = (u32)ioremap(OMAP_PER_PRM_BASE,
+ OMAP_PER_PRM_SIZE);
+ pResources->dwCorePmBase = (u32)ioremap(OMAP_CORE_PRM_BASE,
+ OMAP_CORE_PRM_SIZE);
+#else
+
+ pResources->dwCm1Base = (u32)ioremap(OMAP_IVA2_CM1_BASE,
+ OMAP_IVA2_CM1_SIZE);
+ pResources->dwCm2Base = (u32)ioremap(OMAP_IVA2_CM2_BASE,
+ OMAP_IVA2_CM2_SIZE);
+#endif
+ pResources->dwDmmuBase = ioremap(OMAP_DMMU_BASE,
+ OMAP_DMMU_SIZE);
+ pResources->dwWdTimerDspBase = NULL;
+
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
+ pResources->dwMemBase[0]);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
+ pResources->dwMemBase[1]);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
+ pResources->dwMemBase[2]);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
+ pResources->dwMemBase[3]);
+ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
+ pResources->dwMemBase[4]);
+ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
+ pResources->dwPrmBase);
+#ifdef OMAP44XX
+ GT_1trace(curTrace, GT_2CLASS, "dwCm1Base 0x%x\n",
+ pResources->dwCm1Base);
+ GT_1trace(curTrace, GT_2CLASS, "dwCm2Base 0x%x\n",
+ pResources->dwCm2Base);
+#else
+ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
+ pResources->dwCmBase);
+#endif
+ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
+ pResources->dwWdTimerDspBase);
+ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
+ pResources->dwMboxBase);
+ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
+ pResources->dwDmmuBase);
+ dwBuffSize = sizeof(shm_size);
+ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
+ (u8 *)&shm_size, &dwBuffSize);
+ if (DSP_SUCCEEDED(status)) {
+ /* Allocate Physically contiguous,
+ * non-cacheable memory */
+ pResources->dwMemBase[1] =
+ (u32)MEM_AllocPhysMem(shm_size, 0x100000,
+ &dmaAddr);
+ if (pResources->dwMemBase[1] == 0) {
+ status = DSP_EMEMORY;
+ GT_0trace(curTrace, GT_7CLASS,
+ "SHM reservation Failed\n");
+ } else {
+ pResources->dwMemLength[1] = shm_size;
+ pResources->dwMemPhys[1] = dmaAddr;
+
+ GT_3trace(curTrace, GT_1CLASS,
+ "Bridge SHM address 0x%x dmaAddr"
+ " %x size %x\n",
+ pResources->dwMemBase[1],
+ dmaAddr, shm_size);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* for Linux, these are hard-coded values */
+ pResources->bIRQRegisters = 0;
+ pResources->bIRQAttrib = 0;
+ pResources->dwOffsetForMonitor = 0;
+ pResources->dwChnlOffset = 0;
+ /* CHNL_MAXCHANNELS */
+ pResources->dwNumChnls = CHNL_MAXCHANNELS;
+ pResources->dwChnlBufSize = 0x400;
+ dwBuffSize = sizeof(struct CFG_HOSTRES);
+ status = REG_SetValue(NULL, (char *)dwContext,
+ CURRENTCONFIG, REG_BINARY,
+ (u8 *)pResources,
+ sizeof(struct CFG_HOSTRES));
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(curTrace, GT_1CLASS,
+ " Successfully set the registry"
+ " value for CURRENTCONFIG\n");
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ " Failed to set the registry value"
+ " for CURRENTCONFIG\n");
+ }
+ }
+ MEM_Free(pResources);
+ }
+ /* End Mem alloc */
+ return status;
+}
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
new file mode 100644
index 000000000000..a81b12d21625
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv_interface.c
@@ -0,0 +1,760 @@
+/*
+ * drv_interface.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== linux_driver.c ========
+ * Description:
+ * DSP/BIOS Bridge driver interface.
+ *
+ * Public Functions:
+ * driver_init
+ * driver_exit
+ * driver_open
+ * driver_release
+ * driver_ioctl
+ * driver_mmap
+ *
+ *! Revision History
+ *! ================
+ *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
+ *! greater than 2.5, use module_param.
+ *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
+ *! loop after image load and waits in a loop for DSP to start
+ *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
+ *! MOD_DEC_USE_COUNT
+ *! for kernel versions greater than 2.5
+ *! 20-May-2003 vp Added unregister functions for the DPM.
+ *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
+ *! 24-Mar-2003 vp Added Power Management support.
+ *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
+ *! 10-Feb-2003 vp Updated based on code review comments
+ *! 18-Oct-2002 sb Created initial version
+ */
+
+/* ----------------------------------- Host OS */
+
+#include <dspbridge/host_os.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#ifdef CONFIG_PM
+#include <mach/board-3430sdp.h>
+#endif
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/gt.h>
+#include <dspbridge/dbc.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/services.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/reg.h>
+#include <dspbridge/csl.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/wcdioctl.h>
+#include <dspbridge/_dcd.h>
+#include <dspbridge/dspdrv.h>
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/pwr.h>
+
+/* ----------------------------------- This */
+#include <drv_interface.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/cfg.h>
+#include <dspbridge/resourcecleanup.h>
+#include <dspbridge/chnl.h>
+#include <dspbridge/proc.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/drvdefs.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/dbreg.h>
+#endif
+#ifdef CONFIG_PM
+#include <mach/omap-pm.h>
+#include <mach-omap2/omap3-opp.h>
+#endif
+
+#define BRIDGE_NAME "C6410"
+/* ----------------------------------- Globals */
+#define DRIVER_NAME "DspBridge"
+#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
+#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
+
+#ifdef OMAP44XX
+s32 dsp_debug = 1;
+#else
+s32 dsp_debug;
+#endif
+
+struct platform_device *omap_dspbridge_dev;
+
+struct bridge_dev {
+ struct cdev cdev;
+};
+
+static struct bridge_dev *bridge_device;
+
+static struct class *bridge_class;
+
+static u32 driverContext;
+#ifdef CONFIG_BRIDGE_DEBUG
+static char *GT_str;
+#endif /* CONFIG_BRIDGE_DEBUG */
+static s32 driver_major = DRIVER_MAJOR;
+static s32 driver_minor = DRIVER_MINOR;
+static char *base_img;
+char *iva_img;
+static char *num_procs = "C55=1";
+static s32 shm_size = 0x400000; /* 4 MB */
+static u32 phys_mempool_base;
+static u32 phys_mempool_size;
+static int tc_wordswapon; /* Default value is always false */
+
+#ifdef CONFIG_PM
+struct omap34xx_bridge_suspend_data {
+ int suspended;
+ wait_queue_head_t suspend_wq;
+};
+
+static struct omap34xx_bridge_suspend_data bridge_suspend_data;
+
+static int omap34xxbridge_suspend_lockout(
+ struct omap34xx_bridge_suspend_data *s, struct file *f)
+{
+ if ((s)->suspended) {
+ if ((f)->f_flags & O_NONBLOCK)
+ return DSP_EDPMSUSPEND;
+ wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef DEBUG
+module_param(GT_str, charp, 0);
+MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
+
+module_param(dsp_debug, int, 0);
+MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
+#endif
+
+module_param(driver_major, int, 0); /* Driver's major number */
+MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
+
+module_param(driver_minor, int, 0); /* Driver's major number */
+MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
+
+module_param(base_img, charp, 0);
+MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
+
+module_param(shm_size, int, 0);
+MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
+
+module_param(phys_mempool_base, uint, 0);
+MODULE_PARM_DESC(phys_mempool_base,
+ "Physical memory pool base passed to driver");
+
+module_param(phys_mempool_size, uint, 0);
+MODULE_PARM_DESC(phys_mempool_size,
+ "Physical memory pool size passed to driver");
+module_param(tc_wordswapon, int, 0);
+MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
+
+static char *driver_name = DRIVER_NAME;
+
+#ifdef CONFIG_BRIDGE_DEBUG
+static struct GT_Mask driverTrace;
+#endif /* CONFIG_BRIDGE_DEBUG */
+
+static struct file_operations bridge_fops = {
+ .open = bridge_open,
+ .release = bridge_release,
+ .ioctl = bridge_ioctl,
+ .mmap = bridge_mmap,
+};
+
+#ifdef CONFIG_PM
+static u32 timeOut = 1000;
+#ifdef CONFIG_BRIDGE_DVFS
+static struct clk *clk_handle;
+s32 dsp_max_opps = VDD1_OPP5;
+#endif
+
+/* Maximum Opps that can be requested by IVA*/
+/*vdd1 rate table*/
+#ifdef CONFIG_BRIDGE_DVFS
+const struct omap_opp vdd1_rate_table_bridge[] = {
+ {0, 0, 0},
+ /*OPP1*/
+ {S125M, VDD1_OPP1, 0},
+ /*OPP2*/
+ {S250M, VDD1_OPP2, 0},
+ /*OPP3*/
+ {S500M, VDD1_OPP3, 0},
+ /*OPP4*/
+ {S550M, VDD1_OPP4, 0},
+ /*OPP5*/
+ {S600M, VDD1_OPP5, 0},
+};
+#endif
+#endif
+
+struct dspbridge_platform_data *omap_dspbridge_pdata;
+
+u32 vdd1_dsp_freq[6][4] = {
+ {0, 0, 0, 0},
+ /*OPP1*/
+ {0, 90000, 0, 86000},
+ /*OPP2*/
+ {0, 180000, 80000, 170000},
+ /*OPP3*/
+ {0, 360000, 160000, 340000},
+ /*OPP4*/
+ {0, 396000, 325000, 376000},
+ /*OPP5*/
+ {0, 430000, 355000, 430000},
+};
+
+#ifdef CONFIG_BRIDGE_DVFS
+static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
+ void *ptr)
+{
+ PWR_PM_PostScale(PRCM_VDD1, level);
+ return 0;
+}
+
+static struct notifier_block iva_clk_notifier = {
+ .notifier_call = dspbridge_post_scale,
+ NULL,
+};
+#endif
+
+static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
+{
+ int status;
+ u32 initStatus;
+ u32 temp;
+ dev_t dev = 0 ;
+ int result;
+#ifdef CONFIG_BRIDGE_DVFS
+ int i = 0;
+#endif
+ struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
+
+ omap_dspbridge_dev = pdev;
+
+ /* use 2.6 device model */
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ result = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ result = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ if (result < 0) {
+ GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
+ "Can't get Major %d \n", driver_major);
+ return result;
+ }
+
+ bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
+ if (!bridge_device) {
+ result = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ return result;
+ }
+ memset(bridge_device, 0, sizeof(struct bridge_dev));
+ cdev_init(&bridge_device->cdev, &bridge_fops);
+ bridge_device->cdev.owner = THIS_MODULE;
+ bridge_device->cdev.ops = &bridge_fops;
+
+ status = cdev_add(&bridge_device->cdev, dev, 1);
+
+ if (status) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "Failed to add the bridge device \n");
+ return status;
+ }
+
+ /* udev support */
+ bridge_class = class_create(THIS_MODULE, "ti_bridge");
+
+ if (IS_ERR(bridge_class))
+ GT_0trace(driverTrace, GT_7CLASS,
+ "Error creating bridge class \n");
+
+ device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
+ NULL, "DspBridge");
+
+ GT_init();
+ GT_create(&driverTrace, "LD");
+
+#ifdef DEBUG
+ if (GT_str)
+ GT_set(GT_str);
+#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
+ GT_set("**=67");
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
+
+#ifdef CONFIG_PM
+ /* Initialize the wait queue */
+ if (!status) {
+ bridge_suspend_data.suspended = 0;
+ init_waitqueue_head(&bridge_suspend_data.suspend_wq);
+ }
+#endif
+
+ SERVICES_Init();
+
+ /* Autostart flag. This should be set to true if the DSP image should
+ * be loaded and run during bridge module initialization */
+
+ if (base_img) {
+ temp = true;
+ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+ sizeof(temp));
+ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
+ strlen(base_img) + 1);
+ } else {
+ temp = false;
+ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+ sizeof(temp));
+ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
+ }
+ REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
+ strlen(num_procs) + 1);
+
+ if (shm_size >= 0x10000) { /* 64 KB */
+ initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
+ (u8 *)&shm_size, sizeof(shm_size));
+ } else {
+ initStatus = DSP_EINVALIDARG;
+ status = -1;
+ GT_0trace(driverTrace, GT_7CLASS,
+ "SHM size must be at least 64 KB\n");
+ }
+ GT_1trace(driverTrace, GT_7CLASS,
+ "requested shm_size = 0x%x\n", shm_size);
+
+ if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
+ phys_mempool_base = pdata->phys_mempool_base;
+ phys_mempool_size = pdata->phys_mempool_size;
+ }
+
+ if (phys_mempool_base > 0x0) {
+ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
+ REG_DWORD, (u8 *)&phys_mempool_base,
+ sizeof(phys_mempool_base));
+ }
+ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
+ phys_mempool_base);
+
+ if (phys_mempool_size > 0x0) {
+ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
+ REG_DWORD, (u8 *)&phys_mempool_size,
+ sizeof(phys_mempool_size));
+ }
+ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
+ phys_mempool_base);
+ if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
+ MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
+ if (tc_wordswapon) {
+ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
+ REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
+ (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
+ REG_SetValue(NULL, NULL, TCWORDSWAP,
+ REG_DWORD, (u8 *)&tc_wordswapon,
+ sizeof(tc_wordswapon));
+ }
+ if (DSP_SUCCEEDED(initStatus)) {
+#ifdef CONFIG_BRIDGE_DVFS
+ for (i = 0; i < 6; i++)
+ pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
+
+ clk_handle = clk_get(NULL, "iva2_ck");
+ if (!clk_handle) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_get failed to get iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_get PASS to get iva2_ck \n");
+ }
+ if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_register PASS for iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_register FAIL for iva2_ck \n");
+ }
+#endif
+ driverContext = DSP_Init(&initStatus);
+ if (DSP_FAILED(initStatus)) {
+ status = -1;
+ GT_0trace(driverTrace, GT_7CLASS,
+ "DSP/BIOS Bridge initialization Failed\n");
+ } else {
+ GT_0trace(driverTrace, GT_5CLASS,
+ "DSP/BIOS Bridge driver loaded\n");
+ }
+ }
+
+ DBC_Assert(status == 0);
+ DBC_Assert(DSP_SUCCEEDED(initStatus));
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
+ return status;
+}
+
+static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
+{
+ dev_t devno;
+ bool ret;
+ DSP_STATUS dsp_status = DSP_SOK;
+ HANDLE hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pTmp = NULL;
+ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
+
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(dsp_status))
+ goto func_cont;
+ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
+ while (pCtxtclosed != NULL) {
+ GT_1trace(driverTrace, GT_5CLASS, "***Cleanup of "
+ "process***%d\n", pCtxtclosed->pid);
+ DRV_RemoveAllResources(pCtxtclosed);
+ PROC_Detach(pCtxtclosed->hProcessor);
+ pTmp = pCtxtclosed->next;
+ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
+ pCtxtclosed, (void *)pCtxtclosed->pid);
+ pCtxtclosed = pTmp;
+ }
+func_cont:
+ if (driverContext) {
+ /* Put the DSP in reset state */
+ ret = DSP_Deinit(driverContext);
+ driverContext = 0;
+ DBC_Assert(ret == true);
+ }
+ SERVICES_Exit();
+ GT_exit();
+ /* unregister the clock notifier */
+#ifdef CONFIG_BRIDGE_DVFS
+ if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_unregister PASS for iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_unregister PASS for iva2_ck \n");
+ }
+
+ clk_put(clk_handle);
+ clk_handle = NULL;
+#endif /* #ifdef CONFIG_BRIDGE_DVFS */
+
+ devno = MKDEV(driver_major, driver_minor);
+ if (bridge_device) {
+ cdev_del(&bridge_device->cdev);
+ kfree(bridge_device);
+ }
+ unregister_chrdev_region(devno, 1);
+ if (bridge_class) {
+ /* remove the device from sysfs */
+ device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
+ class_destroy(bridge_class);
+
+ }
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ u32 status;
+ u32 command = PWR_EMERGENCYDEEPSLEEP;
+
+ status = PWR_SleepDSP(command, timeOut);
+ if (DSP_FAILED(status))
+ return -1;
+
+ bridge_suspend_data.suspended = 1;
+ return 0;
+}
+
+static int bridge_resume(struct platform_device *pdev)
+{
+ u32 status;
+
+ status = PWR_WakeDSP(timeOut);
+ if (DSP_FAILED(status))
+ return -1;
+
+ bridge_suspend_data.suspended = 0;
+ wake_up(&bridge_suspend_data.suspend_wq);
+ return 0;
+}
+#else
+#define bridge_suspend NULL
+#define bridge_resume NULL
+#endif
+
+static struct platform_driver bridge_driver = {
+ .driver = {
+ .name = BRIDGE_NAME,
+ },
+ .probe = omap34xx_bridge_probe,
+ .remove = __devexit_p(omap34xx_bridge_remove),
+ .suspend = bridge_suspend,
+ .resume = bridge_resume,
+};
+
+static int __init bridge_init(void)
+{
+ return platform_driver_register(&bridge_driver);
+}
+
+static void __exit bridge_exit(void)
+{
+ platform_driver_unregister(&bridge_driver);
+}
+
+/* This function is called when an application opens handle to the
+ * bridge driver. */
+
+static int bridge_open(struct inode *ip, struct file *filp)
+{
+ int status = 0;
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ DSP_STATUS dsp_status = DSP_SOK;
+ HANDLE hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pPctxt = NULL;
+ struct PROCESS_CONTEXT *next_node = NULL;
+ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
+ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
+ struct task_struct *tsk = NULL;
+ struct pid *pnr = NULL;
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+
+ /* Checking weather task structure for all process existing
+ * in the process context list If not removing those processes*/
+ if (DSP_FAILED(dsp_status))
+ goto func_cont;
+
+ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
+ while (pCtxtclosed != NULL) {
+ pnr = find_get_pid(pCtxtclosed->pid);
+ tsk = pid_task(pnr, PIDTYPE_PID);
+ next_node = pCtxtclosed->next;
+
+ if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
+
+ GT_1trace(driverTrace, GT_5CLASS,
+ "***Task structure not existing for "
+ "process***%d\n", pCtxtclosed->pid);
+ DRV_RemoveAllResources(pCtxtclosed);
+ if (pCtxtclosed->hProcessor != NULL) {
+ DRV_GetProcCtxtList(&pCtxttraverse,
+ (struct DRV_OBJECT *)hDrvObject);
+ if (pCtxttraverse->next == NULL) {
+ PROC_Detach(pCtxtclosed->hProcessor);
+ } else {
+ if ((pCtxtclosed->pid ==
+ pCtxttraverse->pid) &&
+ (pCtxttraverse->next != NULL)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ }
+ while ((pCtxttraverse != NULL) &&
+ (pCtxtclosed->hProcessor
+ != pCtxttraverse->hProcessor)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ if ((pCtxttraverse != NULL) &&
+ (pCtxtclosed->pid ==
+ pCtxttraverse->pid)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ }
+ }
+ if (pCtxttraverse == NULL) {
+ PROC_Detach
+ (pCtxtclosed->hProcessor);
+ }
+ }
+ }
+ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
+ pCtxtclosed,
+ (void *)pCtxtclosed->pid);
+ }
+ pCtxtclosed = next_node;
+ }
+func_cont:
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(dsp_status))
+ dsp_status = DRV_InsertProcContext(
+ (struct DRV_OBJECT *)hDrvObject, &pPctxt);
+
+ if (pPctxt != NULL) {
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
+ DRV_ProcSetPID(pPctxt, hProcess);
+ }
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
+ return status;
+}
+
+/* This function is called when an application closes handle to the bridge
+ * driver. */
+static int bridge_release(struct inode *ip, struct file *filp)
+{
+ int status;
+ u32 pid;
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
+
+ /* Return PID instead of process handle */
+ pid = current->pid;
+
+ status = DSP_Close(pid);
+
+
+ (status == true) ? (status = 0) : (status = -1);
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
+
+ return status;
+}
+
+/* This function provides IO interface to the bridge driver. */
+static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
+ unsigned long args)
+{
+ int status;
+ u32 retval = DSP_SOK;
+ union Trapped_Args pBufIn;
+
+ DBC_Require(filp != NULL);
+#ifdef CONFIG_PM
+ status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
+ if (status != 0)
+ return status;
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
+
+ status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
+ sizeof(union Trapped_Args));
+
+ if (status >= 0) {
+ status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = retval;
+ } else {
+ GT_1trace(driverTrace, GT_7CLASS,
+ "IOCTL Failed, code : 0x%x\n", code);
+ status = -1;
+ }
+
+ }
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
+
+ return status;
+}
+
+/* This function maps kernel space memory to user space memory. */
+static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+#if GT_TRACE
+ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
+#endif
+ u32 status;
+
+ DBC_Assert(vma->vm_start < vma->vm_end);
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ GT_6trace(driverTrace, GT_3CLASS,
+ "vm filp %p offset %lx start %lx end %lx"
+ " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
+ vma->vm_end, vma->vm_page_prot, vma->vm_flags);
+
+ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ if (status != 0)
+ status = -EAGAIN;
+
+ return status;
+}
+
+#ifndef RES_CLEANUP_DISABLE
+/* To remove all process resources before removing the process from the
+ * process context list*/
+DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ if (pCtxt != NULL) {
+ DRV_RemoveAllSTRMResElements(pCtxt);
+ DRV_RemoveAllNodeResElements(pCtxt);
+ DRV_RemoveAllDMMResElements(pCtxt);
+ DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
+ }
+ return status;
+}
+#endif
+
+/* Bridge driver initialization and de-initialization functions */
+module_init(bridge_init);
+module_exit(bridge_exit);
+
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
new file mode 100644
index 000000000000..f5b068e92ec5
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv_interface.h
@@ -0,0 +1,40 @@
+/*
+ * drv_interface.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== drv_interface.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 24-Mar-2003 vp Added hooks for Power Management Test
+ *! 18-Feb-2003 vp Code review updates
+ *! 18-Oct-2002 sb Created initial version
+
+ */
+
+#ifndef _DRV_INTERFACE_H_
+#define _DRV_INTERFACE_H_
+
+/* Prototypes for all functions in this bridge */
+static int __init bridge_init(void); /* Initialize bridge */
+static void __exit bridge_exit(void); /* Opposite of initialize */
+static int bridge_open(struct inode *, struct file *); /* Open */
+static int bridge_release(struct inode *, struct file *); /* Release */
+static int bridge_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
+#endif /* ifndef _DRV_INTERFACE_H_ */
diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
new file mode 100644
index 000000000000..a7a74fc21d21
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/dspdrv.c
@@ -0,0 +1,276 @@
+/*
+ * dspdrv.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dspdrv.c ========
+ * Description:
+ * Interface to allocate and free bridge resources.
+ *
+ *! Revision History
+ *! ================
+ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
+ *! 09-Feb-2004 vp: Updated to support IVA.
+ *! 10-Feb-2003 vp: Code review updates.
+ *! 18-oct-2002 vp: Ported to the Linux platform.
+ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
+ *! before calling MGR_Destroy.
+ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
+ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
+ *! sllowing the class driver to load irrespective of
+ *! the image load.
+ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
+ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
+ *! Failure in WCD_InitComplete2 will cause the
+ *! DSP_Init to fail.
+ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
+ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
+ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
+ *! DevObjects. Static variables removed. Returns
+ *! the Driver Object in DSP_Init.
+ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
+ *! the list of Device objects.
+ *! 07-Jul-2000 rr: RM implementaion started.
+ *! 24-May-2000 ag: Cleaned up debug msgs.
+ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
+ *! 03-Feb-2000 rr: GT Changes.
+ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
+ *! DSP_Deinit checks return values.dwCode in
+ *! DSP_IO_CONTROL is decoded(not hard coded)
+ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
+ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
+ *! 29-Dec-1999 rr: Code Cleaned up
+ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
+ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and ArrayofInstalledDev
+ *! is Global.DevObject stores this pointer as hDevNode.
+ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
+ *! Comments changed.Deinit handled.Code cleaned up.
+ *! DSP_IOControl, Close, Deinit returns bool values.
+ *! Calls WCD_InitComplete2 for Board AutoStart.
+ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
+ *! Global Arrays keeps track of installed devices.
+ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
+ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
+ *! for multiple mini driver support.PCCARD flag
+ *! checking to include PCMCIA related stuff.
+ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
+ *! return value initalized to S_OK upfront in the
+ *! Process Attach.
+ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
+ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
+ *! DRV_Request Resources is used instead of the
+ *! RegisterMiniDriver as it sounds close to what we are doing.
+ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
+ *! neccessaryPCMCIA fxns are here. Soon they will move out
+ *! either to a seperate file for bus specific inits.
+ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the driver structure as
+ *! - This is the Class driver. After successfully initialized
+ *! the Class driver will attempt to load the Mini driver.
+ *! - Need to seperate the PCMCIA stuff based on bus type.
+ *! - Changed the name of the file to wcdce.c
+ *! - Made the Media Handle as Global again
+ *!
+ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
+ *! Modified the DSP_Init, now three windows are opened.
+ *! Split the driver into PDD so that hardware dependent
+ *! functions will reside in PDD.
+ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet card driver.
+ *!
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/reg.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/drv.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/_dcd.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/mgr.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dspdrv.h>
+
+/* ----------------------------------- Globals */
+struct GT_Mask curTrace;
+
+/*
+ * ======== DSP_Init ========
+ * Allocates bridge resources. Loads a base image onto DSP, if specified.
+ */
+u32 DSP_Init(OUT u32 *initStatus)
+{
+ char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
+ DSP_STATUS status = DSP_EFAIL;
+ struct DRV_OBJECT *drvObject = NULL;
+ u32 index = 0;
+ u32 deviceNode;
+ u32 deviceNodeString;
+
+ GT_create(&curTrace, "DD");
+
+ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
+
+ if (DSP_FAILED(WCD_Init())) {
+ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
+ goto func_cont;
+ } /* End WCD_Exit */
+ if (DSP_FAILED(DRV_Create(&drvObject))) {
+ GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
+ WCD_Exit();
+ goto func_cont;
+ } /* End DRV_Create */
+ GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
+
+ /* Request Resources */
+ if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
+ &deviceNodeString))) {
+ /* Attempt to Start the Device */
+ if (DSP_SUCCEEDED(DEV_StartDevice(
+ (struct CFG_DEVNODE *)deviceNodeString))) {
+ /* Retreive the DevObject from the Registry */
+ GT_2trace(curTrace, GT_1CLASS,
+ "DSP_Init Succeeded for Device1:"
+ "%d: value: %x\n", index, deviceNodeString);
+ status = DSP_SOK;
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ "DSP_Init:DEV_StartDevice Failed\n");
+ (void)DRV_ReleaseResources
+ ((u32) deviceNodeString, drvObject);
+ status = DSP_EFAIL;
+ }
+ } else {
+ GT_0trace(curTrace, GT_7CLASS,
+ "DSP_Init:DRV_RequestResources Failed \r\n");
+ status = DSP_EFAIL;
+ } /* DRV_RequestResources */
+ index++;
+
+ /* Unwind whatever was loaded */
+ if (DSP_FAILED(status)) {
+ /* irrespective of the status of DEV_RemoveDevice we conitinue
+ * unloading. Get the Driver Object iterate through and remove.
+ * Reset the status to E_FAIL to avoid going through
+ * WCD_InitComplete2. */
+ status = DSP_EFAIL;
+ for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
+ deviceNode = DRV_GetNextDevExtension(deviceNode)) {
+ (void)DEV_RemoveDevice
+ ((struct CFG_DEVNODE *)deviceNode);
+ (void)DRV_ReleaseResources((u32)deviceNode,
+ drvObject);
+ }
+ /* Remove the Driver Object */
+ (void)DRV_Destroy(drvObject);
+ drvObject = NULL;
+ WCD_Exit();
+ GT_0trace(curTrace, GT_7CLASS,
+ "DSP_Init:Logical device Failed to Load\n");
+ } /* Unwinding the loaded drivers */
+func_cont:
+ /* Attempt to Start the Board */
+ if (DSP_SUCCEEDED(status)) {
+ /* BRD_AutoStart could fail if the dsp execuetable is not the
+ * correct one. We should not propagate that error
+ * into the device loader. */
+ (void)WCD_InitComplete2();
+ GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
+ } else {
+ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
+ } /* End WCD_InitComplete2 */
+ DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) ||
+ (DSP_FAILED(status) && drvObject == NULL));
+ *initStatus = status;
+ /* Return the Driver Object */
+ return (u32)drvObject;
+}
+
+/*
+ * ======== DSP_Deinit ========
+ * Frees the resources allocated for bridge.
+ */
+bool DSP_Deinit(u32 deviceContext)
+{
+ bool retVal = true;
+ u32 deviceNode;
+ struct MGR_OBJECT *mgrObject = NULL;
+
+ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
+
+ while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
+ (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
+
+ (void)DRV_ReleaseResources((u32)deviceNode,
+ (struct DRV_OBJECT *)deviceContext);
+ }
+
+ (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
+
+ /* Get the Manager Object from Registry
+ * MGR Destroy will unload the DCD dll */
+ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
+ (void)MGR_Destroy(mgrObject);
+
+ WCD_Exit();
+
+ return retVal;
+}
+
+/*
+ * ======== DSP_Close ========
+ * The Calling Process handle is passed to DEV_CleanupProcesState
+ * for cleaning up of any resources used by the application
+ */
+bool DSP_Close(u32 dwOpenContext)
+{
+ bool retVal = false;
+
+ DBC_Require(dwOpenContext != 0);
+
+ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
+
+#ifdef RES_CLEANUP_DISABLE
+
+ if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
+ GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
+ retVal = true;
+ } else {
+ GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
+ }
+#endif
+
+ return retVal;
+}
diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
new file mode 100644
index 000000000000..943cf932a35b
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/mgr.c
@@ -0,0 +1,491 @@
+/*
+ * mgr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== mgr.c ========
+ * Description:
+ * Implementation of Manager interface to the device object at the
+ * driver level. This queries the NDB data base and retrieves the
+ * data about Node and Processor.
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 12-Feb-2003 vp: Code review updates.
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
+ *! 03-Nov-2000 rr: Updated after code review.
+ *! 25-Sep-2000 rr: Updated to Version 0.9
+ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
+ *! as it is taken care by MEM_AllocObject. stdwin.h added
+ *! for retail build to succeed.
+ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
+ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
+ *! 20-Jun-2000 rr: Created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbdcd.h>
+#include <dspbridge/dbreg.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/mgr.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define ZLDLLNAME ""
+#define SIGNATURE 0x5f52474d /* "MGR_" (in reverse) */
+
+struct MGR_OBJECT {
+ u32 dwSignature;
+ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask MGR_DebugMask = { NULL, NULL };
+#endif
+
+static u32 cRefs;
+
+/*
+ * ========= MGR_Create =========
+ * Purpose:
+ * MGR Object gets created only once during driver Loading.
+ */
+DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
+ struct CFG_DEVNODE *hDevNode)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct MGR_OBJECT *pMgrObject = NULL;
+
+ DBC_Require(phMgrObject != NULL);
+ DBC_Require(cRefs > 0);
+ GT_1trace(MGR_DebugMask, GT_ENTER,
+ "Entering MGR_Create phMgrObject 0x%x\n ",
+ phMgrObject);
+ MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
+ if (pMgrObject) {
+ if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
+ &pMgrObject->hDcdMgr))) {
+ /* If succeeded store the handle in the MGR Object */
+ if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
+ REG_MGR_OBJECT))) {
+ *phMgrObject = pMgrObject;
+ GT_0trace(MGR_DebugMask, GT_1CLASS,
+ "MGR_Create:MGR Created\r\n");
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "MGR_Create:CFG_SetObject "
+ "Failed\r\n");
+ DCD_DestroyManager(pMgrObject->hDcdMgr);
+ MEM_FreeObject(pMgrObject);
+ }
+ } else {
+ /* failed to Create DCD Manager */
+ status = DSP_EFAIL;
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "MGR_Create:DCD_ManagerCreate Failed\r\n");
+ MEM_FreeObject(pMgrObject);
+ }
+ } else {
+ status = DSP_EMEMORY;
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "MGR_Create DSP_FAILED to allocate memory \n");
+ }
+ GT_2trace(MGR_DebugMask, GT_ENTER,
+ "Exiting MGR_Create: phMgrObject: 0x%x\t"
+ "status: 0x%x\n", phMgrObject, status);
+ DBC_Ensure(DSP_FAILED(status) ||
+ MEM_IsValidHandle(pMgrObject, SIGNATURE));
+ return status;
+}
+
+/*
+ * ========= MGR_Destroy =========
+ * This function is invoked during bridge driver unloading.Frees MGR object.
+ */
+DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
+
+ GT_1trace(MGR_DebugMask, GT_ENTER,
+ "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
+ /* Free resources */
+ if (hMgrObject->hDcdMgr)
+ DCD_DestroyManager(hMgrObject->hDcdMgr);
+
+ MEM_FreeObject(pMgrObject);
+ /* Update the Registry with NULL for MGR Object */
+ (void)CFG_SetObject(0, REG_MGR_OBJECT);
+
+ GT_2trace(MGR_DebugMask, GT_ENTER,
+ "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
+ "status: 0x%x\n", hMgrObject, status);
+
+ DBC_Ensure(DSP_FAILED(status) ||
+ !MEM_IsValidHandle(hMgrObject, SIGNATURE));
+
+ return status;
+}
+
+/*
+ * ======== MGR_EnumNodeInfo ========
+ * Enumerate and get configuration information about nodes configured
+ * in the node database.
+ */
+DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
+ u32 uNDBPropsSize, OUT u32 *puNumNodes)
+{
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+ struct DSP_UUID Uuid, uTempUuid;
+ u32 uTempIndex = 0;
+ u32 uNodeIndex = 0;
+ struct DCD_GENERICOBJ GenObj;
+ struct MGR_OBJECT *pMgrObject = NULL;
+
+ DBC_Require(pNDBProps != NULL);
+ DBC_Require(puNumNodes != NULL);
+ DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
+ DBC_Require(cRefs > 0);
+
+ GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
+ "args:\n\t uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
+ "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
+ uNDBPropsSize, puNumNodes);
+ *puNumNodes = 0;
+ /* Get The Manager Object from the Registry */
+ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
+ REG_MGR_OBJECT))) {
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumNodeInfo:Failed To Get"
+ " MGR Object from Registry\r\n");
+ goto func_cont;
+ }
+ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
+ /* Forever loop till we hit failed or no more items in the
+ * Enumeration. We will exit the loop other than DSP_SOK; */
+ while (status == DSP_SOK) {
+ status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
+ &uTempUuid);
+ if (status == DSP_SOK) {
+ uNodeIndex++;
+ if (uNode == (uNodeIndex - 1))
+ Uuid = uTempUuid;
+
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ if (uNode > (uNodeIndex - 1)) {
+ status = DSP_EINVALIDARG;
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumNodeInfo: uNode"
+ " is Invalid \r\n");
+ } else {
+ status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
+ (struct DSP_UUID *)&Uuid,
+ DSP_DCDNODETYPE, &GenObj);
+ if (DSP_SUCCEEDED(status1)) {
+ /* Get the Obj def */
+ *pNDBProps = GenObj.objData.nodeObj.ndbProps;
+ *puNumNodes = uNodeIndex;
+ status = DSP_SOK;
+ } else {
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumNodeInfo: "
+ "Failed to Get Node Info \r\n");
+ status = DSP_EFAIL;
+ }
+ }
+ } else {
+ /* This could be changed during enum, EFAIL ... */
+ GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
+ "Enumeration failure\r\n");
+ status = DSP_EFAIL;
+ }
+func_cont:
+ GT_4trace(MGR_DebugMask, GT_ENTER,
+ "Exiting Manager_EnumNodeInfo, args:\n\t"
+ "uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
+ " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
+ uNDBPropsSize, *puNumNodes);
+ DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
+ (DSP_FAILED(status) && *puNumNodes == 0));
+
+ return status;
+}
+
+/*
+ * ======== MGR_EnumProcessorInfo ========
+ * Enumerate and get configuration information about available
+ * DSP processors.
+ */
+DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
+ OUT struct DSP_PROCESSORINFO *pProcessorInfo,
+ u32 uProcessorInfoSize, OUT u32 *puNumProcs)
+{
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+ DSP_STATUS status2 = DSP_SOK;
+ struct DSP_UUID uTempUuid;
+ u32 uTempIndex = 0;
+ u32 uProcIndex = 0;
+ struct DCD_GENERICOBJ GenObj;
+ struct MGR_OBJECT *pMgrObject = NULL;
+ struct MGR_PROCESSOREXTINFO *pExtInfo;
+ struct DEV_OBJECT *hDevObject;
+ struct DRV_OBJECT *hDrvObject;
+ s32 devType;
+ struct CFG_DEVNODE *devNode;
+ struct CFG_DSPRES chipResources;
+ bool procDetect = false;
+
+ DBC_Require(pProcessorInfo != NULL);
+ DBC_Require(puNumProcs != NULL);
+ DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
+ DBC_Require(cRefs > 0);
+
+ GT_4trace(MGR_DebugMask, GT_ENTER,
+ "Entered Manager_EnumProcessorInfo, "
+ "args:\n\tuProcessor: 0x%x\n\tpProcessorInfo: 0x%x\n\t"
+ "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
+ pProcessorInfo, uProcessorInfoSize, puNumProcs);
+ *puNumProcs = 0;
+ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(status)) {
+ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetDevType(hDevObject, (u32 *) &devType);
+ status = DEV_GetDevNode(hDevObject, &devNode);
+ if (devType == DSP_UNIT) {
+ status = CFG_GetDSPResources(devNode,
+ &chipResources);
+ } else {
+ status = DSP_EFAIL;
+ GT_1trace(MGR_DebugMask, GT_7CLASS,
+ "Unsupported dev type gotten"
+ "from device object %d\n", devType);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pProcessorInfo->uProcessorType =
+ chipResources.uChipType;
+ }
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Get The Manager Object from the Registry */
+ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
+ REG_MGR_OBJECT))) {
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumProcessorInfo: "
+ "Failed To Get MGR Object from Registry\r\n");
+ goto func_end;
+ }
+ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
+ /* Forever loop till we hit no more items in the
+ * Enumeration. We will exit the loop other than DSP_SOK; */
+ while (status1 == DSP_SOK) {
+ status1 = DCD_EnumerateObject(uTempIndex++,
+ DSP_DCDPROCESSORTYPE,
+ &uTempUuid);
+ if (status1 != DSP_SOK)
+ break;
+
+ uProcIndex++;
+ /* Get the Object properties to find the Device/Processor
+ * Type */
+ if (procDetect != false)
+ continue;
+
+ status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
+ (struct DSP_UUID *)&uTempUuid,
+ DSP_DCDPROCESSORTYPE,
+ &GenObj);
+ if (DSP_SUCCEEDED(status2)) {
+ /* Get the Obj def */
+ if (uProcessorInfoSize <
+ sizeof(struct MGR_PROCESSOREXTINFO)) {
+ *pProcessorInfo = GenObj.objData.procObj;
+ } else {
+ /* extended info */
+ pExtInfo = (struct MGR_PROCESSOREXTINFO *)
+ pProcessorInfo;
+ *pExtInfo = GenObj.objData.extProcObj;
+ }
+ GT_1trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumProcessorInfo: Got"
+ " Proctype from DCD %x \r\n",
+ pProcessorInfo->uProcessorType);
+ /* See if we got the needed processor */
+ if (devType == DSP_UNIT) {
+ if (pProcessorInfo->uProcessorType ==
+ DSPPROCTYPE_C64)
+ procDetect = true;
+ } else if (devType == IVA_UNIT) {
+ if (pProcessorInfo->uProcessorType ==
+ IVAPROCTYPE_ARM7)
+ procDetect = true;
+ }
+ /* User applciatiuons aonly check for chip type, so
+ * this clumsy overwrite */
+ pProcessorInfo->uProcessorType =
+ chipResources.uChipType;
+ } else {
+ GT_1trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumProcessorInfo: "
+ "Failed to Get DCD Processor Info %x \r\n",
+ status2);
+ status = DSP_EFAIL;
+ }
+ }
+ *puNumProcs = uProcIndex;
+ if (procDetect == false) {
+ GT_0trace(MGR_DebugMask, GT_7CLASS,
+ "Manager_EnumProcessorInfo: Failed"
+ " to get Proc info from DCD , so use CFG registry\n");
+ pProcessorInfo->uProcessorType = chipResources.uChipType;
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== MGR_Exit ========
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ */
+void MGR_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+ cRefs--;
+ if (cRefs == 0)
+ DCD_Exit();
+
+ GT_1trace(MGR_DebugMask, GT_5CLASS,
+ "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== MGR_GetDCDHandle ========
+ * Retrieves the MGR handle. Accessor Function.
+ */
+DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
+ OUT u32 *phDCDHandle)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDCDHandle != NULL);
+
+ *phDCDHandle = (u32)NULL;
+ if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
+ *phDCDHandle = (u32) pMgrObject->hDcdMgr;
+ status = DSP_SOK;
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
+ (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
+
+ return status;
+}
+
+/*
+ * ======== MGR_Init ========
+ * Initialize MGR's private state, keeping a reference count on each call.
+ */
+bool MGR_Init(void)
+{
+ bool fRetval = true;
+ bool fInitDCD = false;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+
+ /* Set the Trace mask */
+ DBC_Assert(!MGR_DebugMask.flags);
+
+ GT_create(&MGR_DebugMask, "MG"); /* "MG" for Manager */
+ fInitDCD = DCD_Init(); /* DCD Module */
+
+ if (!fInitDCD) {
+ fRetval = false;
+ GT_0trace(MGR_DebugMask, GT_6CLASS,
+ "MGR_Init failed\n");
+ }
+ }
+
+ if (fRetval)
+ cRefs++;
+
+
+ GT_1trace(MGR_DebugMask, GT_5CLASS,
+ "Entered MGR_Init, ref count: 0x%x\n", cRefs);
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+/*
+ * ======== MGR_WaitForBridgeEvents ========
+ * Block on any Bridge event(s)
+ */
+DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
+ u32 uCount, OUT u32 *puIndex, u32 uTimeout)
+{
+ DSP_STATUS status;
+ struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
+ u32 i;
+
+ DBC_Require(uCount < MAX_EVENTS);
+
+ for (i = 0; i < uCount; i++)
+ hSyncEvents[i] = aNotifications[i]->handle;
+
+ status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
+ puIndex);
+
+ return status;
+
+}
+
diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
new file mode 100644
index 000000000000..79f75059d11b
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/nldr.c
@@ -0,0 +1,1967 @@
+/*
+ * nldr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== nldr.c ========
+ * Description:
+ * DSP/BIOS Bridge dynamic + overlay Node loader.
+ *
+ * Public Functions:
+ * NLDR_Allocate
+ * NLDR_Create
+ * NLDR_Delete
+ * NLDR_Exit
+ * NLDR_Free
+ * NLDR_GetFxnAddr
+ * NLDR_Init
+ * NLDR_Load
+ * NLDR_Unload
+ *
+ * Notes:
+ *
+ *! Revision History
+ *! ================
+ *! 07-Apr-2003 map Removed references to dead DLDR module
+ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
+ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
+ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
+ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
+ *! sections > 1024 bytes.
+ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
+ *! libs for symbols
+ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
+ *! correct deallocation
+ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
+ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
+ *! 05-Aug-2002 jeh Created.
+ */
+
+#include <dspbridge/host_os.h>
+
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+#ifdef DEBUG
+#include <dspbridge/dbg.h>
+#endif
+
+/* OS adaptation layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* Platform manager */
+#include <dspbridge/cod.h>
+#include <dspbridge/dev.h>
+
+/* Resource manager */
+#include <dspbridge/dbll.h>
+#include <dspbridge/dbdcd.h>
+#include <dspbridge/rmm.h>
+#include <dspbridge/uuidutil.h>
+
+#include <dspbridge/nldr.h>
+
+#define NLDR_SIGNATURE 0x52444c4e /* "RDLN" */
+#define NLDR_NODESIGNATURE 0x4e444c4e /* "NDLN" */
+
+/* Name of section containing dynamic load mem */
+#define DYNMEMSECT ".dspbridge_mem"
+
+/* Name of section containing dependent library information */
+#define DEPLIBSECT ".dspbridge_deplibs"
+
+/* Max depth of recursion for loading node's dependent libraries */
+#define MAXDEPTH 5
+
+/* Max number of persistent libraries kept by a node */
+#define MAXLIBS 5
+
+/*
+ * Defines for extracting packed dynamic load memory requirements from two
+ * masks.
+ * These defines must match node.cdb and dynm.cdb
+ * Format of data/code mask is:
+ * uuuuuuuu|fueeeeee|fudddddd|fucccccc|
+ * where
+ * u = unused
+ * cccccc = prefered/required dynamic mem segid for create phase data/code
+ * dddddd = prefered/required dynamic mem segid for delete phase data/code
+ * eeeeee = prefered/req. dynamic mem segid for execute phase data/code
+ * f = flag indicating if memory is preferred or required:
+ * f = 1 if required, f = 0 if preferred.
+ *
+ * The 6 bits of the segid are interpreted as follows:
+ *
+ * If the 6th bit (bit 5) is not set, then this specifies a memory segment
+ * between 0 and 31 (a maximum of 32 dynamic loading memory segments).
+ * If the 6th bit (bit 5) is set, segid has the following interpretation:
+ * segid = 32 - Any internal memory segment can be used.
+ * segid = 33 - Any external memory segment can be used.
+ * segid = 63 - Any memory segment can be used (in this case the
+ * required/preferred flag is irrelevant).
+ *
+ */
+/* Maximum allowed dynamic loading memory segments */
+#define MAXMEMSEGS 32
+
+#define MAXSEGID 3 /* Largest possible (real) segid */
+#define MEMINTERNALID 32 /* Segid meaning use internal mem */
+#define MEMEXTERNALID 33 /* Segid meaning use external mem */
+#define NULLID 63 /* Segid meaning no memory req/pref */
+#define FLAGBIT 7 /* 7th bit is pref./req. flag */
+#define SEGMASK 0x3f /* Bits 0 - 5 */
+
+#define CREATEBIT 0 /* Create segid starts at bit 0 */
+#define DELETEBIT 8 /* Delete segid starts at bit 8 */
+#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */
+
+/*
+ * Masks that define memory type. Must match defines in dynm.cdb.
+ */
+#define DYNM_CODE 0x2
+#define DYNM_DATA 0x4
+#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
+#define DYNM_INTERNAL 0x8
+#define DYNM_EXTERNAL 0x10
+
+/*
+ * Defines for packing memory requirement/preference flags for code and
+ * data of each of the node's phases into one mask.
+ * The bit is set if the segid is required for loading code/data of the
+ * given phase. The bit is not set, if the segid is preferred only.
+ *
+ * These defines are also used as indeces into a segid array for the node.
+ * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
+ * create phase data is required or preferred to be loaded into.
+ */
+#define CREATEDATAFLAGBIT 0
+#define CREATECODEFLAGBIT 1
+#define EXECUTEDATAFLAGBIT 2
+#define EXECUTECODEFLAGBIT 3
+#define DELETEDATAFLAGBIT 4
+#define DELETECODEFLAGBIT 5
+#define MAXFLAGS 6
+
+#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
+ hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
+ (segid) == MEMINTERNALID)
+
+#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
+ hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
+ (segid) == MEMEXTERNALID)
+
+#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
+ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
+
+#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
+
+ /*
+ * These names may be embedded in overlay sections to identify which
+ * node phase the section should be overlayed.
+ */
+#define PCREATE "create"
+#define PDELETE "delete"
+#define PEXECUTE "execute"
+
+#define IsEqualUUID(uuid1, uuid2) (\
+ ((uuid1).ulData1 == (uuid2).ulData1) && \
+ ((uuid1).usData2 == (uuid2).usData2) && \
+ ((uuid1).usData3 == (uuid2).usData3) && \
+ ((uuid1).ucData4 == (uuid2).ucData4) && \
+ ((uuid1).ucData5 == (uuid2).ucData5) && \
+ (strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
+
+ /*
+ * ======== MemInfo ========
+ * Format of dynamic loading memory segment info in coff file.
+ * Must match dynm.h55.
+ */
+struct MemInfo {
+ u32 segid; /* Dynamic loading memory segment number */
+ u32 base;
+ u32 len;
+ u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
+};
+
+/*
+ * ======== LibNode ========
+ * For maintaining a tree of library dependencies.
+ */
+struct LibNode {
+ struct DBLL_LibraryObj *lib; /* The library */
+ u16 nDepLibs; /* Number of dependent libraries */
+ struct LibNode *pDepLibs; /* Dependent libraries of lib */
+};
+
+/*
+ * ======== OvlySect ========
+ * Information needed to overlay a section.
+ */
+struct OvlySect {
+ struct OvlySect *pNextSect;
+ u32 loadAddr; /* Load address of section */
+ u32 runAddr; /* Run address of section */
+ u32 size; /* Size of section */
+ u16 page; /* DBL_CODE, DBL_DATA */
+};
+
+/*
+ * ======== OvlyNode ========
+ * For maintaining a list of overlay nodes, with sections that need to be
+ * overlayed for each of the nodes phases.
+ */
+struct OvlyNode {
+ struct DSP_UUID uuid;
+ char *pNodeName;
+ struct OvlySect *pCreateSects;
+ struct OvlySect *pDeleteSects;
+ struct OvlySect *pExecuteSects;
+ struct OvlySect *pOtherSects;
+ u16 nCreateSects;
+ u16 nDeleteSects;
+ u16 nExecuteSects;
+ u16 nOtherSects;
+ u16 createRef;
+ u16 deleteRef;
+ u16 executeRef;
+ u16 otherRef;
+};
+
+/*
+ * ======== NLDR_OBJECT ========
+ * Overlay loader object.
+ */
+struct NLDR_OBJECT {
+ u32 dwSignature; /* For object validation */
+ struct DEV_OBJECT *hDevObject; /* Device object */
+ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
+ struct DBLL_TarObj *dbll; /* The DBL loader */
+ struct DBLL_LibraryObj *baseLib; /* Base image library */
+ struct RMM_TargetObj *rmm; /* Remote memory manager for DSP */
+ struct DBLL_Fxns dbllFxns; /* Loader function table */
+ struct DBLL_Attrs dbllAttrs; /* attrs to pass to loader functions */
+ NLDR_OVLYFXN ovlyFxn; /* "write" for overlay nodes */
+ NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
+ struct OvlyNode *ovlyTable; /* Table of overlay nodes */
+ u16 nOvlyNodes; /* Number of overlay nodes in base */
+ u16 nNode; /* Index for tracking overlay nodes */
+ u16 nSegs; /* Number of dynamic load mem segs */
+ u32 *segTable; /* memtypes of dynamic memory segs
+ * indexed by segid
+ */
+ u16 usDSPMauSize; /* Size of DSP MAU */
+ u16 usDSPWordSize; /* Size of DSP word */
+};
+
+/*
+ * ======== NLDR_NODEOBJECT ========
+ * Dynamic node object. This object is created when a node is allocated.
+ */
+struct NLDR_NODEOBJECT {
+ u32 dwSignature; /* For object validation */
+ struct NLDR_OBJECT *pNldr; /* Dynamic loader handle */
+ void *pPrivRef; /* Handle to pass to DBL_WriteFxn */
+ struct DSP_UUID uuid; /* Node's UUID */
+ bool fDynamic; /* Dynamically loaded node? */
+ bool fOverlay; /* Overlay node? */
+ bool *pfPhaseSplit; /* Multiple phase libraries? */
+ struct LibNode root; /* Library containing node phase */
+ struct LibNode createLib; /* Library containing create phase lib */
+ struct LibNode executeLib; /* Library containing execute phase lib */
+ struct LibNode deleteLib; /* Library containing delete phase lib */
+ struct LibNode persLib[MAXLIBS]; /* libs remain loaded until Delete */
+ s32 nPersLib; /* Number of persistent libraries */
+ /* Path in lib dependency tree */
+ struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
+ enum NLDR_PHASE phase; /* Node phase currently being loaded */
+
+ /*
+ * Dynamic loading memory segments for data and code of each phase.
+ */
+ u16 segId[MAXFLAGS];
+
+ /*
+ * Mask indicating whether each mem segment specified in segId[]
+ * is preferred or required.
+ * For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
+ * then it is required to load execute phase data into the memory
+ * specified by segId[EXECUTEDATAFLAGBIT].
+ */
+ u32 codeDataFlagMask;
+};
+
+/* Dynamic loader function table */
+static struct DBLL_Fxns dbllFxns = {
+ (DBLL_CloseFxn) DBLL_close,
+ (DBLL_CreateFxn) DBLL_create,
+ (DBLL_DeleteFxn) DBLL_delete,
+ (DBLL_ExitFxn) DBLL_exit,
+ (DBLL_GetAttrsFxn) DBLL_getAttrs,
+ (DBLL_GetAddrFxn) DBLL_getAddr,
+ (DBLL_GetCAddrFxn) DBLL_getCAddr,
+ (DBLL_GetSectFxn) DBLL_getSect,
+ (DBLL_InitFxn) DBLL_init,
+ (DBLL_LoadFxn) DBLL_load,
+ (DBLL_LoadSectFxn) DBLL_loadSect,
+ (DBLL_OpenFxn) DBLL_open,
+ (DBLL_ReadSectFxn) DBLL_readSect,
+ (DBLL_SetAttrsFxn) DBLL_setAttrs,
+ (DBLL_UnloadFxn) DBLL_unload,
+ (DBLL_UnloadSectFxn) DBLL_unloadSect,
+};
+
+static struct GT_Mask NLDR_debugMask = { NULL, NULL }; /* GT trace variable */
+static u32 cRefs; /* module reference count */
+
+static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
+ u32 addr, u32 nBytes);
+static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
+ enum DSP_DCDOBJTYPE objType,
+ IN void *handle);
+static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
+ struct OvlySect **pList,
+ struct DBLL_SectInfo *pSectInfo, bool *pExists,
+ u32 addr, u32 nBytes);
+static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
+ s32 mtype);
+static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
+ u16 nAlloc);
+static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
+ char *symName, struct DBLL_Symbol **sym);
+static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
+ struct LibNode *root, struct DSP_UUID uuid,
+ bool rootPersistent, struct DBLL_LibraryObj **libPath,
+ enum NLDR_PHASE phase, u16 depth);
+static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
+ u32 align, u32 *dspAddr,
+ OPTIONAL s32 segmentId, OPTIONAL s32 req,
+ bool reserve);
+static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
+ u32 size, bool reserve);
+
+static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
+static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase);
+static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
+ struct DBLL_LibraryObj *lib);
+static u32 findLcm(u32 a, u32 b);
+static u32 findGcf(u32 a, u32 b);
+
+/*
+ * ======== NLDR_Allocate ========
+ */
+DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
+ IN CONST struct DCD_NODEPROPS *pNodeProps,
+ OUT struct NLDR_NODEOBJECT **phNldrNode,
+ IN bool *pfPhaseSplit)
+{
+ struct NLDR_NODEOBJECT *pNldrNode = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pNodeProps != NULL);
+ DBC_Require(phNldrNode != NULL);
+ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+
+ GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
+ "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
+ pfPhaseSplit);
+
+ /* Initialize handle in case of failure */
+ *phNldrNode = NULL;
+ /* Allocate node object */
+ MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
+
+ if (pNldrNode == NULL) {
+ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
+ "Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ pNldrNode->pfPhaseSplit = pfPhaseSplit;
+ pNldrNode->nPersLib = 0;
+ pNldrNode->pNldr = hNldr;
+ pNldrNode->pPrivRef = pPrivRef;
+ /* Save node's UUID. */
+ pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
+ /*
+ * Determine if node is a dynamically loaded node from
+ * ndbProps.
+ */
+ if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
+ /* Dynamic node */
+ pNldrNode->fDynamic = true;
+ /*
+ * Extract memory requirements from ndbProps masks
+ */
+ /* Create phase */
+ pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
+ (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
+ SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulDataMemSegMask >>
+ (CREATEBIT + FLAGBIT)) & 1) <<
+ CREATEDATAFLAGBIT;
+ pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
+ (pNodeProps->ulCodeMemSegMask >>
+ CREATEBIT) & SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulCodeMemSegMask >>
+ (CREATEBIT + FLAGBIT)) & 1) <<
+ CREATECODEFLAGBIT;
+ /* Execute phase */
+ pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
+ (pNodeProps->ulDataMemSegMask >>
+ EXECUTEBIT) & SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulDataMemSegMask >>
+ (EXECUTEBIT + FLAGBIT)) & 1) <<
+ EXECUTEDATAFLAGBIT;
+ pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
+ (pNodeProps->ulCodeMemSegMask >>
+ EXECUTEBIT) & SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulCodeMemSegMask >>
+ (EXECUTEBIT + FLAGBIT)) & 1) <<
+ EXECUTECODEFLAGBIT;
+ /* Delete phase */
+ pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
+ (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
+ SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulDataMemSegMask >>
+ (DELETEBIT + FLAGBIT)) & 1) <<
+ DELETEDATAFLAGBIT;
+ pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
+ (pNodeProps->ulCodeMemSegMask >>
+ DELETEBIT) & SEGMASK;
+ pNldrNode->codeDataFlagMask |=
+ ((pNodeProps->ulCodeMemSegMask >>
+ (DELETEBIT + FLAGBIT)) & 1) <<
+ DELETECODEFLAGBIT;
+ } else {
+ /* Non-dynamically loaded nodes are part of the
+ * base image */
+ pNldrNode->root.lib = hNldr->baseLib;
+ /* Check for overlay node */
+ if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
+ pNldrNode->fOverlay = true;
+
+ }
+ *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
+ }
+ /* Cleanup on failure */
+ if (DSP_FAILED(status) && pNldrNode)
+ NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
+
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
+ NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
+ *phNldrNode == NULL));
+ return status;
+}
+
+/*
+ * ======== NLDR_Create ========
+ */
+DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct NLDR_ATTRS *pAttrs)
+{
+ struct COD_MANAGER *hCodMgr; /* COD manager */
+ char *pszCoffBuf = NULL;
+ char szZLFile[COD_MAXPATHLENGTH];
+ struct NLDR_OBJECT *pNldr = NULL;
+ struct DBLL_Attrs saveAttrs;
+ struct DBLL_Attrs newAttrs;
+ DBLL_Flags flags;
+ u32 ulEntry;
+ u16 nSegs = 0;
+ struct MemInfo *pMemInfo;
+ u32 ulLen = 0;
+ u32 ulAddr;
+ struct RMM_Segment *rmmSegs = NULL;
+ u16 i;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(phNldr != NULL);
+ DBC_Require(hDevObject != NULL);
+ DBC_Require(pAttrs != NULL);
+ DBC_Require(pAttrs->pfnOvly != NULL);
+ DBC_Require(pAttrs->pfnWrite != NULL);
+ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
+ phNldr, hDevObject, pAttrs);
+ /* Allocate dynamic loader object */
+ MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
+ if (pNldr) {
+ pNldr->hDevObject = hDevObject;
+ /* warning, lazy status checking alert! */
+ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ status = COD_GetLoader(hCodMgr, &pNldr->dbll);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ status = DSP_SOK;
+ /* end lazy status checking */
+ pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
+ pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
+ pNldr->dbllFxns = dbllFxns;
+ if (!(pNldr->dbllFxns.initFxn()))
+ status = DSP_EMEMORY;
+
+ } else {
+ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
+ "Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ }
+ /* Create the DCD Manager */
+ if (DSP_SUCCEEDED(status))
+ status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
+
+ /* Get dynamic loading memory sections from base lib */
+ if (DSP_SUCCEEDED(status)) {
+ status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
+ &ulAddr, &ulLen);
+ if (DSP_SUCCEEDED(status)) {
+ pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
+ MEM_PAGED);
+ if (!pszCoffBuf) {
+ GT_0trace(NLDR_debugMask, GT_6CLASS,
+ "NLDR_Create: Memory "
+ "allocation failed\n");
+ status = DSP_EMEMORY;
+ }
+ } else {
+ /* Ok to not have dynamic loading memory */
+ status = DSP_SOK;
+ ulLen = 0;
+ GT_1trace(NLDR_debugMask, GT_6CLASS,
+ "NLDR_Create: DBLL_getSect "
+ "failed (no dynamic loading mem segments): "
+ "0x%lx\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status) && ulLen > 0) {
+ /* Read section containing dynamic load mem segments */
+ status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
+ pszCoffBuf, ulLen);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NLDR_debugMask, GT_6CLASS,
+ "NLDR_Create: DBLL_read Section"
+ "failed: 0x%lx\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status) && ulLen > 0) {
+ /* Parse memory segment data */
+ nSegs = (u16)(*((u32 *)pszCoffBuf));
+ if (nSegs > MAXMEMSEGS) {
+ GT_1trace(NLDR_debugMask, GT_6CLASS,
+ "NLDR_Create: Invalid number of "
+ "dynamic load mem segments: 0x%lx\n", nSegs);
+ status = DSP_ECORRUPTFILE;
+ }
+ }
+ /* Parse dynamic load memory segments */
+ if (DSP_SUCCEEDED(status) && nSegs > 0) {
+ rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
+ MEM_PAGED);
+ pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
+ if (rmmSegs == NULL || pNldr->segTable == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ pNldr->nSegs = nSegs;
+ pMemInfo = (struct MemInfo *)(pszCoffBuf +
+ sizeof(u32));
+ for (i = 0; i < nSegs; i++) {
+ rmmSegs[i].base = (pMemInfo + i)->base;
+ rmmSegs[i].length = (pMemInfo + i)->len;
+ rmmSegs[i].space = 0;
+ pNldr->segTable[i] = (pMemInfo + i)->type;
+#ifdef DEBUG
+ DBG_Trace(DBG_LEVEL7,
+ "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
+ "Length: 0x%x\n", i, rmmSegs[i].base,
+ rmmSegs[i].length);
+#endif
+ }
+ }
+ }
+ /* Create Remote memory manager */
+ if (DSP_SUCCEEDED(status))
+ status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
+
+ if (DSP_SUCCEEDED(status)) {
+ /* set the alloc, free, write functions for loader */
+ pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
+ newAttrs = saveAttrs;
+ newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
+ newAttrs.free = (DBLL_FreeFxn) RemoteFree;
+ newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
+ newAttrs.symHandle = pNldr;
+ newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
+ pNldr->ovlyFxn = pAttrs->pfnOvly;
+ pNldr->writeFxn = pAttrs->pfnWrite;
+ pNldr->dbllAttrs = newAttrs;
+ }
+ if (rmmSegs)
+ MEM_Free(rmmSegs);
+
+ if (pszCoffBuf)
+ MEM_Free(pszCoffBuf);
+
+ /* Get overlay nodes */
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
+ /* lazy check */
+ DBC_Assert(DSP_SUCCEEDED(status));
+ /* First count number of overlay nodes */
+ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
+ (void *) pNldr);
+ /* Now build table of overlay nodes */
+ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
+ /* Allocate table for overlay nodes */
+ pNldr->ovlyTable =
+ MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
+ MEM_PAGED);
+ /* Put overlay nodes in the table */
+ pNldr->nNode = 0;
+ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
+ AddOvlyNode,
+ (void *) pNldr);
+ }
+ }
+ /* Do a fake reload of the base image to get overlay section info */
+ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
+ saveAttrs.write = fakeOvlyWrite;
+ saveAttrs.logWrite = AddOvlyInfo;
+ saveAttrs.logWriteHandle = pNldr;
+ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
+ status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
+ &saveAttrs, &ulEntry);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ *phNldr = (struct NLDR_OBJECT *) pNldr;
+ } else {
+ if (pNldr)
+ NLDR_Delete((struct NLDR_OBJECT *) pNldr);
+
+ *phNldr = NULL;
+ }
+ /* FIXME:Temp. Fix. Must be removed */
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
+ NLDR_SIGNATURE))
+ || (DSP_FAILED(status) && (*phNldr == NULL)));
+ return status;
+}
+
+/*
+ * ======== NLDR_Delete ========
+ */
+void NLDR_Delete(struct NLDR_OBJECT *hNldr)
+{
+ struct OvlySect *pSect;
+ struct OvlySect *pNext;
+ u16 i;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
+ hNldr->dbllFxns.exitFxn();
+ if (hNldr->rmm)
+ RMM_delete(hNldr->rmm);
+
+ if (hNldr->segTable)
+ MEM_Free(hNldr->segTable);
+
+ if (hNldr->hDcdMgr)
+ DCD_DestroyManager(hNldr->hDcdMgr);
+
+ /* Free overlay node information */
+ if (hNldr->ovlyTable) {
+ for (i = 0; i < hNldr->nOvlyNodes; i++) {
+ pSect = hNldr->ovlyTable[i].pCreateSects;
+ while (pSect) {
+ pNext = pSect->pNextSect;
+ MEM_Free(pSect);
+ pSect = pNext;
+ }
+ pSect = hNldr->ovlyTable[i].pDeleteSects;
+ while (pSect) {
+ pNext = pSect->pNextSect;
+ MEM_Free(pSect);
+ pSect = pNext;
+ }
+ pSect = hNldr->ovlyTable[i].pExecuteSects;
+ while (pSect) {
+ pNext = pSect->pNextSect;
+ MEM_Free(pSect);
+ pSect = pNext;
+ }
+ pSect = hNldr->ovlyTable[i].pOtherSects;
+ while (pSect) {
+ pNext = pSect->pNextSect;
+ MEM_Free(pSect);
+ pSect = pNext;
+ }
+ }
+ MEM_Free(hNldr->ovlyTable);
+ }
+ MEM_FreeObject(hNldr);
+ DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+}
+
+/*
+ * ======== NLDR_Exit ========
+ * Discontinue usage of NLDR module.
+ */
+void NLDR_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(NLDR_debugMask, GT_5CLASS,
+ "Entered NLDR_Exit, ref count: 0x%x\n", cRefs);
+
+ if (cRefs == 0) {
+ RMM_exit();
+ NLDR_debugMask.flags = NULL;
+ }
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== NLDR_Free ========
+ */
+void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+
+ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
+
+ MEM_FreeObject(hNldrNode);
+}
+
+/*
+ * ======== NLDR_GetFxnAddr ========
+ */
+DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
+ u32 *pulAddr)
+{
+ struct DBLL_Symbol *pSym;
+ struct NLDR_OBJECT *hNldr;
+ DSP_STATUS status = DSP_SOK;
+ bool status1 = false;
+ s32 i = 0;
+ struct LibNode root = { NULL, 0, NULL };
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+ DBC_Require(pulAddr != NULL);
+ DBC_Require(pstrFxn != NULL);
+ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
+ hNldrNode, pstrFxn, pulAddr);
+
+ hNldr = hNldrNode->pNldr;
+ /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
+ if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
+ switch (hNldrNode->phase) {
+ case NLDR_CREATE:
+ root = hNldrNode->createLib;
+ break;
+ case NLDR_EXECUTE:
+ root = hNldrNode->executeLib;
+ break;
+ case NLDR_DELETE:
+ root = hNldrNode->deleteLib;
+ break;
+ default:
+ DBC_Assert(false);
+ break;
+ }
+ } else {
+ /* for Overlay nodes or non-split Dynamic nodes */
+ root = hNldrNode->root;
+ }
+ status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
+ if (!status1)
+ status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
+
+ /* If symbol not found, check dependent libraries */
+ if (!status1) {
+ for (i = 0; i < root.nDepLibs; i++) {
+ status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
+ lib, pstrFxn, &pSym);
+ if (!status1) {
+ status1 = hNldr->dbllFxns.getCAddrFxn(root.
+ pDepLibs[i].lib, pstrFxn, &pSym);
+ }
+ if (status1) {
+ /* Symbol found */
+ break;
+ }
+ }
+ }
+ /* Check persistent libraries */
+ if (!status1) {
+ for (i = 0; i < hNldrNode->nPersLib; i++) {
+ status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
+ persLib[i].lib, pstrFxn, &pSym);
+ if (!status1) {
+ status1 =
+ hNldr->dbllFxns.getCAddrFxn(hNldrNode->
+ persLib[i].lib, pstrFxn, &pSym);
+ }
+ if (status1) {
+ /* Symbol found */
+ break;
+ }
+ }
+ }
+
+ if (status1) {
+ *pulAddr = pSym->value;
+ } else {
+ GT_1trace(NLDR_debugMask, GT_6CLASS,
+ "NLDR_GetFxnAddr: Symbol not found: "
+ "%s\n", pstrFxn);
+ status = DSP_ESYMBOL;
+ }
+
+ return status;
+}
+
+/*
+ * ======== NLDR_GetRmmManager ========
+ * Given a NLDR object, retrieve RMM Manager Handle
+ */
+DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
+ OUT struct RMM_TargetObj **phRmmMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct NLDR_OBJECT *pNldrObject = hNldrObject;
+ DBC_Require(phRmmMgr != NULL);
+ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
+ hNldrObject, phRmmMgr);
+ if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
+ *phRmmMgr = pNldrObject->rmm;
+ } else {
+ *phRmmMgr = NULL;
+ status = DSP_EHANDLE;
+ GT_0trace(NLDR_debugMask, GT_7CLASS,
+ "NLDR_GetRmmManager:Invalid handle");
+ }
+
+ GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
+ "0x%x\n\tphRmmMgr: 0x%x\n", status, *phRmmMgr);
+
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
+ (*phRmmMgr == NULL)));
+
+ return status;
+}
+
+/*
+ * ======== NLDR_Init ========
+ * Initialize the NLDR module.
+ */
+bool NLDR_Init(void)
+{
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!NLDR_debugMask.flags);
+ GT_create(&NLDR_debugMask, "NL"); /* "NL" for NLdr */
+
+ RMM_init();
+ }
+
+ cRefs++;
+
+ GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure(cRefs > 0);
+ return true;
+}
+
+/*
+ * ======== NLDR_Load ========
+ */
+DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+ struct NLDR_OBJECT *hNldr;
+ struct DSP_UUID libUUID;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+
+ hNldr = hNldrNode->pNldr;
+
+ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
+ hNldrNode, phase);
+
+ if (hNldrNode->fDynamic) {
+ hNldrNode->phase = phase;
+
+ libUUID = hNldrNode->uuid;
+
+ /* At this point, we may not know if node is split into
+ * different libraries. So we'll go ahead and load the
+ * library, and then save the pointer to the appropriate
+ * location after we know. */
+
+ status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
+ hNldrNode->libPath, phase, 0);
+
+ if (DSP_SUCCEEDED(status)) {
+ if (*hNldrNode->pfPhaseSplit) {
+ switch (phase) {
+ case NLDR_CREATE:
+ hNldrNode->createLib = hNldrNode->root;
+ break;
+
+ case NLDR_EXECUTE:
+ hNldrNode->executeLib = hNldrNode->root;
+ break;
+
+ case NLDR_DELETE:
+ hNldrNode->deleteLib = hNldrNode->root;
+ break;
+
+ default:
+ DBC_Assert(false);
+ break;
+ }
+ }
+ }
+ } else {
+ if (hNldrNode->fOverlay)
+ status = LoadOvly(hNldrNode, phase);
+
+ }
+
+ return status;
+}
+
+/*
+ * ======== NLDR_Unload ========
+ */
+DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct LibNode *pRootLib = NULL;
+ s32 i = 0;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
+ hNldrNode, phase);
+ if (hNldrNode != NULL) {
+ if (hNldrNode->fDynamic) {
+ if (*hNldrNode->pfPhaseSplit) {
+ switch (phase) {
+ case NLDR_CREATE:
+ pRootLib = &hNldrNode->createLib;
+ break;
+ case NLDR_EXECUTE:
+ pRootLib = &hNldrNode->executeLib;
+ break;
+ case NLDR_DELETE:
+ pRootLib = &hNldrNode->deleteLib;
+ /* Unload persistent libraries */
+ for (i = 0; i < hNldrNode->nPersLib;
+ i++) {
+ UnloadLib(hNldrNode,
+ &hNldrNode->persLib[i]);
+ }
+ hNldrNode->nPersLib = 0;
+ break;
+ default:
+ DBC_Assert(false);
+ break;
+ }
+ } else {
+ /* Unload main library */
+ pRootLib = &hNldrNode->root;
+ }
+ UnloadLib(hNldrNode, pRootLib);
+ } else {
+ if (hNldrNode->fOverlay)
+ UnloadOvly(hNldrNode, phase);
+
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== AddOvlyInfo ========
+ */
+static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
+ u32 addr, u32 nBytes)
+{
+ char *pNodeName;
+ char *pSectName = (char *)sectInfo->name;
+ bool fExists = false;
+ char seps = ':';
+ char *pch;
+ u16 i;
+ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+ DSP_STATUS status = DSP_SOK;
+
+ /* Is this an overlay section (load address != run address)? */
+ if (sectInfo->loadAddr == sectInfo->runAddr)
+ goto func_end;
+
+ /* Find the node it belongs to */
+ for (i = 0; i < hNldr->nOvlyNodes; i++) {
+ pNodeName = hNldr->ovlyTable[i].pNodeName;
+ DBC_Require(pNodeName);
+ if (strncmp(pNodeName, pSectName + 1,
+ strlen(pNodeName)) == 0) {
+ /* Found the node */
+ break;
+ }
+ }
+ if (!(i < hNldr->nOvlyNodes))
+ goto func_end;
+
+ /* Determine which phase this section belongs to */
+ for (pch = pSectName + 1; *pch && *pch != seps; pch++)
+ ;;
+
+ if (*pch) {
+ pch++; /* Skip over the ':' */
+ if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) {
+ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+ pCreateSects, sectInfo, &fExists, addr, nBytes);
+ if (DSP_SUCCEEDED(status) && !fExists)
+ hNldr->ovlyTable[i].nCreateSects++;
+
+ } else
+ if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) {
+ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+ pDeleteSects, sectInfo, &fExists,
+ addr, nBytes);
+ if (DSP_SUCCEEDED(status) && !fExists)
+ hNldr->ovlyTable[i].nDeleteSects++;
+
+ } else
+ if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) {
+ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+ pExecuteSects, sectInfo, &fExists,
+ addr, nBytes);
+ if (DSP_SUCCEEDED(status) && !fExists)
+ hNldr->ovlyTable[i].nExecuteSects++;
+
+ } else {
+ /* Put in "other" sectins */
+ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+ pOtherSects, sectInfo, &fExists,
+ addr, nBytes);
+ if (DSP_SUCCEEDED(status) && !fExists)
+ hNldr->ovlyTable[i].nOtherSects++;
+
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== AddOvlyNode =========
+ * Callback function passed to DCD_GetObjects.
+ */
+static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
+ enum DSP_DCDOBJTYPE objType,
+ IN void *handle)
+{
+ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+ char *pNodeName = NULL;
+ char *pBuf = NULL;
+ u32 uLen;
+ struct DCD_GENERICOBJ objDef;
+ DSP_STATUS status = DSP_SOK;
+
+ if (objType != DSP_DCDNODETYPE)
+ goto func_end;
+
+ status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* If overlay node, add to the list */
+ if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
+ if (hNldr->ovlyTable == NULL) {
+ hNldr->nOvlyNodes++;
+ } else {
+ /* Add node to table */
+ hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
+ DBC_Require(objDef.objData.nodeObj.ndbProps.acName);
+ uLen = strlen(objDef.objData.nodeObj.ndbProps.acName);
+ pNodeName = objDef.objData.nodeObj.ndbProps.acName;
+ pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
+ if (pBuf == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ strncpy(pBuf, pNodeName, uLen);
+ hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
+ hNldr->nNode++;
+ }
+ }
+ }
+ /* These were allocated in DCD_GetObjectDef */
+ if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
+ MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
+
+ if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
+ MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
+
+ if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
+ MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
+
+ if (objDef.objData.nodeObj.pstrIAlgName)
+ MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
+
+func_end:
+ return status;
+}
+
+/*
+ * ======== AddOvlySect ========
+ */
+static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
+ struct OvlySect **pList,
+ struct DBLL_SectInfo *pSectInfo, bool *pExists,
+ u32 addr, u32 nBytes)
+{
+ struct OvlySect *pNewSect = NULL;
+ struct OvlySect *pLastSect;
+ struct OvlySect *pSect;
+ DSP_STATUS status = DSP_SOK;
+
+ pSect = pLastSect = *pList;
+ *pExists = false;
+ while (pSect) {
+ /*
+ * Make sure section has not already been added. Multiple
+ * 'write' calls may be made to load the section.
+ */
+ if (pSect->loadAddr == addr) {
+ /* Already added */
+ *pExists = true;
+ break;
+ }
+ pLastSect = pSect;
+ pSect = pSect->pNextSect;
+ }
+
+ if (!pSect) {
+ /* New section */
+ pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
+ if (pNewSect == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ pNewSect->loadAddr = addr;
+ pNewSect->runAddr = pSectInfo->runAddr +
+ (addr - pSectInfo->loadAddr);
+ pNewSect->size = nBytes;
+ pNewSect->page = pSectInfo->type;
+ }
+
+ /* Add to the list */
+ if (DSP_SUCCEEDED(status)) {
+ if (*pList == NULL) {
+ /* First in the list */
+ *pList = pNewSect;
+ } else {
+ pLastSect->pNextSect = pNewSect;
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== fakeOvlyWrite ========
+ */
+static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
+ s32 mtype)
+{
+ return (s32)nBytes;
+}
+
+/*
+ * ======== FreeSects ========
+ */
+static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
+ u16 nAlloc)
+{
+ struct OvlySect *pSect = pPhaseSects;
+ u16 i = 0;
+ bool fRet;
+
+ while (pSect && i < nAlloc) {
+ /* 'Deallocate' */
+ /* segid - page not supported yet */
+ /* Reserved memory */
+ fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
+ true);
+ DBC_Assert(fRet);
+ pSect = pSect->pNextSect;
+ i++;
+ }
+}
+
+/*
+ * ======== GetSymbolValue ========
+ * Find symbol in library's base image. If not there, check dependent
+ * libraries.
+ */
+static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
+ char *name, struct DBLL_Symbol **sym)
+{
+ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+ struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
+ struct LibNode *root = (struct LibNode *)pArg;
+ u16 i;
+ bool status = false;
+
+ /* check the base image */
+ status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
+ if (!status)
+ status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
+
+ /*
+ * Check in root lib itself. If the library consists of
+ * multiple object files linked together, some symbols in the
+ * library may need to be resolved.
+ */
+ if (!status) {
+ status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
+ if (!status) {
+ status =
+ hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
+ }
+ }
+
+ /*
+ * Check in root lib's dependent libraries, but not dependent
+ * libraries' dependents.
+ */
+ if (!status) {
+ for (i = 0; i < root->nDepLibs; i++) {
+ status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
+ lib, name, sym);
+ if (!status) {
+ status = hNldr->dbllFxns.getCAddrFxn(root->
+ pDepLibs[i].lib, name, sym);
+ }
+ if (status) {
+ /* Symbol found */
+ break;
+ }
+ }
+ }
+ /*
+ * Check in persistent libraries
+ */
+ if (!status) {
+ for (i = 0; i < hNldrNode->nPersLib; i++) {
+ status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
+ persLib[i].lib, name, sym);
+ if (!status) {
+ status = hNldr->dbllFxns.getCAddrFxn
+ (hNldrNode->persLib[i].lib, name, sym);
+ }
+ if (status) {
+ /* Symbol found */
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== LoadLib ========
+ * Recursively load library and all its dependent libraries. The library
+ * we're loading is specified by a uuid.
+ */
+static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
+ struct LibNode *root, struct DSP_UUID uuid,
+ bool rootPersistent, struct DBLL_LibraryObj **libPath,
+ enum NLDR_PHASE phase, u16 depth)
+{
+ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+ u16 nLibs = 0; /* Number of dependent libraries */
+ u16 nPLibs = 0; /* Number of persistent libraries */
+ u16 nLoaded = 0; /* Number of dep. libraries loaded */
+ u16 i;
+ u32 entry;
+ u32 dwBufSize = NLDR_MAXPATHLENGTH;
+ DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
+ struct DBLL_Attrs newAttrs;
+ char *pszFileName = NULL;
+ struct DSP_UUID *depLibUUIDs = NULL;
+ bool *persistentDepLibs = NULL;
+ DSP_STATUS status = DSP_SOK;
+ bool fStatus = false;
+ struct LibNode *pDepLib;
+
+ if (depth > MAXDEPTH) {
+ /* Error */
+ DBC_Assert(false);
+ }
+ root->lib = NULL;
+ /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
+ pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
+ if (pszFileName == NULL)
+ status = DSP_EMEMORY;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Get the name of the library */
+ if (depth == 0) {
+ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
+ &uuid, pszFileName, &dwBufSize, phase,
+ hNldrNode->pfPhaseSplit);
+ } else {
+ /* Dependent libraries are registered with a phase */
+ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
+ &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
+ NULL);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Open the library, don't load symbols */
+ status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
+ DBLL_NOLOAD, &root->lib);
+ }
+ /* Done with file name */
+ if (pszFileName)
+ MEM_Free(pszFileName);
+
+ /* Check to see if library not already loaded */
+ if (DSP_SUCCEEDED(status) && rootPersistent) {
+ fStatus = findInPersistentLibArray(hNldrNode, root->lib);
+ /* Close library */
+ if (fStatus) {
+ hNldr->dbllFxns.closeFxn(root->lib);
+ return DSP_SALREADYLOADED;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Check for circular dependencies. */
+ for (i = 0; i < depth; i++) {
+ if (root->lib == libPath[i]) {
+ /* This condition could be checked by a
+ * tool at build time. */
+ status = DSP_EDYNLOAD;
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Add library to current path in dependency tree */
+ libPath[depth] = root->lib;
+ depth++;
+ /* Get number of dependent libraries */
+ status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
+ &nLibs, &nPLibs, phase);
+ }
+ DBC_Assert(nLibs >= nPLibs);
+ if (DSP_SUCCEEDED(status)) {
+ if (!(*hNldrNode->pfPhaseSplit))
+ nPLibs = 0;
+
+ /* nLibs = #of dependent libraries */
+ root->nDepLibs = nLibs - nPLibs;
+ if (nLibs > 0) {
+ depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
+ nLibs, MEM_PAGED);
+ persistentDepLibs =
+ MEM_Calloc(sizeof(bool) * nLibs, MEM_PAGED);
+ if (!depLibUUIDs || !persistentDepLibs)
+ status = DSP_EMEMORY;
+
+ if (root->nDepLibs > 0) {
+ /* Allocate arrays for dependent lib UUIDs,
+ * lib nodes */
+ root->pDepLibs = MEM_Calloc
+ (sizeof(struct LibNode) *
+ (root->nDepLibs), MEM_PAGED);
+ if (!(root->pDepLibs))
+ status = DSP_EMEMORY;
+
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Get the dependent library UUIDs */
+ status = DCD_GetDepLibs(hNldrNode->pNldr->
+ hDcdMgr, &uuid, nLibs, depLibUUIDs,
+ persistentDepLibs, phase);
+ }
+ }
+ }
+
+ /*
+ * Recursively load dependent libraries.
+ */
+ if (DSP_SUCCEEDED(status) && persistentDepLibs) {
+ for (i = 0; i < nLibs; i++) {
+ /* If root library is NOT persistent, and dep library
+ * is, then record it. If root library IS persistent,
+ * the deplib is already included */
+ if (!rootPersistent && persistentDepLibs[i] &&
+ *hNldrNode->pfPhaseSplit) {
+ if ((hNldrNode->nPersLib) > MAXLIBS) {
+ status = DSP_EDYNLOAD;
+ break;
+ }
+
+ /* Allocate library outside of phase */
+ pDepLib = &hNldrNode->persLib[hNldrNode->
+ nPersLib];
+ } else {
+ if (rootPersistent)
+ persistentDepLibs[i] = true;
+
+
+ /* Allocate library within phase */
+ pDepLib = &root->pDepLibs[nLoaded];
+ }
+
+ if (depLibUUIDs) {
+ status = LoadLib(hNldrNode, pDepLib,
+ depLibUUIDs[i],
+ persistentDepLibs[i], libPath,
+ phase,
+ depth);
+ } else {
+ status = DSP_EMEMORY;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ if ((status != DSP_SALREADYLOADED) &&
+ !rootPersistent && persistentDepLibs[i] &&
+ *hNldrNode->pfPhaseSplit) {
+ (hNldrNode->nPersLib)++;
+ } else {
+ if (!persistentDepLibs[i] ||
+ !(*hNldrNode->pfPhaseSplit)) {
+ nLoaded++;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ /* Now we can load the root library */
+ if (DSP_SUCCEEDED(status)) {
+ newAttrs = hNldr->dbllAttrs;
+ newAttrs.symArg = root;
+ newAttrs.rmmHandle = hNldrNode;
+ newAttrs.wHandle = hNldrNode->pPrivRef;
+ newAttrs.baseImage = false;
+
+ status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
+ &entry);
+ }
+
+ /*
+ * In case of failure, unload any dependent libraries that
+ * were loaded, and close the root library.
+ * (Persistent libraries are unloaded from the very top)
+ */
+ if (DSP_FAILED(status)) {
+ if (phase != NLDR_EXECUTE) {
+ for (i = 0; i < hNldrNode->nPersLib; i++)
+ UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
+
+ hNldrNode->nPersLib = 0;
+ }
+ for (i = 0; i < nLoaded; i++)
+ UnloadLib(hNldrNode, &root->pDepLibs[i]);
+
+ if (root->lib)
+ hNldr->dbllFxns.closeFxn(root->lib);
+
+ }
+
+ /* Going up one node in the dependency tree */
+ depth--;
+
+ if (depLibUUIDs) {
+ MEM_Free(depLibUUIDs);
+ depLibUUIDs = NULL;
+ }
+
+ if (persistentDepLibs) {
+ MEM_Free(persistentDepLibs);
+ persistentDepLibs = NULL;
+ }
+
+ return status;
+}
+
+/*
+ * ======== LoadOvly ========
+ */
+static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+ enum NLDR_PHASE phase)
+{
+ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+ struct OvlyNode *pONode = NULL;
+ struct OvlySect *pPhaseSects = NULL;
+ struct OvlySect *pOtherSects = NULL;
+ u16 i;
+ u16 nAlloc = 0;
+ u16 nOtherAlloc = 0;
+ u16 *pRefCount = NULL;
+ u16 *pOtherRef = NULL;
+ u32 nBytes;
+ struct OvlySect *pSect;
+ DSP_STATUS status = DSP_SOK;
+
+ /* Find the node in the table */
+ for (i = 0; i < hNldr->nOvlyNodes; i++) {
+ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
+ /* Found it */
+ pONode = &(hNldr->ovlyTable[i]);
+ break;
+ }
+ }
+
+ DBC_Assert(i < hNldr->nOvlyNodes);
+ switch (phase) {
+ case NLDR_CREATE:
+ pRefCount = &(pONode->createRef);
+ pOtherRef = &(pONode->otherRef);
+ pPhaseSects = pONode->pCreateSects;
+ pOtherSects = pONode->pOtherSects;
+ break;
+
+ case NLDR_EXECUTE:
+ pRefCount = &(pONode->executeRef);
+ pPhaseSects = pONode->pExecuteSects;
+ break;
+
+ case NLDR_DELETE:
+ pRefCount = &(pONode->deleteRef);
+ pPhaseSects = pONode->pDeleteSects;
+ break;
+
+ default:
+ DBC_Assert(false);
+ break;
+ }
+
+ DBC_Assert(pRefCount != NULL);
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ if (pRefCount == NULL)
+ goto func_end;
+
+ if (*pRefCount != 0)
+ goto func_end;
+
+ /* 'Allocate' memory for overlay sections of this phase */
+ pSect = pPhaseSects;
+ while (pSect) {
+ /* allocate */ /* page not supported yet */
+ /* reserve */ /* align */
+ status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
+ &(pSect->runAddr), true);
+ if (DSP_SUCCEEDED(status)) {
+ pSect = pSect->pNextSect;
+ nAlloc++;
+ } else {
+ break;
+ }
+ }
+ if (pOtherRef && *pOtherRef == 0) {
+ /* 'Allocate' memory for other overlay sections
+ * (create phase) */
+ if (DSP_SUCCEEDED(status)) {
+ pSect = pOtherSects;
+ while (pSect) {
+ /* page not supported */ /* align */
+ /* reserve */
+ status = RMM_alloc(hNldr->rmm, 0, pSect->size,
+ 0, &(pSect->runAddr), true);
+ if (DSP_SUCCEEDED(status)) {
+ pSect = pSect->pNextSect;
+ nOtherAlloc++;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ if (*pRefCount == 0) {
+ if (DSP_SUCCEEDED(status)) {
+ /* Load sections for this phase */
+ pSect = pPhaseSects;
+ while (pSect && DSP_SUCCEEDED(status)) {
+ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
+ pSect->runAddr, pSect->loadAddr,
+ pSect->size, pSect->page);
+ if (nBytes != pSect->size)
+ status = DSP_EFAIL;
+
+ pSect = pSect->pNextSect;
+ }
+ }
+ }
+ if (pOtherRef && *pOtherRef == 0) {
+ if (DSP_SUCCEEDED(status)) {
+ /* Load other sections (create phase) */
+ pSect = pOtherSects;
+ while (pSect && DSP_SUCCEEDED(status)) {
+ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
+ pSect->runAddr, pSect->loadAddr,
+ pSect->size, pSect->page);
+ if (nBytes != pSect->size)
+ status = DSP_EFAIL;
+
+ pSect = pSect->pNextSect;
+ }
+ }
+ }
+ if (DSP_FAILED(status)) {
+ /* 'Deallocate' memory */
+ FreeSects(hNldr, pPhaseSects, nAlloc);
+ FreeSects(hNldr, pOtherSects, nOtherAlloc);
+ }
+func_end:
+ if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
+ *pRefCount += 1;
+ if (pOtherRef)
+ *pOtherRef += 1;
+
+ }
+
+ return status;
+}
+
+/*
+ * ======== RemoteAlloc ========
+ */
+static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
+ u32 align, u32 *dspAddr,
+ OPTIONAL s32 segmentId, OPTIONAL s32 req,
+ bool reserve)
+{
+ struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
+ struct NLDR_OBJECT *hNldr;
+ struct RMM_TargetObj *rmm;
+ u16 memPhaseBit = MAXFLAGS;
+ u16 segid = 0;
+ u16 i;
+ u16 memType;
+ u32 nWords;
+ struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
+ bool fReq = false;
+ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
+ DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
+ DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
+ space == DBLL_BSS);
+ hNldr = hNode->pNldr;
+ rmm = hNldr->rmm;
+ /* Convert size to DSP words */
+ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
+ /* Modify memory 'align' to account for DSP cache line size */
+ align = findLcm(GEM_CACHE_LINE_SIZE, align);
+ GT_1trace(NLDR_debugMask, GT_7CLASS,
+ "RemoteAlloc: memory align to 0x%x \n", align);
+ if (segmentId != -1) {
+ pRmmAddr->segid = segmentId;
+ segid = segmentId;
+ fReq = req;
+ } else {
+ switch (hNode->phase) {
+ case NLDR_CREATE:
+ memPhaseBit = CREATEDATAFLAGBIT;
+ break;
+ case NLDR_DELETE:
+ memPhaseBit = DELETEDATAFLAGBIT;
+ break;
+ case NLDR_EXECUTE:
+ memPhaseBit = EXECUTEDATAFLAGBIT;
+ break;
+ default:
+ DBC_Assert(false);
+ break;
+ }
+ if (space == DBLL_CODE)
+ memPhaseBit++;
+
+ if (memPhaseBit < MAXFLAGS)
+ segid = hNode->segId[memPhaseBit];
+
+ /* Determine if there is a memory loading requirement */
+ if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
+ fReq = true;
+
+ }
+ memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
+
+ /* Find an appropriate segment based on space */
+ if (segid == NULLID) {
+ /* No memory requirements of preferences */
+ DBC_Assert(!fReq);
+ goto func_cont;
+ }
+ if (segid <= MAXSEGID) {
+ DBC_Assert(segid < hNldr->nSegs);
+ /* Attempt to allocate from segid first. */
+ pRmmAddr->segid = segid;
+ status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NLDR_debugMask, GT_6CLASS,
+ "RemoteAlloc:Unable allocate "
+ "from segment %d.\n", segid);
+ }
+ } else {
+ /* segid > MAXSEGID ==> Internal or external memory */
+ DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
+ /* Check for any internal or external memory segment,
+ * depending on segid.*/
+ memType |= segid == MEMINTERNALID ?
+ DYNM_INTERNAL : DYNM_EXTERNAL;
+ for (i = 0; i < hNldr->nSegs; i++) {
+ if ((hNldr->segTable[i] & memType) != memType)
+ continue;
+
+ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
+ false);
+ if (DSP_SUCCEEDED(status)) {
+ /* Save segid for freeing later */
+ pRmmAddr->segid = i;
+ break;
+ }
+ }
+ }
+func_cont:
+ /* Haven't found memory yet, attempt to find any segment that works */
+ if (status == DSP_EMEMORY && !fReq) {
+ GT_0trace(NLDR_debugMask, GT_6CLASS,
+ "RemoteAlloc: Preferred segment "
+ "unavailable, trying another segment.\n");
+ for (i = 0; i < hNldr->nSegs; i++) {
+ /* All bits of memType must be set */
+ if ((hNldr->segTable[i] & memType) != memType)
+ continue;
+
+ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
+ false);
+ if (DSP_SUCCEEDED(status)) {
+ /* Save segid */
+ pRmmAddr->segid = i;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
+ u32 size, bool reserve)
+{
+ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
+ struct RMM_TargetObj *rmm;
+ u32 nWords;
+ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
+
+ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+
+ rmm = hNldr->rmm;
+
+ /* Convert size to DSP words */
+ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
+
+ if (RMM_free(rmm, space, dspAddr, nWords, reserve))
+ status = DSP_SOK;
+
+ return status;
+}
+
+/*
+ * ======== UnloadLib ========
+ */
+static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
+{
+ struct DBLL_Attrs newAttrs;
+ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+ u16 i;
+
+ DBC_Assert(root != NULL);
+
+ /* Unload dependent libraries */
+ for (i = 0; i < root->nDepLibs; i++)
+ UnloadLib(hNldrNode, &root->pDepLibs[i]);
+
+ root->nDepLibs = 0;
+
+ newAttrs = hNldr->dbllAttrs;
+ newAttrs.rmmHandle = hNldr->rmm;
+ newAttrs.wHandle = hNldrNode->pPrivRef;
+ newAttrs.baseImage = false;
+ newAttrs.symArg = root;
+
+ if (root->lib) {
+ /* Unload the root library */
+ hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
+ hNldr->dbllFxns.closeFxn(root->lib);
+ }
+
+ /* Free dependent library list */
+ if (root->pDepLibs) {
+ MEM_Free(root->pDepLibs);
+ root->pDepLibs = NULL;
+ }
+}
+
+/*
+ * ======== UnloadOvly ========
+ */
+static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+ struct OvlyNode *pONode = NULL;
+ struct OvlySect *pPhaseSects = NULL;
+ struct OvlySect *pOtherSects = NULL;
+ u16 i;
+ u16 nAlloc = 0;
+ u16 nOtherAlloc = 0;
+ u16 *pRefCount = NULL;
+ u16 *pOtherRef = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ /* Find the node in the table */
+ for (i = 0; i < hNldr->nOvlyNodes; i++) {
+ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
+ /* Found it */
+ pONode = &(hNldr->ovlyTable[i]);
+ break;
+ }
+ }
+
+ DBC_Assert(i < hNldr->nOvlyNodes);
+ switch (phase) {
+ case NLDR_CREATE:
+ pRefCount = &(pONode->createRef);
+ pPhaseSects = pONode->pCreateSects;
+ nAlloc = pONode->nCreateSects;
+ break;
+ case NLDR_EXECUTE:
+ pRefCount = &(pONode->executeRef);
+ pPhaseSects = pONode->pExecuteSects;
+ nAlloc = pONode->nExecuteSects;
+ break;
+ case NLDR_DELETE:
+ pRefCount = &(pONode->deleteRef);
+ pOtherRef = &(pONode->otherRef);
+ pPhaseSects = pONode->pDeleteSects;
+ /* 'Other' overlay sections are unloaded in the delete phase */
+ pOtherSects = pONode->pOtherSects;
+ nAlloc = pONode->nDeleteSects;
+ nOtherAlloc = pONode->nOtherSects;
+ break;
+ default:
+ DBC_Assert(false);
+ break;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(pRefCount && (*pRefCount > 0));
+ if (pRefCount && (*pRefCount > 0)) {
+ *pRefCount -= 1;
+ if (pOtherRef) {
+ DBC_Assert(*pOtherRef > 0);
+ *pOtherRef -= 1;
+ }
+ }
+ }
+ if (pRefCount && (*pRefCount == 0)) {
+ /* 'Deallocate' memory */
+ FreeSects(hNldr, pPhaseSects, nAlloc);
+ }
+ if (pOtherRef && *pOtherRef == 0)
+ FreeSects(hNldr, pOtherSects, nOtherAlloc);
+
+}
+
+/*
+ * ======== findInPersistentLibArray ========
+ */
+static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
+ struct DBLL_LibraryObj *lib)
+{
+ s32 i = 0;
+
+ for (i = 0; i < hNldrNode->nPersLib; i++) {
+ if (lib == hNldrNode->persLib[i].lib)
+ return true;
+
+ }
+
+ return false;
+}
+
+/*
+ * ================ Find LCM (Least Common Multiplier ===
+ */
+static u32 findLcm(u32 a, u32 b)
+{
+ u32 retVal;
+
+ retVal = a * b / findGcf(a, b);
+
+ return retVal;
+}
+
+/*
+ * ================ Find GCF (Greatest Common Factor ) ===
+ */
+static u32 findGcf(u32 a, u32 b)
+{
+ u32 c;
+
+ /* Get the GCF (Greatest common factor between the numbers,
+ * using Euclidian Algo */
+ while ((c = (a % b))) {
+ a = b;
+ b = c;
+ }
+ return b;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
new file mode 100644
index 000000000000..53a42bf3ca41
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/node.c
@@ -0,0 +1,3550 @@
+/*
+ * node.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== node.c ========
+ *
+ * Description:
+ * DSP/BIOS Bridge Node Manager.
+ *
+ * Public Functions:
+ * NODE_Allocate
+ * NODE_AllocMsgBuf
+ * NODE_ChangePriority
+ * NODE_Connect
+ * NODE_Create
+ * NODE_CreateMgr
+ * NODE_Delete
+ * NODE_DeleteMgr
+ * NODE_EnumNodes
+ * NODE_Exit
+ * NODE_FreeMsgBuf
+ * NODE_GetAttr
+ * NODE_GetChannelId
+ * NODE_GetMessage
+ * NODE_GetStrmMgr
+ * NODE_Init
+ * NODE_OnExit
+ * NODE_Pause
+ * NODE_PutMessage
+ * NODE_RegisterNotify
+ * NODE_Run
+ * NODE_Terminate
+ *
+ *! Revision History:
+ *! =================
+ *! 12-Apr-2004 hp Compile IVA only for 24xx
+ *! 09-Feb-2004 vp Updated to support IVA.
+ *! 07-Apr-2003 map Eliminated references to old DLDR
+ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in Node_Delete
+ *! function.
+ *! 18-Feb-2003 vp Code review updates.
+ *! 06-Feb-2003 kc Fixed FreeStream to release streams correctly.
+ *! 23-Jan-2003 map Removed call to DISP_DoCinit within Write()
+ *! 03-Jan-2003 map Only unload code after phase has executed if
+ *! overlay or split dynload phases
+ *! 18-Oct-2002 vp Ported to Linux platform.
+ *! 06-Nov-2002 map Fixed NODE_Run on NODE_PAUSED bug
+ *! 12-Oct-2002 map Fixed DeleteNode bug in NODE_Create
+ *! 11-Sep-2002 rr DeleteNode frees the memory for strmConnect and dcd obj
+ *! 29-Aug-2002 map Modified Ovly and Write to use ARM-side copy
+ *! 22-May-2002 sg Changed use of cbData for PWR calls.
+ *! 17-May-2002 jeh Removed LoadLoaderFxns(). Get address of RMS_cinit()
+ *! function. Call DISP_DoCinit() from Write(), if .cinit.
+ *! 13-May-2002 sg Added timeout to wake/sleep calls.
+ *! 02-May-2002 sg Added wake/sleep of DSP to support "nap" mode.
+ *! 18-Apr-2002 jeh Use dynamic loader if compile flag is set.
+ *! 13-Feb-2002 jeh Get uSysStackSize from DSP_NDBPROPS.
+ *! 07-Jan-2002 ag STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
+ *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
+ *! 12-Dec-2001 ag Check for valid stream mode in NODE_Connect().
+ *! 04-Dec-2001 jeh Check for node sufficiently connected in NODE_Create().
+ *! 15-Nov-2001 jeh Removed DBC_Require(pNode->hXlator != NULL) from
+ *! NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
+ *! 11-Sep-2001 ag Zero-copy messaging support.
+ *! 28-Aug-2001 jeh Overlay/dynamic loader infrastructure added. Removed
+ *! NODE_GetDispatcher, excess node states.
+ *! 07-Aug-2001 jeh Removed critical section for dispatcher.
+ *! 26-Jul-2001 jeh Get ZL dll name through CFG.
+ *! 05-Jun-2001 jeh Assume DSP_STRMATTRS.uBufsize in GPP bytes.
+ *! 11-May-2001 jeh Some code review cleanup.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 15-Dec-2000 sg Convert IALG_Fxn address from byte addr to word addr.
+ *! 04-Dec-2000 jeh Call MSG Get and Put functions.
+ *! 04-Dec-2000 ag Added SM support for node messaging.
+ *! 10-Nov-2000 rr: NODE_MIN/MAX Priority is defined in dspdefs.h.
+ *! 27-Oct-2000 jeh Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
+ *! 11-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
+ *! NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
+ *! 19-Jun-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/proc.h>
+#include <dspbridge/strm.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/ntfy.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/cmm.h>
+#include <dspbridge/cod.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/msg.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/dbdcd.h>
+#include <dspbridge/disp.h>
+#include <dspbridge/rms_sh.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmd.h>
+#include <dspbridge/wmdioctl.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/gb.h>
+#ifdef DEBUG
+#include <dspbridge/uuidutil.h>
+#include <dspbridge/dbg.h>
+#endif
+
+/* ----------------------------------- This */
+#include <dspbridge/nodepriv.h>
+#include <dspbridge/node.h>
+
+/* Static/Dynamic Loader includes */
+#include <dspbridge/dbll.h>
+#include <dspbridge/nldr.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/drv.h>
+#include <dspbridge/drvdefs.h>
+#include <dspbridge/dbreg.h>
+#include <dspbridge/resourcecleanup.h>
+#endif
+
+
+#define NODE_SIGNATURE 0x45444f4e /* "EDON" */
+#define NODEMGR_SIGNATURE 0x52474d4e /* "RGMN" */
+
+#define HOSTPREFIX "/host"
+#define PIPEPREFIX "/dbpipe"
+
+#define MaxInputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
+#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
+
+#define NODE_GetPriority(h) ((h)->nPriority)
+#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
+#define NODE_SetState(hNode, state) ((hNode)->nState = state)
+
+#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
+#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
+
+#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
+#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
+
+#define MAXDEVNAMELEN 32 /* DSP_NDBPROPS.acName size */
+#define CREATEPHASE 1
+#define EXECUTEPHASE 2
+#define DELETEPHASE 3
+
+/* Define default STRM parameters */
+/*
+ * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
+ * or make defaults configurable.
+ */
+#define DEFAULTBUFSIZE 32
+#define DEFAULTNBUFS 2
+#define DEFAULTSEGID 0
+#define DEFAULTALIGNMENT 0
+#define DEFAULTTIMEOUT 10000
+
+#define RMSQUERYSERVER 0
+#define RMSCONFIGURESERVER 1
+#define RMSCREATENODE 2
+#define RMSEXECUTENODE 3
+#define RMSDELETENODE 4
+#define RMSCHANGENODEPRIORITY 5
+#define RMSREADMEMORY 6
+#define RMSWRITEMEMORY 7
+#define RMSCOPY 8
+#define MAXTIMEOUT 2000
+
+#define NUMRMSFXNS 9
+
+#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
+
+#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Address */
+
+/*
+ * ======== NODE_MGR ========
+ */
+struct NODE_MGR {
+ u32 dwSignature; /* For object validation */
+ struct DEV_OBJECT *hDevObject; /* Device object */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
+ struct DISP_OBJECT *hDisp; /* Node dispatcher */
+ struct LST_LIST *nodeList; /* List of all allocated nodes */
+ u32 uNumNodes; /* Number of nodes in nodeList */
+ u32 uNumCreated; /* Number of nodes *created* on DSP */
+ struct GB_TMap *pipeMap; /* Pipe connection bit map */
+ struct GB_TMap *pipeDoneMap; /* Pipes that are half free */
+ struct GB_TMap *chnlMap; /* Channel allocation bit map */
+ struct GB_TMap *dmaChnlMap; /* DMA Channel allocation bit map */
+ struct GB_TMap *zChnlMap; /* Zero-Copy Channel alloc bit map */
+ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
+ struct SYNC_CSOBJECT *hSync; /* For critical sections */
+ u32 ulFxnAddrs[NUMRMSFXNS]; /* RMS function addresses */
+ struct MSG_MGR *hMsg;
+
+ /* Processor properties needed by Node Dispatcher */
+ u32 ulNumChnls; /* Total number of channels */
+ u32 ulChnlOffset; /* Offset of chnl ids rsvd for RMS */
+ u32 ulChnlBufSize; /* Buffer size for data to RMS */
+ DSP_PROCFAMILY procFamily; /* eg, 5000 */
+ DSP_PROCTYPE procType; /* eg, 5510 */
+ u32 uDSPWordSize; /* Size of DSP word on host bytes */
+ u32 uDSPDataMauSize; /* Size of DSP data MAU */
+ u32 uDSPMauSize; /* Size of MAU */
+ s32 nMinPri; /* Minimum runtime priority for node */
+ s32 nMaxPri; /* Maximum runtime priority for node */
+
+ struct STRM_MGR *hStrmMgr; /* STRM manager */
+
+ /* Loader properties */
+ struct NLDR_OBJECT *hNldr; /* Handle to loader */
+ struct NLDR_FXNS nldrFxns; /* Handle to loader functions */
+ bool fLoaderInit; /* Loader Init function succeeded? */
+};
+
+/*
+ * ======== CONNECTTYPE ========
+ */
+enum CONNECTTYPE {
+ NOTCONNECTED = 0,
+ NODECONNECT,
+ HOSTCONNECT,
+ DEVICECONNECT,
+} ;
+
+/*
+ * ======== STREAM ========
+ */
+struct STREAM {
+ enum CONNECTTYPE type; /* Type of stream connection */
+ u32 devId; /* pipe or channel id */
+};
+
+/*
+ * ======== NODE_OBJECT ========
+ */
+struct NODE_OBJECT {
+ struct LST_ELEM listElem;
+ u32 dwSignature; /* For object validation */
+ struct NODE_MGR *hNodeMgr; /* The manager of this node */
+ struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
+ struct DSP_UUID nodeId; /* Node's ID */
+ s32 nPriority; /* Node's current priority */
+ u32 uTimeout; /* Timeout for blocking NODE calls */
+ u32 uHeapSize; /* Heap Size */
+ u32 uDSPHeapVirtAddr; /* Heap Size */
+ u32 uGPPHeapVirtAddr; /* Heap Size */
+ enum NODE_TYPE nType; /* Type of node: message, task, etc */
+ enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
+ u32 uNumInputs; /* Current number of inputs */
+ u32 uNumOutputs; /* Current number of outputs */
+ u32 uMaxInputIndex; /* Current max input stream index */
+ u32 uMaxOutputIndex; /* Current max output stream index */
+ struct STREAM *inputs; /* Node's input streams */
+ struct STREAM *outputs; /* Node's output streams */
+ struct NODE_CREATEARGS createArgs; /* Args for node create function */
+ NODE_ENV nodeEnv; /* Environment returned by RMS */
+ struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
+ struct DSP_CBDATA *pArgs; /* Optional args to pass to node */
+ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
+ char *pstrDevName; /* device name, if device node */
+ struct SYNC_OBJECT *hSyncDone; /* Synchronize NODE_Terminate */
+ s32 nExitStatus; /* execute function return status */
+
+ /* Information needed for NODE_GetAttr() */
+ DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
+ u32 uNumGPPInputs; /* Current # of from GPP streams */
+ u32 uNumGPPOutputs; /* Current # of to GPP streams */
+ /* Current stream connections */
+ struct DSP_STREAMCONNECT *streamConnect;
+
+ /* Message queue */
+ struct MSG_QUEUE *hMsgQueue;
+
+ /* These fields used for SM messaging */
+ struct CMM_XLATOROBJECT *hXlator; /* Node's SM address translator */
+
+ /* Handle to pass to dynamic loader */
+ struct NLDR_NODEOBJECT *hNldrNode;
+ bool fLoaded; /* Code is (dynamically) loaded */
+ bool fPhaseSplit; /* Phases split in many libs or ovly */
+
+} ;
+
+/* Default buffer attributes */
+static struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
+ 0, /* cbStruct */
+ 1, /* uSegment */
+ 0, /* uAlignment */
+};
+
+static void DeleteNode(struct NODE_OBJECT *hNode);
+static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
+static void FillStreamConnect(struct NODE_OBJECT *hNode1,
+ struct NODE_OBJECT *hNode2, u32 uStream1,
+ u32 uStream2);
+static void FillStreamDef(struct NODE_OBJECT *hNode,
+ struct NODE_STRMDEF *pstrmDef,
+ struct DSP_STRMATTR *pAttrs);
+static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
+static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
+ u32 uPhase);
+static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
+ struct NODE_OBJECT *hNode,
+ CONST struct DSP_UUID *pNodeId,
+ struct DCD_GENERICOBJ *pdcdProps);
+static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
+ struct DEV_OBJECT *hDevObject);
+static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
+static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
+ u32 ulNumBytes, u32 nMemSpace);
+static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
+ u32 ulNumBytes, u32 nMemSpace);
+
+#if GT_TRACE
+static struct GT_Mask NODE_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+#ifdef DSP_DMM_DEBUG
+extern u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
+#endif
+
+static u32 cRefs; /* module reference count */
+
+/* Dynamic loader functions. */
+static struct NLDR_FXNS nldrFxns = {
+ NLDR_Allocate,
+ NLDR_Create,
+ NLDR_Delete,
+ NLDR_Exit,
+ NLDR_Free,
+ NLDR_GetFxnAddr,
+ NLDR_Init,
+ NLDR_Load,
+ NLDR_Unload,
+};
+
+enum NODE_STATE NODE_GetState(HANDLE hNode)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_GetState:hNode 0x%x\n", pNode);
+ return -1;
+ } else
+ return pNode->nState;
+
+}
+
+/*
+ * ======== NODE_Allocate ========
+ * Purpose:
+ * Allocate GPP resources to manage a node on the DSP.
+ */
+DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
+ IN CONST struct DSP_UUID *pNodeId,
+ OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
+ OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
+ OUT struct NODE_OBJECT **phNode)
+{
+ struct NODE_MGR *hNodeMgr;
+ struct DEV_OBJECT *hDevObject;
+ struct NODE_OBJECT *pNode = NULL;
+ enum NODE_TYPE nodeType = NODE_TASK;
+ struct NODE_MSGARGS *pmsgArgs;
+ struct NODE_TASKARGS *ptaskArgs;
+ u32 uNumStreams;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
+ u32 procId;
+ char *label;
+ u32 pulValue;
+ u32 dynextBase;
+ u32 offSet = 0;
+ u32 ulStackSegAddr, ulStackSegVal;
+ u32 ulGppMemBase;
+ struct CFG_HOSTRES hostRes;
+ u32 pMappedAddr = 0;
+ u32 mapAttrs = 0x0;
+ struct DSP_PROCESSORSTATE procStatus;
+#ifdef DSP_DMM_DEBUG
+ struct DMM_OBJECT *hDmmMgr;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+#endif
+
+#ifndef RES_CLEANUP_DISABLE
+ HANDLE hDrvObject;
+ HANDLE nodeRes;
+ u32 hProcess;
+ struct PROCESS_CONTEXT *pPctxt = NULL;
+ DSP_STATUS res_status = DSP_SOK;
+#endif
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hProcessor != NULL);
+ DBC_Require(phNode != NULL);
+ DBC_Require(pNodeId != NULL);
+
+ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
+ "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
+ "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
+ phNode);
+
+ *phNode = NULL;
+
+ status = PROC_GetProcessorId(hProcessor, &procId);
+
+ status = PROC_GetDevObject(hProcessor, &hDevObject);
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
+ if (hNodeMgr == NULL)
+ status = DSP_EFAIL;
+
+ }
+ if (procId != DSP_UNIT)
+ goto func_cont;
+
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt
+ to send the message */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: proc Status 0x%x\n",
+ procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+
+ /* Assuming that 0 is not a valid function address */
+ if (hNodeMgr->ulFxnAddrs[0] == 0) {
+ /* No RMS on target - we currently can't handle this */
+ GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
+ "image. Node allocation fails.\n");
+ status = DSP_EFAIL;
+ } else {
+ /* Validate pAttrIn fields, if non-NULL */
+ if (pAttrIn) {
+ /* Check if pAttrIn->iPriority is within range */
+ if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
+ pAttrIn->iPriority > hNodeMgr->nMaxPri)
+ status = DSP_ERANGE;
+ }
+ }
+func_cont:
+ /* Allocate node object and fill in */
+ if (DSP_FAILED(status))
+ goto func_cont2;
+
+ MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
+ if (pNode == NULL) {
+ status = DSP_EMEMORY;
+ goto func_cont1;
+ }
+ pNode->hNodeMgr = hNodeMgr;
+ /* This critical section protects GetNodeProps */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (procId != DSP_UNIT)
+ goto func_cont3;
+
+ /* Get DSP_NDBPROPS from node database */
+ status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
+ &(pNode->dcdProps));
+ if (DSP_FAILED(status))
+ goto func_cont3;
+
+ pNode->nodeId = *pNodeId;
+ pNode->hProcessor = hProcessor;
+ pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
+ pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
+ pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
+
+ /* Currently only C64 DSP builds support Node Dynamic * heaps */
+ /* Allocate memory for node heap */
+ pNode->createArgs.asa.taskArgs.uHeapSize = 0;
+ pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
+ pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
+ pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
+ if (!pAttrIn)
+ goto func_cont3;
+
+ /* Check if we have a user allocated node heap */
+ if (!(pAttrIn->pGPPVirtAddr))
+ goto func_cont3;
+
+ /* check for page aligned Heap size */
+ if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
+ GT_1trace(NODE_debugMask, GT_7CLASS,
+ "NODE_Allocate: node heap page size"
+ " not aligned to 4K page, size=0x%x \n",
+ pAttrIn->uHeapSize);
+ status = DSP_EINVALIDARG;
+ } else {
+ pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
+ pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
+ (u32)pAttrIn->pGPPVirtAddr;
+ }
+ if (DSP_FAILED(status))
+ goto func_cont3;
+
+ status = PROC_ReserveMemory(hProcessor,
+ pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
+ (void **)&(pNode->createArgs.asa.taskArgs.
+ uDSPHeapResAddr));
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate:Failed to reserve "
+ "memory for Heap: 0x%x\n", status);
+ } else {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: DSPProcessor_Reserve"
+ " Memory successful: 0x%x\n", status);
+ }
+#ifdef DSP_DMM_DEBUG
+ status = DMM_GetHandle(pProcObject, &hDmmMgr);
+ if (DSP_SUCCEEDED(status))
+ DMM_MemMapDump(hDmmMgr);
+#endif
+ if (DSP_FAILED(status))
+ goto func_cont3;
+
+ mapAttrs |= DSP_MAPLITTLEENDIAN;
+ mapAttrs |= DSP_MAPELEMSIZE32;
+ mapAttrs |= DSP_MAPVIRTUALADDR;
+ status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
+ pNode->createArgs.asa.taskArgs.uHeapSize,
+ (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
+ (void **)&pMappedAddr, mapAttrs);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to map memory"
+ " for Heap: 0x%x\n", status);
+ } else {
+ pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
+ (u32) pMappedAddr;
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate:DSPProcessor_Map"
+ " successful: 0x%x\n", status);
+ }
+
+func_cont3:
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_cont1:
+ if (pAttrIn != NULL) {
+ /* Overrides of NBD properties */
+ pNode->uTimeout = pAttrIn->uTimeout;
+ pNode->nPriority = pAttrIn->iPriority;
+ }
+func_cont2:
+ /* Create object to manage notifications */
+ if (DSP_SUCCEEDED(status))
+ status = NTFY_Create(&pNode->hNtfy);
+
+ if (DSP_SUCCEEDED(status)) {
+ nodeType = NODE_GetType(pNode);
+ /* Allocate DSP_STREAMCONNECT array for device, task, and
+ * dais socket nodes. */
+ if (nodeType != NODE_MESSAGE) {
+ uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
+ pNode->streamConnect = MEM_Calloc(uNumStreams *
+ sizeof(struct DSP_STREAMCONNECT),
+ MEM_PAGED);
+ if (uNumStreams > 0 && pNode->streamConnect == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
+ nodeType == NODE_DAISSOCKET)) {
+ /* Allocate arrays for maintainig stream connections */
+ pNode->inputs =
+ MEM_Calloc(MaxInputs(pNode) *
+ sizeof(struct STREAM), MEM_PAGED);
+ pNode->outputs =
+ MEM_Calloc(MaxOutputs(pNode) *
+ sizeof(struct STREAM), MEM_PAGED);
+ ptaskArgs = &(pNode->createArgs.asa.taskArgs);
+ ptaskArgs->strmInDef =
+ MEM_Calloc(MaxInputs(pNode) *
+ sizeof(struct NODE_STRMDEF),
+ MEM_PAGED);
+ ptaskArgs->strmOutDef =
+ MEM_Calloc(MaxOutputs(pNode) *
+ sizeof(struct NODE_STRMDEF),
+ MEM_PAGED);
+ if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
+ ptaskArgs->strmInDef == NULL)) ||
+ (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
+ ptaskArgs->strmOutDef == NULL)))
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
+ /* Create an event that will be posted when RMS_EXIT is
+ * received. */
+ status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
+ if (DSP_SUCCEEDED(status)) {
+ /*Get the shared mem mgr for this nodes dev object */
+ status = CMM_GetHandle(hProcessor, &hCmmMgr);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to"
+ " get CMM Mgr handle: 0x%x\n", status);
+ } else {
+ /* Allocate a SM addr translator for this node
+ * w/ deflt attr */
+ status = CMM_XlatorCreate(&pNode->hXlator,
+ hCmmMgr, NULL);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed"
+ " to create SM translator: 0x%x\n",
+ status);
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in message args */
+ if ((pArgs != NULL) && (pArgs->cbData > 0)) {
+ pmsgArgs = &(pNode->createArgs.asa.msgArgs);
+ pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
+ MEM_PAGED);
+ if (pmsgArgs->pData == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ pmsgArgs->uArgLength = pArgs->cbData;
+ memcpy(pmsgArgs->pData, pArgs->cData,
+ pArgs->cbData);
+ }
+ }
+ }
+ }
+
+ if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
+ /* Create a message queue for this node */
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
+ &pNode->hMsgQueue, 0,
+ pNode->createArgs.asa.msgArgs.uMaxMessages,
+ pNode);
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Create object for dynamic loading */
+
+ status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
+ (void *) pNode,
+ &pNode->dcdProps.objData.nodeObj,
+ &pNode->hNldrNode,
+ &pNode->fPhaseSplit);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to "
+ "allocate NLDR node: 0x%x\n", status);
+ }
+ }
+
+ /* Comapare value read from Node Properties and check if it is same as
+ * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
+ * GPP Address, Read the value in that address and override the
+ * uStackSeg value in task args */
+ if (DSP_SUCCEEDED(status) &&
+ (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
+ NULL) {
+ label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
+ strncpy(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
+
+ if (strcmp((char *)pNode->dcdProps.objData.nodeObj.
+ ndbProps.uStackSegName, label) == 0) {
+ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
+ hNldrNode, "DYNEXT_BEG", &dynextBase);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to get Address for "
+ "DYNEXT_BEG: 0x%x\n", status);
+ }
+
+ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
+ hNldrNode, "L1DSRAM_HEAP", &pulValue);
+
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to get Address for "
+ "L1DSRAM_HEAP: 0x%x\n", status);
+ }
+
+ status = CFG_GetHostResources((struct CFG_DEVNODE *)
+ DRV_GetFirstDevExtension(), &hostRes);
+
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Allocate: Failed to get host resource "
+ "0x%x\n", status);
+ }
+
+ ulGppMemBase = (u32)hostRes.dwMemBase[1];
+ offSet = pulValue - dynextBase;
+ ulStackSegAddr = ulGppMemBase + offSet;
+ ulStackSegVal = (u32)*((REG_UWORD32 *)
+ ((u32)(ulStackSegAddr)));
+
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "StackSegVal =0x%x\n", ulStackSegVal);
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
+
+ pNode->createArgs.asa.taskArgs.uStackSeg =
+ ulStackSegVal;
+
+ }
+
+ if (label)
+ MEM_Free(label);
+
+ }
+
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Add the node to the node manager's list of allocated
+ * nodes. */
+ LST_InitElem((struct LST_ELEM *)pNode);
+ NODE_SetState(pNode, NODE_ALLOCATED);
+
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+
+ if (DSP_SUCCEEDED(status)) {
+ LST_PutTail(hNodeMgr->nodeList,
+ (struct LST_ELEM *) pNode);
+ ++(hNodeMgr->uNumNodes);
+ }
+
+ /* Exit critical section */
+ (void) SYNC_LeaveCS(hNodeMgr->hSync);
+
+ /* Preset this to assume phases are split
+ * (for overlay and dll) */
+ pNode->fPhaseSplit = true;
+
+ if (DSP_SUCCEEDED(status))
+ *phNode = pNode;
+
+
+ /* Notify all clients registered for DSP_NODESTATECHANGE. */
+ PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
+ } else {
+ /* Cleanup */
+ if (pNode)
+ DeleteNode(pNode);
+
+ }
+
+#ifndef RES_CLEANUP_DISABLE
+ if (DSP_SUCCEEDED(status)) {
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject,
+ REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDrvObject,
+ &pPctxt, *phNode, 0);
+ if (pPctxt == NULL) {
+ DRV_InsertProcContext(
+ (struct DRV_OBJECT *)hDrvObject,
+ &pPctxt);
+ if (pPctxt != NULL) {
+ DRV_ProcUpdatestate(pPctxt,
+ PROC_RES_ALLOCATED);
+ DRV_ProcSetPID(pPctxt, hProcess);
+ pPctxt->hProcessor =
+ (DSP_HPROCESSOR)hProcessor;
+ }
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+ res_status = CFG_GetObject((u32 *)&hDrvObject,
+ REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDrvObject,
+ &pPctxt, *phNode, 0);
+ if (pPctxt != NULL) {
+ DRV_InsertNodeResElement(*phNode, &nodeRes,
+ pPctxt);
+ DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
+ DRV_ProcNodeUpdateStatus(nodeRes, true);
+ }
+ }
+ }
+#endif
+ DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
+ (DSP_SUCCEEDED(status)
+ && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_AllocMsgBuf ========
+ * Purpose:
+ * Allocates buffer for zero copy messaging.
+ */
+DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
+ OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
+ OUT u8 **pBuffer)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ DSP_STATUS status = DSP_SOK;
+ bool bVirtAddr = false;
+ bool bSetInfo;
+ u32 procId;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBuffer != NULL);
+
+ DBC_Require(uSize > 0);
+
+ GT_4trace(NODE_debugMask, GT_ENTER,
+ "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
+ " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
+ pBuffer);
+
+ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
+ status = DSP_EHANDLE;
+ else if (NODE_GetType(pNode) == NODE_DEVICE)
+ status = DSP_ENODETYPE;
+
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ if (pAttr == NULL)
+ pAttr = &NODE_DFLTBUFATTRS; /* set defaults */
+
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+ if (procId != DSP_UNIT) {
+ DBC_Assert(NULL);
+ goto func_end;
+ }
+ /* If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
+ * virt address, so set this info in this node's translator
+ * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
+ * virtual address from node's translator. */
+ if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
+ (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
+ bVirtAddr = true;
+ bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
+ true : false;
+ pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
+ /* Set/get this node's translators virtual address base/size */
+ status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
+ pAttr->uSegment, bSetInfo);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_7CLASS,
+ "NODE_AllocMsgBuf "
+ "failed: 0x%lx\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
+ if (pAttr->uSegment != 1) {
+ /* Node supports single SM segment only. */
+ status = DSP_EBADSEGID;
+ }
+ /* Arbitrary SM buffer alignment not supported for host side
+ * allocs, but guaranteed for the following alignment
+ * values. */
+ switch (pAttr->uAlignment) {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ /* alignment value not suportted */
+ status = DSP_EALIGNMENT;
+ break;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* allocate physical buffer from segId in node's
+ * translator */
+ (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
+ uSize);
+ if (*pBuffer == NULL) {
+ GT_0trace(NODE_debugMask, GT_7CLASS,
+ "NODE_AllocMsgBuf: "
+ "ERROR: Out of shared memory.\n");
+ status = DSP_EMEMORY;
+ }
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_ChangePriority ========
+ * Purpose:
+ * Change the priority of a node in the allocated state, or that is
+ * currently running or paused on the target.
+ */
+DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ struct NODE_MGR *hNodeMgr = NULL;
+ enum NODE_TYPE nodeType;
+ enum NODE_STATE state;
+ DSP_STATUS status = DSP_SOK;
+ u32 procId;
+
+ DBC_Require(cRefs > 0);
+
+ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
+ "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
+
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ GT_1trace(NODE_debugMask, GT_7CLASS,
+ "Invalid NODE Handle: 0x%x\n", hNode);
+ status = DSP_EHANDLE;
+ } else {
+ hNodeMgr = hNode->hNodeMgr;
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
+ status = DSP_ENODETYPE;
+ else if (nPriority < hNodeMgr->nMinPri ||
+ nPriority > hNodeMgr->nMaxPri)
+ status = DSP_ERANGE;
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ state = NODE_GetState(hNode);
+ if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
+ NODE_SetPriority(hNode, nPriority);
+ } else {
+ if (state != NODE_RUNNING) {
+ status = DSP_EWRONGSTATE;
+ goto func_cont;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_GetProcessorId(pNode->hProcessor,
+ &procId);
+ if (procId == DSP_UNIT) {
+ status = DISP_NodeChangePriority(hNodeMgr->
+ hDisp, hNode,
+ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
+ hNode->nodeEnv, nPriority);
+ }
+ if (DSP_SUCCEEDED(status))
+ NODE_SetPriority(hNode, nPriority);
+
+ }
+ }
+func_cont:
+ /* Leave critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_Connect ========
+ * Purpose:
+ * Connect two nodes on the DSP, or a node on the DSP to the GPP.
+ */
+DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
+ struct NODE_OBJECT *hNode2,
+ u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
+ OPTIONAL IN struct DSP_CBDATA *pConnParam)
+{
+ struct NODE_MGR *hNodeMgr;
+ char *pstrDevName = NULL;
+ enum NODE_TYPE node1Type = NODE_TASK;
+ enum NODE_TYPE node2Type = NODE_TASK;
+ struct NODE_STRMDEF *pstrmDef;
+ struct NODE_STRMDEF *pInput = NULL;
+ struct NODE_STRMDEF *pOutput = NULL;
+ struct NODE_OBJECT *hDevNode;
+ struct NODE_OBJECT *hNode;
+ struct STREAM *pStream;
+ GB_BitNum pipeId = GB_NOBITS;
+ GB_BitNum chnlId = GB_NOBITS;
+ CHNL_MODE uMode;
+ u32 dwLength;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ GT_5trace(NODE_debugMask, GT_ENTER,
+ "NODE_Connect: hNode1: 0x%x\tuStream1:"
+ " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
+ uStream1, hNode2, uStream2, pAttrs);
+ if (DSP_SUCCEEDED(status)) {
+ if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
+ !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
+ (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
+ !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
+ status = DSP_EHANDLE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* The two nodes must be on the same processor */
+ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
+ hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
+ hNode1->hNodeMgr != hNode2->hNodeMgr)
+ status = DSP_EFAIL;
+ /* Cannot connect a node to itself */
+ if (hNode1 == hNode2)
+ status = DSP_EFAIL;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* NODE_GetType() will return NODE_GPP if hNode =
+ * DSP_HGPPNODE. */
+ node1Type = NODE_GetType(hNode1);
+ node2Type = NODE_GetType(hNode2);
+ /* Check stream indices ranges */
+ if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
+ uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
+ node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
+ status = DSP_EVALUE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /*
+ * Only the following types of connections are allowed:
+ * task/dais socket < == > task/dais socket
+ * task/dais socket < == > device
+ * task/dais socket < == > GPP
+ *
+ * ie, no message nodes, and at least one task or dais
+ * socket node.
+ */
+ if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
+ (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
+ node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
+ status = DSP_EFAIL;
+ }
+ /*
+ * Check stream mode. Default is STRMMODE_PROCCOPY.
+ */
+ if (DSP_SUCCEEDED(status) && pAttrs) {
+ if (pAttrs->lMode != STRMMODE_PROCCOPY)
+ status = DSP_ESTRMMODE; /* illegal stream mode */
+
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ if (node1Type != NODE_GPP) {
+ hNodeMgr = hNode1->hNodeMgr;
+ } else {
+ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
+ hNodeMgr = hNode2->hNodeMgr;
+ }
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ /* Nodes must be in the allocated state */
+ if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
+ status = DSP_EWRONGSTATE;
+
+ if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
+ status = DSP_EWRONGSTATE;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Check that stream indices for task and dais socket nodes
+ * are not already be used. (Device nodes checked later) */
+ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
+ pOutput = &(hNode1->createArgs.asa.taskArgs.
+ strmOutDef[uStream1]);
+ if (pOutput->szDevice != NULL)
+ status = DSP_EALREADYCONNECTED;
+
+ }
+ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
+ pInput = &(hNode2->createArgs.asa.taskArgs.
+ strmInDef[uStream2]);
+ if (pInput->szDevice != NULL)
+ status = DSP_EALREADYCONNECTED;
+
+ }
+ }
+ /* Connecting two task nodes? */
+ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
+ node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
+ node2Type == NODE_DAISSOCKET))) {
+ /* Find available pipe */
+ pipeId = GB_findandset(hNodeMgr->pipeMap);
+ if (pipeId == GB_NOBITS) {
+ status = DSP_ENOMORECONNECTIONS;
+ } else {
+ hNode1->outputs[uStream1].type = NODECONNECT;
+ hNode2->inputs[uStream2].type = NODECONNECT;
+ hNode1->outputs[uStream1].devId = pipeId;
+ hNode2->inputs[uStream2].devId = pipeId;
+ pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
+ MEM_PAGED);
+ pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
+ MEM_PAGED);
+ if (pOutput->szDevice == NULL ||
+ pInput->szDevice == NULL) {
+ /* Undo the connection */
+ if (pOutput->szDevice)
+ MEM_Free(pOutput->szDevice);
+
+ if (pInput->szDevice)
+ MEM_Free(pInput->szDevice);
+
+ pOutput->szDevice = NULL;
+ pInput->szDevice = NULL;
+ GB_clear(hNodeMgr->pipeMap, pipeId);
+ status = DSP_EMEMORY;
+ } else {
+ /* Copy "/dbpipe<pipId>" name to device names */
+ sprintf(pOutput->szDevice, "%s%d",
+ PIPEPREFIX, pipeId);
+ strcpy(pInput->szDevice, pOutput->szDevice);
+ }
+ }
+ }
+ /* Connecting task node to host? */
+ if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
+ node2Type == NODE_GPP)) {
+ if (node1Type == NODE_GPP) {
+ uMode = CHNL_MODETODSP;
+ } else {
+ DBC_Assert(node2Type == NODE_GPP);
+ uMode = CHNL_MODEFROMDSP;
+ }
+ /* Reserve a channel id. We need to put the name "/host<id>"
+ * in the node's createArgs, but the host
+ * side channel will not be opened until DSPStream_Open is
+ * called for this node. */
+ if (pAttrs) {
+ if (pAttrs->lMode == STRMMODE_RDMA) {
+ chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
+ /* dma chans are 2nd transport chnl set
+ * ids(e.g. 16-31)*/
+ (chnlId != GB_NOBITS) ?
+ (chnlId = chnlId + hNodeMgr->ulNumChnls) :
+ chnlId;
+ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
+ chnlId = GB_findandset(hNodeMgr->zChnlMap);
+ /* zero-copy chans are 3nd transport set
+ * (e.g. 32-47) */
+ (chnlId != GB_NOBITS) ? (chnlId = chnlId +
+ (2 * hNodeMgr->ulNumChnls)) : chnlId;
+ } else { /* must be PROCCOPY */
+ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
+ chnlId = GB_findandset(hNodeMgr->chnlMap);
+ /* e.g. 0-15 */
+ }
+ } else {
+ /* default to PROCCOPY */
+ chnlId = GB_findandset(hNodeMgr->chnlMap);
+ }
+ if (chnlId == GB_NOBITS) {
+ status = DSP_ENOMORECONNECTIONS;
+ goto func_cont2;
+ }
+ pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
+ if (pstrDevName != NULL)
+ goto func_cont2;
+
+ if (pAttrs) {
+ if (pAttrs->lMode == STRMMODE_RDMA) {
+ GB_clear(hNodeMgr->dmaChnlMap, chnlId -
+ hNodeMgr->ulNumChnls);
+ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
+ GB_clear(hNodeMgr->zChnlMap, chnlId -
+ (2*hNodeMgr->ulNumChnls));
+ } else {
+ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
+ GB_clear(hNodeMgr->chnlMap, chnlId);
+ }
+ } else {
+ GB_clear(hNodeMgr->chnlMap, chnlId);
+ }
+ status = DSP_EMEMORY;
+func_cont2:
+ if (DSP_SUCCEEDED(status)) {
+ if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
+ hNode2->inputs[uStream2].type = HOSTCONNECT;
+ hNode2->inputs[uStream2].devId = chnlId;
+ pInput->szDevice = pstrDevName;
+ } else {
+ hNode1->outputs[uStream1].type = HOSTCONNECT;
+ hNode1->outputs[uStream1].devId = chnlId;
+ pOutput->szDevice = pstrDevName;
+ }
+ sprintf(pstrDevName, "%s%d", HOSTPREFIX, chnlId);
+ }
+ }
+ /* Connecting task node to device node? */
+ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
+ (node2Type == NODE_DEVICE))) {
+ if (node2Type == NODE_DEVICE) {
+ /* node1 == > device */
+ hDevNode = hNode2;
+ hNode = hNode1;
+ pStream = &(hNode1->outputs[uStream1]);
+ pstrmDef = pOutput;
+ } else {
+ /* device == > node2 */
+ hDevNode = hNode1;
+ hNode = hNode2;
+ pStream = &(hNode2->inputs[uStream2]);
+ pstrmDef = pInput;
+ }
+ /* Set up create args */
+ pStream->type = DEVICECONNECT;
+ dwLength = strlen(hDevNode->pstrDevName);
+ if (pConnParam != NULL) {
+ pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
+ (u32) pConnParam->cbData,
+ MEM_PAGED);
+ } else {
+ pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
+ MEM_PAGED);
+ }
+ if (pstrmDef->szDevice == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Copy device name */
+ strncpy(pstrmDef->szDevice, hDevNode->pstrDevName,
+ dwLength);
+ if (pConnParam != NULL) {
+ strncat(pstrmDef->szDevice,
+ (char *)pConnParam->cData,
+ (u32)pConnParam->cbData);
+ }
+ hDevNode->hDeviceOwner = hNode;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in create args */
+ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
+ hNode1->createArgs.asa.taskArgs.uNumOutputs++;
+ FillStreamDef(hNode1, pOutput, pAttrs);
+ }
+ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
+ hNode2->createArgs.asa.taskArgs.uNumInputs++;
+ FillStreamDef(hNode2, pInput, pAttrs);
+ }
+ /* Update hNode1 and hNode2 streamConnect */
+ if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
+ hNode1->uNumOutputs++;
+ if (uStream1 > hNode1->uMaxOutputIndex)
+ hNode1->uMaxOutputIndex = uStream1;
+
+ }
+ if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
+ hNode2->uNumInputs++;
+ if (uStream2 > hNode2->uMaxInputIndex)
+ hNode2->uMaxInputIndex = uStream2;
+
+ }
+ FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
+ }
+func_cont:
+ /* end of SYNC_EnterCS */
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_Create ========
+ * Purpose:
+ * Create a node on the DSP by remotely calling the node's create function.
+ */
+DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ struct NODE_MGR *hNodeMgr;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ u32 ulCreateFxn;
+ enum NODE_TYPE nodeType;
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+ bool bJustWokeDSP = false;
+ struct DSP_CBDATA cbData;
+ u32 procId = 255;
+ struct DSP_PROCESSORSTATE procStatus;
+ struct PROC_OBJECT *hProcessor;
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+#endif
+
+ DBC_Require(cRefs > 0);
+ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
+ hNode);
+ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ hProcessor = hNode->hProcessor;
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt to create
+ new node */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
+ " proc Status 0x%x\n", procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ /* create struct DSP_CBDATA struct for PWR calls */
+ cbData.cbData = PWR_TIMEOUT;
+ nodeType = NODE_GetType(hNode);
+ hNodeMgr = hNode->hNodeMgr;
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ /* Get access to node dispatcher */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ /* Check node state */
+ if (NODE_GetState(hNode) != NODE_ALLOCATED)
+ status = DSP_EWRONGSTATE;
+
+ if (DSP_SUCCEEDED(status))
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+ if (DSP_FAILED(status))
+ goto func_cont2;
+
+ if (procId != DSP_UNIT)
+ goto func_cont2;
+
+ /* Make sure streams are properly connected */
+ if ((hNode->uNumInputs && hNode->uMaxInputIndex >
+ hNode->uNumInputs - 1) ||
+ (hNode->uNumOutputs && hNode->uMaxOutputIndex >
+ hNode->uNumOutputs - 1))
+ status = DSP_ENOTCONNECTED;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* If node's create function is not loaded, load it */
+ /* Boost the OPP level to max level that DSP can be requested */
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ if (pdata->cpu_set_freq) {
+ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP3]);
+
+ if (pdata->dsp_get_opp) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
+ "after setting to VDD1_OPP3 is %d\n",
+ (*pdata->dsp_get_opp)());
+ }
+ }
+#endif
+ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
+ NLDR_CREATE);
+ /* Get address of node's create function */
+ if (DSP_SUCCEEDED(status)) {
+ hNode->fLoaded = true;
+ if (nodeType != NODE_DEVICE) {
+ status = GetFxnAddress(hNode, &ulCreateFxn,
+ CREATEPHASE);
+ }
+ } else {
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Create: failed to load"
+ " create code: 0x%x\n", status);
+ }
+ /* Request the lowest OPP level*/
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ if (pdata->cpu_set_freq) {
+ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
+
+ if (pdata->dsp_get_opp) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
+ "after setting to VDD1_OPP1 is %d\n",
+ (*pdata->dsp_get_opp)());
+ }
+ }
+#endif
+ /* Get address of iAlg functions, if socket node */
+ if (DSP_SUCCEEDED(status)) {
+ if (nodeType == NODE_DAISSOCKET) {
+ status = hNodeMgr->nldrFxns.pfnGetFxnAddr
+ (hNode->hNldrNode, hNode->dcdProps.
+ objData.nodeObj.pstrIAlgName,
+ &hNode->createArgs.asa.taskArgs.
+ ulDaisArg);
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ if (nodeType != NODE_DEVICE) {
+ status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
+ hNodeMgr->ulFxnAddrs[RMSCREATENODE],
+ ulCreateFxn, &(hNode->createArgs),
+ &(hNode->nodeEnv));
+ if (DSP_SUCCEEDED(status)) {
+ /* Set the message queue id to the node env
+ * pointer */
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
+ hNode->nodeEnv);
+ }
+ }
+ }
+ /* Phase II/Overlays: Create, execute, delete phases possibly in
+ * different files/sections. */
+ if (hNode->fLoaded && hNode->fPhaseSplit) {
+ /* If create code was dynamically loaded, we can now unload
+ * it. */
+ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
+ NLDR_CREATE);
+ hNode->fLoaded = false;
+ }
+ if (DSP_FAILED(status1)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Create: Failed to unload "
+ "create code: 0x%x\n", status1);
+ }
+func_cont2:
+ /* Update node state and node manager state */
+ if (DSP_SUCCEEDED(status)) {
+ NODE_SetState(hNode, NODE_CREATED);
+ hNodeMgr->uNumCreated++;
+ goto func_cont;
+ }
+ if (status != DSP_EWRONGSTATE) {
+ /* Put back in NODE_ALLOCATED state if error occurred */
+ NODE_SetState(hNode, NODE_ALLOCATED);
+ }
+ if (procId == DSP_UNIT) {
+ /* If node create failed, see if should sleep DSP now */
+ if (bJustWokeDSP == true) {
+ /* Check to see if partial create happened on DSP */
+ if (hNode->nodeEnv == (u32)NULL) {
+ /* No environment allocated on DSP, re-sleep
+ * DSP now */
+ PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
+ &cbData);
+ } else {
+ /* Increment count, sleep later when node fully
+ * deleted */
+ hNodeMgr->uNumCreated++;
+ }
+ }
+ }
+func_cont:
+ /* Free access to node dispatcher */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+ if (DSP_SUCCEEDED(status)) {
+ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
+ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+ }
+
+ return status;
+}
+
+/*
+ * ======== NODE_CreateMgr ========
+ * Purpose:
+ * Create a NODE Manager object.
+ */
+DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
+ struct DEV_OBJECT *hDevObject)
+{
+ u32 i;
+ struct NODE_MGR *pNodeMgr = NULL;
+ struct DISP_ATTRS dispAttrs;
+ char *szZLFile = "";
+ struct NLDR_ATTRS nldrAttrs;
+ DSP_STATUS status = DSP_SOK;
+ u32 devType;
+ DBC_Require(cRefs > 0);
+ DBC_Require(phNodeMgr != NULL);
+ DBC_Require(hDevObject != NULL);
+ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
+ "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
+ *phNodeMgr = NULL;
+ /* Allocate Node manager object */
+ MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
+ if (pNodeMgr) {
+ pNodeMgr->hDevObject = hDevObject;
+ pNodeMgr->nodeList = LST_Create();
+ pNodeMgr->pipeMap = GB_create(MAXPIPES);
+ pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
+ if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
+ pNodeMgr->pipeDoneMap == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(NODE_debugMask, GT_6CLASS,
+ "NODE_CreateMgr: Memory "
+ "allocation failed\n");
+ } else {
+ status = NTFY_Create(&pNodeMgr->hNtfy);
+ }
+ pNodeMgr->uNumCreated = 0;
+ } else {
+ GT_0trace(NODE_debugMask, GT_6CLASS,
+ "NODE_CreateMgr: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ }
+ /* get devNodeType */
+ if (DSP_SUCCEEDED(status))
+ status = DEV_GetDevType(hDevObject, &devType);
+
+ /* Create the DCD Manager */
+ if (DSP_SUCCEEDED(status)) {
+ status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
+ if (DSP_SUCCEEDED(status))
+ status = GetProcProps(pNodeMgr, hDevObject);
+
+ }
+ /* Create NODE Dispatcher */
+ if (DSP_SUCCEEDED(status)) {
+ dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
+ dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
+ dispAttrs.procFamily = pNodeMgr->procFamily;
+ dispAttrs.procType = pNodeMgr->procType;
+ status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
+ }
+ /* Create a STRM Manager */
+ if (DSP_SUCCEEDED(status))
+ status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
+
+ if (DSP_SUCCEEDED(status)) {
+ DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
+ /* Get MSG queue manager */
+ DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
+ status = SYNC_InitializeCS(&pNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ status = DSP_EMEMORY;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
+ /* dma chnl map. ulNumChnls is # per transport */
+ pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
+ pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
+ if ((pNodeMgr->chnlMap == NULL) ||
+ (pNodeMgr->dmaChnlMap == NULL) ||
+ (pNodeMgr->zChnlMap == NULL)) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Block out reserved channels */
+ for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
+ GB_set(pNodeMgr->chnlMap, i);
+
+ /* Block out channels reserved for RMS */
+ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
+ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* NO RM Server on the IVA */
+ if (devType != IVA_UNIT) {
+ /* Get addresses of any RMS functions loaded */
+ status = GetRMSFxns(pNodeMgr);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_6CLASS,
+ "NODE_CreateMgr: Failed to"
+ " get RMS functions: status = 0x%x", status);
+ }
+ }
+ }
+
+ /* Get loader functions and create loader */
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(NODE_debugMask, GT_1CLASS,
+ "NODE_CreateMgr: using dynamic loader\n");
+ pNodeMgr->nldrFxns = nldrFxns; /* Dynamic loader functions */
+ }
+ if (DSP_SUCCEEDED(status)) {
+ nldrAttrs.pfnOvly = Ovly;
+ nldrAttrs.pfnWrite = Write;
+ nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
+ nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
+ pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
+ status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
+ hDevObject, &nldrAttrs);
+ if (DSP_FAILED(status)) {
+ GT_1trace(NODE_debugMask, GT_6CLASS,
+ "NODE_CreateMgr: Failed to "
+ "create loader: status = 0x%x\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status))
+ *phNodeMgr = pNodeMgr;
+ else
+ DeleteNodeMgr(pNodeMgr);
+
+ DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
+ (DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
+
+ return status;
+}
+
+/*
+ * ======== NODE_Delete ========
+ * Purpose:
+ * Delete a node on the DSP by remotely calling the node's delete function.
+ * Loads the node's delete function if necessary. Free GPP side resources
+ * after node's delete function returns.
+ */
+DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ struct NODE_MGR *hNodeMgr;
+ struct PROC_OBJECT *hProcessor;
+ struct DISP_OBJECT *hDisp;
+ u32 ulDeleteFxn;
+ enum NODE_TYPE nodeType;
+ enum NODE_STATE state;
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+ struct DSP_CBDATA cbData;
+ u32 procId;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ HANDLE nodeRes;
+ HANDLE hDrvObject;
+ struct PROCESS_CONTEXT *pCtxt = NULL;
+ DSP_STATUS res_status = DSP_SOK;
+#endif
+ struct DSP_PROCESSORSTATE procStatus;
+ DBC_Require(cRefs > 0);
+ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
+ hNode);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ /* create struct DSP_CBDATA struct for PWR call */
+ cbData.cbData = PWR_TIMEOUT;
+ hNodeMgr = hNode->hNodeMgr;
+ hProcessor = hNode->hProcessor;
+ hDisp = hNodeMgr->hDisp;
+ nodeType = NODE_GetType(hNode);
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ state = NODE_GetState(hNode);
+ /* Execute delete phase code for non-device node in all cases
+ * except when the node was only allocated. Delete phase must be
+ * executed even if create phase was executed, but failed.
+ * If the node environment pointer is non-NULL, the delete phase
+ * code must be executed. */
+ if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
+ nodeType != NODE_DEVICE) {
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+ if (DSP_FAILED(status))
+ goto func_cont1;
+
+ if (procId == DSP_UNIT || procId == IVA_UNIT) {
+ /* If node has terminated, execute phase code will
+ * have already been unloaded in NODE_OnExit(). If the
+ * node is PAUSED, the execute phase is loaded, and it
+ * is now ok to unload it. If the node is running, we
+ * will unload the execute phase only after deleting
+ * the node. */
+ if (state == NODE_PAUSED && hNode->fLoaded &&
+ hNode->fPhaseSplit) {
+ /* Ok to unload execute code as long as node
+ * is not * running */
+ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
+ hNldrNode, NLDR_EXECUTE);
+ hNode->fLoaded = false;
+ NODE_SetState(hNode, NODE_DONE);
+ }
+ /* Load delete phase code if not loaded or if haven't
+ * * unloaded EXECUTE phase */
+ if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
+ hNode->fPhaseSplit) {
+ status = hNodeMgr->nldrFxns.pfnLoad(hNode->
+ hNldrNode, NLDR_DELETE);
+ if (DSP_SUCCEEDED(status)) {
+ hNode->fLoaded = true;
+ } else {
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Delete: failed to "
+ "load delete code: 0x%x\n",
+ status);
+ }
+ }
+ }
+func_cont1:
+ if (DSP_SUCCEEDED(status)) {
+ /* Unblock a thread trying to terminate the node */
+ (void)SYNC_SetEvent(hNode->hSyncDone);
+ if (procId == DSP_UNIT) {
+ /* ulDeleteFxn = address of node's delete
+ * function */
+ status = GetFxnAddress(hNode, &ulDeleteFxn,
+ DELETEPHASE);
+ } else if (procId == IVA_UNIT)
+ ulDeleteFxn = (u32)hNode->nodeEnv;
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ GT_1trace(NODE_debugMask, GT_4CLASS,
+ "NODE_Delete: proc Status "
+ "0x%x\n", procStatus.iState);
+ if (procStatus.iState != PROC_ERROR) {
+ status = DISP_NodeDelete(hDisp, hNode,
+ hNodeMgr->ulFxnAddrs[RMSDELETENODE],
+ ulDeleteFxn, hNode->nodeEnv);
+ } else
+ NODE_SetState(hNode, NODE_DONE);
+
+ /* Unload execute, if not unloaded, and delete
+ * function */
+ if (state == NODE_RUNNING &&
+ hNode->fPhaseSplit) {
+ status1 = hNodeMgr->nldrFxns.pfnUnload(
+ hNode->hNldrNode, NLDR_EXECUTE);
+ }
+ if (DSP_FAILED(status1)) {
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Delete: failed to"
+ "unload execute code: 0x%x\n",
+ status1);
+ }
+ status1 = hNodeMgr->nldrFxns.pfnUnload(
+ hNode->hNldrNode, NLDR_DELETE);
+ hNode->fLoaded = false;
+ if (DSP_FAILED(status1)) {
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Delete: failed to"
+ "unload delete code: 0x%x\n",
+ status1);
+ }
+ }
+ }
+ }
+ /* Free host side resources even if a failure occurred */
+ /* Remove node from hNodeMgr->nodeList */
+ LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
+ hNodeMgr->uNumNodes--;
+ /* Decrement count of nodes created on DSP */
+ if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
+ (hNode->nodeEnv != (u32) NULL)))
+ hNodeMgr->uNumCreated--;
+ /* Free host-side resources allocated by NODE_Create()
+ * DeleteNode() fails if SM buffers not freed by client! */
+#ifndef RES_CLEANUP_DISABLE
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(res_status))
+ goto func_cont;
+ DRV_GetProcContext(0, (struct DRV_OBJECT *)hDrvObject,
+ &pCtxt, hNode, 0);
+ if (pCtxt == NULL)
+ goto func_cont;
+ if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
+ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
+ DRV_ProcNodeUpdateStatus(nodeRes, false);
+ }
+#endif
+func_cont:
+ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
+ DeleteNode(hNode);
+#ifndef RES_CLEANUP_DISABLE
+ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
+ if (pCtxt != NULL)
+ DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
+#endif
+ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_DeleteMgr ========
+ * Purpose:
+ * Delete the NODE Manager.
+ */
+DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
+
+ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
+ hNodeMgr);
+ DeleteNodeMgr(hNodeMgr);
+
+ return status;
+}
+
+/*
+ * ======== NODE_EnumNodes ========
+ * Purpose:
+ * Enumerate currently allocated nodes.
+ */
+DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
+ u32 uNodeTabSize, OUT u32 *puNumNodes,
+ OUT u32 *puAllocated)
+{
+ struct NODE_OBJECT *hNode;
+ u32 i;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
+ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
+ DBC_Require(puNumNodes != NULL);
+ DBC_Require(puAllocated != NULL);
+ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
+ "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
+ "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
+ puAllocated);
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ if (hNodeMgr->uNumNodes > uNodeTabSize) {
+ *puAllocated = hNodeMgr->uNumNodes;
+ *puNumNodes = 0;
+ status = DSP_ESIZE;
+ } else {
+ hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
+ nodeList);
+ for (i = 0; i < hNodeMgr->uNumNodes; i++) {
+ DBC_Assert(MEM_IsValidHandle(hNode,
+ NODE_SIGNATURE));
+ aNodeTab[i] = hNode;
+ hNode = (struct NODE_OBJECT *)LST_Next
+ (hNodeMgr->nodeList,
+ (struct LST_ELEM *)hNode);
+ }
+ *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
+ }
+ }
+ /* end of SYNC_EnterCS */
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ return status;
+}
+
+/*
+ * ======== NODE_Exit ========
+ * Purpose:
+ * Discontinue usage of NODE module.
+ */
+void NODE_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "Entered NODE_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== NODE_FreeMsgBuf ========
+ * Purpose:
+ * Frees the message buffer.
+ */
+DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
+ OPTIONAL struct DSP_BUFFERATTR *pAttr)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ DSP_STATUS status = DSP_SOK;
+ u32 procId;
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBuffer != NULL);
+ DBC_Require(pNode != NULL);
+ DBC_Require(pNode->hXlator != NULL);
+ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
+ "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+ if (procId == DSP_UNIT) {
+ if (DSP_SUCCEEDED(status)) {
+ if (pAttr == NULL) {
+ /* set defaults */
+ pAttr = &NODE_DFLTBUFATTRS;
+ }
+ /* Node supports single SM segment only */
+ if (pAttr->uSegment != 1)
+ status = DSP_EBADSEGID;
+
+ /* pBuffer is clients Va. */
+ status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
+ if (DSP_FAILED(status))
+ status = DSP_EFAIL;
+ else
+ status = DSP_SOK;
+
+ }
+ } else {
+ DBC_Assert(NULL); /* BUG */
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_GetAttr ========
+ * Purpose:
+ * Copy the current attributes of the specified node into a DSP_NODEATTR
+ * structure.
+ */
+DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
+ OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
+{
+ struct NODE_MGR *hNodeMgr;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(cRefs > 0);
+ DBC_Require(pAttr != NULL);
+ DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
+ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
+ "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
+ uAttrSize);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ hNodeMgr = hNode->hNodeMgr;
+ /* Enter hNodeMgr critical section (since we're accessing
+ * data that could be changed by NODE_ChangePriority() and
+ * NODE_Connect(). */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
+ /* DSP_NODEATTRIN */
+ pAttr->inNodeAttrIn.cbStruct =
+ sizeof(struct DSP_NODEATTRIN);
+ pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
+ pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
+ pAttr->inNodeAttrIn.uHeapSize =
+ hNode->createArgs.asa.taskArgs.uHeapSize;
+ pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
+ hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
+ pAttr->uInputs = hNode->uNumGPPInputs;
+ pAttr->uOutputs = hNode->uNumGPPOutputs;
+ /* DSP_NODEINFO */
+ GetNodeInfo(hNode, &(pAttr->iNodeInfo));
+ }
+ /* end of SYNC_EnterCS */
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ }
+ return status;
+}
+
+/*
+ * ======== NODE_GetChannelId ========
+ * Purpose:
+ * Get the channel index reserved for a stream connection between the
+ * host and a node.
+ */
+DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
+ OUT u32 *pulId)
+{
+ enum NODE_TYPE nodeType;
+ DSP_STATUS status = DSP_EVALUE;
+ DBC_Require(cRefs > 0);
+ DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
+ DBC_Require(pulId != NULL);
+ GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
+ "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
+ uIndex, pulId);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
+ status = DSP_ENODETYPE;
+ return status;
+ }
+ if (uDir == DSP_TONODE) {
+ if (uIndex < MaxInputs(hNode)) {
+ if (hNode->inputs[uIndex].type == HOSTCONNECT) {
+ *pulId = hNode->inputs[uIndex].devId;
+ status = DSP_SOK;
+ }
+ }
+ } else {
+ DBC_Assert(uDir == DSP_FROMNODE);
+ if (uIndex < MaxOutputs(hNode)) {
+ if (hNode->outputs[uIndex].type == HOSTCONNECT) {
+ *pulId = hNode->outputs[uIndex].devId;
+ status = DSP_SOK;
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== NODE_GetMessage ========
+ * Purpose:
+ * Retrieve a message from a node on the DSP.
+ */
+DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
+ u32 uTimeout)
+{
+ struct NODE_MGR *hNodeMgr;
+ enum NODE_TYPE nodeType;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+ void *pTmpBuf;
+ struct DSP_PROCESSORSTATE procStatus;
+ struct PROC_OBJECT *hProcessor;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pMsg != NULL);
+ GT_3trace(NODE_debugMask, GT_ENTER,
+ "NODE_GetMessage: hNode: 0x%x\tpMsg: "
+ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ hProcessor = hNode->hProcessor;
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt to get the
+ message */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_GetMessage:"
+ " proc Status 0x%x\n", procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ hNodeMgr = hNode->hNodeMgr;
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
+ nodeType != NODE_DAISSOCKET) {
+ status = DSP_ENODETYPE;
+ goto func_end;
+ }
+ /* This function will block unless a message is available. Since
+ * DSPNode_RegisterNotify() allows notification when a message
+ * is available, the system can be designed so that
+ * DSPNode_GetMessage() is only called when a message is
+ * available. */
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
+ /* Check if message contains SM descriptor */
+ if (DSP_FAILED(status) || !(pMsg->dwCmd & DSP_RMSBUFDESC))
+ goto func_end;
+
+ /* Translate DSP byte addr to GPP Va. */
+ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
+ (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
+ CMM_DSPPA2PA);
+ if (pTmpBuf != NULL) {
+ /* now convert this GPP Pa to Va */
+ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
+ CMM_PA2VA);
+ if (pTmpBuf != NULL) {
+ /* Adjust SM size in msg */
+ pMsg->dwArg1 = (u32) pTmpBuf;
+ pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
+ } else {
+ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
+ "Failed SM translation!\n");
+ status = DSP_ETRANSLATE;
+ }
+ } else {
+ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
+ "SM Pa/Pa translation!\n");
+ status = DSP_ETRANSLATE;
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_GetNldrObj ========
+ */
+DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
+ struct NLDR_OBJECT **phNldrObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct NODE_MGR *pNodeMgr = hNodeMgr;
+ DBC_Require(phNldrObj != NULL);
+ GT_2trace(NODE_debugMask, GT_ENTER,
+ "Entered NODE_GetNldrObj, hNodeMgr: "
+ "0x%x\n\tphNldrObj: 0x%x\n", hNodeMgr, phNldrObj);
+ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
+ status = DSP_EHANDLE;
+ else
+ *phNldrObj = pNodeMgr->hNldr;
+
+ GT_2trace(NODE_debugMask, GT_ENTER,
+ "Exit NODE_GetNldrObj: status 0x%x\n\t"
+ "phNldrObj: 0x%x\n", status, *phNldrObj);
+ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
+ (*phNldrObj == NULL)));
+ return status;
+}
+
+/*
+ * ======== NODE_GetStrmMgr ========
+ * Purpose:
+ * Returns the Stream manager.
+ */
+DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
+ struct STRM_MGR **phStrmMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+ status = DSP_EHANDLE;
+ else
+ *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
+
+ return status;
+}
+
+/*
+ * ======== NODE_GetLoadType ========
+ */
+enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
+{
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_GetLoadType: Failed. hNode:"
+ " 0x%x\n", hNode);
+ return -1;
+ } else
+ return hNode->dcdProps.objData.nodeObj.usLoadType;
+}
+
+/*
+ * ======== NODE_GetTimeout ========
+ * Purpose:
+ * Returns the timeout value for this node.
+ */
+u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_GetTimeout: Failed. hNode:"
+ " 0x%x\n", hNode);
+ return 0;
+ } else
+ return hNode->uTimeout;
+}
+
+/*
+ * ======== NODE_GetType ========
+ * Purpose:
+ * Returns the node type.
+ */
+enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
+{
+ enum NODE_TYPE nodeType;
+
+ if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
+ nodeType = NODE_GPP;
+ else {
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+ nodeType = -1;
+ else
+ nodeType = hNode->nType;
+ }
+ return nodeType;
+}
+
+/*
+ * ======== NODE_Init ========
+ * Purpose:
+ * Initialize the NODE module.
+ */
+bool NODE_Init(void)
+{
+ bool fRetVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!NODE_debugMask.flags);
+ GT_create(&NODE_debugMask, "NO"); /* "NO" for NOde */
+ }
+
+ if (fRetVal)
+ cRefs++;
+
+ GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+ return fRetVal;
+}
+
+/*
+ * ======== NODE_OnExit ========
+ * Purpose:
+ * Gets called when RMS_EXIT is received for a node.
+ */
+void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
+{
+ DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ /* Set node state to done */
+ NODE_SetState(hNode, NODE_DONE);
+ hNode->nExitStatus = nStatus;
+ if (hNode->fLoaded && hNode->fPhaseSplit) {
+ (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
+ NLDR_EXECUTE);
+ hNode->fLoaded = false;
+ }
+ /* Unblock call to NODE_Terminate */
+ (void) SYNC_SetEvent(hNode->hSyncDone);
+ /* Notify clients */
+ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
+ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+}
+
+/*
+ * ======== NODE_Pause ========
+ * Purpose:
+ * Suspend execution of a node currently running on the DSP.
+ */
+DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ enum NODE_TYPE nodeType;
+ enum NODE_STATE state;
+ struct NODE_MGR *hNodeMgr;
+ DSP_STATUS status = DSP_SOK;
+ u32 procId;
+ struct DSP_PROCESSORSTATE procStatus;
+ struct PROC_OBJECT *hProcessor;
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
+
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ } else {
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
+ status = DSP_ENODETYPE;
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+ if (procId == IVA_UNIT)
+ status = DSP_ENOTIMPL;
+
+ if (DSP_SUCCEEDED(status)) {
+ hNodeMgr = hNode->hNodeMgr;
+
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+
+ if (DSP_SUCCEEDED(status)) {
+ state = NODE_GetState(hNode);
+ /* Check node state */
+ if (state != NODE_RUNNING)
+ status = DSP_EWRONGSTATE;
+
+ hProcessor = hNode->hProcessor;
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt
+ to send the message */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS,
+ "NODE_Pause: proc Status 0x%x\n",
+ procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = DISP_NodeChangePriority(hNodeMgr->
+ hDisp, hNode,
+ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
+ hNode->nodeEnv, NODE_SUSPENDEDPRI);
+ }
+
+ /* Update state */
+ if (DSP_SUCCEEDED(status)) {
+ NODE_SetState(hNode, NODE_PAUSED);
+ } else {
+ GT_1trace(NODE_debugMask, GT_6CLASS,
+ "NODE_Pause: Failed. hNode:"
+ " 0x%x\n", hNode);
+ }
+ }
+ /* End of SYNC_EnterCS */
+ /* Leave critical section */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ PROC_NotifyClients(hNode->hProcessor,
+ DSP_NODESTATECHANGE);
+ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_PutMessage ========
+ * Purpose:
+ * Send a message to a message node, task node, or XDAIS socket node. This
+ * function will block until the message stream can accommodate the
+ * message, or a timeout occurs.
+ */
+DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
+ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
+{
+ struct NODE_MGR *hNodeMgr = NULL;
+ enum NODE_TYPE nodeType;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ enum NODE_STATE state;
+ DSP_STATUS status = DSP_SOK;
+ void *pTmpBuf;
+ struct DSP_MSG newMsg;
+ struct DSP_PROCESSORSTATE procStatus;
+ struct PROC_OBJECT *hProcessor;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pMsg != NULL);
+ GT_3trace(NODE_debugMask, GT_ENTER,
+ "NODE_PutMessage: hNode: 0x%x\tpMsg: "
+ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ hProcessor = hNode->hProcessor;
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in bad state then don't attempt sending the
+ message */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_PutMessage:"
+ " proc Status 0x%x\n", procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ hNodeMgr = hNode->hNodeMgr;
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
+ nodeType != NODE_DAISSOCKET)
+ status = DSP_ENODETYPE;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Check node state. Can't send messages to a node after
+ * we've sent the RMS_EXIT command. There is still the
+ * possibility that NODE_Terminate can be called after we've
+ * checked the state. Could add another SYNC object to
+ * prevent this (can't use hNodeMgr->hSync, since we don't
+ * want to block other NODE functions). However, the node may
+ * still exit on its own, before this message is sent. */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ state = NODE_GetState(hNode);
+ if (state == NODE_TERMINATING || state == NODE_DONE)
+ status = DSP_EWRONGSTATE;
+
+ }
+ /* end of SYNC_EnterCS */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* assign pMsg values to new msg */
+ newMsg = *pMsg;
+ /* Now, check if message contains a SM buffer descriptor */
+ if (pMsg->dwCmd & DSP_RMSBUFDESC) {
+ /* Translate GPP Va to DSP physical buf Ptr. */
+ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
+ (void *)newMsg.dwArg1, CMM_VA2DSPPA);
+ if (pTmpBuf != NULL) {
+ /* got translation, convert to MAUs in msg */
+ if (hNode->hNodeMgr->uDSPWordSize != 0) {
+ newMsg.dwArg1 =
+ (u32)pTmpBuf /
+ hNode->hNodeMgr->uDSPWordSize;
+ /* MAUs */
+ newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
+ } else {
+ GT_0trace(NODE_debugMask, GT_7CLASS,
+ "NODE_PutMessage: "
+ "uDSPWordSize is zero!\n");
+ status = DSP_EFAIL; /* bad DSPWordSize */
+ }
+ } else { /* failed to translate buffer address */
+ GT_0trace(NODE_debugMask, GT_7CLASS,
+ "NODE_PutMessage: Failed to"
+ " translate SM address\n");
+ status = DSP_ETRANSLATE;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
+ &newMsg, uTimeout);
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_RegisterNotify ========
+ * Purpose:
+ * Register to be notified on specific events for this node.
+ */
+DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hNotification != NULL);
+
+ GT_4trace(NODE_debugMask, GT_ENTER,
+ "NODE_RegisterNotify: hNode: 0x%x\t"
+ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
+ hNode, uEventMask, uNotifyType, hNotification);
+
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ /* Check if event mask is a valid node related event */
+ if (uEventMask & ~(DSP_NODESTATECHANGE |
+ DSP_NODEMESSAGEREADY))
+ status = DSP_EVALUE;
+
+ /* Check if notify type is valid */
+ if (uNotifyType != DSP_SIGNALEVENT)
+ status = DSP_EVALUE;
+
+ /* Only one Notification can be registered at a
+ * time - Limitation */
+ if (uEventMask == (DSP_NODESTATECHANGE |
+ DSP_NODEMESSAGEREADY))
+ status = DSP_EVALUE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ if (uEventMask == DSP_NODESTATECHANGE) {
+ status = NTFY_Register(hNode->hNtfy, hNotification,
+ uEventMask & DSP_NODESTATECHANGE, uNotifyType);
+ } else {
+ /* Send Message part of event mask to MSG */
+ pIntfFxns = hNode->hNodeMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnMsgRegisterNotify)
+ (hNode->hMsgQueue,
+ uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
+ hNotification);
+ }
+
+ }
+ return status;
+}
+
+/*
+ * ======== NODE_Run ========
+ * Purpose:
+ * Start execution of a node's execute phase, or resume execution of a node
+ * that has been suspended (via NODE_NodePause()) on the DSP. Load the
+ * node's execute function if necessary.
+ */
+DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ struct NODE_MGR *hNodeMgr;
+ enum NODE_TYPE nodeType;
+ enum NODE_STATE state;
+ u32 ulExecuteFxn;
+ u32 ulFxnAddr;
+ DSP_STATUS status = DSP_SOK;
+ u32 procId;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct DSP_PROCESSORSTATE procStatus;
+ struct PROC_OBJECT *hProcessor;
+
+ DBC_Require(cRefs > 0);
+ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ hProcessor = hNode->hProcessor;
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt to run the node */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Run:"
+ " proc Status 0x%x\n", procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ nodeType = NODE_GetType(hNode);
+ if (nodeType == NODE_DEVICE)
+ status = DSP_ENODETYPE;
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ hNodeMgr = hNode->hNodeMgr;
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ /* Enter critical section */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ state = NODE_GetState(hNode);
+ if (state != NODE_CREATED && state != NODE_PAUSED)
+ status = DSP_EWRONGSTATE;
+
+ if (DSP_SUCCEEDED(status))
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+ if (DSP_FAILED(status))
+ goto func_cont1;
+
+ if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
+ goto func_cont1;
+
+ if (state == NODE_CREATED) {
+ /* If node's execute function is not loaded, load it */
+ if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
+ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
+ NLDR_EXECUTE);
+ if (DSP_SUCCEEDED(status)) {
+ hNode->fLoaded = true;
+ } else {
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Run: failed to load "
+ "execute code:0x%x\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get address of node's execute function */
+ if (procId == IVA_UNIT)
+ ulExecuteFxn = (u32) hNode->nodeEnv;
+ else {
+ status = GetFxnAddress(hNode, &ulExecuteFxn,
+ EXECUTEPHASE);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
+ status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
+ ulExecuteFxn, hNode->nodeEnv);
+ }
+ } else if (state == NODE_PAUSED) {
+ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
+ status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
+ ulFxnAddr, hNode->nodeEnv,
+ NODE_GetPriority(hNode));
+ } else {
+ /* We should never get here */
+ DBC_Assert(false);
+ }
+func_cont1:
+ /* Update node state. */
+ if (DSP_SUCCEEDED(status))
+ NODE_SetState(hNode, NODE_RUNNING);
+ else /* Set state back to previous value */
+ NODE_SetState(hNode, state);
+ /*End of SYNC_EnterCS */
+ /* Exit critical section */
+func_cont:
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ PROC_NotifyClients(hNode->hProcessor,
+ DSP_NODESTATECHANGE);
+ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== NODE_Terminate ========
+ * Purpose:
+ * Signal a node running on the DSP that it should exit its execute phase
+ * function.
+ */
+DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
+{
+ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+ struct NODE_MGR *hNodeMgr = NULL;
+ enum NODE_TYPE nodeType;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ enum NODE_STATE state;
+ struct DSP_MSG msg, killmsg;
+ DSP_STATUS status = DSP_SOK;
+ u32 procId, killTimeOut;
+ struct DEH_MGR *hDehMgr;
+ struct DSP_PROCESSORSTATE procStatus;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pStatus != NULL);
+
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Terminate: hNode: 0x%x\n", hNode);
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ if (pNode->hProcessor == NULL) {
+ GT_1trace(NODE_debugMask, GT_4CLASS,
+ "NODE_Terminate: pNode->hProcessor = 0x%x\n",
+ pNode->hProcessor);
+ goto func_end;
+ }
+ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+ if (DSP_SUCCEEDED(status)) {
+ hNodeMgr = hNode->hNodeMgr;
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_TASK && nodeType !=
+ NODE_DAISSOCKET)
+ status = DSP_ENODETYPE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Check node state */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ state = NODE_GetState(hNode);
+ if (state != NODE_RUNNING) {
+ status = DSP_EWRONGSTATE;
+ /* Set the exit status if node terminated on
+ * its own. */
+ if (state == NODE_DONE)
+ *pStatus = hNode->nExitStatus;
+
+ } else {
+ NODE_SetState(hNode, NODE_TERMINATING);
+ }
+ }
+ /* end of SYNC_EnterCS */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /*
+ * Send exit message. Do not change state to NODE_DONE
+ * here. That will be done in callback.
+ */
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
+
+ status = PROC_GetState(pNode->hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_cont;
+ /* If processor is in error state then don't attempt to send
+ * A kill task command */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Terminate:"
+ " proc Status 0x%x\n", procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_cont;
+ }
+
+ msg.dwCmd = RMS_EXIT;
+ msg.dwArg1 = hNode->nodeEnv;
+ killmsg.dwCmd = RMS_KILLTASK;
+ killmsg.dwArg1 = hNode->nodeEnv;
+ pIntfFxns = hNodeMgr->pIntfFxns;
+
+ if (hNode->uTimeout > MAXTIMEOUT)
+ killTimeOut = MAXTIMEOUT;
+ else
+ killTimeOut = (hNode->uTimeout)*2;
+
+ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
+ hNode->uTimeout);
+ if (DSP_SUCCEEDED(status)) {
+ /* Wait on synchronization object that will be
+ * posted in the callback on receiving RMS_EXIT
+ * message, or by NODE_Delete. Check for valid hNode,
+ * in case posted by NODE_Delete(). */
+ status = SYNC_WaitOnEvent(hNode->hSyncDone,
+ killTimeOut/2);
+ if (DSP_FAILED(status)) {
+ if (status == DSP_ETIMEOUT) {
+ status = (*pIntfFxns->pfnMsgPut)
+ (hNode->hMsgQueue, &killmsg,
+ hNode->uTimeout);
+ if (DSP_SUCCEEDED(status)) {
+ status = SYNC_WaitOnEvent
+ (hNode->hSyncDone,
+ killTimeOut/2);
+ if (DSP_FAILED(status)) {
+ /* Here it goes the part
+ * of the simulation of
+ * the DSP exception */
+ DEV_GetDehMgr(hNodeMgr->
+ hDevObject, &hDehMgr);
+ if (hDehMgr) {
+ (*pIntfFxns->
+ pfnDehNotify)(hDehMgr,
+ DSP_SYSERROR,
+ DSP_EXCEPTIONABORT);
+ status = DSP_EFAIL;
+ }
+ } else
+ status = DSP_SOK;
+ }
+ } else
+ status = DSP_EFAIL;
+ } else /* Convert SYNC status to DSP status */
+ status = DSP_SOK;
+ }
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status)) {
+ /* Enter CS before getting exit status, in case node was
+ * deleted. */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+ /* Make sure node wasn't deleted while we blocked */
+ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+ status = DSP_EFAIL;
+ } else {
+ *pStatus = hNode->nExitStatus;
+ GT_1trace(NODE_debugMask, GT_ENTER,
+ "NODE_Terminate: env = 0x%x "
+ "succeeded.\n", hNode->nodeEnv);
+ }
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ } /*End of SYNC_EnterCS */
+func_end:
+ return status;
+}
+
+/*
+ * ======== DeleteNode ========
+ * Purpose:
+ * Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
+ */
+static void DeleteNode(struct NODE_OBJECT *hNode)
+{
+ struct NODE_MGR *hNodeMgr;
+ struct CMM_XLATOROBJECT *hXlator;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ u32 i;
+ enum NODE_TYPE nodeType;
+ struct STREAM stream;
+ struct NODE_MSGARGS msgArgs;
+ struct NODE_TASKARGS taskArgs;
+#ifdef DSP_DMM_DEBUG
+ struct DMM_OBJECT *hDmmMgr;
+ struct PROC_OBJECT *pProcObject =
+ (struct PROC_OBJECT *)hNode->hProcessor;
+#endif
+ DSP_STATUS status;
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ hNodeMgr = hNode->hNodeMgr;
+ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
+ return;
+ hXlator = hNode->hXlator;
+ nodeType = NODE_GetType(hNode);
+ if (nodeType != NODE_DEVICE) {
+ msgArgs = hNode->createArgs.asa.msgArgs;
+ if (msgArgs.pData)
+ MEM_Free(msgArgs.pData);
+
+ /* Free MSG queue */
+ if (hNode->hMsgQueue) {
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
+ hNode->hMsgQueue = NULL;
+
+ }
+ if (hNode->hSyncDone)
+ (void) SYNC_CloseEvent(hNode->hSyncDone);
+
+ /* Free all stream info */
+ if (hNode->inputs) {
+ for (i = 0; i < MaxInputs(hNode); i++) {
+ stream = hNode->inputs[i];
+ FreeStream(hNodeMgr, stream);
+ }
+ MEM_Free(hNode->inputs);
+ hNode->inputs = NULL;
+ }
+ if (hNode->outputs) {
+ for (i = 0; i < MaxOutputs(hNode); i++) {
+ stream = hNode->outputs[i];
+ FreeStream(hNodeMgr, stream);
+ }
+ MEM_Free(hNode->outputs);
+ hNode->outputs = NULL;
+ }
+ taskArgs = hNode->createArgs.asa.taskArgs;
+ if (taskArgs.strmInDef) {
+ for (i = 0; i < MaxInputs(hNode); i++) {
+ if (taskArgs.strmInDef[i].szDevice) {
+ MEM_Free(taskArgs.strmInDef[i].
+ szDevice);
+ taskArgs.strmInDef[i].szDevice = NULL;
+ }
+ }
+ MEM_Free(taskArgs.strmInDef);
+ taskArgs.strmInDef = NULL;
+ }
+ if (taskArgs.strmOutDef) {
+ for (i = 0; i < MaxOutputs(hNode); i++) {
+ if (taskArgs.strmOutDef[i].szDevice) {
+ MEM_Free(taskArgs.strmOutDef[i].
+ szDevice);
+ taskArgs.strmOutDef[i].szDevice = NULL;
+ }
+ }
+ MEM_Free(taskArgs.strmOutDef);
+ taskArgs.strmOutDef = NULL;
+ }
+ if (taskArgs.uDSPHeapResAddr) {
+ status = PROC_UnMap(hNode->hProcessor,
+ (void *)taskArgs.uDSPHeapAddr);
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(NODE_debugMask, GT_5CLASS,
+ "DSPProcessor_UnMap succeeded.\n");
+ } else {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "DSPProcessor_UnMap failed."
+ " Status = 0x%x\n", (u32)status);
+ }
+ status = PROC_UnReserveMemory(hNode->hProcessor,
+ (void *)taskArgs.uDSPHeapResAddr);
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(NODE_debugMask, GT_5CLASS,
+ "DSPProcessor_UnReserveMemory "
+ "succeeded.\n");
+ } else {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "DSPProcessor_UnReserveMemory "
+ "failed. Status = 0x%x\n",
+ (u32)status);
+ }
+#ifdef DSP_DMM_DEBUG
+ status = DMM_GetHandle(pProcObject, &hDmmMgr);
+ if (DSP_SUCCEEDED(status))
+ DMM_MemMapDump(hDmmMgr);
+#endif
+ }
+ }
+ if (nodeType != NODE_MESSAGE) {
+ if (hNode->streamConnect) {
+ MEM_Free(hNode->streamConnect);
+ hNode->streamConnect = NULL;
+ }
+ }
+ if (hNode->pstrDevName) {
+ MEM_Free(hNode->pstrDevName);
+ hNode->pstrDevName = NULL;
+ }
+
+ if (hNode->hNtfy) {
+ NTFY_Delete(hNode->hNtfy);
+ hNode->hNtfy = NULL;
+ }
+
+ /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
+ if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn) {
+ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
+ hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn = NULL;
+ }
+
+ if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn) {
+ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
+ hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn = NULL;
+ }
+
+ if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn) {
+ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
+ hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn = NULL;
+ }
+
+ if (hNode->dcdProps.objData.nodeObj.pstrIAlgName) {
+ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
+ hNode->dcdProps.objData.nodeObj.pstrIAlgName = NULL;
+ }
+
+ /* Free all SM address translator resources */
+ if (hXlator) {
+ (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
+ hXlator = NULL;
+ }
+
+ if (hNode->hNldrNode) {
+ hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
+ hNode->hNldrNode = NULL;
+ }
+
+ MEM_FreeObject(hNode);
+ hNode = NULL;
+}
+
+/*
+ * ======== DeleteNodeMgr ========
+ * Purpose:
+ * Frees the node manager.
+ */
+static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
+{
+ struct NODE_OBJECT *hNode;
+
+ if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
+ /* Free resources */
+ if (hNodeMgr->hDcdMgr)
+ DCD_DestroyManager(hNodeMgr->hDcdMgr);
+
+ /* Remove any elements remaining in lists */
+ if (hNodeMgr->nodeList) {
+ while ((hNode =
+ (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
+ nodeList)))
+ DeleteNode(hNode);
+
+ DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
+ LST_Delete(hNodeMgr->nodeList);
+ }
+ if (hNodeMgr->hNtfy)
+ NTFY_Delete(hNodeMgr->hNtfy);
+
+ if (hNodeMgr->pipeMap)
+ GB_delete(hNodeMgr->pipeMap);
+
+ if (hNodeMgr->pipeDoneMap)
+ GB_delete(hNodeMgr->pipeDoneMap);
+
+ if (hNodeMgr->chnlMap)
+ GB_delete(hNodeMgr->chnlMap);
+
+ if (hNodeMgr->dmaChnlMap)
+ GB_delete(hNodeMgr->dmaChnlMap);
+
+ if (hNodeMgr->zChnlMap)
+ GB_delete(hNodeMgr->zChnlMap);
+
+ if (hNodeMgr->hDisp)
+ DISP_Delete(hNodeMgr->hDisp);
+
+ if (hNodeMgr->hSync)
+ SYNC_DeleteCS(hNodeMgr->hSync);
+
+ if (hNodeMgr->hStrmMgr)
+ STRM_Delete(hNodeMgr->hStrmMgr);
+
+ /* Delete the loader */
+ if (hNodeMgr->hNldr)
+ hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
+
+ if (hNodeMgr->fLoaderInit)
+ hNodeMgr->nldrFxns.pfnExit();
+
+ MEM_FreeObject(hNodeMgr);
+ }
+}
+
+/*
+ * ======== FillStreamConnect ========
+ * Purpose:
+ * Fills stream information.
+ */
+static void FillStreamConnect(struct NODE_OBJECT *hNode1,
+ struct NODE_OBJECT *hNode2,
+ u32 uStream1, u32 uStream2)
+{
+ u32 uStrmIndex;
+ struct DSP_STREAMCONNECT *pStrm1 = NULL;
+ struct DSP_STREAMCONNECT *pStrm2 = NULL;
+ enum NODE_TYPE node1Type = NODE_TASK;
+ enum NODE_TYPE node2Type = NODE_TASK;
+
+ node1Type = NODE_GetType(hNode1);
+ node2Type = NODE_GetType(hNode2);
+ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
+
+ if (node1Type != NODE_DEVICE) {
+ uStrmIndex = hNode1->uNumInputs +
+ hNode1->uNumOutputs - 1;
+ pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
+ pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
+ pStrm1->uThisNodeStreamIndex = uStream1;
+ }
+
+ if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
+ /* NODE == > NODE */
+ if (node1Type != NODE_DEVICE) {
+ pStrm1->hConnectedNode = hNode2;
+ pStrm1->uiConnectedNodeID = hNode2->nodeId;
+ pStrm1->uConnectedNodeStreamIndex = uStream2;
+ pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
+ }
+ if (node2Type != NODE_DEVICE) {
+ uStrmIndex = hNode2->uNumInputs +
+ hNode2->uNumOutputs - 1;
+ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
+ pStrm2->cbStruct =
+ sizeof(struct DSP_STREAMCONNECT);
+ pStrm2->uThisNodeStreamIndex = uStream2;
+ pStrm2->hConnectedNode = hNode1;
+ pStrm2->uiConnectedNodeID = hNode1->nodeId;
+ pStrm2->uConnectedNodeStreamIndex = uStream1;
+ pStrm2->lType = CONNECTTYPE_NODEINPUT;
+ }
+ } else if (node1Type != NODE_DEVICE)
+ pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
+ } else {
+ /* GPP == > NODE */
+ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
+ uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
+ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
+ pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
+ pStrm2->uThisNodeStreamIndex = uStream2;
+ pStrm2->lType = CONNECTTYPE_GPPINPUT;
+ }
+}
+
+/*
+ * ======== FillStreamDef ========
+ * Purpose:
+ * Fills Stream attributes.
+ */
+static void FillStreamDef(struct NODE_OBJECT *hNode,
+ struct NODE_STRMDEF *pstrmDef,
+ struct DSP_STRMATTR *pAttrs)
+{
+ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
+
+ if (pAttrs != NULL) {
+ pstrmDef->uNumBufs = pAttrs->uNumBufs;
+ pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
+ uDSPDataMauSize;
+ pstrmDef->uSegid = pAttrs->uSegid;
+ pstrmDef->uAlignment = pAttrs->uAlignment;
+ pstrmDef->uTimeout = pAttrs->uTimeout;
+ } else {
+ pstrmDef->uNumBufs = DEFAULTNBUFS;
+ pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
+ uDSPDataMauSize;
+ pstrmDef->uSegid = DEFAULTSEGID;
+ pstrmDef->uAlignment = DEFAULTALIGNMENT;
+ pstrmDef->uTimeout = DEFAULTTIMEOUT;
+ }
+}
+
+/*
+ * ======== FreeStream ========
+ * Purpose:
+ * Updates the channel mask and frees the pipe id.
+ */
+static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
+{
+ /* Free up the pipe id unless other node has not yet been deleted. */
+ if (stream.type == NODECONNECT) {
+ if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
+ /* The other node has already been deleted */
+ GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
+ GB_clear(hNodeMgr->pipeMap, stream.devId);
+ } else {
+ /* The other node has not been deleted yet */
+ GB_set(hNodeMgr->pipeDoneMap, stream.devId);
+ }
+ } else if (stream.type == HOSTCONNECT) {
+ if (stream.devId < hNodeMgr->ulNumChnls) {
+ GB_clear(hNodeMgr->chnlMap, stream.devId);
+ } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
+ /* dsp-dma */
+ GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
+ (1 * hNodeMgr->ulNumChnls));
+ } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
+ /* zero-copy */
+ GB_clear(hNodeMgr->zChnlMap, stream.devId -
+ (2 * hNodeMgr->ulNumChnls));
+ }
+ }
+}
+
+/*
+ * ======== GetFxnAddress ========
+ * Purpose:
+ * Retrieves the address for create, execute or delete phase for a node.
+ */
+static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
+ u32 uPhase)
+{
+ char *pstrFxnName = NULL;
+ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
+ DSP_STATUS status = DSP_SOK;
+ DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
+ NODE_GetType(hNode) == NODE_DAISSOCKET ||
+ NODE_GetType(hNode) == NODE_MESSAGE);
+
+ switch (uPhase) {
+ case CREATEPHASE:
+ pstrFxnName = hNode->dcdProps.objData.nodeObj.
+ pstrCreatePhaseFxn;
+ break;
+ case EXECUTEPHASE:
+ pstrFxnName = hNode->dcdProps.objData.nodeObj.
+ pstrExecutePhaseFxn;
+ break;
+ case DELETEPHASE:
+ pstrFxnName = hNode->dcdProps.objData.nodeObj.
+ pstrDeletePhaseFxn;
+ break;
+ default:
+ /* Should never get here */
+ DBC_Assert(false);
+ break;
+ }
+
+ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
+ pulFxnAddr);
+
+ return status;
+}
+
+/*
+ * ======== GetNodeInfo ========
+ * Purpose:
+ * Retrieves the node information.
+ */
+void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
+{
+ u32 i;
+
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ DBC_Require(pNodeInfo != NULL);
+
+ pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
+ pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
+ ndbProps;
+ pNodeInfo->uExecutionPriority = hNode->nPriority;
+ pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
+ pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
+ pNodeInfo->uNodeEnv = hNode->nodeEnv;
+
+ pNodeInfo->nsExecutionState = NODE_GetState(hNode);
+
+ /* Copy stream connect data */
+ for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
+ pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
+
+}
+
+/*
+ * ======== GetNodeProps ========
+ * Purpose:
+ * Retrieve node properties.
+ */
+static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
+ struct NODE_OBJECT *hNode,
+ CONST struct DSP_UUID *pNodeId,
+ struct DCD_GENERICOBJ *pdcdProps)
+{
+ u32 uLen;
+ struct NODE_MSGARGS *pMsgArgs;
+ struct NODE_TASKARGS *pTaskArgs;
+ enum NODE_TYPE nodeType = NODE_TASK;
+ struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
+ DSP_STATUS status = DSP_SOK;
+#ifdef DEBUG
+ char szUuid[MAXUUIDLEN];
+#endif
+
+ status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
+ DSP_DCDNODETYPE, pdcdProps);
+
+ if (DSP_SUCCEEDED(status)) {
+ hNode->nType = nodeType = pndbProps->uNodeType;
+
+#ifdef DEBUG
+ /* Create UUID value to set in registry. */
+ UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
+ MAXUUIDLEN);
+ DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
+#endif
+
+ /* Fill in message args that come from NDB */
+ if (nodeType != NODE_DEVICE) {
+ pMsgArgs = &(hNode->createArgs.asa.msgArgs);
+ pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
+ pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
+ uMsgNotifyType;
+ pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
+#ifdef DEBUG
+ DBG_Trace(DBG_LEVEL7,
+ "** (node) Max Number of Messages: 0x%x\n",
+ pMsgArgs->uMaxMessages);
+#endif
+ } else {
+ /* Copy device name */
+ DBC_Require(pndbProps->acName);
+ uLen = strlen(pndbProps->acName);
+ DBC_Assert(uLen < MAXDEVNAMELEN);
+ hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
+ if (hNode->pstrDevName == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ strncpy(hNode->pstrDevName,
+ pndbProps->acName, uLen);
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in create args that come from NDB */
+ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
+ pTaskArgs = &(hNode->createArgs.asa.taskArgs);
+ pTaskArgs->nPriority = pndbProps->iPriority;
+ pTaskArgs->uStackSize = pndbProps->uStackSize;
+ pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
+ pTaskArgs->uStackSeg = pndbProps->uStackSeg;
+#ifdef DEBUG
+ DBG_Trace(DBG_LEVEL7,
+ "** (node) Priority: 0x%x\n" "** (node) Stack"
+ " Size: 0x%x words\n" "** (node) System Stack"
+ " Size: 0x%x words\n" "** (node) Stack"
+ " Segment: 0x%x\n\n",
+ "** (node) profile count : 0x%x \n \n",
+ pTaskArgs->nPriority, pTaskArgs->uStackSize,
+ pTaskArgs->uSysStackSize,
+ pTaskArgs->uStackSeg,
+ pndbProps->uCountProfiles);
+#endif
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== GetProcProps ========
+ * Purpose:
+ * Retrieve the processor properties.
+ */
+static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
+ struct DEV_OBJECT *hDevObject)
+{
+ struct CFG_DEVNODE *hDevNode;
+ struct CFG_HOSTRES hostRes;
+ DSP_STATUS status = DSP_SOK;
+
+ status = DEV_GetDevNode(hDevObject, &hDevNode);
+ if (DSP_SUCCEEDED(status))
+ status = CFG_GetHostResources(hDevNode, &hostRes);
+
+ if (DSP_SUCCEEDED(status)) {
+ hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
+ hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
+ hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
+
+ /*
+ * PROC will add an API to get DSP_PROCESSORINFO.
+ * Fill in default values for now.
+ */
+ /* TODO -- Instead of hard coding, take from registry */
+ hNodeMgr->procFamily = 6000;
+ hNodeMgr->procType = 6410;
+ hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
+ hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
+ hNodeMgr->uDSPWordSize = DSPWORDSIZE;
+ hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
+ hNodeMgr->uDSPMauSize = 1;
+
+ }
+ return status;
+}
+
+
+
+/*
+ * ======== NODE_GetUUIDProps ========
+ * Purpose:
+ * Fetch Node UUID properties from DCD/DOF file.
+ */
+DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
+ IN CONST struct DSP_UUID *pNodeId,
+ OUT struct DSP_NDBPROPS *pNodeProps)
+{
+ struct NODE_MGR *hNodeMgr = NULL;
+ struct DEV_OBJECT *hDevObject;
+ DSP_STATUS status = DSP_SOK;
+ struct DCD_NODEPROPS dcdNodeProps;
+ struct DSP_PROCESSORSTATE procStatus;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hProcessor != NULL);
+ DBC_Require(pNodeId != NULL);
+
+ if (hProcessor == NULL || pNodeId == NULL) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ status = PROC_GetState(hProcessor, &procStatus,
+ sizeof(struct DSP_PROCESSORSTATE));
+ if (DSP_FAILED(status))
+ goto func_end;
+ /* If processor is in error state then don't attempt
+ to send the message */
+ if (procStatus.iState == PROC_ERROR) {
+ GT_1trace(NODE_debugMask, GT_5CLASS,
+ "NODE_GetUUIDProps: proc Status 0x%x\n",
+ procStatus.iState);
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+
+ GT_3trace(NODE_debugMask, GT_ENTER,
+ "NODE_GetUUIDProps: " "\thProcessor: "
+ "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
+ pNodeId, pNodeProps);
+
+ status = PROC_GetDevObject(hProcessor, &hDevObject);
+ if (DSP_SUCCEEDED(status) && hDevObject != NULL) {
+ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
+ if (hNodeMgr == NULL) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ }
+
+ /*
+ * Enter the critical section. This is needed because
+ * DCD_GetObjectDef will ultimately end up calling DBLL_open/close,
+ * which needs to be protected in order to not corrupt the zlib manager
+ * (COD).
+ */
+ status = SYNC_EnterCS(hNodeMgr->hSync);
+
+ if (DSP_SUCCEEDED(status)) {
+ dcdNodeProps.pstrCreatePhaseFxn = NULL;
+ dcdNodeProps.pstrExecutePhaseFxn = NULL;
+ dcdNodeProps.pstrDeletePhaseFxn = NULL;
+ dcdNodeProps.pstrIAlgName = NULL;
+
+ status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
+ (struct DSP_UUID *) pNodeId,
+ DSP_DCDNODETYPE,
+ (struct DCD_GENERICOBJ *) &dcdNodeProps);
+ if (DSP_SUCCEEDED(status)) {
+ *pNodeProps = dcdNodeProps.ndbProps;
+ if (dcdNodeProps.pstrCreatePhaseFxn)
+ MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
+
+ if (dcdNodeProps.pstrExecutePhaseFxn)
+ MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
+
+ if (dcdNodeProps.pstrDeletePhaseFxn)
+ MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
+
+ if (dcdNodeProps.pstrIAlgName)
+ MEM_Free(dcdNodeProps.pstrIAlgName);
+ }
+ /* Leave the critical section, we're done. */
+ (void)SYNC_LeaveCS(hNodeMgr->hSync);
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== GetRMSFxns ========
+ * Purpose:
+ * Retrieve the RMS functions.
+ */
+static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
+{
+ s32 i;
+ struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
+ DSP_STATUS status = DSP_SOK;
+
+ static char *pszFxns[NUMRMSFXNS] = {
+ "RMS_queryServer", /* RMSQUERYSERVER */
+ "RMS_configureServer", /* RMSCONFIGURESERVER */
+ "RMS_createNode", /* RMSCREATENODE */
+ "RMS_executeNode", /* RMSEXECUTENODE */
+ "RMS_deleteNode", /* RMSDELETENODE */
+ "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
+ "RMS_readMemory", /* RMSREADMEMORY */
+ "RMS_writeMemory", /* RMSWRITEMEMORY */
+ "RMS_copy", /* RMSCOPY */
+ };
+
+ for (i = 0; i < NUMRMSFXNS; i++) {
+ status = DEV_GetSymbol(hDev, pszFxns[i],
+ &(hNodeMgr->ulFxnAddrs[i]));
+ if (DSP_FAILED(status)) {
+ if (status == COD_E_SYMBOLNOTFOUND) {
+ /*
+ * May be loaded dynamically (in the future),
+ * but return an error for now.
+ */
+ GT_1trace(NODE_debugMask, GT_6CLASS,
+ "RMS function: %s "
+ "currently not loaded\n", pszFxns[i]);
+ } else {
+ GT_2trace(NODE_debugMask, GT_6CLASS,
+ "GetRMSFxns: Symbol not "
+ "found: %s\tstatus = 0x%x\n",
+ pszFxns[i], status);
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/*
+ * ======== Ovly ========
+ * Purpose:
+ * Called during overlay.Sends command to RMS to copy a block of data.
+ */
+static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
+ u32 ulNumBytes, u32 nMemSpace)
+{
+ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
+ struct NODE_MGR *hNodeMgr;
+ u32 ulBytes = 0;
+ u32 ulSize;
+ u32 ulTimeout;
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *hWmdContext;
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+
+ hNodeMgr = hNode->hNodeMgr;
+
+ ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
+ ulTimeout = hNode->uTimeout;
+
+ /* Call new MemCopy function */
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
+ status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
+ ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
+
+ if (DSP_SUCCEEDED(status))
+ ulBytes = ulNumBytes;
+
+ return ulBytes;
+}
+
+/*
+ * ======== Write ========
+ */
+static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
+ u32 ulNumBytes, u32 nMemSpace)
+{
+ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
+ struct NODE_MGR *hNodeMgr;
+ u16 memType;
+ u32 ulTimeout;
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *hWmdContext;
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+
+ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+ DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
+
+ hNodeMgr = hNode->hNodeMgr;
+
+ ulTimeout = hNode->uTimeout;
+ memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
+
+ /* Call new MemWrite function */
+ pIntfFxns = hNodeMgr->pIntfFxns;
+ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
+ status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
+ ulNumBytes, memType);
+
+ return ulNumBytes;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
new file mode 100755
index 000000000000..34d29696a6b2
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/proc.c
@@ -0,0 +1,2111 @@
+/*
+ * proc.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== proc.c ========
+ * Description:
+ * Processor interface at the driver level.
+ *
+ * Public Functions:
+ * PROC_Attach
+ * PROC_Ctrl
+ * PROC_Detach
+ * PROC_EnumNodes
+ * PROC_GetResourceInfo
+ * PROC_Exit
+ * PROC_FlushMemory
+ * PROC_GetState
+ * PROC_GetProcessorId
+ * PROC_GetTrace
+ * PROC_Init
+ * PROC_Load
+ * PROC_Map
+ * PROC_NotifyClients
+ * PROC_RegisterNotify
+ * PROC_ReserveMemory
+ * PROC_Start
+ * PROC_UnMap
+ * PROC_UnReserveMemory
+ * PROC_InvalidateMemory
+
+ *! Revision History
+ *! ======== ========
+ *! 04-Apr-2007 sh Added PROC_InvalidateMemory API
+ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
+ *! Used MEM_FlushCache instead of OS specific API
+ *! Integrated Alan's code review updates
+ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
+ *! 08-Mar-2004 vp Added g_pszLastCoff member to PROC_OBJECT.
+ *! This is required for multiprocessor environment.
+ *! 09-Feb-2004 vp Added PROC_GetProcessorID function
+ *! 22-Apr-2003 vp Fixed issue with the string that stores coff file name
+ *! 03-Apr-2003 sb Fix DEH deregistering bug
+ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in PROC_Start function.
+ *! 18-Feb-2003 vp Code review updates.
+ *! 18-Oct-2002 vp Ported to Linux platform.
+ *! 22-May-2002 sg Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
+ *! 14-May-2002 sg Use CSL_Atoi() instead of atoi().
+ *! 13-May-2002 sg Propagate PWR return codes upwards.
+ *! 07-May-2002 sg Added check for, and call to PWR functions in PROC_Ctrl.
+ *! 02-May-2002 sg Added "nap" mode: put DSP to sleep once booted.
+ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
+ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
+ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
+ *! DEH module.
+ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
+ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
+ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
+ *! to facilitate the external loading.
+ *! 14-Aug-2001 ag DCD_AutoRegister() now called before IOOnLoaded() fxn.
+ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
+ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
+ *! error other than E_NOTIMPL.
+ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
+ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
+ *! if DEV_Create2 fails; ie, no non-RMS targets can be
+ *! loaded.
+ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
+ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
+ *! 29-Nov-2000 rr: Incorporated code review changes.
+ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
+ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
+ *! WMD_BRD_STOP is always followed by DEV_Destroy2.
+ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
+ *! different way.
+ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
+ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
+ *! WMD fxns are checked for WSX_STATUS.
+ *! PROC_Attach does not alter the state of the BRD.
+ *! PROC_Run removed.
+ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
+ *! invalid
+ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
+ *! ver 0.8 API.
+ *! 06-Jul-2000 rr: Created.
+ */
+
+/* ------------------------------------ Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/sync.h>
+/* ----------------------------------- Mini Driver */
+#include <dspbridge/wmd.h>
+#include <dspbridge/wmddeh.h>
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/cod.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/procpriv.h>
+#include <dspbridge/dmm.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/mgr.h>
+#include <dspbridge/node.h>
+#include <dspbridge/nldr.h>
+#include <dspbridge/rmm.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbdcd.h>
+#include <dspbridge/dbreg.h>
+#include <dspbridge/msg.h>
+#include <dspbridge/wmdioctl.h>
+#include <dspbridge/drv.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/proc.h>
+#include <dspbridge/pwr.h>
+#ifdef CONFIG_PM
+#include <mach-omap2/omap3-opp.h>
+#endif
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/resourcecleanup.h>
+#endif
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define PROC_SIGNATURE 0x434F5250 /* "PROC" (in reverse). */
+#define MAXCMDLINELEN 255
+#define PROC_ENVPROCID "PROC_ID=%d"
+#define MAXPROCIDLEN (8 + 5)
+#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
+#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
+#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
+
+#ifdef OMAP44XX
+/* Start address of memory for dynamic mapping */
+const u32 DEXTMEMMAP_BEG = 0x30000000 ;
+
+/* End address of memory for dynamic mapping */
+
+const u32 DEXTMEMMAP_END = 0x40000000 ;
+#endif
+
+extern char *iva_img;
+
+/* The PROC_OBJECT structure. */
+struct PROC_OBJECT {
+ struct LST_ELEM link; /* Link to next PROC_OBJECT */
+ u32 dwSignature; /* Used for object validation */
+ struct DEV_OBJECT *hDevObject; /* Device this PROC represents */
+ u32 hProcess; /* Process owning this Processor */
+ struct MGR_OBJECT *hMgrObject; /* Manager Object Handle */
+ u32 uAttachCount; /* Processor attach count */
+ u32 uProcessor; /* Processor number */
+ u32 uTimeout; /* Time out count */
+ enum DSP_PROCSTATE sState; /* Processor state */
+ u32 ulUnit; /* DDSP unit number */
+ bool bIsAlreadyAttached; /*
+ * True if the Device below has
+ * GPP Client attached
+ */
+ struct NTFY_OBJECT *hNtfy; /* Manages notifications */
+ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+ char *g_pszLastCoff;
+} ;
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask PROC_DebugMask = { NULL, NULL }; /* WCD MGR Mask */
+#endif
+
+static u32 cRefs;
+
+struct SYNC_CSOBJECT *hProcLock; /* For critical sections */
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#ifdef status = DSP_EFAILo CONFIG_OMAP3_PM
+extern struct constraint_handle *mpu_constraint_handle;
+#endif
+#endif
+#endif
+
+
+/* ----------------------------------- Function Prototypes */
+static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
+static s32 GetEnvpCount(char **envp);
+static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
+ char *szVar);
+
+/*
+ * ======== PROC_CleanupAllResources =====
+ * Purpose:
+ * Funtion to clean the process resources.
+ * This function is intended to be called when the
+ * processor is in error state
+ */
+DSP_STATUS PROC_CleanupAllResources(void)
+{
+ DSP_STATUS dsp_status = DSP_SOK;
+ HANDLE hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
+ GT_0trace(PROC_DebugMask, GT_ENTER, "PROC_CleanupAllResources\n");
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(dsp_status))
+ goto func_end;
+ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
+ while (pCtxtclosed != NULL) {
+ if (current->pid != pCtxtclosed->pid) {
+ GT_1trace(PROC_DebugMask, GT_5CLASS,
+ "***Cleanup of "
+ "process***%d\n", pCtxtclosed->pid);
+ if (pCtxtclosed->hProcessor)
+ PROC_Detach(pCtxtclosed->hProcessor);
+ }
+ pCtxtclosed = pCtxtclosed->next;
+ }
+ WMD_DEH_ReleaseDummyMem();
+func_end:
+ return dsp_status;
+}
+
+/*
+ * ======== PROC_Attach ========
+ * Purpose:
+ * Prepare for communication with a particular DSP processor, and return
+ * a handle to the processor object.
+ */
+DSP_STATUS
+PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
+ OUT DSP_HPROCESSOR *phProcessor)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEV_OBJECT *hDevObject;
+ struct PROC_OBJECT *pProcObject = NULL;
+ struct MGR_OBJECT *hMgrObject = NULL;
+ struct DRV_OBJECT *hDrvObject = NULL;
+ u32 devType;
+
+#ifndef RES_CLEANUP_DISABLE
+ HANDLE hDRVObject;
+ u32 hProcess;
+ DSP_STATUS res_status = DSP_SOK;
+ struct PROCESS_CONTEXT *pPctxt = NULL;
+#endif
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phProcessor != NULL);
+
+ GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
+ "uProcessor: 0x%x\n\tpAttrIn: 0x%x\n\tphProcessor:"
+ "0x%x\n", uProcessor, pAttrIn, phProcessor);
+ /* Get the Driver and Manager Object Handles */
+ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(status)) {
+ status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
+ if (DSP_FAILED(status)) {
+ /* don't propogate CFG errors from this PROC function */
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: DSP_FAILED to get"
+ "the Manager Object.\n", status);
+ }
+ } else {
+ /* don't propogate CFG errors from this PROC function */
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: failed to get the"
+ " DriverObject, 0x%x!\n", status);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get the Device Object */
+ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: failed to get"
+ " DevObject, 0x%x!\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetDevType(hDevObject, &devType);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: failed to get"
+ " DevType, 0x%x!\n", status);
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* If we made it this far, create the Proceesor object: */
+ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
+ /* Fill out the Processor Object: */
+ if (pProcObject == NULL) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach:Out of memeory \n");
+ status = DSP_EFAIL;
+ goto func_end;
+ }
+ pProcObject->hDevObject = hDevObject;
+ pProcObject->hMgrObject = hMgrObject;
+ pProcObject->uProcessor = devType;
+ /* Get Caller Process and store it */
+ /* Return PID instead of process handle */
+ pProcObject->hProcess = current->pid;
+
+ if (pAttrIn)
+ pProcObject->uTimeout = pAttrIn->uTimeout;
+ else
+ pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
+
+ status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetWMDContext(hDevObject,
+ &pProcObject->hWmdContext);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach Could not"
+ " get the WMD Context.\n", status);
+ MEM_FreeObject(pProcObject);
+ }
+ } else {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach Could not get"
+ " the DEV_ Interface fxns.\n", status);
+ MEM_FreeObject(pProcObject);
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Create the Notification Object */
+ /* This is created with no event mask, no notify mask
+ * and no valid handle to the notification. They all get
+ * filled up when PROC_RegisterNotify is called */
+ status = NTFY_Create(&pProcObject->hNtfy);
+ if (DSP_SUCCEEDED(status)) {
+ /* Insert the Processor Object into the DEV List.
+ * Return handle to this Processor Object:
+ * Find out if the Device is already attached to a
+ * Processor. If so, return AlreadyAttached status */
+ LST_InitElem(&pProcObject->link);
+ status = DEV_InsertProcObject(pProcObject->hDevObject,
+ (u32)pProcObject,
+ &pProcObject->bIsAlreadyAttached);
+ if (DSP_SUCCEEDED(status)) {
+ if (pProcObject->bIsAlreadyAttached) {
+ status = DSP_SALREADYATTACHED;
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Attach: Processor "
+ "Already Attached!\n");
+ }
+ } else {
+ if (pProcObject->hNtfy)
+ NTFY_Delete(pProcObject->hNtfy);
+
+ MEM_FreeObject(pProcObject);
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: failed to insert "
+ "Proc Object into DEV, 0x%x!\n", status);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ *phProcessor = (DSP_HPROCESSOR)pProcObject;
+ (void)PROC_NotifyClients(pProcObject,
+ DSP_PROCESSORATTACH);
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Attach: Processor "
+ "Attach Success!\n");
+ }
+ } else {
+ /* Don't leak memory if DSP_FAILED */
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Attach: Could not allocate "
+ "storage for notification \n");
+ MEM_FreeObject(pProcObject);
+ }
+func_end:
+#ifndef RES_CLEANUP_DISABLE
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(res_status))
+ goto func_cont;
+
+ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDRVObject,
+ &pPctxt, NULL, 0);
+ if (pPctxt == NULL) {
+ DRV_InsertProcContext((struct DRV_OBJECT *)hDRVObject, &pPctxt);
+ if (pPctxt != NULL) {
+ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
+ DRV_ProcSetPID(pPctxt, hProcess);
+ }
+ }
+func_cont:
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
+ NULL, 0);
+ if (pPctxt != NULL)
+ pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
+
+ }
+#endif
+ DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
+ (DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
+ (status == DSP_SALREADYATTACHED &&
+ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
+ GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
+ "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
+
+ return status;
+}
+
+static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
+ struct DEV_OBJECT *hDevObject,
+ u32 size, char *execFile)
+{
+ s32 devType;
+ s32 len;
+
+ DEV_GetDevType(hDevObject, (u32 *) &devType);
+ if (devType == DSP_UNIT) {
+ return CFG_GetExecFile(hDevNode, size, execFile);
+ } else if (devType == IVA_UNIT) {
+ if (iva_img) {
+ len = strlen(iva_img);
+ strncpy(execFile, iva_img, len + 1);
+ return DSP_SOK;
+ }
+ }
+ return DSP_EFILE;
+}
+
+/*
+ * ======== PROC_AutoStart ======== =
+ * Purpose:
+ * A Particular device gets loaded with the default image
+ * if the AutoStart flag is set.
+ * Parameters:
+ * hDevObject: Handle to the Device
+ * Returns:
+ * DSP_SOK: On Successful Loading
+ * DSP_EFAIL General Failure
+ * Requires:
+ * hDevObject != NULL
+ * Ensures:
+ */
+DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
+ struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ u32 dwAutoStart = 0; /* autostart flag */
+ struct PROC_OBJECT *pProcObject;
+ struct PROC_OBJECT *hProcObject;
+ char szExecFile[MAXCMDLINELEN];
+ char *argv[2];
+ struct MGR_OBJECT *hMgrObject = NULL;
+ s32 devType;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hDevNode != NULL);
+ DBC_Require(hDevObject != NULL);
+
+ GT_2trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_AutoStart, args:\n\t"
+ "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
+ /* Create a Dummy PROC Object */
+ if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
+ REG_MGR_OBJECT))) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: DSP_FAILED to "
+ "Get MGR Object\n");
+ goto func_end;
+ }
+ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
+ if (pProcObject == NULL) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: DSP_FAILED "
+ "to Create a dummy Processor\n");
+ goto func_end;
+ }
+ GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
+ pProcObject->hDevObject = hDevObject;
+ pProcObject->hMgrObject = hMgrObject;
+ hProcObject = pProcObject;
+ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+ &pProcObject->pIntfFxns))) {
+ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+ &pProcObject->hWmdContext))) {
+ status = DSP_SOK;
+ } else {
+ MEM_FreeObject(hProcObject);
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: Failed "
+ "to get WMD Context \n");
+ }
+ } else {
+ MEM_FreeObject(hProcObject);
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: Failed to "
+ "get IntFxns \n");
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Stop the Device, put it into standby mode */
+ status = PROC_Stop(hProcObject);
+ if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
+ !dwAutoStart) {
+ status = DSP_EFAIL;
+ /* DSP_FAILED to Get s32 Fxn or Wmd Context */
+ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
+ "CFG_GetAutoStart DSP_FAILED \n");
+ goto func_cont;
+ }
+ /* Get the default executable for this board... */
+ DEV_GetDevType(hDevObject, (u32 *)&devType);
+ pProcObject->uProcessor = devType;
+ if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
+ sizeof(szExecFile), szExecFile))) {
+ argv[0] = szExecFile;
+ argv[1] = NULL;
+ /* ...and try to load it: */
+ status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_Start(hProcObject);
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_AutoStart: Processor started "
+ "running\n");
+ } else {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: DSP_FAILED To "
+ "Start \n");
+ }
+ } else {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_AutoStart: DSP_FAILED to Load\n");
+ }
+ } else {
+ status = DSP_EFILE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
+ "No Exec file found \n");
+ }
+func_cont:
+ MEM_FreeObject(hProcObject);
+func_end:
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Exiting PROC_AutoStart, status:0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== PROC_Ctrl ========
+ * Purpose:
+ * Pass control information to the GPP device driver managing the
+ * DSP processor.
+ *
+ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
+ * application developer's API.
+ * Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
+ * Operation. arg can be null.
+ */
+DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
+ IN struct DSP_CBDATA *arg)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = hProcessor;
+ u32 timeout = 0;
+
+ DBC_Require(cRefs > 0);
+ GT_3trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_Ctrl, args:\n\thProcessor:"
+ " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
+
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ /* intercept PWR deep sleep command */
+ if (dwCmd == WMDIOCTL_DEEPSLEEP) {
+ timeout = arg->cbData;
+ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
+ }
+ /* intercept PWR emergency sleep command */
+ else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
+ timeout = arg->cbData;
+ status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
+ } else if (dwCmd == PWR_DEEPSLEEP) {
+ /* timeout = arg->cbData; */
+ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
+ }
+ /* intercept PWR wake commands */
+ else if (dwCmd == WMDIOCTL_WAKEUP) {
+ timeout = arg->cbData;
+ status = PWR_WakeDSP(timeout);
+ } else if (dwCmd == PWR_WAKEUP) {
+ /* timeout = arg->cbData; */
+ status = PWR_WakeDSP(timeout);
+ } else
+ if (DSP_SUCCEEDED
+ ((*pProcObject->pIntfFxns->pfnDevCntrl)
+ (pProcObject->hWmdContext, dwCmd, arg))) {
+ status = DSP_SOK;
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Ctrl: Failed \n");
+ }
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Ctrl: InValid Processor Handle \n");
+ }
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== PROC_Detach ========
+ * Purpose:
+ * Destroys the Processor Object. Removes the notification from the Dev
+ * List.
+ */
+DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+#ifndef RES_CLEANUP_DISABLE
+ HANDLE hDRVObject;
+ u32 hProcess;
+ DSP_STATUS res_status = DSP_SOK;
+ struct PROCESS_CONTEXT *pPctxt = NULL;
+#endif
+ DBC_Require(cRefs > 0);
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
+ "hProcessor: 0x%x\n", hProcessor);
+
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+#ifndef RES_CLEANUP_DISABLE
+ /* Return PID instead of process handle */
+ hProcess = pProcObject->hProcess;
+ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
+ NULL, 0);
+ if (pPctxt != NULL) {
+ DRV_RemoveAllResources(pPctxt);
+ pPctxt->hProcessor = NULL;
+ }
+ }
+#endif
+ /* Notify the Client */
+ NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
+ /* Remove the notification memory */
+ if (pProcObject->hNtfy)
+ NTFY_Delete(pProcObject->hNtfy);
+
+ if (pProcObject->g_pszLastCoff) {
+ MEM_Free(pProcObject->g_pszLastCoff);
+ pProcObject->g_pszLastCoff = NULL;
+ }
+ /* Remove the Proc from the DEV List */
+ (void)DEV_RemoveProcObject(pProcObject->hDevObject,
+ (u32)pProcObject);
+ /* Free the Processor Object */
+ MEM_FreeObject(pProcObject);
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Detach: InValid Processor Handle \n");
+ }
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== PROC_EnumNodes ========
+ * Purpose:
+ * Enumerate and get configuration information about nodes allocated
+ * on a DSP processor.
+ */
+DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
+ IN u32 uNodeTabSize, OUT u32 *puNumNodes,
+ OUT u32 *puAllocated)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct NODE_MGR *hNodeMgr = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
+ DBC_Require(puNumNodes != NULL);
+ DBC_Require(puAllocated != NULL);
+
+ GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
+ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
+ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
+ hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
+ puAllocated);
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
+ &hNodeMgr))) {
+ if (hNodeMgr) {
+ status = NODE_EnumNodes(hNodeMgr, aNodeTab,
+ uNodeTabSize,
+ puNumNodes,
+ puAllocated);
+ }
+ }
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
+ "InValid Processor Handle \n");
+ }
+ GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
+ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
+ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
+ "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
+ puNumNodes, puAllocated, status);
+
+ return status;
+}
+
+/*
+ * ======== PROC_FlushMemory ========
+ * Purpose:
+ * Flush cache
+ */
+DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
+ u32 ulSize, u32 ulFlags)
+{
+ /* Keep STATUS here for future additions to this function */
+ DSP_STATUS status = DSP_SOK;
+ enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ DBC_Require(cRefs > 0);
+
+ GT_4trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_FlushMemory, args:\n\t"
+ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
+ hProcessor, pMpuAddr, ulSize, ulFlags);
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ /* Critical section */
+ (void)SYNC_EnterCS(hProcLock);
+ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
+ (void)SYNC_LeaveCS(hProcLock);
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_FlushMemory: "
+ "InValid Processor Handle \n");
+ }
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
+ status);
+ return status;
+}
+
+
+/*
+ * ======== PROC_InvalidateMemory ========
+ * Purpose:
+ * Invalidates the memory specified
+ */
+DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
+ u32 ulSize)
+{
+ /* Keep STATUS here for future additions to this function */
+ DSP_STATUS status = DSP_SOK;
+ enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ DBC_Require(cRefs > 0);
+ GT_3trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_InvalidateMemory, args:\n\t"
+ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
+ pMpuAddr, ulSize);
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ (void)SYNC_EnterCS(hProcLock);
+ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
+ (void)SYNC_LeaveCS(hProcLock);
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_InvalidateMemory: "
+ "InValid Processor Handle \n");
+ }
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Leaving PROC_InvalidateMemory [0x%x]", status);
+ return status;
+}
+
+/*
+ * ======== PROC_GetResourceInfo ========
+ * Purpose:
+ * Enumerate the resources currently available on a processor.
+ */
+DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
+ OUT struct DSP_RESOURCEINFO *pResourceInfo,
+ u32 uResourceInfoSize)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct NODE_MGR *hNodeMgr = NULL;
+ struct NLDR_OBJECT *hNldr = NULL;
+ struct RMM_TargetObj *rmm = NULL;
+ struct IO_MGR *hIOMgr = NULL; /* IO manager handle */
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pResourceInfo != NULL);
+ DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
+
+ GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
+ "hProcessor: 0x%x\n\tuResourceType: 0x%x\n\tpResourceInfo:"
+ " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
+ uResourceType, pResourceInfo, uResourceInfoSize);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_GetResourceInfo: InValid "
+ "Processor Handle \n");
+ goto func_end;
+ }
+ switch (uResourceType) {
+ case DSP_RESOURCE_DYNDARAM:
+ case DSP_RESOURCE_DYNSARAM:
+ case DSP_RESOURCE_DYNEXTERNAL:
+ case DSP_RESOURCE_DYNSRAM:
+ if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
+ &hNodeMgr)))
+ goto func_end;
+
+ if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
+ if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
+ DBC_Assert(rmm != NULL);
+ status = DSP_EVALUE;
+ if (RMM_stat(rmm,
+ (enum DSP_MEMTYPE)uResourceType,
+ (struct DSP_MEMSTAT *)&(pResourceInfo->
+ result.memStat)))
+ status = DSP_SOK;
+ }
+ }
+ break;
+ case DSP_RESOURCE_PROCLOAD:
+ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
+ status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
+ (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
+ result.procLoadStat));
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "Error in procLoadStat function 0x%x\n", status);
+ }
+ break;
+ default:
+ status = DSP_EFAIL;
+ break;
+ }
+func_end:
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
+ "status 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== PROC_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count is
+ * 0.
+ */
+void PROC_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ if (hProcLock)
+ (void)SYNC_DeleteCS(hProcLock);
+
+ cRefs--;
+
+ GT_1trace(PROC_DebugMask, GT_5CLASS,
+ "Entered PROC_Exit, ref count:0x%x\n", cRefs);
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== PROC_GetDevObject ========
+ * Purpose:
+ * Return the Dev Object handle for a given Processor.
+ *
+ */
+DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
+ struct DEV_OBJECT **phDevObject)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phDevObject != NULL);
+
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ *phDevObject = pProcObject->hDevObject;
+ status = DSP_SOK;
+ } else {
+ *phDevObject = NULL;
+ status = DSP_EHANDLE;
+ }
+
+ DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject != NULL) ||
+ (DSP_FAILED(status) && *phDevObject == NULL));
+
+ return status;
+}
+
+/*
+ * ======== PROC_GetState ========
+ * Purpose:
+ * Report the state of the specified DSP processor.
+ */
+DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
+ OUT struct DSP_PROCESSORSTATE *pProcStatus,
+ u32 uStateInfoSize)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ BRD_STATUS brdStatus;
+ struct DEH_MGR *hDehMgr;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pProcStatus != NULL);
+ DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
+
+ GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
+ "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
+ " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ /* First, retrieve BRD state information */
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+ (pProcObject->hWmdContext, &brdStatus))) {
+ switch (brdStatus) {
+ case BRD_STOPPED:
+ pProcStatus->iState = PROC_STOPPED;
+ break;
+ case BRD_DSP_HIBERNATION:
+ /* Fall through */
+ case BRD_RUNNING:
+ pProcStatus->iState = PROC_RUNNING;
+ break;
+ case BRD_LOADED:
+ pProcStatus->iState = PROC_LOADED;
+ break;
+ case BRD_ERROR:
+ pProcStatus->iState = PROC_ERROR;
+ break;
+ default:
+ pProcStatus->iState = 0xFF;
+ status = DSP_EFAIL;
+ break;
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_GetState: General Failure"
+ " to read the PROC Status \n");
+ }
+ /* Next, retrieve error information, if any */
+ status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
+ if (DSP_SUCCEEDED(status) && hDehMgr) {
+ status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
+ (hDehMgr, &(pProcStatus->errInfo));
+ if (DSP_FAILED(status)) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_GetState: Failed "
+ "retrieve exception info.\n");
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_GetState: Failed to "
+ "retrieve DEH handle.\n");
+ }
+ } else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_GetState:InValid Processor Handle \n");
+ }
+ GT_2trace(PROC_DebugMask, GT_ENTER,
+ "Exiting PROC_GetState, results:\n\t"
+ "status: 0x%x\n\tpProcStatus: 0x%x\n", status,
+ pProcStatus->iState);
+ return status;
+}
+
+/*
+ * ======== PROC_GetTrace ========
+ * Purpose:
+ * Retrieve the current contents of the trace buffer, located on the
+ * Processor. Predefined symbols for the trace buffer must have been
+ * configured into the DSP executable.
+ * Details:
+ * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
+ * trace buffer, only. Treat it as an undocumented feature.
+ * This call is destructive, meaning the processor is placed in the monitor
+ * state as a result of this function.
+ */
+DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
+{
+ DSP_STATUS status;
+ status = DSP_ENOTIMPL;
+ return status;
+}
+
+/*
+ * ======== PROC_Init ========
+ * Purpose:
+ * Initialize PROC's private state, keeping a reference count on each call
+ */
+bool PROC_Init(void)
+{
+ bool fRetval = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ /* Set the Trace mask */
+ DBC_Assert(!PROC_DebugMask.flags);
+ GT_create(&PROC_DebugMask, "PR"); /* "PR" for Processor */
+
+ (void)SYNC_InitializeCS(&hProcLock);
+ }
+
+ if (fRetval)
+ cRefs++;
+
+ GT_1trace(PROC_DebugMask, GT_5CLASS,
+ "Entered PROC_Init, ref count:0x%x\n", cRefs);
+ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+ return fRetval;
+}
+
+/*
+ * ======== PROC_Load ========
+ * Purpose:
+ * Reset a processor and load a new base program image.
+ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
+ * application developer's API.
+ */
+DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
+ IN CONST char **aArgv, IN CONST char **aEnvp)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct IO_MGR *hIOMgr; /* IO manager handle */
+ struct MSG_MGR *hMsgMgr;
+ struct COD_MANAGER *hCodMgr; /* Code manager handle */
+ char *pargv0; /* temp argv[0] ptr */
+ char **newEnvp; /* Updated envp[] array. */
+ char szProcID[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
+ s32 cEnvp; /* Num elements in envp[]. */
+ s32 cNewEnvp; /* " " in newEnvp[] */
+ s32 nProcID = 0; /* Anticipate MP version. */
+ struct DCD_MANAGER *hDCDHandle;
+ struct DMM_OBJECT *hDmmMgr;
+
+#ifdef OMAP_3430
+ u32 dwExtEnd;
+#endif
+ u32 uProcId;
+
+#ifdef OMAP44XX
+ u32 dwDmmStart;
+#endif
+
+#ifdef DEBUG
+ BRD_STATUS uBrdState;
+#endif
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+ struct timeval tv1;
+ struct timeval tv2;
+#endif
+ DBC_Require(cRefs > 0);
+ DBC_Require(iArgc > 0);
+ DBC_Require(aArgv != NULL);
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+ do_gettimeofday(&tv1);
+#endif
+
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+#endif
+ GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
+ "hProcessor: 0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
+ /* Call the WMD_BRD_Load Fxn */
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Load: Invalid Processor Handle..\n");
+ goto func_end;
+ }
+ if (pProcObject->bIsAlreadyAttached) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load GPP "
+ "Client is already attached status \n");
+ }
+ if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
+ status = DSP_EFAIL;
+ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
+ "DEV_GetCodMgr status 0x%x \n", status);
+ goto func_end;
+ }
+ status = PROC_Stop(hProcessor);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: DSP_FAILED to Place the"
+ " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
+ status);
+ goto func_end;
+ }
+ /* Place the board in the monitor state. */
+ status = PROC_Monitor(hProcessor);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: DSP_FAILED to Place the"
+ " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
+ status);
+ goto func_end;
+ }
+ /* Save ptr to original argv[0]. */
+ pargv0 = (char *)aArgv[0];
+ /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
+ cEnvp = GetEnvpCount((char **)aEnvp);
+ cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
+ newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
+ if (newEnvp) {
+ status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
+ nProcID);
+ if (status == -1) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
+ "Proc ID string overflow \n");
+ status = DSP_EFAIL;
+ } else {
+ newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
+ cNewEnvp, szProcID);
+ /* Get the DCD Handle */
+ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
+ (u32 *)&hDCDHandle);
+ if (DSP_SUCCEEDED(status)) {
+ /* Before proceeding with new load,
+ * check if a previously registered COFF
+ * exists.
+ * If yes, unregister nodes in previously
+ * registered COFF. If any error occurred,
+ * set previously registered COFF to NULL. */
+ if (pProcObject->g_pszLastCoff != NULL) {
+ status = DCD_AutoUnregister(hDCDHandle,
+ pProcObject->g_pszLastCoff);
+ /* Regardless of auto unregister status,
+ * free previously allocated
+ * memory. */
+ MEM_Free(pProcObject->g_pszLastCoff);
+ pProcObject->g_pszLastCoff = NULL;
+ }
+ }
+ /* On success, do COD_OpenBase() */
+ status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
+ COD_SYMB);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: COD_OpenBase "
+ "failed (0x%x)\n", status);
+ }
+ }
+ } else {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ " PROC_Load:Out of Memory \n");
+ status = DSP_EMEMORY;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Auto-register data base */
+ /* Get the DCD Handle */
+ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
+ (u32 *)&hDCDHandle);
+ if (DSP_SUCCEEDED(status)) {
+ /* Auto register nodes in specified COFF
+ * file. If registration did not fail,
+ * (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
+ * save the name of the COFF file for
+ * de-registration in the future. */
+ status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
+ if (status == DSP_EDCDNOAUTOREGISTER) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: No Auto "
+ "Register section. Proceeding..\n");
+ status = DSP_SOK;
+ }
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: Failed to "
+ "Auto Register..\n");
+ } else {
+ DBC_Assert(pProcObject->g_pszLastCoff == NULL);
+ /* Allocate memory for pszLastCoff */
+ pProcObject->g_pszLastCoff = MEM_Calloc(
+ (strlen((char *)aArgv[0]) + 1),
+ MEM_PAGED);
+ /* If memory allocated, save COFF file name*/
+ if (pProcObject->g_pszLastCoff) {
+ strncpy(pProcObject->g_pszLastCoff,
+ (char *)aArgv[0],
+ (strlen((char *)aArgv[0]) + 1));
+ }
+ }
+ }
+ }
+ /* Update shared memory address and size */
+ if (DSP_SUCCEEDED(status)) {
+ /* Create the message manager. This must be done
+ * before calling the IOOnLoaded function. */
+ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+ if (!hMsgMgr) {
+ status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
+ (MSG_ONEXIT)NODE_OnExit);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
+ }
+ if (status == DSP_ENOTIMPL) {
+ /* It's OK not to have a message manager */
+ status = DSP_SOK;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Set the Device object's message manager */
+ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
+ if (status == DSP_ENOTIMPL) {
+ /* Ok not to implement this function */
+ status = DSP_SOK;
+ } else {
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: Failed to get shared "
+ "memory or message buffer address "
+ "from COFF status 0x%x\n", status);
+ status = DSP_EFAIL;
+ }
+ }
+ } else {
+ status = DSP_EFAIL;
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: DSP_FAILED in "
+ "MSG_Create status 0x%x\n", status);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Now, attempt to load an exec: */
+
+ /* Boost the OPP level to Maximum level supported by baseport*/
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ if (pdata->cpu_set_freq)
+ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP5]);
+#endif
+ status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
+ DEV_BrdWriteFxn,
+ pProcObject->hDevObject, NULL);
+ if (DSP_FAILED(status)) {
+ if (status == COD_E_OPENFAILED) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load:Failure to Load the EXE\n");
+ }
+ if (status == COD_E_SYMBOLNOTFOUND) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load:Could not parse the file\n");
+ } else {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: DSP_FAILED in "
+ "COD_Load status 0x%x \n", status);
+ }
+ }
+ /* Requesting the lowest opp supported*/
+#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
+ if (pdata->cpu_set_freq)
+ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
+#endif
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Update the Processor status to loaded */
+ status = (*pProcObject->pIntfFxns->pfnBrdSetState)
+ (pProcObject->hWmdContext, BRD_LOADED);
+ if (DSP_SUCCEEDED(status)) {
+ pProcObject->sState = PROC_LOADED;
+ if (pProcObject->hNtfy) {
+ PROC_NotifyClients(pProcObject,
+ DSP_PROCESSORSTATECHANGE);
+ }
+ } else {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load, pfnBrdSetState "
+ "failed: 0x%x\n", status);
+ status = DSP_EFAIL;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = PROC_GetProcessorId(hProcessor, &uProcId);
+ if (uProcId == DSP_UNIT) {
+ /* Use all available DSP address space after EXTMEM
+ * for DMM */
+ if (DSP_SUCCEEDED(status)) {
+#ifdef OMAP_3430
+ status = COD_GetSymValue(hCodMgr, EXTEND,
+ &dwExtEnd);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Load: Failed on "
+ "COD_GetSymValue %s.\n",
+ EXTEND);
+ }
+#endif
+ }
+ /* Reset DMM structs and add an initial free chunk*/
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetDmmMgr(pProcObject->hDevObject,
+ &hDmmMgr);
+ if (DSP_SUCCEEDED(status)) {
+#ifdef OMAP_3430
+ /* Set dwExtEnd to DMM START u8
+ * address */
+ dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
+ /* DMM memory is from EXT_END */
+ status = DMM_CreateTables(hDmmMgr,
+ dwExtEnd, DMMPOOLSIZE);
+#else
+ dwDmmStart = (DEXTMEMMAP_BEG) * (DSPWORDSIZE);
+
+ status = DMM_CreateTables(hDmmMgr,dwDmmStart,
+ DMMPOOLSIZE);
+#endif
+
+
+
+
+ }
+ }
+ }
+ }
+ /* Restore the original argv[0] */
+ MEM_Free(newEnvp);
+ aArgv[0] = pargv0;
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+ (pProcObject->hWmdContext, &uBrdState))) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Load: Processor Loaded\n");
+ DBC_Assert(uBrdState == BRD_LOADED);
+ }
+ }
+#endif
+func_end:
+#ifdef DEBUG
+ if (DSP_FAILED(status)) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
+ "Processor Load Failed.\n");
+
+ }
+#endif
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Exiting PROC_Load, status: 0x%x\n", status);
+ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
+ || DSP_FAILED(status));
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+ do_gettimeofday(&tv2);
+ if (tv2.tv_usec < tv1.tv_usec) {
+ tv2.tv_usec += 1000000;
+ tv2.tv_sec--;
+ }
+ GT_2trace(PROC_DebugMask, GT_1CLASS,
+ "Proc_Load: time to load %d sec and %d usec \n",
+ tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
+#endif
+ return status;
+}
+
+/*
+ * ======== PROC_Map ========
+ * Purpose:
+ * Maps a MPU buffer to DSP address space.
+ */
+DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
+ void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
+{
+ u32 vaAlign;
+ u32 paAlign;
+ struct DMM_OBJECT *hDmmMgr;
+ u32 sizeAlign;
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE dmmRes;
+ DSP_STATUS res_status = DSP_SOK;
+#endif
+
+ GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
+ "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
+ "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
+ pReqAddr, ulMapAttr, ppMapAddr);
+ /* Calculate the page-aligned PA, VA and size */
+ vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
+ paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
+ sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
+ PG_SIZE_4K);
+
+ GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
+ "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
+
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Map: "
+ "InValid Processor Handle \n");
+ goto func_end;
+ }
+ /* Critical section */
+ (void)SYNC_EnterCS(hProcLock);
+ status = DMM_GetHandle(pProcObject, &hDmmMgr);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Map: Failed to get DMM Mgr "
+ "handle: 0x%x\n", status);
+ } else {
+ status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
+ }
+ /* Add mapping to the page tables. */
+ if (DSP_SUCCEEDED(status)) {
+
+ status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
+ (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
+ ulMapAttr);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Mapped address = MSB of VA | LSB of PA */
+ *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
+ (PG_SIZE_4K - 1)));
+ } else {
+ DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
+ }
+ (void)SYNC_LeaveCS(hProcLock);
+
+#ifndef RES_CLEANUP_DISABLE
+ if (DSP_SUCCEEDED(status)) {
+ /* Update the node and stream resource status */
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject,
+ REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ if (DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDrvObject, &pCtxt, NULL,
+ (u32)pMpuAddr) != DSP_ENOTFOUND) {
+ DRV_InsertDMMResElement(&dmmRes, pCtxt);
+ DRV_UpdateDMMResElement(dmmRes, (u32)pMpuAddr,
+ ulSize, (u32)pReqAddr,
+ (u32)*ppMapAddr, hProcessor);
+ }
+ }
+ }
+#endif
+func_end:
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
+ return status;
+}
+
+/*
+ * ======== PROC_RegisterNotify ========
+ * Purpose:
+ * Register to be notified of specific processor events.
+ */
+DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
+ u32 uNotifyType, struct DSP_NOTIFICATION
+ *hNotification)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct DEH_MGR *hDehMgr;
+
+ DBC_Require(hNotification != NULL);
+ DBC_Require(cRefs > 0);
+
+ GT_4trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_RegisterNotify, args:\n\t"
+ "hProcessor: 0x%x\n\tuEventMask: 0x%x\n\tuNotifyMask:"
+ " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
+ uNotifyType, hNotification);
+
+ /* Check processor handle */
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_RegsiterNotify Invalid "
+ "ProcessorHandle 0x%x\n", hProcessor);
+ goto func_end;
+ }
+ /* Check if event mask is a valid processor related event */
+ if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
+ DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
+ DSP_SYSERROR | DSP_PWRERROR))
+ status = DSP_EVALUE;
+
+ /* Check if notify type is valid */
+ if (uNotifyType != DSP_SIGNALEVENT)
+ status = DSP_EVALUE;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* If event mask is not DSP_SYSERROR, DSP_MMUFAULT,
+ * or DSP_PWRERROR then register event immediately. */
+ if (uEventMask &
+ ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR)) {
+ status = NTFY_Register(pProcObject->hNtfy,
+ hNotification, uEventMask, uNotifyType);
+ /* Special case alert, special case alert!
+ * If we're trying to *deregister* (i.e. uEventMask
+ * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
+ * we have to deregister with the DEH manager.
+ * There's no way to know, based on uEventMask which
+ * manager the notification event was registered with,
+ * so if we're trying to deregister and NTFY_Register
+ * failed, we'll give the deh manager a shot.
+ */
+ if ((uEventMask == 0) && DSP_FAILED(status)) {
+ status = DEV_GetDehMgr(pProcObject->hDevObject,
+ &hDehMgr);
+ DBC_Assert(pProcObject->pIntfFxns->
+ pfnDehRegisterNotify);
+ status = (*pProcObject->pIntfFxns->
+ pfnDehRegisterNotify)
+ (hDehMgr, uEventMask, uNotifyType,
+ hNotification);
+ }
+ } else {
+ status = DEV_GetDehMgr(pProcObject->hDevObject,
+ &hDehMgr);
+ DBC_Assert(pProcObject->pIntfFxns->
+ pfnDehRegisterNotify);
+ status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
+ (hDehMgr, uEventMask, uNotifyType,
+ hNotification);
+ if (DSP_FAILED(status))
+ status = DSP_EFAIL;
+
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== PROC_ReserveMemory ========
+ * Purpose:
+ * Reserve a virtually contiguous region of DSP address space.
+ */
+DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
+ void **ppRsvAddr)
+{
+ struct DMM_OBJECT *hDmmMgr;
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+ GT_3trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_ReserveMemory, args:\n\t"
+ "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
+ ulSize, ppRsvAddr);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Map: "
+ "InValid Processor Handle \n");
+ goto func_end;
+ }
+ status = DMM_GetHandle(pProcObject, &hDmmMgr);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
+ "Failed to get DMM Mgr handle: 0x%x\n", status);
+ } else
+ status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
+
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
+ status);
+func_end:
+ return status;
+}
+
+/*
+ * ======== PROC_Start ========
+ * Purpose:
+ * Start a processor running.
+ */
+DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct COD_MANAGER *hCodMgr; /* Code manager handle */
+ u32 dwDspAddr; /* Loaded code's entry point. */
+#ifdef DEBUG
+ BRD_STATUS uBrdState;
+#endif
+ DBC_Require(cRefs > 0);
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
+ "hProcessor: 0x%x\n", hProcessor);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Start :InValid Handle \n");
+ goto func_end;
+ }
+ /* Call the WMD_BRD_Start */
+ if (pProcObject->sState != PROC_LOADED) {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Start :Wrong state \n");
+ status = DSP_EWRONGSTATE;
+ goto func_end;
+ }
+ status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "Processor Start DSP_FAILED "
+ "in Getting DEV_GetCodMgr status 0x%x\n", status);
+ goto func_cont;
+ }
+ status = COD_GetEntry(hCodMgr, &dwDspAddr);
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "Processor Start DSP_FAILED in "
+ "Getting COD_GetEntry status 0x%x\n", status);
+ goto func_cont;
+ }
+ status = (*pProcObject->pIntfFxns->pfnBrdStart)
+ (pProcObject->hWmdContext, dwDspAddr);
+ if (DSP_FAILED(status)) {
+ status = DSP_EFAIL;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Start Failed to Start the board\n");
+ goto func_cont;
+ }
+ /* Call DEV_Create2 */
+ status = DEV_Create2(pProcObject->hDevObject);
+ if (DSP_SUCCEEDED(status)) {
+ pProcObject->sState = PROC_RUNNING;
+ /* Deep sleep switces off the peripheral clocks.
+ * we just put the DSP CPU in idle in the idle loop.
+ * so there is no need to send a command to DSP */
+
+ if (pProcObject->hNtfy) {
+ PROC_NotifyClients(pProcObject,
+ DSP_PROCESSORSTATECHANGE);
+ }
+ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
+ "Started and running \n");
+ } else {
+ /* Failed to Create Node Manager and DISP Object
+ * Stop the Processor from running. Put it in STOPPED State */
+ (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
+ hWmdContext);
+ status = DSP_EFAIL;
+ pProcObject->sState = PROC_STOPPED;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
+ "Failed to Create the Node Manager\n");
+ }
+func_cont:
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+ (pProcObject->hWmdContext, &uBrdState))) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Start: Processor State is RUNNING \n");
+ DBC_Assert(uBrdState != BRD_HIBERNATION);
+ }
+ }
+#endif
+func_end:
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Exiting PROC_Start, status 0x%x\n", status);
+ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
+ PROC_RUNNING) || DSP_FAILED(status));
+ return status;
+}
+
+/*
+ * ======== PROC_Stop ========
+ * Purpose:
+ * Stop a processor running.
+ */
+DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct MSG_MGR *hMsgMgr;
+ struct NODE_MGR *hNodeMgr;
+ DSP_HNODE hNode;
+ u32 uNodeTabSize = 1;
+ u32 uNumNodes = 0;
+ u32 uNodesAllocated = 0;
+ BRD_STATUS uBrdState;
+
+ DBC_Require(cRefs > 0);
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
+ "hProcessor: 0x%x\n", hProcessor);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Stop :InValid Handle \n");
+ goto func_end;
+ }
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+ (pProcObject->hWmdContext, &uBrdState))) {
+ /* Clean up all the resources except the current running
+ process resources */
+ if (uBrdState == BRD_ERROR)
+ PROC_CleanupAllResources();
+ }
+ /* check if there are any running nodes */
+ status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
+ if (DSP_SUCCEEDED(status) && hNodeMgr) {
+ status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
+ &uNumNodes, &uNodesAllocated);
+ if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "Can't stop device, Active "
+ "nodes = 0x%x \n", uNodesAllocated);
+ return DSP_EWRONGSTATE;
+ }
+ }
+ /* Call the WMD_BRD_Stop */
+ /* It is OK to stop a device that does n't have nodes OR not started */
+ status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
+ hWmdContext);
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Stop: Processor Stopped, "
+ "i.e in standby mode \n");
+ pProcObject->sState = PROC_STOPPED;
+ /* Destory the Node Manager, MSG Manager */
+ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
+ /* Destroy the MSG by calling MSG_Delete */
+ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+ if (hMsgMgr) {
+ MSG_Delete(hMsgMgr);
+ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
+ pfnBrdStatus)(pProcObject->hWmdContext,
+ &uBrdState))) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Monitor:Processor Stopped \n");
+ DBC_Assert(uBrdState == BRD_STOPPED);
+ }
+#endif
+ } else {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Stop Couldn't delete node manager \n");
+ }
+ } else {
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Stop Failed to Stop the processor/device \n");
+ }
+func_end:
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status 0x%x\n",
+ status);
+
+ return status;
+}
+
+/*
+ * ======== PROC_UnMap ========
+ * Purpose:
+ * Removes a MPU buffer mapping from the DSP address space.
+ */
+DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+ struct DMM_OBJECT *hDmmMgr;
+ u32 vaAlign;
+ u32 sizeAlign;
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE dmmRes;
+ DSP_STATUS res_status = DSP_SOK;
+#endif
+ GT_2trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_UnMap, args:\n\thProcessor:"
+ "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
+
+ vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
+ "InValid Processor Handle \n");
+ goto func_end;
+ }
+
+ status = DMM_GetHandle(hProcessor, &hDmmMgr);
+ /* Critical section */
+ (void)SYNC_EnterCS(hProcLock);
+ if (DSP_FAILED(status)) {
+ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
+ "Failed to get DMM Mgr handle: 0x%x\n", status);
+ } else {
+ /* Update DMM structures. Get the size to unmap.
+ This function returns error if the VA is not mapped */
+ status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
+ }
+ /* Remove mapping from the page tables. */
+ if (DSP_SUCCEEDED(status)) {
+ status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
+ (pProcObject->hWmdContext, vaAlign, sizeAlign);
+ }
+ (void)SYNC_LeaveCS(hProcLock);
+#ifndef RES_CLEANUP_DISABLE
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "PROC_UnMap DRV_GetDMMResElement "
+ "pMapAddr:[0x%x]", pMapAddr);
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Update the node and stream resource status */
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(res_status))
+ goto func_end;
+
+ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
+ &pCtxt, NULL, (u32)pMapAddr);
+ if (pCtxt != NULL) {
+ if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
+ DSP_ENOTFOUND)
+ DRV_RemoveDMMResElement(dmmRes, pCtxt);
+ }
+func_end:
+#endif
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Leaving PROC_UnMap [0x%x]", status);
+ return status;
+}
+
+/*
+ * ======== PROC_UnReserveMemory ========
+ * Purpose:
+ * Frees a previously reserved region of DSP address space.
+ */
+DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
+{
+ struct DMM_OBJECT *hDmmMgr;
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+ GT_2trace(PROC_DebugMask, GT_ENTER,
+ "Entered PROC_UnReserveMemory, args:\n\t"
+ "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
+ "InValid Processor Handle \n");
+ goto func_end;
+ }
+ status = DMM_GetHandle(pProcObject, &hDmmMgr);
+ if (DSP_FAILED(status))
+ GT_1trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_UnReserveMemory: Failed to get DMM Mgr "
+ "handle: 0x%x\n", status);
+ else
+ status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
+
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Leaving PROC_UnReserveMemory [0x%x]",
+ status);
+func_end:
+ return status;
+}
+
+/*
+ * ======== = PROC_Monitor ======== ==
+ * Purpose:
+ * Place the Processor in Monitor State. This is an internal
+ * function and a requirement before Processor is loaded.
+ * This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
+ * In DEV_Destroy2 we delete the node manager.
+ * Parameters:
+ * hProcObject: Handle to Processor Object
+ * Returns:
+ * DSP_SOK: Processor placed in monitor mode.
+ * !DSP_SOK: Failed to place processor in monitor mode.
+ * Requires:
+ * Valid Processor Handle
+ * Ensures:
+ * Success: ProcObject state is PROC_IDLE
+ */
+static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
+{
+ DSP_STATUS status = DSP_EFAIL;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
+ struct MSG_MGR *hMsgMgr;
+#ifdef DEBUG
+ BRD_STATUS uBrdState;
+#endif
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+
+ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
+ "hProcessor: 0x%x\n", hProcObject);
+ /* This is needed only when Device is loaded when it is
+ * already 'ACTIVE' */
+ /* Destory the Node Manager, MSG Manager */
+ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
+ /* Destroy the MSG by calling MSG_Delete */
+ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+ if (hMsgMgr) {
+ MSG_Delete(hMsgMgr);
+ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
+ }
+ }
+ /* Place the Board in the Monitor State */
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
+ (pProcObject->hWmdContext))) {
+ status = DSP_SOK;
+#ifdef DEBUG
+ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+ (pProcObject->hWmdContext, &uBrdState))) {
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_Monitor:Processor in "
+ "Monitor State\n");
+ DBC_Assert(uBrdState == BRD_IDLE);
+ }
+#endif
+ } else {
+ /* Monitor Failure */
+ GT_0trace(PROC_DebugMask, GT_7CLASS,
+ "PROC_Monitor: Processor Could not"
+ "be put in Monitor mode \n");
+ }
+ GT_1trace(PROC_DebugMask, GT_ENTER,
+ "Exiting PROC_Monitor, status 0x%x\n",
+ status);
+#ifdef DEBUG
+ DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
+ DSP_FAILED(status));
+#endif
+ return status;
+}
+
+/*
+ * ======== GetEnvpCount ========
+ * Purpose:
+ * Return the number of elements in the envp array, including the
+ * terminating NULL element.
+ */
+static s32 GetEnvpCount(char **envp)
+{
+ s32 cRetval = 0;
+ if (envp) {
+ while (*envp++)
+ cRetval++;
+
+ cRetval += 1; /* Include the terminating NULL in the count. */
+ }
+
+ return cRetval;
+}
+
+/*
+ * ======== PrependEnvp ========
+ * Purpose:
+ * Prepend an environment variable=value pair to the new envp array, and
+ * copy in the existing var=value pairs in the old envp array.
+ */
+static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
+ char *szVar)
+{
+ char **ppEnvp = newEnvp;
+
+ DBC_Require(newEnvp);
+
+ /* Prepend new environ var=value string */
+ *newEnvp++ = szVar;
+
+ /* Copy user's environment into our own. */
+ while (cEnvp--)
+ *newEnvp++ = *envp++;
+
+ /* Ensure NULL terminates the new environment strings array. */
+ if (cEnvp == 0)
+ *newEnvp = NULL;
+
+ return ppEnvp;
+}
+
+/*
+ * ======== PROC_NotifyClients ========
+ * Purpose:
+ * Notify the processor the events.
+ */
+DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+ DBC_Require(IsValidProcEvent(uEvents));
+ DBC_Require(cRefs > 0);
+ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_NotifyClients: "
+ "InValid Processor Handle \n");
+ goto func_end;
+ }
+
+ NTFY_Notify(pProcObject->hNtfy, uEvents);
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_NotifyClients :Signaled. \n");
+func_end:
+ return status;
+}
+
+/*
+ * ======== PROC_NotifyAllClients ========
+ * Purpose:
+ * Notify the processor the events. This includes notifying all clients
+ * attached to a particulat DSP.
+ */
+DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+ DBC_Require(IsValidProcEvent(uEvents));
+ DBC_Require(cRefs > 0);
+
+ DEV_NotifyClients(pProcObject->hDevObject, uEvents);
+
+ GT_0trace(PROC_DebugMask, GT_1CLASS,
+ "PROC_NotifyAllClients :Signaled. \n");
+
+ return status;
+}
+
+/*
+ * ======== PROC_GetProcessorId ========
+ * Purpose:
+ * Retrieves the processor ID.
+ */
+DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE))
+ *procID = pProcObject->uProcessor;
+ else {
+ status = DSP_EHANDLE;
+ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_GetProcessorId: "
+ "InValid Processor Handle \n");
+ }
+ return status;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
new file mode 100644
index 000000000000..50a3f7948a44
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/pwr.c
@@ -0,0 +1,184 @@
+/*
+ * pwr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== PWR.c ========
+ * PWR API for controlling DSP power states.
+ *
+ * Public Functions:
+ * PWR_SleepDSP
+ * PWR_WakeDSP
+ *
+ *! Revision History
+ *! ================
+ *! 18-Feb-2003 vp Code review updates.
+ *! 18-Oct-2002 vp Ported to Linux platform.
+ *! 22-May-2002 sg Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
+ *! 29-Apr-2002 sg Initial.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/pwr.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/devdefs.h>
+#include <dspbridge/drv.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmdioctl.h>
+
+/*
+ * ======== PWR_SleepDSP ========
+ * Send command to DSP to enter sleep state.
+ */
+DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct WMD_DEV_CONTEXT *dwContext;
+ DSP_STATUS status = DSP_EFAIL;
+ struct DEV_OBJECT *hDevObject = NULL;
+ u32 ioctlcode = 0;
+ u32 arg = timeout;
+
+ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+ hDevObject != NULL;
+ hDevObject =
+ (struct DEV_OBJECT *)DRV_GetNextDevObject
+ ((u32)hDevObject)) {
+ if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
+ (struct WMD_DEV_CONTEXT **)&dwContext))) {
+ continue;
+ }
+ if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
+ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+ continue;
+ }
+ if (sleepCode == PWR_DEEPSLEEP)
+ ioctlcode = WMDIOCTL_DEEPSLEEP;
+ else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
+ ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
+ else
+ status = DSP_EINVALIDARG;
+
+ if (status != DSP_EINVALIDARG) {
+ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+ ioctlcode, (void *)&arg);
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== PWR_WakeDSP ========
+ * Send command to DSP to wake it from sleep.
+ */
+DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct WMD_DEV_CONTEXT *dwContext;
+ DSP_STATUS status = DSP_EFAIL;
+ struct DEV_OBJECT *hDevObject = NULL;
+ u32 arg = timeout;
+
+ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+ hDevObject != NULL;
+ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+ ((u32)hDevObject)) {
+ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+ (struct WMD_DEV_CONTEXT **)&dwContext))) {
+ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+ WMDIOCTL_WAKEUP, (void *)&arg);
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== PWR_PM_PreScale========
+ * Sends pre-notification message to DSP.
+ */
+DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct WMD_DEV_CONTEXT *dwContext;
+ DSP_STATUS status = DSP_EFAIL;
+ struct DEV_OBJECT *hDevObject = NULL;
+ u32 arg[2];
+
+ arg[0] = voltage_domain;
+ arg[1] = level;
+
+ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+ hDevObject != NULL;
+ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+ ((u32)hDevObject)) {
+ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+ (struct WMD_DEV_CONTEXT **)&dwContext))) {
+ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+ WMDIOCTL_PRESCALE_NOTIFY,
+ (void *)&arg);
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== PWR_PM_PostScale========
+ * Sends post-notification message to DSP.
+ */
+DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct WMD_DEV_CONTEXT *dwContext;
+ DSP_STATUS status = DSP_EFAIL;
+ struct DEV_OBJECT *hDevObject = NULL;
+ u32 arg[2];
+
+ arg[0] = voltage_domain;
+ arg[1] = level;
+
+ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+ hDevObject != NULL;
+ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+ ((u32)hDevObject)) {
+ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+ (struct WMD_DEV_CONTEXT **)&dwContext))) {
+ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+ WMDIOCTL_POSTSCALE_NOTIFY,
+ (void *)&arg);
+ }
+ }
+ }
+ return status;
+
+}
+
+
diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
new file mode 100644
index 000000000000..575f6751bac1
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/rmm.c
@@ -0,0 +1,604 @@
+/*
+ * rmm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== rmm.c ========
+ * Description:
+ *
+ * This memory manager provides general heap management and arbitrary
+ * alignment for any number of memory segments.
+ *
+ * Notes:
+ *
+ * Memory blocks are allocated from the end of the first free memory
+ * block large enough to satisfy the request. Alignment requirements
+ * are satisfied by "sliding" the block forward until its base satisfies
+ * the alignment specification; if this is not possible then the next
+ * free block large enough to hold the request is tried.
+ *
+ * Since alignment can cause the creation of a new free block - the
+ * unused memory formed between the start of the original free block
+ * and the start of the allocated block - the memory manager must free
+ * this memory to prevent a memory leak.
+ *
+ * Overlay memory is managed by reserving through RMM_alloc, and freeing
+ * it through RMM_free. The memory manager prevents DSP code/data that is
+ * overlayed from being overwritten as long as the memory it runs at has
+ * been allocated, and not yet freed.
+ *
+ *! Revision History
+ *! ================
+ *! 18-Feb-2003 vp Code review updates.
+ *! 18-Oct-2002 vp Ported to Linux Platform.
+ *! 24-Sep-2002 map Updated from Code Review
+ *! 25-Jun-2002 jeh Free from segid passed to RMM_free().
+ *! 24-Apr-2002 jeh Determine segid based on address in RMM_free(). (No way
+ *! to keep track of segid with dynamic loader library.)
+ *! 16-Oct-2001 jeh Based on gen tree rm.c. Added support for overlays.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/rmm.h>
+
+#define RMM_TARGSIGNATURE 0x544d4d52 /* "TMMR" */
+
+/*
+ * ======== RMM_Header ========
+ * This header is used to maintain a list of free memory blocks.
+ */
+struct RMM_Header {
+ struct RMM_Header *next; /* form a free memory link list */
+ u32 size; /* size of the free memory */
+ u32 addr; /* DSP address of memory block */
+} ;
+
+/*
+ * ======== RMM_OvlySect ========
+ * Keeps track of memory occupied by overlay section.
+ */
+struct RMM_OvlySect {
+ struct LST_ELEM listElem;
+ u32 addr; /* Start of memory section */
+ u32 size; /* Length (target MAUs) of section */
+ s32 page; /* Memory page */
+};
+
+/*
+ * ======== RMM_TargetObj ========
+ */
+struct RMM_TargetObj {
+ u32 dwSignature;
+ struct RMM_Segment *segTab;
+ struct RMM_Header **freeList;
+ u32 numSegs;
+ struct LST_LIST *ovlyList; /* List of overlay memory in use */
+};
+
+#if GT_TRACE
+static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+
+static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
+ u32 align, u32 *dspAddr);
+static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
+ u32 size);
+
+/*
+ * ======== RMM_alloc ========
+ */
+DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
+ u32 align, u32 *dspAddr, bool reserve)
+{
+ struct RMM_OvlySect *sect;
+ struct RMM_OvlySect *prevSect = NULL;
+ struct RMM_OvlySect *newSect;
+ u32 addr;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+ DBC_Require(dspAddr != NULL);
+ DBC_Require(size > 0);
+ DBC_Require(reserve || (target->numSegs > 0));
+ DBC_Require(cRefs > 0);
+
+ GT_6trace(RMM_debugMask, GT_ENTER,
+ "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+ "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
+ reserve);
+ if (!reserve) {
+ if (!allocBlock(target, segid, size, align, dspAddr)) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Increment the number of allocated blocks in this
+ * segment */
+ target->segTab[segid].number++;
+ }
+ goto func_end;
+ }
+ /* An overlay section - See if block is already in use. If not,
+ * insert into the list in ascending address size. */
+ addr = *dspAddr;
+ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
+ /* Find place to insert new list element. List is sorted from
+ * smallest to largest address. */
+ while (sect != NULL) {
+ if (addr <= sect->addr) {
+ /* Check for overlap with sect */
+ if ((addr + size > sect->addr) || (prevSect &&
+ (prevSect->addr + prevSect->size > addr))) {
+ status = DSP_EOVERLAYMEMORY;
+ }
+ break;
+ }
+ prevSect = sect;
+ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
+ (struct LST_ELEM *)sect);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* No overlap - allocate list element for new section. */
+ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
+ if (newSect == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ LST_InitElem((struct LST_ELEM *)newSect);
+ newSect->addr = addr;
+ newSect->size = size;
+ newSect->page = segid;
+ if (sect == NULL) {
+ /* Put new section at the end of the list */
+ LST_PutTail(target->ovlyList,
+ (struct LST_ELEM *)newSect);
+ } else {
+ /* Put new section just before sect */
+ LST_InsertBefore(target->ovlyList,
+ (struct LST_ELEM *)newSect,
+ (struct LST_ELEM *)sect);
+ }
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== RMM_create ========
+ */
+DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
+ struct RMM_Segment segTab[], u32 numSegs)
+{
+ struct RMM_Header *hptr;
+ struct RMM_Segment *sptr, *tmp;
+ struct RMM_TargetObj *target;
+ s32 i;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(pTarget != NULL);
+ DBC_Require(numSegs == 0 || segTab != NULL);
+
+ GT_3trace(RMM_debugMask, GT_ENTER,
+ "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
+ pTarget, segTab, numSegs);
+
+ /* Allocate DBL target object */
+ MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
+
+ if (target == NULL) {
+ GT_0trace(RMM_debugMask, GT_6CLASS,
+ "RMM_create: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ }
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ target->numSegs = numSegs;
+ if (!(numSegs > 0))
+ goto func_cont;
+
+ /* Allocate the memory for freelist from host's memory */
+ target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
+ MEM_PAGED);
+ if (target->freeList == NULL) {
+ GT_0trace(RMM_debugMask, GT_6CLASS,
+ "RMM_create: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ /* Allocate headers for each element on the free list */
+ for (i = 0; i < (s32) numSegs; i++) {
+ target->freeList[i] =
+ MEM_Calloc(sizeof(struct RMM_Header),
+ MEM_PAGED);
+ if (target->freeList[i] == NULL) {
+ GT_0trace(RMM_debugMask, GT_6CLASS,
+ "RMM_create: Memory "
+ "allocation failed\n");
+ status = DSP_EMEMORY;
+ break;
+ }
+ }
+ /* Allocate memory for initial segment table */
+ target->segTab = MEM_Calloc(numSegs *
+ sizeof(struct RMM_Segment), MEM_PAGED);
+ if (target->segTab == NULL) {
+ GT_0trace(RMM_debugMask, GT_6CLASS,
+ "RMM_create: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ } else {
+ /* Initialize segment table and free list */
+ sptr = target->segTab;
+ for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
+ *sptr = *tmp;
+ hptr = target->freeList[i];
+ hptr->addr = tmp->base;
+ hptr->size = tmp->length;
+ hptr->next = NULL;
+ tmp++;
+ sptr++;
+ }
+ }
+ }
+func_cont:
+ /* Initialize overlay memory list */
+ if (DSP_SUCCEEDED(status)) {
+ target->ovlyList = LST_Create();
+ if (target->ovlyList == NULL) {
+ GT_0trace(RMM_debugMask, GT_6CLASS,
+ "RMM_create: Memory allocation failed\n");
+ status = DSP_EMEMORY;
+ }
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ *pTarget = target;
+ } else {
+ *pTarget = NULL;
+ if (target)
+ RMM_delete(target);
+
+ }
+
+ DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
+ RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
+ NULL));
+
+ return status;
+}
+
+/*
+ * ======== RMM_delete ========
+ */
+void RMM_delete(struct RMM_TargetObj *target)
+{
+ struct RMM_OvlySect *pSect;
+ struct RMM_Header *hptr;
+ struct RMM_Header *next;
+ u32 i;
+
+ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+
+ GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
+
+ if (target->segTab != NULL)
+ MEM_Free(target->segTab);
+
+ if (target->ovlyList) {
+ while ((pSect = (struct RMM_OvlySect *)LST_GetHead
+ (target->ovlyList))) {
+ MEM_Free(pSect);
+ }
+ DBC_Assert(LST_IsEmpty(target->ovlyList));
+ LST_Delete(target->ovlyList);
+ }
+
+ if (target->freeList != NULL) {
+ /* Free elements on freelist */
+ for (i = 0; i < target->numSegs; i++) {
+ hptr = next = target->freeList[i];
+ while (next) {
+ hptr = next;
+ next = hptr->next;
+ MEM_Free(hptr);
+ }
+ }
+ MEM_Free(target->freeList);
+ }
+
+ MEM_FreeObject(target);
+}
+
+/*
+ * ======== RMM_exit ========
+ */
+void RMM_exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
+ cRefs);
+
+ if (cRefs == 0)
+ MEM_Exit();
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== RMM_free ========
+ */
+bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
+ bool reserved)
+
+{
+ struct RMM_OvlySect *sect;
+ bool retVal = true;
+
+ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+
+ DBC_Require(reserved || segid < target->numSegs);
+ DBC_Require(reserved || (addr >= target->segTab[segid].base &&
+ (addr + size) <= (target->segTab[segid].base +
+ target->segTab[segid].length)));
+
+ GT_5trace(RMM_debugMask, GT_ENTER,
+ "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+ "0x%lx)\n", target, segid, addr, size, reserved);
+ /*
+ * Free or unreserve memory.
+ */
+ if (!reserved) {
+ retVal = freeBlock(target, segid, addr, size);
+ if (retVal)
+ target->segTab[segid].number--;
+
+ } else {
+ /* Unreserve memory */
+ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
+ while (sect != NULL) {
+ if (addr == sect->addr) {
+ DBC_Assert(size == sect->size);
+ /* Remove from list */
+ LST_RemoveElem(target->ovlyList,
+ (struct LST_ELEM *)sect);
+ MEM_Free(sect);
+ break;
+ }
+ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
+ (struct LST_ELEM *)sect);
+ }
+ if (sect == NULL)
+ retVal = false;
+
+ }
+ return retVal;
+}
+
+/*
+ * ======== RMM_init ========
+ */
+bool RMM_init(void)
+{
+ bool retVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ DBC_Assert(!RMM_debugMask.flags);
+ GT_create(&RMM_debugMask, "RM"); /* "RM" for RMm */
+
+ retVal = MEM_Init();
+
+ if (!retVal)
+ MEM_Exit();
+
+ }
+
+ if (retVal)
+ cRefs++;
+
+ GT_1trace(RMM_debugMask, GT_5CLASS,
+ "RMM_init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
+
+ return retVal;
+}
+
+/*
+ * ======== RMM_stat ========
+ */
+bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
+ struct DSP_MEMSTAT *pMemStatBuf)
+{
+ struct RMM_Header *head;
+ bool retVal = false;
+ u32 maxFreeSize = 0;
+ u32 totalFreeSize = 0;
+ u32 freeBlocks = 0;
+
+ DBC_Require(pMemStatBuf != NULL);
+ DBC_Assert(target != NULL);
+
+ if ((u32) segid < target->numSegs) {
+ head = target->freeList[segid];
+
+ /* Collect data from freeList */
+ while (head != NULL) {
+ maxFreeSize = max(maxFreeSize, head->size);
+ totalFreeSize += head->size;
+ freeBlocks++;
+ head = head->next;
+ }
+
+ /* ulSize */
+ pMemStatBuf->ulSize = target->segTab[segid].length;
+
+ /* ulNumFreeBlocks */
+ pMemStatBuf->ulNumFreeBlocks = freeBlocks;
+
+ /* ulTotalFreeSize */
+ pMemStatBuf->ulTotalFreeSize = totalFreeSize;
+
+ /* ulLenMaxFreeBlock */
+ pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
+
+ /* ulNumAllocBlocks */
+ pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
+
+ retVal = true;
+ }
+
+ return retVal;
+}
+
+/*
+ * ======== balloc ========
+ * This allocation function allocates memory from the lowest addresses
+ * first.
+ */
+static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
+ u32 align, u32 *dspAddr)
+{
+ struct RMM_Header *head;
+ struct RMM_Header *prevhead = NULL;
+ struct RMM_Header *next;
+ u32 tmpalign;
+ u32 alignbytes;
+ u32 hsize;
+ u32 allocsize;
+ u32 addr;
+
+ alignbytes = (align == 0) ? 1 : align;
+ prevhead = NULL;
+ head = target->freeList[segid];
+
+ do {
+ hsize = head->size;
+ next = head->next;
+
+ addr = head->addr; /* alloc from the bottom */
+
+ /* align allocation */
+ (tmpalign = (u32) addr % alignbytes);
+ if (tmpalign != 0)
+ tmpalign = alignbytes - tmpalign;
+
+ allocsize = size + tmpalign;
+
+ if (hsize >= allocsize) { /* big enough */
+ if (hsize == allocsize && prevhead != NULL) {
+ prevhead->next = next;
+ MEM_Free(head);
+ } else {
+ head->size = hsize - allocsize;
+ head->addr += allocsize;
+ }
+
+ /* free up any hole created by alignment */
+ if (tmpalign)
+ freeBlock(target, segid, addr, tmpalign);
+
+ *dspAddr = addr + tmpalign;
+ return true;
+ }
+
+ prevhead = head;
+ head = next;
+
+ } while (head != NULL);
+
+ return false;
+}
+
+/*
+ * ======== freeBlock ========
+ * TO DO: freeBlock() allocates memory, which could result in failure.
+ * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
+ * freeBlock() could use an RMM_Header from the pool, freeing as blocks
+ * are coalesced.
+ */
+static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
+ u32 size)
+{
+ struct RMM_Header *head;
+ struct RMM_Header *thead;
+ struct RMM_Header *rhead;
+ bool retVal = true;
+
+ /* Create a memory header to hold the newly free'd block. */
+ rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
+ if (rhead == NULL) {
+ retVal = false;
+ } else {
+ /* search down the free list to find the right place for addr */
+ head = target->freeList[segid];
+
+ if (addr >= head->addr) {
+ while (head->next != NULL && addr > head->next->addr)
+ head = head->next;
+
+ thead = head->next;
+
+ head->next = rhead;
+ rhead->next = thead;
+ rhead->addr = addr;
+ rhead->size = size;
+ } else {
+ *rhead = *head;
+ head->next = rhead;
+ head->addr = addr;
+ head->size = size;
+ thead = rhead->next;
+ }
+
+ /* join with upper block, if possible */
+ if (thead != NULL && (rhead->addr + rhead->size) ==
+ thead->addr) {
+ head->next = rhead->next;
+ thead->size = size + thead->size;
+ thead->addr = addr;
+ MEM_Free(rhead);
+ rhead = thead;
+ }
+
+ /* join with the lower block, if possible */
+ if ((head->addr + head->size) == rhead->addr) {
+ head->next = rhead->next;
+ head->size = head->size + rhead->size;
+ MEM_Free(rhead);
+ }
+ }
+
+ return retVal;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
new file mode 100644
index 000000000000..bd55fd3d102c
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/strm.c
@@ -0,0 +1,1066 @@
+/*
+ * strm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== strm.c ========
+ * Description:
+ * DSP/BIOS Bridge Stream Manager.
+ *
+ * Public Functions:
+ * STRM_AllocateBuffer
+ * STRM_Close
+ * STRM_Create
+ * STRM_Delete
+ * STRM_Exit
+ * STRM_FreeBuffer
+ * STRM_GetEventHandle
+ * STRM_GetInfo
+ * STRM_Idle
+ * STRM_Init
+ * STRM_Issue
+ * STRM_Open
+ * STRM_PrepareBuffer
+ * STRM_Reclaim
+ * STRM_RegisterNotify
+ * STRM_Select
+ * STRM_UnprepareBuffer
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! =================
+ *! 18-Feb-2003 vp Code review updates.
+ *! 18-Oct-2002 vp Ported to Linux platform.
+ *! 13-Mar-2002 map pStrm init'd to NULL in STRM_Open to prevent error
+ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
+ *! in DEV and CMM function calls to avoid confusion.
+ *! Return DSP_SOK instead of S_OK from API fxns.
+ *! 12-Mar-2002 map Changed FAILED(..) to DSP_FAILED(..)
+ *! 25-Jan-2002 ag Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
+ *! 15-Nov-2001 ag Added STRMMODE & SM for DMA/ZCopy streaming.
+ *! Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
+ *! Use strm timeout value for dma flush timeout.
+ *! 09-May-2001 jeh Code review cleanup.
+ *! 06-Feb-2001 kc Updated DBC_Ensure in STRM_Select to check timeout.
+ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
+ *! tests to pass.
+ *! 25-Sep-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Mini Driver */
+#include <dspbridge/wmd.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/nodepriv.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/cmm.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/strm.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/cfg.h>
+#include <dspbridge/dbreg.h>
+#include <dspbridge/resourcecleanup.h>
+#endif
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define STRM_SIGNATURE 0x4d525453 /* "MRTS" */
+#define STRMMGR_SIGNATURE 0x5254534d /* "RTSM" */
+
+#define DEFAULTTIMEOUT 10000
+#define DEFAULTNUMBUFS 2
+
+/*
+ * ======== STRM_MGR ========
+ * The STRM_MGR contains device information needed to open the underlying
+ * channels of a stream.
+ */
+struct STRM_MGR {
+ u32 dwSignature;
+ struct DEV_OBJECT *hDev; /* Device for this processor */
+ struct CHNL_MGR *hChnlMgr; /* Channel manager */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+ struct SYNC_CSOBJECT *hSync; /* For critical sections */
+} ;
+
+/*
+ * ======== STRM_OBJECT ========
+ * This object is allocated in STRM_Open().
+ */
+ struct STRM_OBJECT {
+ u32 dwSignature;
+ struct STRM_MGR *hStrmMgr;
+ struct CHNL_OBJECT *hChnl;
+ u32 uDir; /* DSP_TONODE or DSP_FROMNODE */
+ u32 uTimeout;
+ u32 uNumBufs; /* Max # of bufs allowed in stream */
+ u32 uNBufsInStrm; /* Current # of bufs in stream */
+ u32 ulNBytes; /* bytes transferred since idled */
+ enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
+ HANDLE hUserEvent; /* Saved for STRM_GetInfo() */
+ enum DSP_STRMMODE lMode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
+ u32 uDMAChnlId; /* DMA chnl id */
+ u32 uDMAPriority; /* DMA priority:DMAPRI_[LOW][HIGH] */
+ u32 uSegment; /* >0 is SM segment.=0 is local heap */
+ u32 uAlignment; /* Alignment for stream bufs */
+ struct CMM_XLATOROBJECT *hXlator; /* Stream's SM address translator */
+} ;
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask STRM_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+static u32 cRefs; /* module reference count */
+
+/* ----------------------------------- Function Prototypes */
+static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
+static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
+
+/*
+ * ======== STRM_AllocateBuffer ========
+ * Purpose:
+ * Allocates buffers for a stream.
+ */
+DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
+ OUT u8 **apBuffer, u32 uNumBufs)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 uAllocated = 0;
+ u32 i;
+ #ifndef RES_CLEANUP_DISABLE
+ DSP_STATUS res_status = DSP_SOK;
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE hSTRMRes;
+ #endif
+ DBC_Require(cRefs > 0);
+ DBC_Require(apBuffer != NULL);
+
+ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
+ "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
+ hStrm, uSize, apBuffer, uNumBufs);
+ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ /*
+ * Allocate from segment specified at time of stream open.
+ */
+ if (uSize == 0)
+ status = DSP_ESIZE;
+
+ }
+ if (DSP_FAILED(status)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ for (i = 0; i < uNumBufs; i++) {
+ DBC_Assert(hStrm->hXlator != NULL);
+ (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
+ if (apBuffer[i] == NULL) {
+ GT_0trace(STRM_debugMask, GT_7CLASS,
+ "STRM_AllocateBuffer: "
+ "DSP_FAILED to alloc shared memory.\n");
+ status = DSP_EMEMORY;
+ uAllocated = i;
+ break;
+ }
+ }
+ if (DSP_FAILED(status))
+ STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
+
+#ifndef RES_CLEANUP_DISABLE
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(res_status))
+ goto func_end;
+
+ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
+ &pCtxt, NULL, 0);
+ if (pCtxt != NULL) {
+ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
+ DSP_ENOTFOUND) {
+ DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
+ }
+ }
+#endif
+func_end:
+ return status;
+}
+
+/*
+ * ======== STRM_Close ========
+ * Purpose:
+ * Close a stream opened with STRM_Open().
+ */
+DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct CHNL_INFO chnlInfo;
+ DSP_STATUS status = DSP_SOK;
+
+
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE hSTRMRes;
+ DSP_STATUS res_status = DSP_SOK;
+#endif
+
+
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
+
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ /* Have all buffers been reclaimed? If not, return
+ * DSP_EPENDING */
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
+ DBC_Assert(DSP_SUCCEEDED(status));
+
+ if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
+ status = DSP_EPENDING;
+ } else {
+
+ status = DeleteStrm(hStrm);
+
+ if (DSP_FAILED(status)) {
+ /* we already validated the handle. */
+ DBC_Assert(status != DSP_EHANDLE);
+
+ /* make sure we return a documented result */
+ status = DSP_EFAIL;
+ }
+ }
+ }
+#ifndef RES_CLEANUP_DISABLE
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Update the node and stream resource status */
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(res_status))
+ goto func_end;
+
+ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
+ &pCtxt, NULL, 0);
+ if (pCtxt != NULL) {
+ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
+ DSP_ENOTFOUND) {
+ DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
+ }
+ }
+func_end:
+#endif
+ DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
+ status == DSP_EPENDING || status == DSP_EFAIL);
+
+ return status;
+}
+
+/*
+ * ======== STRM_Create ========
+ * Purpose:
+ * Create a STRM manager object.
+ */
+DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
+{
+ struct STRM_MGR *pStrmMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(phStrmMgr != NULL);
+ DBC_Require(hDev != NULL);
+
+ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
+ "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
+ *phStrmMgr = NULL;
+ /* Allocate STRM manager object */
+ MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
+ if (pStrmMgr == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
+ "MEM_AllocObject() failed!\n ");
+ } else {
+ pStrmMgr->hDev = hDev;
+ }
+ /* Get Channel manager and WMD function interface */
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
+ if (DSP_SUCCEEDED(status)) {
+ (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
+ DBC_Assert(pStrmMgr->pIntfFxns != NULL);
+ } else {
+ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
+ "Failed to get channel manager! status = "
+ "0x%x\n", status);
+ }
+ }
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_InitializeCS(&pStrmMgr->hSync);
+
+ if (DSP_SUCCEEDED(status))
+ *phStrmMgr = pStrmMgr;
+ else
+ DeleteStrmMgr(pStrmMgr);
+
+ DBC_Ensure(DSP_SUCCEEDED(status) &&
+ (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
+ (DSP_FAILED(status) && *phStrmMgr == NULL)));
+
+ return status;
+}
+
+/*
+ * ======== STRM_Delete ========
+ * Purpose:
+ * Delete the STRM Manager Object.
+ */
+void STRM_Delete(struct STRM_MGR *hStrmMgr)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
+
+ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
+ hStrmMgr);
+
+ DeleteStrmMgr(hStrmMgr);
+
+ DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
+}
+
+/*
+ * ======== STRM_Exit ========
+ * Purpose:
+ * Discontinue usage of STRM module.
+ */
+void STRM_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ cRefs--;
+
+ GT_1trace(STRM_debugMask, GT_5CLASS,
+ "Entered STRM_Exit, ref count: 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== STRM_FreeBuffer ========
+ * Purpose:
+ * Frees the buffers allocated for a stream.
+ */
+DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
+ u32 uNumBufs)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 i = 0;
+
+ #ifndef RES_CLEANUP_DISABLE
+ DSP_STATUS res_status = DSP_SOK;
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE hSTRMRes = NULL;
+ #endif
+ DBC_Require(cRefs > 0);
+ DBC_Require(apBuffer != NULL);
+
+ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
+ "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
+
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
+ status = DSP_EHANDLE;
+
+ if (DSP_SUCCEEDED(status)) {
+ for (i = 0; i < uNumBufs; i++) {
+ DBC_Assert(hStrm->hXlator != NULL);
+ status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
+ if (DSP_FAILED(status)) {
+ GT_0trace(STRM_debugMask, GT_7CLASS,
+ "STRM_FreeBuffer: DSP_FAILED"
+ " to free shared memory.\n");
+ break;
+ }
+ apBuffer[i] = NULL;
+ }
+ }
+#ifndef RES_CLEANUP_DISABLE
+ /* Update the node and stream resource status */
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
+ NULL, 0);
+ if (pCtxt != NULL) {
+ if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
+ DSP_ENOTFOUND) {
+ DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
+ pCtxt);
+ }
+ }
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== STRM_GetInfo ========
+ * Purpose:
+ * Retrieves information about a stream.
+ */
+DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
+ OUT struct STRM_INFO *pStreamInfo,
+ u32 uStreamInfoSize)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct CHNL_INFO chnlInfo;
+ DSP_STATUS status = DSP_SOK;
+ void *pVirtBase = NULL; /* NULL if no SM used */
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pStreamInfo != NULL);
+ DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
+
+ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
+ "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
+ pStreamInfo, uStreamInfoSize);
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
+ /* size of users info */
+ status = DSP_ESIZE;
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ if (hStrm->hXlator) {
+ /* We have a translator */
+ DBC_Assert(hStrm->uSegment > 0);
+ CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
+ hStrm->uSegment, false);
+ }
+ pStreamInfo->uSegment = hStrm->uSegment;
+ pStreamInfo->lMode = hStrm->lMode;
+ pStreamInfo->pVirtBase = pVirtBase;
+ pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
+ pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
+ chnlInfo.cIOReqs;
+ /* # of bytes transferred since last call to DSPStream_Idle() */
+ pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
+ pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
+ /* Determine stream state based on channel state and info */
+ if (chnlInfo.dwState & CHNL_STATEEOS) {
+ pStreamInfo->pUser->ssStreamState = STREAM_DONE;
+ } else {
+ if (chnlInfo.cIOCs > 0)
+ pStreamInfo->pUser->ssStreamState = STREAM_READY;
+ else if (chnlInfo.cIOReqs > 0)
+ pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
+ else
+ pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
+
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== STRM_Idle ========
+ * Purpose:
+ * Idles a particular stream.
+ */
+DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+
+ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
+ "fFlush: 0x%x\n", hStrm, fFlush);
+
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+ status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
+ hStrm->uTimeout, fFlush);
+ }
+ return status;
+}
+
+/*
+ * ======== STRM_Init ========
+ * Purpose:
+ * Initialize the STRM module.
+ */
+bool STRM_Init(void)
+{
+ bool fRetVal = true;
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+#if GT_TRACE
+ DBC_Assert(!STRM_debugMask.flags);
+ GT_create(&STRM_debugMask, "ST"); /* "ST" for STrm */
+#endif
+ }
+
+ if (fRetVal)
+ cRefs++;
+
+ GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+
+ return fRetVal;
+}
+
+/*
+ * ======== STRM_Issue ========
+ * Purpose:
+ * Issues a buffer on a stream
+ */
+DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
+ u32 ulBufSize, u32 dwArg)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+ void *pTmpBuf = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBuf != NULL);
+
+ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
+ "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
+ dwArg);
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+ if (hStrm->uSegment != 0) {
+ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+ (void *)pBuf, CMM_VA2DSPPA);
+ if (pTmpBuf == NULL)
+ status = DSP_ETRANSLATE;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = (*pIntfFxns->pfnChnlAddIOReq)
+ (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
+ (u32) pTmpBuf, dwArg);
+ }
+ if (DSP_FAILED(status)) {
+ if (status == CHNL_E_NOIORPS)
+ status = DSP_ESTREAMFULL;
+ else
+ status = DSP_EFAIL;
+
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== STRM_Open ========
+ * Purpose:
+ * Open a stream for sending/receiving data buffers to/from a task or
+ * XDAIS socket node on the DSP.
+ */
+DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
+ IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
+{
+ struct STRM_MGR *hStrmMgr;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ u32 ulChnlId;
+ struct STRM_OBJECT *pStrm = NULL;
+ CHNL_MODE uMode;
+ struct CHNL_ATTRS chnlAttrs;
+ DSP_STATUS status = DSP_SOK;
+ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
+
+ #ifndef RES_CLEANUP_DISABLE
+ DSP_STATUS res_status = DSP_SOK;
+ u32 hProcess;
+ HANDLE pCtxt = NULL;
+ HANDLE hDrvObject;
+ HANDLE hSTRMRes;
+ #endif
+ DBC_Require(cRefs > 0);
+ DBC_Require(phStrm != NULL);
+ DBC_Require(pAttr != NULL);
+ GT_5trace(STRM_debugMask, GT_ENTER,
+ "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
+ "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
+ hNode, uDir, uIndex, pAttr, phStrm);
+ *phStrm = NULL;
+ if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
+ status = DSP_EDIRECTION;
+ } else {
+ /* Get the channel id from the node (set in NODE_Connect()) */
+ status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
+ }
+ if (DSP_SUCCEEDED(status))
+ status = NODE_GetStrmMgr(hNode, &hStrmMgr);
+
+ if (DSP_SUCCEEDED(status)) {
+ MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
+ if (pStrm == NULL) {
+ status = DSP_EMEMORY;
+ GT_0trace(STRM_debugMask, GT_6CLASS,
+ "STRM_Open: MEM_AllocObject() failed!\n ");
+ } else {
+ pStrm->hStrmMgr = hStrmMgr;
+ pStrm->uDir = uDir;
+ pStrm->strmState = STREAM_IDLE;
+ pStrm->hUserEvent = pAttr->hUserEvent;
+ if (pAttr->pStreamAttrIn != NULL) {
+ pStrm->uTimeout = pAttr->pStreamAttrIn->
+ uTimeout;
+ pStrm->uNumBufs = pAttr->pStreamAttrIn->
+ uNumBufs;
+ pStrm->lMode = pAttr->pStreamAttrIn->lMode;
+ pStrm->uSegment = pAttr->pStreamAttrIn->
+ uSegment;
+ pStrm->uAlignment = pAttr->pStreamAttrIn->
+ uAlignment;
+ pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
+ uDMAChnlId;
+ pStrm->uDMAPriority = pAttr->pStreamAttrIn->
+ uDMAPriority;
+ chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
+ uNumBufs;
+ } else {
+ pStrm->uTimeout = DEFAULTTIMEOUT;
+ pStrm->uNumBufs = DEFAULTNUMBUFS;
+ pStrm->lMode = STRMMODE_PROCCOPY;
+ pStrm->uSegment = 0; /* local memory */
+ pStrm->uAlignment = 0;
+ pStrm->uDMAChnlId = 0;
+ pStrm->uDMAPriority = 0;
+ chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
+ }
+ chnlAttrs.hReserved1 = NULL;
+ /* DMA chnl flush timeout */
+ chnlAttrs.hReserved2 = pStrm->uTimeout;
+ chnlAttrs.hEvent = NULL;
+ if (pAttr->hUserEvent != NULL)
+ chnlAttrs.hEvent = pAttr->hUserEvent;
+
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
+ goto func_cont;
+
+ DBC_Assert(pStrm->lMode != STRMMODE_LDMA); /* no System DMA */
+ /* Get the shared mem mgr for this streams dev object */
+ status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
+ if (DSP_FAILED(status)) {
+ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
+ "CMM Mgr handle: 0x%x\n", status);
+ } else {
+ /*Allocate a SM addr translator for this strm.*/
+ status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
+ if (DSP_FAILED(status)) {
+ GT_1trace(STRM_debugMask, GT_6CLASS,
+ "STRM_Open: Failed to "
+ "create SM translator: 0x%x\n", status);
+ } else {
+ DBC_Assert(pStrm->uSegment > 0);
+ /* Set translators Virt Addr attributes */
+ status = CMM_XlatorInfo(pStrm->hXlator,
+ (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
+ pStrm->uSegment, true);
+ if (status != DSP_SOK) {
+ GT_0trace(STRM_debugMask, GT_6CLASS,
+ "STRM_Open: ERROR: "
+ "in setting CMM_XlatorInfo.\n");
+ }
+ }
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status)) {
+ /* Open channel */
+ uMode = (uDir == DSP_TONODE) ?
+ CHNL_MODETODSP : CHNL_MODEFROMDSP;
+ pIntfFxns = hStrmMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
+ hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
+ if (DSP_FAILED(status)) {
+ /*
+ * over-ride non-returnable status codes so we return
+ * something documented
+ */
+ if (status != DSP_EMEMORY && status !=
+ DSP_EINVALIDARG && status != DSP_EFAIL) {
+ /*
+ * We got a status that's not return-able.
+ * Assert that we got something we were
+ * expecting (DSP_EHANDLE isn't acceptable,
+ * hStrmMgr->hChnlMgr better be valid or we
+ * assert here), and then return DSP_EFAIL.
+ */
+ DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
+ status == CHNL_E_BADCHANID ||
+ status == CHNL_E_CHANBUSY ||
+ status == CHNL_E_NOIORPS);
+ status = DSP_EFAIL;
+ }
+ GT_2trace(STRM_debugMask, GT_6CLASS,
+ "STRM_Open: Channel open failed, "
+ "chnl id = %d, status = 0x%x\n", ulChnlId,
+ status);
+ }
+ }
+ if (DSP_SUCCEEDED(status))
+ *phStrm = pStrm;
+ else
+ (void)DeleteStrm(pStrm);
+
+#ifndef RES_CLEANUP_DISABLE
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(res_status)) {
+ DRV_GetProcContext(hProcess,
+ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
+ hNode, 0);
+ if (pCtxt != NULL)
+ DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
+
+ }
+#endif
+
+ /* ensure we return a documented error code */
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
+ (*phStrm == NULL && (status == DSP_EHANDLE ||
+ status == DSP_EDIRECTION || status == DSP_EVALUE ||
+ status == DSP_EFAIL)));
+ return status;
+}
+
+/*
+ * ======== STRM_Reclaim ========
+ * Purpose:
+ * Relcaims a buffer from a stream.
+ */
+DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
+ u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct CHNL_IOC chnlIOC;
+ DSP_STATUS status = DSP_SOK;
+ void *pTmpBuf = NULL;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(pBufPtr != NULL);
+ DBC_Require(pulBytes != NULL);
+ DBC_Require(pdwArg != NULL);
+
+ GT_4trace(STRM_debugMask, GT_ENTER,
+ "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
+ "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
+ pdwArg);
+
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+ status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
+ &chnlIOC);
+ if (DSP_FAILED(status)) {
+ GT_1trace(STRM_debugMask, GT_6CLASS,
+ "STRM_Reclaim: GetIOC failed! "
+ "Status = 0x%x\n", status);
+ } else {
+ *pulBytes = chnlIOC.cBytes;
+ if (pulBufSize)
+ *pulBufSize = chnlIOC.cBufSize;
+
+ *pdwArg = chnlIOC.dwArg;
+ if (!CHNL_IsIOComplete(chnlIOC)) {
+ if (CHNL_IsTimedOut(chnlIOC)) {
+ status = DSP_ETIMEOUT;
+ } else {
+ /* Allow reclaims after idle to succeed */
+ if (!CHNL_IsIOCancelled(chnlIOC))
+ status = DSP_EFAIL;
+
+ }
+ }
+ /* Translate zerocopy buffer if channel not canceled. */
+ if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
+ (hStrm->lMode == STRMMODE_ZEROCOPY)) {
+ /*
+ * This is a zero-copy channel so chnlIOC.pBuf
+ * contains the DSP address of SM. We need to
+ * translate it to a virtual address for the user
+ * thread to access.
+ * Note: Could add CMM_DSPPA2VA to CMM in the future.
+ */
+ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+ chnlIOC.pBuf, CMM_DSPPA2PA);
+ if (pTmpBuf != NULL) {
+ /* now convert this GPP Pa to Va */
+ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+ pTmpBuf, CMM_PA2VA);
+ }
+ if (pTmpBuf == NULL) {
+ GT_0trace(STRM_debugMask, GT_7CLASS,
+ "STRM_Reclaim: Failed "
+ "SM translation!\n");
+ status = DSP_ETRANSLATE;
+ }
+ chnlIOC.pBuf = pTmpBuf;
+ }
+ *pBufPtr = chnlIOC.pBuf;
+ }
+func_end:
+ /* ensure we return a documented return code */
+ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
+ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
+ status == DSP_EFAIL);
+ return status;
+}
+
+/*
+ * ======== STRM_RegisterNotify ========
+ * Purpose:
+ * Register to be notified on specific events for this stream.
+ */
+DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
+ u32 uNotifyType, struct DSP_NOTIFICATION
+ *hNotification)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(hNotification != NULL);
+
+ GT_4trace(STRM_debugMask, GT_ENTER,
+ "STRM_RegisterNotify: hStrm: 0x%x\t"
+ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
+ hStrm, uEventMask, uNotifyType, hNotification);
+ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
+ DSP_STREAMDONE)) != 0) {
+ status = DSP_EVALUE;
+ } else {
+ if (uNotifyType != DSP_SIGNALEVENT)
+ status = DSP_ENOTIMPL;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+ status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
+ uEventMask, uNotifyType, hNotification);
+ }
+ /* ensure we return a documented return code */
+ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
+ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
+ status == DSP_ENOTIMPL || status == DSP_EFAIL);
+ return status;
+}
+
+/*
+ * ======== STRM_Select ========
+ * Purpose:
+ * Selects a ready stream.
+ */
+DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
+ OUT u32 *pMask, u32 uTimeout)
+{
+ u32 uIndex;
+ struct CHNL_INFO chnlInfo;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct SYNC_OBJECT **hSyncEvents = NULL;
+ u32 i;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(cRefs > 0);
+ DBC_Require(aStrmTab != NULL);
+ DBC_Require(pMask != NULL);
+ DBC_Require(nStrms > 0);
+
+ GT_4trace(STRM_debugMask, GT_ENTER,
+ "STRM_Select: aStrmTab: 0x%x \tnStrms: "
+ "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
+ nStrms, pMask, uTimeout);
+ *pMask = 0;
+ for (i = 0; i < nStrms; i++) {
+ if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ break;
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Determine which channels have IO ready */
+ for (i = 0; i < nStrms; i++) {
+ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
+ &chnlInfo);
+ if (DSP_FAILED(status)) {
+ break;
+ } else {
+ if (chnlInfo.cIOCs > 0)
+ *pMask |= (1 << i);
+
+ }
+ }
+ if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
+ /* Non-zero timeout */
+ hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
+ sizeof(struct SYNC_OBJECT *), MEM_PAGED);
+ if (hSyncEvents == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ for (i = 0; i < nStrms; i++) {
+ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
+ status = (*pIntfFxns->pfnChnlGetInfo)
+ (aStrmTab[i]->hChnl, &chnlInfo);
+ if (DSP_FAILED(status))
+ break;
+ else
+ hSyncEvents[i] = chnlInfo.hSyncEvent;
+
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
+ uTimeout, &uIndex);
+ if (DSP_SUCCEEDED(status)) {
+ /* Since we waited on the event, we have to
+ * reset it */
+ SYNC_SetEvent(hSyncEvents[uIndex]);
+ *pMask = 1 << uIndex;
+ }
+ }
+ }
+func_end:
+ if (hSyncEvents)
+ MEM_Free(hSyncEvents);
+
+ DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
+ (DSP_FAILED(status) && *pMask == 0));
+
+ return status;
+}
+
+/*
+ * ======== DeleteStrm ========
+ * Purpose:
+ * Frees the resources allocated for a stream.
+ */
+static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
+{
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ DSP_STATUS status = DSP_SOK;
+
+ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+ if (hStrm->hChnl) {
+ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+ /* Channel close can fail only if the channel handle
+ * is invalid. */
+ status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
+ /* Free all SM address translator resources */
+ if (DSP_SUCCEEDED(status)) {
+ if (hStrm->hXlator) {
+ /* force free */
+ (void)CMM_XlatorDelete(hStrm->hXlator,
+ true);
+ }
+ }
+ }
+ MEM_FreeObject(hStrm);
+ } else {
+ status = DSP_EHANDLE;
+ }
+ return status;
+}
+
+/*
+ * ======== DeleteStrmMgr ========
+ * Purpose:
+ * Frees stream manager.
+ */
+static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
+{
+ if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
+
+ if (hStrmMgr->hSync)
+ SYNC_DeleteCS(hStrmMgr->hSync);
+
+ MEM_FreeObject(hStrmMgr);
+ }
+}
+
diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
new file mode 100644
index 000000000000..67656bfaf48d
--- /dev/null
+++ b/drivers/dsp/bridge/services/cfg.c
@@ -0,0 +1,483 @@
+/*
+ * cfg.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cfgce.c ========
+ * Purpose:
+ * Implementation of platform specific config services.
+ *
+ * Private Functions:
+ * CFG_Exit
+ * CFG_GetAutoStart
+ * CFG_GetDevObject
+ * CFG_GetDSPResources
+ * CFG_GetExecFile
+ * CFG_GetHostResources
+ * CFG_GetObject
+ * CFG_Init
+ * CFG_SetDevObject
+ * CFG_SetObject
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Arp-2004 hp Support for handling more than one Device.
+ *! 26-Feb-2003 kc Removed unused CFG fxns.
+ *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
+ *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
+ *! 10-Aug-2000 rr: Cosmetic changes.
+ *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
+ *! replaces CFG_GetMgrObject & CFG_SetMgrObject.
+ *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 31-Jan-2000 rr: Comments and bugfixes: modified after code review
+ *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks strlen of the
+ *! read value from the registry against the passed in BufSize;
+ *! CFG_GetZLFile,CFG_GetWMDFileName and
+ *! CFG_GetExecFile also modified same way.
+ *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
+ *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
+ *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
+ *! CFG_GetDevNode reads the Devnodestring from the registry.
+ *! CFG_SetDevObject stores the registry path as
+ *! DevNodestring in the registry.
+ *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
+ *! 22-Nov-1999 kc: Added windows.h to remove warnings.
+ *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
+ *! from the registry which was set by the DRV Request
+ *! Resources.
+ *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
+ *! changes for drv.h resource structure and wsxreg.h new
+ *! entry(DevObject) Hard coded entries removed for those items
+ *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
+ *! registry. CFG_Get HostResources modified for opening up
+ *! two mem winodws.
+ *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
+ *! type of Resource Structure.
+ *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/reg.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/cfg.h>
+#include <dspbridge/list.h>
+
+struct DRV_EXT {
+ struct LST_ELEM link;
+ char szString[MAXREGPATHLENGTH];
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
+#endif
+
+/*
+ * ======== CFG_Exit ========
+ * Purpose:
+ * Discontinue usage of the CFG module.
+ */
+void CFG_Exit(void)
+{
+ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
+}
+
+/*
+ * ======== CFG_GetAutoStart ========
+ * Purpose:
+ * Retreive the autostart mask, if any, for this board.
+ */
+DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
+ OUT u32 *pdwAutoStart)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 dwBufSize;
+ GT_2trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_GetAutoStart: \n\thDevNode:"
+ "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
+ dwBufSize = sizeof(*pdwAutoStart);
+ if (!hDevNode)
+ status = CFG_E_INVALIDHDEVNODE;
+ if (!pdwAutoStart)
+ status = CFG_E_INVALIDPOINTER;
+ if (DSP_SUCCEEDED(status)) {
+ status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
+ (u8 *)pdwAutoStart, &dwBufSize);
+ if (DSP_FAILED(status))
+ status = CFG_E_RESOURCENOTAVAIL;
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetAutoStart SUCCESS \n");
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_GetAutoStart Failed \n");
+ }
+#endif
+ DBC_Ensure((status == DSP_SOK &&
+ (*pdwAutoStart == 0 || *pdwAutoStart == 1))
+ || status != DSP_SOK);
+ return status;
+}
+
+/*
+ * ======== CFG_GetDevObject ========
+ * Purpose:
+ * Retrieve the Device Object handle for a given devnode.
+ */
+DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 dwBufSize;
+ GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
+ "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
+ *pdwValue);
+ if (!hDevNode)
+ status = CFG_E_INVALIDHDEVNODE;
+
+ if (!pdwValue)
+ status = CFG_E_INVALIDHDEVNODE;
+
+ dwBufSize = sizeof(pdwValue);
+ if (DSP_SUCCEEDED(status)) {
+
+ /* check the device string and then call the REG_SetValue*/
+ if (!(strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
+ "TIOMAP1510"))) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "Fetching DSP Device from "
+ "Registry \n");
+ status = REG_GetValue(NULL, (char *)hDevNode,
+ "DEVICE_DSP",
+ (u8 *)pdwValue, &dwBufSize);
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "Failed to Identify the Device to Fetch \n");
+ }
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ GT_1trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetDevObject SUCCESS DevObject"
+ ": 0x%x\n ", *pdwValue);
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_GetDevObject Failed \n");
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== CFG_GetDSPResources ========
+ * Purpose:
+ * Get the DSP resources available to a given device.
+ */
+DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
+ OUT struct CFG_DSPRES *pDSPResTable)
+{
+ DSP_STATUS status = DSP_SOK; /* return value */
+ u32 dwResSize;
+ GT_2trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_GetDSPResources, args: "
+ "\n\thDevNode: 0x%x\n\tpDSPResTable: 0x%x\n",
+ hDevNode, pDSPResTable);
+ if (!hDevNode) {
+ status = CFG_E_INVALIDHDEVNODE;
+ } else if (!pDSPResTable) {
+ status = CFG_E_INVALIDPOINTER;
+ } else {
+ status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
+ (u8 *)pDSPResTable,
+ &dwResSize);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetDSPResources SUCCESS\n");
+ } else {
+ status = CFG_E_RESOURCENOTAVAIL;
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_GetDSPResources Failed \n");
+ }
+#ifdef DEBUG
+ /* assert that resource values are reasonable */
+ DBC_Assert(pDSPResTable->uChipType < 256);
+ DBC_Assert(pDSPResTable->uWordSize > 0);
+ DBC_Assert(pDSPResTable->uWordSize < 32);
+ DBC_Assert(pDSPResTable->cChips > 0);
+ DBC_Assert(pDSPResTable->cChips < 256);
+#endif
+ return status;
+}
+
+/*
+ * ======== CFG_GetExecFile ========
+ * Purpose:
+ * Retreive the default executable, if any, for this board.
+ */
+DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
+ OUT char *pstrExecFile)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 cExecSize = ulBufSize;
+ GT_3trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_GetExecFile:\n\tthDevNode: "
+ "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
+ ulBufSize, pstrExecFile);
+ if (!hDevNode)
+ status = CFG_E_INVALIDHDEVNODE;
+
+ if (!pstrExecFile)
+ status = CFG_E_INVALIDPOINTER;
+
+ if (DSP_SUCCEEDED(status)) {
+ status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
+ (u8 *)pstrExecFile, &cExecSize);
+ if (DSP_FAILED(status))
+ status = CFG_E_RESOURCENOTAVAIL;
+ else if (cExecSize > ulBufSize)
+ status = DSP_ESIZE;
+
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ GT_1trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetExecFile SUCCESS Exec File"
+ "name : %s\n ", pstrExecFile);
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_GetExecFile Failed \n");
+ }
+#endif
+ DBC_Ensure(((status == DSP_SOK) &&
+ (strlen(pstrExecFile) <= ulBufSize)) || (status != DSP_SOK));
+ return status;
+}
+
+/*
+ * ======== CFG_GetHostResources ========
+ * Purpose:
+ * Get the Host allocated resources assigned to a given device.
+ */
+DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
+ OUT struct CFG_HOSTRES *pHostResTable)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 dwBufSize;
+ GT_2trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_GetHostResources, args:\n\t"
+ "pHostResTable: 0x%x\n\thDevNode: 0x%x\n",
+ pHostResTable, hDevNode);
+ if (!hDevNode)
+ status = CFG_E_INVALIDHDEVNODE;
+
+ if (!pHostResTable)
+ status = CFG_E_INVALIDPOINTER;
+
+ if (DSP_SUCCEEDED(status)) {
+ dwBufSize = sizeof(struct CFG_HOSTRES);
+ if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
+ CURRENTCONFIG,
+ (u8 *)pHostResTable, &dwBufSize))) {
+ status = CFG_E_RESOURCENOTAVAIL;
+ }
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetHostResources SUCCESS \n");
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_GetHostResources Failed \n");
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== CFG_GetObject ========
+ * Purpose:
+ * Retrieve the Object handle from the Registry
+ */
+DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
+{
+ DSP_STATUS status = DSP_EINVALIDARG;
+ u32 dwBufSize;
+ DBC_Require(pdwValue != NULL);
+ GT_1trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_GetObject, args:pdwValue: "
+ "0x%x\n", *pdwValue);
+ dwBufSize = sizeof(pdwValue);
+ switch (dwType) {
+ case (REG_DRV_OBJECT):
+ status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
+ (u8 *)pdwValue,
+ &dwBufSize);
+ break;
+ case (REG_MGR_OBJECT):
+ status = REG_GetValue(NULL, CONFIG, MGROBJECT,
+ (u8 *)pdwValue,
+ &dwBufSize);
+ break;
+ default:
+ break;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ GT_1trace(CFG_debugMask, GT_1CLASS,
+ "CFG_GetObject SUCCESS DrvObject: "
+ "0x%x\n ", *pdwValue);
+ } else {
+ status = CFG_E_RESOURCENOTAVAIL;
+ *pdwValue = 0;
+ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
+ (DSP_FAILED(status) && *pdwValue == 0));
+ return status;
+}
+
+/*
+ * ======== CFG_Init ========
+ * Purpose:
+ * Initialize the CFG module's private state.
+ */
+bool CFG_Init(void)
+{
+ struct CFG_DSPRES dspResources;
+ GT_create(&CFG_debugMask, "CF"); /* CF for ConFig */
+ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
+ GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
+
+ dspResources.uChipType = DSPTYPE_64;
+ dspResources.cChips = 1;
+ dspResources.uWordSize = DSPWORDSIZE;
+ dspResources.cMemTypes = 0;
+ dspResources.aMemDesc[0].uMemType = 0;
+ dspResources.aMemDesc[0].ulMin = 0;
+ dspResources.aMemDesc[0].ulMax = 0;
+ if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
+ (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
+ GT_0trace(CFG_debugMask, GT_5CLASS,
+ "Initialized DSP resources in "
+ "Registry \n");
+ } else
+ GT_0trace(CFG_debugMask, GT_5CLASS,
+ "Failed to Initialize DSP resources"
+ " in Registry \n");
+ return true;
+}
+
+/*
+ * ======== CFG_SetDevObject ========
+ * Purpose:
+ * Store the Device Object handle and devNode pointer for a given devnode.
+ */
+DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 dwBuffSize;
+ GT_2trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_SetDevObject, args: \n\t"
+ "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
+ if (!hDevNode)
+ status = CFG_E_INVALIDHDEVNODE;
+
+ dwBuffSize = sizeof(dwValue);
+ if (DSP_SUCCEEDED(status)) {
+ /* Store the WCD device object in the Registry */
+
+ if (!(strcmp((char *)hDevNode, "TIOMAP1510"))) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "Registering the DSP Device \n");
+ status = REG_SetValue(NULL, (char *)hDevNode,
+ "DEVICE_DSP", REG_DWORD,\
+ (u8 *)&dwValue, dwBuffSize);
+ if (DSP_SUCCEEDED(status)) {
+ dwBuffSize = sizeof(hDevNode);
+ status = REG_SetValue(NULL,
+ (char *)hDevNode, "DEVNODESTRING_DSP",
+ REG_DWORD, (u8 *)&hDevNode,
+ dwBuffSize);
+ }
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "Failed to Register Device \n");
+ }
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status)) {
+ GT_0trace(CFG_debugMask, GT_1CLASS,
+ "CFG_SetDevObject SUCCESS \n");
+ } else {
+ GT_0trace(CFG_debugMask, GT_6CLASS,
+ "CFG_SetDevObject Failed \n");
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== CFG_SetObject ========
+ * Purpose:
+ * Store the Driver Object handle
+ */
+DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
+{
+ DSP_STATUS status = DSP_EINVALIDARG;
+ u32 dwBuffSize;
+ GT_1trace(CFG_debugMask, GT_ENTER,
+ "Entered CFG_SetObject, args: dwValue: "
+ "0x%x\n", dwValue);
+ dwBuffSize = sizeof(dwValue);
+ switch (dwType) {
+ case (REG_DRV_OBJECT):
+ status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
+ (u8 *)&dwValue, dwBuffSize);
+ break;
+ case (REG_MGR_OBJECT):
+ status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
+ (u8 *) &dwValue, dwBuffSize);
+ break;
+ default:
+ break;
+ }
+#ifdef DEBUG
+ if (DSP_SUCCEEDED(status))
+ GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
+ else
+ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
+
+#endif
+ return status;
+}
diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
new file mode 100644
index 000000000000..b499b1464d0c
--- /dev/null
+++ b/drivers/dsp/bridge/services/clk.c
@@ -0,0 +1,375 @@
+/*
+ * clk.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== clk.c ========
+ * Purpose:
+ * Clock and Timer services.
+ *
+ * Public Functions:
+ * CLK_Exit
+ * CLK_Init
+ * CLK_Enable
+ * CLK_Disable
+ * CLK_GetRate
+ * CLK_Set_32KHz
+ *! Revision History:
+ *! ================
+ *! 08-May-2007 rg: moved all clock functions from sync module.
+ * And added CLK_Set_32KHz, CLK_Set_SysClk.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/clk.h>
+#include <dspbridge/util.h>
+
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+
+typedef volatile unsigned long REG_UWORD32;
+
+#define SSI_Base 0x48058000
+
+#define SSI_BASE IO_ADDRESS(SSI_Base)
+
+
+struct SERVICES_Clk_t {
+ struct clk *clk_handle;
+ const char *clk_name;
+ int id;
+};
+
+/* The row order of the below array needs to match with the clock enumerations
+ * 'SERVICES_ClkId' provided in the header file.. any changes in the
+ * enumerations needs to be fixed in the array as well */
+static struct SERVICES_Clk_t SERVICES_Clks[] = {
+ {NULL, "iva2_ck", -1},
+ {NULL, "mailboxes_ick", -1},
+ {NULL, "gpt5_fck", -1},
+ {NULL, "gpt5_ick", -1},
+ {NULL, "gpt6_fck", -1},
+ {NULL, "gpt6_ick", -1},
+ {NULL, "gpt7_fck", -1},
+ {NULL, "gpt7_ick", -1},
+ {NULL, "gpt8_fck", -1},
+ {NULL, "gpt8_ick", -1},
+ {NULL, "wdt_fck", 3},
+ {NULL, "wdt_ick", 3},
+ {NULL, "mcbsp_fck", 1},
+ {NULL, "mcbsp_ick", 1},
+ {NULL, "mcbsp_fck", 2},
+ {NULL, "mcbsp_ick", 2},
+ {NULL, "mcbsp_fck", 3},
+ {NULL, "mcbsp_ick", 3},
+ {NULL, "mcbsp_fck", 4},
+ {NULL, "mcbsp_ick", 4},
+ {NULL, "mcbsp_fck", 5},
+ {NULL, "mcbsp_ick", 5},
+ {NULL, "ssi_ssr_sst_fck", -1},
+ {NULL, "ssi_ick", -1},
+ {NULL, "omap_32k_fck", -1},
+ {NULL, "sys_ck", -1},
+ {NULL, ""}
+};
+
+/* Generic TIMER object: */
+struct TIMER_OBJECT {
+ struct timer_list timer;
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+/*
+ * ======== CLK_Exit ========
+ * Purpose:
+ * Cleanup CLK module.
+ */
+void CLK_Exit(void)
+{
+ int i = 0;
+
+ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
+ /* Relinquish the clock handles */
+ while (i < SERVICESCLK_NOT_DEFINED) {
+ if (SERVICES_Clks[i].clk_handle)
+ clk_put(SERVICES_Clks[i].clk_handle);
+
+ SERVICES_Clks[i].clk_handle = NULL;
+ i++;
+ }
+
+}
+
+/*
+ * ======== CLK_Init ========
+ * Purpose:
+ * Initialize CLK module.
+ */
+bool CLK_Init(void)
+{
+ static struct platform_device dspbridge_device;
+ struct clk *clk_handle;
+ int i = 0;
+ GT_create(&CLK_debugMask, "CK"); /* CK for CLK */
+ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
+
+ dspbridge_device.dev.bus = &platform_bus_type;
+
+ /* Get the clock handles from base port and store locally */
+ while (i < SERVICESCLK_NOT_DEFINED) {
+ /* get the handle from BP */
+ dspbridge_device.id = SERVICES_Clks[i].id;
+
+ clk_handle = clk_get(&dspbridge_device.dev,
+ SERVICES_Clks[i].clk_name);
+
+ if (!clk_handle) {
+ GT_2trace(CLK_debugMask, GT_7CLASS,
+ "CLK_Init: failed to get Clk handle %s, "
+ "CLK dev id = %d\n",
+ SERVICES_Clks[i].clk_name,
+ SERVICES_Clks[i].id);
+ /* should we fail here?? */
+ } else {
+ GT_2trace(CLK_debugMask, GT_7CLASS,
+ "CLK_Init: PASS and Clk handle %s, "
+ "CLK dev id = %d\n",
+ SERVICES_Clks[i].clk_name,
+ SERVICES_Clks[i].id);
+ }
+ SERVICES_Clks[i].clk_handle = clk_handle;
+ i++;
+ }
+
+ return true;
+}
+
+/*
+ * ======== CLK_Enable ========
+ * Purpose:
+ * Enable Clock .
+ *
+*/
+DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct clk *pClk;
+
+ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
+ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Enable: CLK %s, "
+ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+
+ pClk = SERVICES_Clks[clk_id].clk_handle;
+ if (pClk) {
+ if (clk_enable(pClk) == 0x0) {
+ /* Success ? */
+ } else {
+ pr_err("CLK_Enable: failed to Enable CLK %s, "
+ "CLK dev id = %d\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ } else {
+ pr_err("CLK_Enable: failed to get CLK %s, CLK dev id = %d\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ /* The SSI module need to configured not to have the Forced idle for
+ * master interface. If it is set to forced idle, the SSI module is
+ * transitioning to standby thereby causing the client in the DSP hang
+ * waiting for the SSI module to be active after enabling the clocks
+ */
+ if (clk_id == SERVICESCLK_ssi_fck)
+ SSI_Clk_Prepare(true);
+
+ return status;
+}
+/*
+ * ======== CLK_Set_32KHz ========
+ * Purpose:
+ * To Set parent of a clock to 32KHz.
+ */
+
+DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct clk *pClk;
+ struct clk *pClkParent;
+ enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
+ pClkParent = SERVICES_Clks[sys_32k_id].clk_handle;
+
+ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
+ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK %s, "
+ "CLK dev id = %d is setting to 32KHz \n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ pClk = SERVICES_Clks[clk_id].clk_handle;
+ if (pClk) {
+ if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
+ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_Set_32KHz: "
+ "Failed to set to 32KHz %s, CLK dev id = %d\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== CLK_Disable ========
+ * Purpose:
+ * Disable the clock.
+ *
+*/
+DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct clk *pClk;
+ s32 clkUseCnt;
+
+ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
+ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Disable: CLK %s, "
+ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+
+ pClk = SERVICES_Clks[clk_id].clk_handle;
+
+ clkUseCnt = CLK_Get_UseCnt(clk_id);
+ if (clkUseCnt == -1) {
+ pr_err("CLK_Disable: failed to get CLK Use count for CLK %s,"
+ "CLK dev id = %d\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ } else if (clkUseCnt == 0) {
+ pr_err("CLK_Disable: CLK %s, CLK dev id= %d is already"
+ "disabled\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ return status;
+ }
+ if (clk_id == SERVICESCLK_ssi_ick)
+ SSI_Clk_Prepare(false);
+
+ if (pClk) {
+ clk_disable(pClk);
+ } else {
+ pr_err("CLK_Disable: failed to get CLK %s,"
+ "CLK dev id = %d\n",
+ SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ return status;
+}
+
+/*
+ * ======== CLK_GetRate ========
+ * Purpose:
+ * GetClock Speed.
+ *
+ */
+
+DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct clk *pClk;
+ u32 clkSpeedHz;
+
+ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
+ *speedKhz = 0x0;
+
+ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_GetRate: CLK %s, "
+ "CLK dev Id = %d \n", SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ pClk = SERVICES_Clks[clk_id].clk_handle;
+ if (pClk) {
+ clkSpeedHz = clk_get_rate(pClk);
+ *speedKhz = clkSpeedHz / 1000;
+ GT_2trace(CLK_debugMask, GT_6CLASS,
+ "CLK_GetRate: clkSpeedHz = %d , "
+ "speedinKhz=%d\n", clkSpeedHz, *speedKhz);
+ } else {
+ GT_2trace(CLK_debugMask, GT_7CLASS,
+ "CLK_GetRate: failed to get CLK %s, "
+ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ return status;
+}
+
+s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct clk *pClk;
+ s32 useCount = -1;
+ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
+
+ pClk = SERVICES_Clks[clk_id].clk_handle;
+
+ if (pClk) {
+ useCount = pClk->usecount; /* FIXME: usecount shouldn't be used */
+ } else {
+ GT_2trace(CLK_debugMask, GT_7CLASS,
+ "CLK_GetRate: failed to get CLK %s, "
+ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
+ SERVICES_Clks[clk_id].id);
+ status = DSP_EFAIL;
+ }
+ return useCount;
+}
+
+void SSI_Clk_Prepare(bool FLAG)
+{
+ u32 ssi_sysconfig;
+ ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
+
+ if (FLAG) {
+ /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
+ * no idle
+ */
+ ssi_sysconfig = 0x1011;
+ } else {
+ /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
+ * forced idle
+ */
+ ssi_sysconfig = 0x1;
+ }
+ __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
+}
diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
new file mode 100644
index 000000000000..dd33c2d2973d
--- /dev/null
+++ b/drivers/dsp/bridge/services/csl.c
@@ -0,0 +1,173 @@
+/*
+ * csl.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== cslce.c ========
+ * Purpose:
+ * Provides platform independent C Standard library functions.
+ *
+ * Public Functions:
+ * CSL_Atoi
+ * CSL_Exit
+ * CSL_Init
+ * CSL_NumToAscii
+ * CSL_Strtokr
+ *
+ *! Revision History:
+ *! ================
+ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
+ *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
+ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
+ *! 19-Nov-2000 kc: Added CSL_ByteSwap.
+ *! 09-Nov-2000 kc: Added CSL_Strncat.
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
+ *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
+ *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
+ * CSP_Init().
+ *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
+ *! Removed call to GT_set().
+ *! 19-Jan-1998 cr: Code review cleanup.
+ *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
+ *! combined csl32.c csl95.c and cslnt.c into csl.c. Also
+ *! changed CSL_lowercase to CSL_Uppercase.
+ *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
+ *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/csl.h>
+
+/* Is character c in the string pstrDelim? */
+#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
+ (strchr(pstrDelim, c) != NULL))
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
+#endif
+
+/*
+ * ======== CSL_Exit ========
+ * Purpose:
+ * Discontinue usage of the CSL module.
+ */
+void CSL_Exit(void)
+{
+ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
+}
+
+/*
+ * ======== CSL_Init ========
+ * Purpose:
+ * Initialize the CSL module's private state.
+ */
+bool CSL_Init(void)
+{
+ GT_create(&CSL_DebugMask, "CS");
+
+ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== CSL_NumToAscii ========
+ * Purpose:
+ * Convert a 1 or 2 digit number to a 2 digit string.
+ */
+void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
+{
+ char tens;
+
+ DBC_Require(dwNum < 100);
+
+ if (dwNum < 100) {
+ tens = (char) dwNum / 10;
+ dwNum = dwNum % 10;
+
+ if (tens) {
+ pstrNumber[0] = tens + '0';
+ pstrNumber[1] = (char) dwNum + '0';
+ pstrNumber[2] = '\0';
+ } else {
+ pstrNumber[0] = (char) dwNum + '0';
+ pstrNumber[1] = '\0';
+ }
+ } else {
+ pstrNumber[0] = '\0';
+ }
+}
+
+
+
+
+/*
+ * ======= CSL_Strtokr =======
+ * Purpose:
+ * Re-entrant version of strtok.
+ */
+char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
+ OUT char **ppstrLast)
+{
+ char *pstrTemp;
+ char *pstrToken;
+
+ DBC_Require(szSeparators != NULL);
+ DBC_Require(ppstrLast != NULL);
+ DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
+
+ /*
+ * Set string location to beginning (pstrSrc != NULL) or to the
+ * beginning of the next token.
+ */
+ pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
+ if (*pstrTemp == '\0') {
+ pstrToken = NULL;
+ } else {
+ pstrToken = pstrTemp;
+ while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
+ szSeparators)) {
+ pstrTemp++;
+ }
+ if (*pstrTemp != '\0') {
+ while (IsDelimiter(*pstrTemp, szSeparators)) {
+ /* TODO: Shouldn't we do this for
+ * only 1 char?? */
+ *pstrTemp = '\0';
+ pstrTemp++;
+ }
+ }
+
+ /* Location in string for next call */
+ *ppstrLast = pstrTemp;
+ }
+
+ return pstrToken;
+}
diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
new file mode 100644
index 000000000000..5e1773ff41e7
--- /dev/null
+++ b/drivers/dsp/bridge/services/dbg.c
@@ -0,0 +1,119 @@
+/*
+ * dbg.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dbgce.c ========
+ * Purpose:
+ * Provide debugging services for DSP/BIOS Bridge Mini Drivers.
+ *
+ * Public Functions:
+ * DBG_Exit
+ * DBG_Init
+ * DBG_Trace
+ *
+ * Notes:
+ * Requires gt.h.
+ *
+ * This implementation does not create GT masks on a per WMD basis.
+ * There is currently no facility for a WMD to alter the GT mask.
+ *
+ *! Revision History:
+ *! ================
+ *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 29-Oct-1999 kc: Cleaned up for code review.
+ *! 10-Oct-1997 cr: Added DBG_Printf service.
+ *! 28-May-1997 cr: Added reference counting.
+ *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
+ *! 29-May-1996 gp: Removed WCD_ prefix.
+ *! 20-May-1996 gp: Remove DEBUG conditional compilation.
+ *! 15-May-1996 gp: Created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
+#endif
+
+#if (defined(DEBUG) || defined (DDSP_DEBUG_PRODUCT)) && GT_TRACE
+
+/*
+ * ======== DBG_Init ========
+ * Purpose:
+ * Ensures trace capability is set up for link drivers.
+ */
+bool DBG_Init(void)
+{
+ GT_create(&DBG_debugMask, "WD"); /* for WmD (link driver) debug */
+
+ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== DBG_Trace ========
+ * Purpose:
+ * Output a trace message to the debugger, if the given trace level
+ * is unmasked.
+ */
+DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
+{
+ s32 arg1, arg2, arg3, arg4, arg5, arg6;
+ va_list va;
+
+ va_start(va, pstrFormat);
+
+ arg1 = va_arg(va, s32);
+ arg2 = va_arg(va, s32);
+ arg3 = va_arg(va, s32);
+ arg4 = va_arg(va, s32);
+ arg5 = va_arg(va, s32);
+ arg6 = va_arg(va, s32);
+
+ va_end(va);
+
+ if (bLevel & *(DBG_debugMask).flags)
+ printk(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
+
+ return DSP_SOK;
+}
+
+/*
+ * ======== DBG_Exit ========
+ * Purpose:
+ * Discontinue usage of the DBG module.
+ */
+void DBG_Exit(void)
+{
+ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
+}
+
+#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
new file mode 100644
index 000000000000..bd608d161e4c
--- /dev/null
+++ b/drivers/dsp/bridge/services/dpc.c
@@ -0,0 +1,274 @@
+/*
+ * dpc.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dpcce.c ========
+ * Purpose:
+ * Deferred Procedure Call(DPC) Services.
+ *
+ *
+ * Public Functions:
+ * DPC_Create
+ * DPC_Destroy
+ * DPC_Exit
+ * DPC_Init
+ * DPC_Schedule
+ *
+ *! Revision History:
+ *! ================
+ *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
+ *! to THREAD_PRIORITY_IDLE for polling IPC.
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
+ *! modified.DPC_Destroy frees the DPC_Object only on
+ *! Successful termination of the thread and the handle.
+ *! 06-Jan-1999 ag: Format cleanup for code review.
+ *! Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
+ *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
+ *! (Needed to access client(s) CHNL buffers).
+ *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/dpc.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define SIGNATURE 0x5f435044 /* "DPC_" (in reverse). */
+
+/* The DPC object, passed to our priority event callback routine: */
+struct DPC_OBJECT {
+ u32 dwSignature; /* Used for object validation. */
+ void *pRefData; /* Argument for client's DPC. */
+ DPC_PROC pfnDPC; /* Client's DPC. */
+ u32 numRequested; /* Number of requested DPC's. */
+ u32 numScheduled; /* Number of executed DPC's. */
+ struct tasklet_struct dpc_tasklet;
+
+#ifdef DEBUG
+ u32 cEntryCount; /* Number of times DPC reentered. */
+ u32 numRequestedMax; /* Keep track of max pending DPC's. */
+#endif
+
+ spinlock_t dpc_lock;
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
+#endif
+
+/* ----------------------------------- Function Prototypes */
+static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
+
+/*
+ * ======== DPC_Create ========
+ * Purpose:
+ * Create a DPC object, allowing a client's own DPC procedure to be
+ * scheduled for a call with client reference data.
+ */
+DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
+ void *pRefData)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DPC_OBJECT *pDPCObject = NULL;
+
+ if ((phDPC != NULL) && (pfnDPC != NULL)) {
+ /*
+ * Allocate a DPC object to store information allowing our DPC
+ * callback to dispatch to the client's DPC.
+ */
+ MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
+ if (pDPCObject != NULL) {
+ tasklet_init(&pDPCObject->dpc_tasklet,
+ DPC_DeferredProcedure,
+ (u32) pDPCObject);
+ /* Fill out our DPC Object: */
+ pDPCObject->pRefData = pRefData;
+ pDPCObject->pfnDPC = pfnDPC;
+ pDPCObject->numRequested = 0;
+ pDPCObject->numScheduled = 0;
+#ifdef DEBUG
+ pDPCObject->numRequestedMax = 0;
+ pDPCObject->cEntryCount = 0;
+#endif
+ spin_lock_init(&pDPCObject->dpc_lock);
+ *phDPC = pDPCObject;
+ } else {
+ GT_0trace(DPC_DebugMask, GT_6CLASS,
+ "DPC_Create: DSP_EMEMORY\n");
+ status = DSP_EMEMORY;
+ }
+ } else {
+ GT_0trace(DPC_DebugMask, GT_6CLASS,
+ "DPC_Create: DSP_EPOINTER\n");
+ status = DSP_EPOINTER;
+ }
+ DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
+ || DSP_SUCCEEDED(status));
+ return status;
+}
+
+/*
+ * ======== DPC_Destroy ========
+ * Purpose:
+ * Cancel the last scheduled DPC, and deallocate a DPC object previously
+ * allocated with DPC_Create(). Frees the Object only if the thread
+ * and the event terminated successfuly.
+ */
+DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
+
+ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
+
+ /* Free our DPC object: */
+ if (DSP_SUCCEEDED(status)) {
+ tasklet_kill(&pDPCObject->dpc_tasklet);
+ MEM_FreeObject(pDPCObject);
+ pDPCObject = NULL;
+ GT_0trace(DPC_DebugMask, GT_2CLASS,
+ "DPC_Destroy: SUCCESS\n");
+ }
+ } else {
+ GT_0trace(DPC_DebugMask, GT_6CLASS,
+ "DPC_Destroy: DSP_EHANDLE\n");
+ status = DSP_EHANDLE;
+ }
+ DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
+ || DSP_FAILED(status));
+ return status;
+}
+
+/*
+ * ======== DPC_Exit ========
+ * Purpose:
+ * Discontinue usage of the DPC module.
+ */
+void DPC_Exit(void)
+{
+ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
+}
+
+/*
+ * ======== DPC_Init ========
+ * Purpose:
+ * Initialize the DPC module's private state.
+ */
+bool DPC_Init(void)
+{
+ GT_create(&DPC_DebugMask, "DP");
+
+ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== DPC_Schedule ========
+ * Purpose:
+ * Schedule a deferred procedure call to be executed at a later time.
+ * Latency and order of DPC execution is platform specific.
+ */
+DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
+ unsigned long flags;
+
+ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
+ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
+ /* Increment count of DPC's pending. Needs to be protected
+ * from ISRs since this function is called from process
+ * context also. */
+ spin_lock_irqsave(&hDPC->dpc_lock, flags);
+ pDPCObject->numRequested++;
+ spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
+ tasklet_schedule(&(hDPC->dpc_tasklet));
+#ifdef DEBUG
+ if (pDPCObject->numRequested > pDPCObject->numScheduled +
+ pDPCObject->numRequestedMax) {
+ pDPCObject->numRequestedMax = pDPCObject->numRequested -
+ pDPCObject->numScheduled;
+ }
+#endif
+ /* If an interrupt occurs between incrementing numRequested and the
+ * assertion below, then DPC will get executed while returning from
+ * ISR, which will complete all requests and make numRequested equal
+ * to numScheduled, firing this assertion. This happens only when
+ * DPC is being scheduled in process context */
+ } else {
+ GT_0trace(DPC_DebugMask, GT_6CLASS,
+ "DPC_Schedule: DSP_EHANDLE\n");
+ status = DSP_EHANDLE;
+ }
+ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
+ return status;
+}
+
+/*
+ * ======== DeferredProcedure ========
+ * Purpose:
+ * Main DPC routine. This is called by host OS DPC callback
+ * mechanism with interrupts enabled.
+ */
+static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
+{
+ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
+ /* read numRequested in local variable */
+ u32 requested;
+ u32 serviced;
+
+ DBC_Require(pDPCObject != NULL);
+ requested = pDPCObject->numRequested;
+ serviced = pDPCObject->numScheduled;
+
+ GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
+ "pDeferredContext=%x\n", pDeferredContext);
+ /* Rollover taken care of using != instead of < */
+ if (serviced != requested) {
+ if (pDPCObject->pfnDPC != NULL) {
+ /* Process pending DPC's: */
+ do {
+ /* Call client's DPC: */
+ (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
+ serviced++;
+ } while (serviced != requested);
+ }
+ pDPCObject->numScheduled = requested;
+ }
+ GT_2trace(DPC_DebugMask, GT_ENTER,
+ "< DPC_DeferredProcedure requested %d"
+ " serviced %d\n", requested, serviced);
+}
+
diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
new file mode 100644
index 000000000000..ba1d26fea786
--- /dev/null
+++ b/drivers/dsp/bridge/services/kfile.c
@@ -0,0 +1,338 @@
+/*
+ * kfile.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== kfilece.c ========
+ * Purpose:
+ * This module provides file i/o services.
+ *
+ * Public Functions:
+ * KFILE_Close
+ * KFILE_Exit
+ * KFILE_Init
+ * KFILE_Open
+ * KFILE_Read
+ * KFILE_Seek
+ * KFILE_Tell
+ *
+ *! Revision History
+ *! ================
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 22-Nov-1999 kc: Added changes from code review.
+ *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
+ *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
+ *! Removed GT_set().
+ *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
+ *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/kfile.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define SIGNATURE 0x4c49464b /* hex code of KFIL (reversed) */
+#define MAXFILENAMELENGTH 256
+#define GENERAL_FAILURE 0xffffffff /* SetFilePointer error */
+
+/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
+struct KFILE_FileObj {
+ u32 dwSignature;
+ __kernel_pid_t owner_pid; /* PID of process that opened this file */
+ char *fileName ;
+ bool isOpen ;
+ u32 size ;
+ u32 curPos ;
+ long hInternal; /* internal handle of file */
+ struct file *fileDesc;
+
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask KFILE_debugMask = { NULL, NULL }; /* Debug mask */
+#endif
+
+/*
+ * ======== KFILE_Close ========
+ * Purpose:
+ * This function closes a file's stream.
+ */
+s32 KFILE_Close(struct KFILE_FileObj *hFile)
+{
+ s32 cRetVal = 0; /* 0 indicates success */
+ s32 fRetVal = 0;
+ __kernel_pid_t curr_pid;
+
+ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
+ hFile);
+
+ /* Check for valid handle */
+ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
+ /* Close file only if opened by the same process (id). Otherwise
+ * Linux closes all open file handles when process exits.*/
+ /* Return PID instead of process handle */
+ curr_pid = (__kernel_pid_t)current->pid;
+ fRetVal = filp_close(hFile->fileDesc, NULL) ;
+ if (fRetVal) {
+ cRetVal = E_KFILE_ERROR;
+ GT_1trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Close: sys_close "
+ "returned %d\n", fRetVal);
+ }
+ MEM_FreeObject(hFile);
+ } else {
+ cRetVal = E_KFILE_INVALIDHANDLE;
+ GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
+ "invalid file handle\n");
+ }
+ return cRetVal;
+}
+
+/*
+ * ======== KFILE_Exit ========
+ * Purpose:
+ * Decrement reference count, and free resources when reference count
+ * is 0.
+ */
+void KFILE_Exit(void)
+{
+ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
+}
+
+/*
+ * ======== KFILE_Init ========
+ */
+bool KFILE_Init(void)
+{
+ GT_create(&KFILE_debugMask, "KF"); /* "KF" for KFile */
+
+ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== KFILE_Open ========
+ * Purpose:
+ * Open a file for reading ONLY
+ */
+struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
+{
+ struct KFILE_FileObj *hFile; /* file handle */
+ DSP_STATUS status;
+ mm_segment_t fs;
+
+ struct file*fileDesc = NULL;
+ DBC_Require(pszMode != NULL);
+ DBC_Require(pszFileName != NULL);
+
+ GT_2trace(KFILE_debugMask, GT_ENTER,
+ "KFILE_Open: pszFileName %s, pszMode "
+ "%s\n", pszFileName, pszMode);
+
+ /* create a KFILE object */
+ MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
+
+ if (hFile) {
+ fs = get_fs();
+ set_fs(get_ds());
+ /* Third argument is mode (permissions). Ignored unless creating file */
+ fileDesc = filp_open(pszFileName, O_RDONLY, 0);
+ if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
+ (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
+ || (fileDesc->f_op->llseek == NULL)) {
+ status = DSP_EFILE;
+ } else {
+ hFile->fileDesc = fileDesc;
+ hFile->fileName = (char *)pszFileName;
+ hFile->isOpen = true;
+ hFile->curPos = 0;
+ hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
+ SEEK_END);
+ fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
+ /* Return PID instead of process handle */
+ hFile->owner_pid = current->pid;
+
+ status = DSP_SOK;
+ }
+ set_fs(fs);
+ if (DSP_FAILED(status)) {
+ /* free memory, and clear handle */
+ MEM_FreeObject(hFile);
+ hFile = NULL;
+ }
+ } else {
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Open: MEM_AllocObject failed\n");
+ status = DSP_EMEMORY;
+ }
+ return hFile;
+}
+
+/*
+ * ======== KFILE_Read ========
+ * Purpose:
+ * Reads a specified number of bytes into a buffer.
+ */
+s32
+KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount,
+ struct KFILE_FileObj *hFile)
+{
+ u32 dwBytesRead = 0;
+ s32 cRetVal = 0;
+ mm_segment_t fs;
+
+ DBC_Require(pBuffer != NULL);
+
+ GT_4trace(KFILE_debugMask, GT_4CLASS,
+ "KFILE_Read: buffer 0x%x, cSize 0x%x,"
+ "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
+
+ /* check for valid file handle */
+ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
+ if ((cSize > 0) && (cCount > 0) && pBuffer) {
+ /* read from file */
+ fs = get_fs();
+ set_fs(get_ds());
+ dwBytesRead = hFile->fileDesc->f_op->read(hFile->
+ fileDesc, pBuffer, cSize *cCount,
+ &(hFile->fileDesc->f_pos));
+ set_fs(fs);
+ if (dwBytesRead) {
+ cRetVal = dwBytesRead / cSize;
+ hFile->curPos += dwBytesRead;
+ DBC_Assert((dwBytesRead / cSize) <= \
+ (u32)cCount);
+ } else {
+ cRetVal = E_KFILE_ERROR;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Read: sys_read() failed\n");
+ }
+ } else {
+ cRetVal = DSP_EINVALIDARG;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Read: Invalid argument(s)\n");
+ }
+ } else {
+ cRetVal = E_KFILE_INVALIDHANDLE;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Read: invalid file handle\n");
+ }
+
+ return cRetVal;
+}
+
+/*
+ * ======== KFILE_Seek ========
+ * Purpose:
+ * Sets the file position indicator. NOTE: we don't support seeking
+ * beyond the boundaries of a file.
+ */
+s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
+{
+ s32 cRetVal = 0; /* 0 for success */
+ u32 dwCurPos = 0;
+
+ struct file *fileDesc = NULL;
+
+ GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
+ "lOffset 0x%x, cOrigin 0x%x\n",
+ hFile, lOffset, cOrigin);
+
+ /* check for valid file handle */
+ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
+ /* based on the origin flag, move the internal pointer */
+
+ fileDesc = hFile->fileDesc;
+ switch (cOrigin) {
+ case KFILE_SEEK_SET:
+ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
+ fileDesc, lOffset, SEEK_SET);
+ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
+ break;
+
+ case KFILE_SEEK_CUR:
+ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
+ fileDesc, lOffset, SEEK_CUR);
+ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
+ break;
+ case KFILE_SEEK_END:
+ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
+ fileDesc, lOffset, SEEK_END);
+ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
+ break;
+ default:
+ cRetVal = E_KFILE_BADORIGINFLAG;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Seek:bad origin flag\n");
+ break;
+ }
+ } else {
+ cRetVal = E_KFILE_INVALIDHANDLE;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Seek:invalid file handle\n");
+ }
+ return cRetVal;
+}
+
+/*
+ * ======== KFILE_Tell ========
+ * Purpose:
+ * Reports the current value of the position indicator. We did not
+ * consider 64 bit long file size, which implies a 4GB file limit
+ * (2 to 32 power).
+ */
+s32 KFILE_Tell(struct KFILE_FileObj *hFile)
+{
+ u32 dwCurPos = 0;
+ s32 lRetVal = E_KFILE_ERROR;
+
+ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
+
+ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
+
+ /* Get current position. */
+ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
+ SEEK_CUR);
+ if (dwCurPos >= 0)
+ lRetVal = dwCurPos;
+
+ } else {
+ lRetVal = E_KFILE_INVALIDHANDLE;
+ GT_0trace(KFILE_debugMask, GT_6CLASS,
+ "KFILE_Seek:invalid file handle\n");
+ }
+ return lRetVal;
+}
+
diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
new file mode 100644
index 000000000000..7fa3e76e940a
--- /dev/null
+++ b/drivers/dsp/bridge/services/list.c
@@ -0,0 +1,285 @@
+/*
+ * list.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== listce.c ========
+ * Purpose
+ * Provides standard circular list handling functions.
+ *
+ * Public Functions:
+ * LST_Create
+ * LST_Delete
+ * LST_Exit
+ * LST_First
+ * LST_GetHead
+ * LST_Init
+ * LST_InitElem
+ * LST_InsertBefore
+ * LST_Next
+ * LST_PutTail
+ * LST_RemoveElem
+ *
+ *! Revision History
+ *! ================
+ *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
+ *! 10-Aug-2000 ag: Added LST_InsertBefore().
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 22-Nov-1999 kc: Added changes from code review.
+ *! 10-Aug-1999 kc: Based on wsx-c18.
+ *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
+ *! list manipulation code.
+ *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
+ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/list.h>
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
+#endif
+
+/*
+ * ======== LST_Create ========
+ * Purpose:
+ * Allocates and initializes a circular list.
+ */
+struct LST_LIST *LST_Create(void)
+{
+ struct LST_LIST *pList;
+
+ GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
+
+ pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
+ MEM_NONPAGED);
+ if (pList != NULL) {
+ pList->head.next = &pList->head;
+ pList->head.prev = &pList->head;
+ pList->head.self = NULL;
+ }
+
+ return pList;
+}
+
+/*
+ * ======== LST_Delete ========
+ * Purpose:
+ * Removes a list by freeing its control structure's memory space.
+ */
+void LST_Delete(struct LST_LIST *pList)
+{
+ DBC_Require(pList != NULL);
+
+ GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
+
+ MEM_Free(pList);
+}
+
+/*
+ * ======== LST_Exit ========
+ * Purpose:
+ * Discontinue usage of the LST module.
+ */
+void LST_Exit(void)
+{
+ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
+}
+
+/*
+ * ======== LST_First ========
+ * Purpose:
+ * Returns a pointer to the first element of the list, or NULL if the
+ * list is empty.
+ */
+struct LST_ELEM *LST_First(struct LST_LIST *pList)
+{
+ struct LST_ELEM *pElem = NULL;
+
+ DBC_Require(pList != NULL);
+
+ GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
+
+ if (!LST_IsEmpty(pList))
+ pElem = pList->head.next;
+
+ return pElem;
+}
+
+/*
+ * ======== LST_GetHead ========
+ * Purpose:
+ * "Pops" the head off the list and returns a pointer to it.
+ */
+struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
+{
+ struct LST_ELEM *pElem;
+
+ DBC_Require(pList != NULL);
+
+ GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
+
+ if (LST_IsEmpty(pList))
+ return NULL;
+
+ /* pElem is always valid because the list cannot be empty
+ * at this point */
+ pElem = pList->head.next;
+ pList->head.next = pElem->next;
+ pElem->next->prev = &pList->head;
+
+ return pElem->self;
+}
+
+/*
+ * ======== LST_Init ========
+ * Purpose:
+ * Initialize LST module private state.
+ */
+bool LST_Init(void)
+{
+ GT_create(&LST_debugMask, "LS"); /* LS for LSt module */
+
+ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== LST_InitElem ========
+ * Purpose:
+ * Initializes a list element to default (cleared) values
+ */
+void LST_InitElem(struct LST_ELEM *pElem)
+{
+ DBC_Require(pElem != NULL);
+
+ GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
+
+ if (pElem) {
+ pElem->next = NULL;
+ pElem->prev = NULL;
+ pElem->self = pElem;
+ }
+}
+
+/*
+ * ======== LST_InsertBefore ========
+ * Purpose:
+ * Insert the element before the existing element.
+ */
+void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
+ struct LST_ELEM *pElemExisting)
+{
+ DBC_Require(pList != NULL);
+ DBC_Require(pElem != NULL);
+ DBC_Require(pElemExisting != NULL);
+
+ GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
+ "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
+ pElemExisting);
+
+ pElemExisting->prev->next = pElem;
+ pElem->prev = pElemExisting->prev;
+ pElem->next = pElemExisting;
+ pElemExisting->prev = pElem;
+}
+
+/*
+ * ======== LST_Next ========
+ * Purpose:
+ * Returns a pointer to the next element of the list, or NULL if the
+ * next element is the head of the list or the list is empty.
+ */
+struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
+{
+ struct LST_ELEM *pNextElem = NULL;
+
+ DBC_Require(pList != NULL);
+ DBC_Require(pCurElem != NULL);
+
+ GT_2trace(LST_debugMask, GT_ENTER,
+ "LST_Next: pList 0x%x, pCurElem 0x%x\n",
+ pList, pCurElem);
+
+ if (!LST_IsEmpty(pList)) {
+ if (pCurElem->next != &pList->head)
+ pNextElem = pCurElem->next;
+ }
+
+ return pNextElem;
+}
+
+/*
+ * ======== LST_PutTail ========
+ * Purpose:
+ * Adds the specified element to the tail of the list
+ */
+void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
+{
+ DBC_Require(pList != NULL);
+ DBC_Require(pElem != NULL);
+
+ GT_2trace(LST_debugMask, GT_ENTER,
+ "LST_PutTail: pList 0x%x, pElem 0x%x\n",
+ pList, pElem);
+
+ pElem->prev = pList->head.prev;
+ pElem->next = &pList->head;
+ pList->head.prev = pElem;
+ pElem->prev->next = pElem;
+
+ DBC_Ensure(!LST_IsEmpty(pList));
+}
+
+/*
+ * ======== LST_RemoveElem ========
+ * Purpose:
+ * Removes (unlinks) the given element from the list, if the list is not
+ * empty. Does not free the list element.
+ */
+void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
+{
+ DBC_Require(pList != NULL);
+ DBC_Require(pCurElem != NULL);
+
+ GT_2trace(LST_debugMask, GT_ENTER,
+ "LST_RemoveElem: pList 0x%x, pCurElem "
+ "0x%x\n", pList, pCurElem);
+
+ if (!LST_IsEmpty(pList)) {
+ pCurElem->prev->next = pCurElem->next;
+ pCurElem->next->prev = pCurElem->prev;
+
+ /* set elem fields to NULL to prevent illegal references */
+ pCurElem->next = NULL;
+ pCurElem->prev = NULL;
+ }
+}
+
diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
new file mode 100644
index 000000000000..47ec09bdb066
--- /dev/null
+++ b/drivers/dsp/bridge/services/mem.c
@@ -0,0 +1,599 @@
+/*
+ * mem.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== mem.c ========
+ * Purpose:
+ * Implementation of platform specific memory services.
+ *
+ * Public Functions:
+ * MEM_Alloc
+ * MEM_AllocPhysMem
+ * MEM_Calloc
+ * MEM_Exit
+ * MEM_FlushCache
+ * MEM_Free
+ * MEM_FreePhysMem
+ * MEM_Init
+ * MEM_ExtPhysPoolInit
+ *
+ *! Revision History:
+ *! =================
+ *! 18-Jan-2004 hp: Added support for External physical memory pool
+ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
+ *! 01-Sep-2001 ag: Code cleanup.
+ *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
+ *! Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
+ *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
+ *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 22-Nov-1999 kc: Added changes from code review.
+ *! 16-Aug-1999 kc: modified for WinCE.
+ *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
+ *! Mdl offset now ORed not added to userBuf.
+ *! 23-Dec-1997 cr: Code review changes.
+ *! 08-Dec-1997 cr: Prepared for code review.
+ *! 24-Jun-1997 cr: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/mem.h>
+#include <dspbridge/list.h>
+
+/* ----------------------------------- Defines */
+#define MEM_512MB 0x1fffffff
+#define memInfoSign 0x464E494D /* "MINF" (in reverse). */
+
+#ifdef DEBUG
+#define MEM_CHECK /* Use to detect source of memory leaks */
+#endif
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static u32 cRefs; /* module reference count */
+
+static bool extPhysMemPoolEnabled;
+
+struct extPhysMemPool {
+ u32 physMemBase;
+ u32 physMemSize;
+ u32 virtMemBase;
+ u32 nextPhysAllocPtr;
+};
+
+static struct extPhysMemPool extMemPool;
+
+/* Information about each element allocated on heap */
+struct memInfo {
+ struct LST_ELEM link; /* Must be first */
+ size_t size;
+ void *caller;
+ u32 dwSignature; /* Should be last */
+};
+
+#ifdef MEM_CHECK
+
+/*
+ * This structure holds a linked list to all memory elements allocated on
+ * heap by DSP/BIOS Bridge. This is used to report memory leaks and free
+ * such elements while removing the DSP/BIOS Bridge driver
+ */
+struct memMan {
+ struct LST_LIST lst;
+ spinlock_t lock;
+};
+
+static struct memMan mMan;
+
+/*
+ * These functions are similar to LST_PutTail and LST_RemoveElem and are
+ * duplicated here to make MEM independent of LST
+ */
+static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
+{
+ pElem->prev = pList->head.prev;
+ pElem->next = &pList->head;
+ pList->head.prev = pElem;
+ pElem->prev->next = pElem;
+ pElem->self = pElem;
+}
+
+static inline void MLST_RemoveElem(struct LST_LIST *pList,
+ struct LST_ELEM *pCurElem)
+{
+ pCurElem->prev->next = pCurElem->next;
+ pCurElem->next->prev = pCurElem->prev;
+ pCurElem->next = NULL;
+ pCurElem->prev = NULL;
+}
+
+static void MEM_Check(void)
+{
+ struct memInfo *pMem;
+ struct LST_ELEM *last = &mMan.lst.head;
+ struct LST_ELEM *curr = mMan.lst.head.next;
+
+ if (!LST_IsEmpty(&mMan.lst)) {
+ GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
+ GT_0trace(MEM_debugMask, GT_7CLASS,
+ "Addr Size Caller\n");
+ while (curr != last) {
+ pMem = (struct memInfo *)curr;
+ curr = curr->next;
+ if ((u32)pMem > PAGE_OFFSET &&
+ MEM_IsValidHandle(pMem, memInfoSign)) {
+ GT_3trace(MEM_debugMask, GT_7CLASS,
+ "%lx %d\t [<%p>]\n",
+ (u32) pMem + sizeof(struct memInfo),
+ pMem->size, pMem->caller);
+ MLST_RemoveElem(&mMan.lst,
+ (struct LST_ELEM *) pMem);
+ kfree(pMem);
+ } else {
+ GT_1trace(MEM_debugMask, GT_7CLASS,
+ "Invalid allocation or "
+ "Buffer underflow at %x\n",
+ (u32)pMem + sizeof(struct memInfo));
+ break;
+ }
+ }
+ }
+ DBC_Ensure(LST_IsEmpty(&mMan.lst));
+}
+
+#endif
+
+void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
+{
+ u32 poolVirtBase;
+
+ /* get the virtual address for the physical memory pool passed */
+ poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
+
+ if ((void **)poolVirtBase == NULL) {
+ GT_0trace(MEM_debugMask, GT_7CLASS,
+ "[PHYS_POOL]Mapping External "
+ "physical memory to virt failed \n");
+ extPhysMemPoolEnabled = false;
+ } else {
+ extMemPool.physMemBase = poolPhysBase;
+ extMemPool.physMemSize = poolSize;
+ extMemPool.virtMemBase = poolVirtBase;
+ extMemPool.nextPhysAllocPtr = poolPhysBase;
+ extPhysMemPoolEnabled = true;
+ GT_3trace(MEM_debugMask, GT_1CLASS,
+ "ExtMemory Pool details " "Pool"
+ "Physical mem base = %0x " "Pool Physical mem size "
+ "= %0x" "Pool Virtual mem base = %0x \n",
+ poolPhysBase, poolSize, poolVirtBase);
+ }
+}
+
+static void MEM_ExtPhysPoolRelease(void)
+{
+ GT_0trace(MEM_debugMask, GT_1CLASS,
+ "Releasing External memory pool \n");
+ if (extPhysMemPoolEnabled) {
+ iounmap((void *)(extMemPool.virtMemBase));
+ extPhysMemPoolEnabled = false;
+ }
+}
+
+/*
+ * ======== MEM_ExtPhysMemAlloc ========
+ * Purpose:
+ * Allocate physically contiguous, uncached memory from external memory pool
+ */
+
+static void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
+{
+ u32 newAllocPtr;
+ u32 offset;
+ u32 virtAddr;
+
+ GT_2trace(MEM_debugMask, GT_1CLASS,
+ "Ext Memory Allocation" "bytes=0x%x , "
+ "align=0x%x \n", bytes, align);
+ if (align == 0) {
+ GT_0trace(MEM_debugMask, GT_7CLASS,
+ "ExtPhysical Memory Allocation "
+ "No alignment request in allocation call !! \n");
+ align = 1;
+ }
+ if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
+ - extMemPool.nextPhysAllocPtr)) {
+ GT_1trace(MEM_debugMask, GT_7CLASS,
+ "ExtPhysical Memory Allocation "
+ "unable to allocate memory for bytes = 0x%x \n",
+ bytes);
+ pPhysAddr = NULL;
+ return NULL;
+ } else {
+ offset = (extMemPool.nextPhysAllocPtr & (align - 1));
+ if (offset == 0)
+ newAllocPtr = extMemPool.nextPhysAllocPtr;
+ else
+ newAllocPtr = (extMemPool.nextPhysAllocPtr) +
+ (align - offset);
+ if ((newAllocPtr + bytes) <=
+ (extMemPool.physMemBase + extMemPool.physMemSize)) {
+ /* we can allocate */
+ *pPhysAddr = newAllocPtr;
+ extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
+ virtAddr = extMemPool.virtMemBase + (newAllocPtr -
+ extMemPool.physMemBase);
+ GT_2trace(MEM_debugMask, GT_1CLASS,
+ "Ext Memory Allocation succedded "
+ "phys address=0x%x , virtaddress=0x%x \n",
+ newAllocPtr, virtAddr);
+ return (void *)virtAddr;
+ } else {
+ *pPhysAddr = 0;
+ return NULL;
+ }
+ }
+}
+
+/*
+ * ======== MEM_Alloc ========
+ * Purpose:
+ * Allocate memory from the paged or non-paged pools.
+ */
+void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
+{
+ struct memInfo *pMem = NULL;
+
+ GT_2trace(MEM_debugMask, GT_ENTER,
+ "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
+ if (cBytes > 0) {
+ switch (type) {
+ case MEM_NONPAGED:
+ /* If non-paged memory required, see note at top of file. */
+ case MEM_PAGED:
+#ifndef MEM_CHECK
+ pMem = kmalloc(cBytes,
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
+#else
+ pMem = kmalloc(cBytes + sizeof(struct memInfo),
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
+ if (pMem) {
+ pMem->size = cBytes;
+ pMem->caller = __builtin_return_address(0);
+ pMem->dwSignature = memInfoSign;
+
+ spin_lock(&mMan.lock);
+ MLST_PutTail(&mMan.lst,
+ (struct LST_ELEM *)pMem);
+ spin_unlock(&mMan.lock);
+
+ pMem = (void *)((u32)pMem +
+ sizeof(struct memInfo));
+ }
+#endif
+ break;
+ case MEM_LARGEVIRTMEM:
+#ifndef MEM_CHECK
+ /* FIXME - Replace with 'vmalloc' after BP fix */
+ pMem = __vmalloc(cBytes,
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
+#else
+ /* FIXME - Replace with 'vmalloc' after BP fix */
+ pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
+ if (pMem) {
+ pMem->size = cBytes;
+ pMem->caller = __builtin_return_address(0);
+ pMem->dwSignature = memInfoSign;
+
+ spin_lock(&mMan.lock);
+ MLST_PutTail(&mMan.lst,
+ (struct LST_ELEM *) pMem);
+ spin_unlock(&mMan.lock);
+
+ pMem = (void *)((u32)pMem +
+ sizeof(struct memInfo));
+ }
+#endif
+ break;
+
+ default:
+ GT_0trace(MEM_debugMask, GT_6CLASS,
+ "MEM_Alloc: unexpected "
+ "MEM_POOLATTRS value\n");
+ break;
+ }
+ }
+
+ return pMem;
+}
+
+/*
+ * ======== MEM_AllocPhysMem ========
+ * Purpose:
+ * Allocate physically contiguous, uncached memory
+ */
+void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
+{
+ void *pVaMem = NULL;
+ dma_addr_t paMem;
+
+ DBC_Require(cRefs > 0);
+
+ GT_2trace(MEM_debugMask, GT_ENTER,
+ "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
+ "0x%x\n", cBytes, ulAlign);
+
+ if (cBytes > 0) {
+ if (extPhysMemPoolEnabled) {
+ pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
+ (u32 *)&paMem);
+ } else
+ pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
+ if (pVaMem == NULL) {
+ *pPhysicalAddress = 0;
+ GT_1trace(MEM_debugMask, GT_6CLASS,
+ "MEM_AllocPhysMem failed: "
+ "0x%x\n", pVaMem);
+ } else {
+ *pPhysicalAddress = paMem;
+ }
+ }
+ return pVaMem;
+}
+
+/*
+ * ======== MEM_Calloc ========
+ * Purpose:
+ * Allocate zero-initialized memory from the paged or non-paged pools.
+ */
+void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
+{
+ struct memInfo *pMem = NULL;
+
+ GT_2trace(MEM_debugMask, GT_ENTER,
+ "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
+ cBytes, type);
+
+ if (cBytes > 0) {
+ switch (type) {
+ case MEM_NONPAGED:
+ /* If non-paged memory required, see note at top of file. */
+ case MEM_PAGED:
+#ifndef MEM_CHECK
+ pMem = kmalloc(cBytes,
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
+ if (pMem)
+ memset(pMem, 0, cBytes);
+
+#else
+ pMem = kmalloc(cBytes + sizeof(struct memInfo),
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
+ if (pMem) {
+ memset((void *)((u32)pMem +
+ sizeof(struct memInfo)), 0, cBytes);
+ pMem->size = cBytes;
+ pMem->caller = __builtin_return_address(0);
+ pMem->dwSignature = memInfoSign;
+ spin_lock(&mMan.lock);
+ MLST_PutTail(&mMan.lst,
+ (struct LST_ELEM *) pMem);
+ spin_unlock(&mMan.lock);
+ pMem = (void *)((u32)pMem +
+ sizeof(struct memInfo));
+ }
+#endif
+ break;
+ case MEM_LARGEVIRTMEM:
+#ifndef MEM_CHECK
+ /* FIXME - Replace with 'vmalloc' after BP fix */
+ pMem = __vmalloc(cBytes,
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
+ if (pMem)
+ memset(pMem, 0, cBytes);
+
+#else
+ /* FIXME - Replace with 'vmalloc' after BP fix */
+ pMem = __vmalloc(cBytes + sizeof(struct memInfo),
+ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
+ if (pMem) {
+ memset((void *)((u32)pMem +
+ sizeof(struct memInfo)), 0, cBytes);
+ pMem->size = cBytes;
+ pMem->caller = __builtin_return_address(0);
+ pMem->dwSignature = memInfoSign;
+ spin_lock(&mMan.lock);
+ MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
+ pMem);
+ spin_unlock(&mMan.lock);
+ pMem = (void *)((u32)pMem +
+ sizeof(struct memInfo));
+ }
+#endif
+ break;
+ default:
+ GT_1trace(MEM_debugMask, GT_6CLASS,
+ "MEM_Calloc: unexpected "
+ "MEM_POOLATTRS value 0x%x\n", type);
+ break;
+ }
+ }
+
+ return pMem;
+}
+
+/*
+ * ======== MEM_Exit ========
+ * Purpose:
+ * Discontinue usage of the MEM module.
+ */
+void MEM_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
+
+ cRefs--;
+#ifdef MEM_CHECK
+ if (cRefs == 0)
+ MEM_Check();
+
+#endif
+ MEM_ExtPhysPoolRelease();
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== MEM_FlushCache ========
+ * Purpose:
+ * Flush cache
+ */
+void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
+{
+ DBC_Require(cRefs > 0);
+
+ switch (FlushType) {
+ /* invalidate only */
+ case PROC_INVALIDATE_MEM:
+ dmac_inv_range(pMemBuf, pMemBuf + cBytes);
+ outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
+ cBytes));
+ break;
+ /* writeback only */
+ case PROC_WRITEBACK_MEM:
+ dmac_clean_range(pMemBuf, pMemBuf + cBytes);
+ outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
+ cBytes));
+ break;
+ /* writeback and invalidate */
+ case PROC_WRITEBACK_INVALIDATE_MEM:
+ dmac_flush_range(pMemBuf, pMemBuf + cBytes);
+ outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
+ cBytes));
+ break;
+ default:
+ GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
+ "FlushMemType 0x%x\n", FlushType);
+ break;
+ }
+
+}
+
+
+/*
+ * ======== MEM_Free ========
+ * Purpose:
+ * Free the given block of system memory.
+ */
+void MEM_Free(IN void *pMemBuf)
+{
+#ifdef MEM_CHECK
+ struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
+#endif
+
+ DBC_Require(pMemBuf != NULL);
+
+ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
+ pMemBuf);
+
+ if (pMemBuf) {
+#ifndef MEM_CHECK
+ kfree(pMemBuf);
+#else
+ if (pMem) {
+ if (pMem->dwSignature == memInfoSign) {
+ spin_lock(&mMan.lock);
+ MLST_RemoveElem(&mMan.lst,
+ (struct LST_ELEM *) pMem);
+ spin_unlock(&mMan.lock);
+ pMem->dwSignature = 0;
+ kfree(pMem);
+ } else {
+ GT_1trace(MEM_debugMask, GT_7CLASS,
+ "Invalid allocation or "
+ "Buffer underflow at %x\n",
+ (u32) pMem + sizeof(struct memInfo));
+ }
+ }
+#endif
+ }
+}
+
+/*
+ * ======== MEM_FreePhysMem ========
+ * Purpose:
+ * Free the given block of physically contiguous memory.
+ */
+void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
+ u32 cBytes)
+{
+ DBC_Require(cRefs > 0);
+ DBC_Require(pVirtualAddress != NULL);
+
+ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
+ "0x%x\n", pVirtualAddress);
+
+ if (!extPhysMemPoolEnabled)
+ dma_free_coherent(NULL, cBytes, pVirtualAddress,
+ pPhysicalAddress);
+}
+
+/*
+ * ======== MEM_Init ========
+ * Purpose:
+ * Initialize MEM module private state.
+ */
+bool MEM_Init(void)
+{
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+ GT_create(&MEM_debugMask, "MM"); /* MM for MeM module */
+
+#ifdef MEM_CHECK
+ mMan.lst.head.next = &mMan.lst.head;
+ mMan.lst.head.prev = &mMan.lst.head;
+ mMan.lst.head.self = NULL;
+ spin_lock_init(&mMan.lock);
+#endif
+
+ }
+
+ cRefs++;
+
+ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
+
+ DBC_Ensure(cRefs > 0);
+
+ return true;
+}
diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
new file mode 100644
index 000000000000..2eff3ebfa1fe
--- /dev/null
+++ b/drivers/dsp/bridge/services/ntfy.c
@@ -0,0 +1,329 @@
+/*
+ * ntfy.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== ntfyce.c ========
+ * Purpose:
+ * Manage lists of notification events.
+ *
+ * Public Functions:
+ * NTFY_Create
+ * NTFY_Delete
+ * NTFY_Exit
+ * NTFY_Init
+ * NTFY_Notify
+ * NTFY_Register
+ *
+ *! Revision History:
+ *! =================
+ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE related code.
+ *! 05-Nov-2001 kc Updated DSP_HNOTIFICATION structure.
+ *! 10-May-2001 jeh Removed SERVICES module init/exit from NTFY_Init/Exit.
+ *! NTFY_Register() returns DSP_ENOTIMPL for all but
+ *! DSP_SIGNALEVENT.
+ *! 12-Oct-2000 jeh Use MEM_IsValidHandle().
+ *! 07-Sep-2000 jeh Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/ntfy.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define NTFY_SIGNATURE 0x5946544e /* "YFTN" */
+
+/*
+ * ======== NTFY_OBJECT ========
+ */
+struct NTFY_OBJECT {
+ u32 dwSignature; /* For object validation */
+ struct LST_LIST *notifyList; /* List of NOTIFICATION objects */
+ struct SYNC_CSOBJECT *hSync; /* For critical sections */
+};
+
+/*
+ * ======== NOTIFICATION ========
+ * This object will be created when a client registers for events.
+ */
+struct NOTIFICATION {
+ struct LST_ELEM listElem;
+ u32 uEventMask; /* Events to be notified about */
+ u32 uNotifyType; /* Type of notification to be sent */
+
+ /*
+ * We keep a copy of the event name to check if the event has
+ * already been registered. (SYNC also keeps a copy of the name).
+ */
+ char *pstrName; /* Name of event */
+ HANDLE hEvent; /* Handle for notification */
+ struct SYNC_OBJECT *hSync;
+};
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask NTFY_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+/* ----------------------------------- Function Prototypes */
+static void DeleteNotify(struct NOTIFICATION *pNotify);
+
+/*
+ * ======== NTFY_Create ========
+ * Purpose:
+ * Create an empty list of notifications.
+ */
+DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
+{
+ struct NTFY_OBJECT *pNtfy;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(phNtfy != NULL);
+
+ *phNtfy = NULL;
+ MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
+
+ if (pNtfy) {
+
+ status = SYNC_InitializeDPCCS(&pNtfy->hSync);
+ if (DSP_SUCCEEDED(status)) {
+ pNtfy->notifyList = LST_Create();
+ if (pNtfy->notifyList == NULL) {
+ (void) SYNC_DeleteCS(pNtfy->hSync);
+ MEM_FreeObject(pNtfy);
+ status = DSP_EMEMORY;
+ } else {
+ *phNtfy = pNtfy;
+ }
+ }
+ } else {
+ status = DSP_EMEMORY;
+ }
+
+ DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
+ (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
+ NTFY_SIGNATURE)));
+
+ return status;
+}
+
+/*
+ * ======== NTFY_Delete ========
+ * Purpose:
+ * Free resources allocated in NTFY_Create.
+ */
+void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
+{
+ struct NOTIFICATION *pNotify;
+
+ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
+
+ /* Remove any elements remaining in list */
+ if (hNtfy->notifyList) {
+ while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
+ notifyList))) {
+ DeleteNotify(pNotify);
+ }
+ DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
+ LST_Delete(hNtfy->notifyList);
+ }
+ if (hNtfy->hSync)
+ (void)SYNC_DeleteCS(hNtfy->hSync);
+
+ MEM_FreeObject(hNtfy);
+}
+
+/*
+ * ======== NTFY_Exit ========
+ * Purpose:
+ * Discontinue usage of NTFY module.
+ */
+void NTFY_Exit(void)
+{
+ GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
+}
+
+/*
+ * ======== NTFY_Init ========
+ * Purpose:
+ * Initialize the NTFY module.
+ */
+bool NTFY_Init(void)
+{
+ GT_create(&NTFY_debugMask, "NY"); /* "NY" for NtfY */
+
+ GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
+
+ return true;
+}
+
+/*
+ * ======== NTFY_Notify ========
+ * Purpose:
+ * Execute notify function (signal event) for every
+ * element in the notification list that is to be notified about the
+ * event specified in uEventMask.
+ */
+void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
+{
+ struct NOTIFICATION *pNotify;
+
+ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
+
+ /*
+ * Go through notifyList and notify all clients registered for
+ * uEventMask events.
+ */
+
+ (void) SYNC_EnterCS(hNtfy->hSync);
+
+ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
+ while (pNotify != NULL) {
+ if (pNotify->uEventMask & uEventMask) {
+ /* Notify */
+ if (pNotify->uNotifyType == DSP_SIGNALEVENT)
+ (void)SYNC_SetEvent(pNotify->hSync);
+
+ }
+ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
+ (struct LST_ELEM *)pNotify);
+ }
+
+ (void) SYNC_LeaveCS(hNtfy->hSync);
+}
+
+/*
+ * ======== NTFY_Register ========
+ * Purpose:
+ * Add a notification element to the list. If the notification is already
+ * registered, and uEventMask != 0, the notification will get posted for
+ * events specified in the new event mask. If the notification is already
+ * registered and uEventMask == 0, the notification will be unregistered.
+ */
+DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
+ struct DSP_NOTIFICATION *hNotification,
+ u32 uEventMask, u32 uNotifyType)
+{
+ struct NOTIFICATION *pNotify;
+ struct SYNC_ATTRS syncAttrs;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
+
+ if (hNotification == NULL)
+ status = DSP_EHANDLE;
+
+ /* Return DSP_ENOTIMPL if uNotifyType is not supported */
+ if (DSP_SUCCEEDED(status)) {
+ if (!IsValidNotifyMask(uNotifyType))
+ status = DSP_ENOTIMPL;
+
+ }
+
+ if (DSP_FAILED(status))
+ return status;
+
+ (void)SYNC_EnterCS(hNtfy->hSync);
+
+ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
+ while (pNotify != NULL) {
+ /* If there is more than one notification type, each
+ * type may require its own handler code. */
+
+ if (hNotification->handle == pNotify->hSync) {
+ /* found */
+ break;
+ }
+ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
+ (struct LST_ELEM *)pNotify);
+ }
+ if (pNotify == NULL) {
+ /* Not registered */
+ if (uEventMask == 0) {
+ status = DSP_EVALUE;
+ } else {
+ /* Allocate NOTIFICATION object, add to list */
+ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
+ MEM_PAGED);
+ if (pNotify == NULL)
+ status = DSP_EMEMORY;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ LST_InitElem((struct LST_ELEM *) pNotify);
+ /* If there is more than one notification type, each
+ * type may require its own handler code. */
+ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
+ hNotification->handle = pNotify->hSync;
+
+ if (DSP_SUCCEEDED(status)) {
+ pNotify->uEventMask = uEventMask;
+ pNotify->uNotifyType = uNotifyType;
+ LST_PutTail(hNtfy->notifyList,
+ (struct LST_ELEM *)pNotify);
+ } else {
+ DeleteNotify(pNotify);
+ }
+ }
+ } else {
+ /* Found in list */
+ if (uEventMask == 0) {
+ /* Remove from list and free */
+ LST_RemoveElem(hNtfy->notifyList,
+ (struct LST_ELEM *)pNotify);
+ DeleteNotify(pNotify);
+ } else {
+ /* Update notification mask (type shouldn't change) */
+ pNotify->uEventMask = uEventMask;
+ }
+ }
+ (void)SYNC_LeaveCS(hNtfy->hSync);
+ return status;
+}
+
+/*
+ * ======== DeleteNotify ========
+ * Purpose:
+ * Free the notification object.
+ */
+static void DeleteNotify(struct NOTIFICATION *pNotify)
+{
+ if (pNotify->hSync)
+ (void) SYNC_CloseEvent(pNotify->hSync);
+
+ if (pNotify->pstrName)
+ MEM_Free(pNotify->pstrName);
+
+ MEM_Free(pNotify);
+}
+
diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
new file mode 100644
index 000000000000..0d85f4169dd2
--- /dev/null
+++ b/drivers/dsp/bridge/services/reg.c
@@ -0,0 +1,196 @@
+/*
+ * reg.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== regce.c ========
+ * Purpose:
+ * Provide registry functions.
+ *
+ * Public Functions:
+ * REG_DeleteValue
+ * REG_EnumValue
+ * REG_Exit
+ * REG_GetValue
+ * REG_Init
+ * REG_SetValue
+ *
+ *! Revision History:
+ *! ================
+ *
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/reg.h>
+#include <regsup.h>
+
+#if GT_TRACE
+struct GT_Mask REG_debugMask = { NULL, NULL }; /* GT trace var. */
+#endif
+
+/*
+ * ======== REG_DeleteValue ========
+ * Deletes a registry entry value. NOTE: A registry entry value is not the
+ * same as * a registry key.
+ */
+DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue)
+{
+ DSP_STATUS status;
+ DBC_Require(pstrSubkey && pstrValue);
+ DBC_Require(phKey == NULL);
+ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
+ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
+
+ GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
+
+ /* Note that we don't use phKey */
+ if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
+ status = DSP_SOK;
+ else
+ status = DSP_EFAIL;
+
+ return status;
+}
+
+/*
+ * ======== REG_EnumValue ========
+ * Enumerates a registry key and retrieve values stored under the key.
+ * We will assume the input pdwValueSize is smaller than
+ * REG_MAXREGPATHLENGTH for implementation purposes.
+ */
+DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
+ IN CONST char *pstrKey, IN OUT char *pstrValue,
+ IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
+ IN OUT u32 *pdwDataSize)
+{
+ DSP_STATUS status;
+
+ DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
+ pdwDataSize);
+ DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
+ DBC_Require(phKey == NULL);
+ DBC_Require(strlen(pstrKey) < REG_MAXREGPATHLENGTH);
+
+ GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
+
+ status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
+ pstrData, pdwDataSize);
+
+ return status;
+}
+
+/*
+ * ======== REG_Exit ========
+ * Discontinue usage of the REG module.
+ */
+void REG_Exit(void)
+{
+ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
+
+ regsupExit();
+}
+
+/*
+ * ======== REG_GetValue ========
+ * Retrieve a value from the registry.
+ */
+DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue, OUT u8 *pbData,
+ IN OUT u32 *pdwDataSize)
+{
+ DSP_STATUS status;
+
+ DBC_Require(pstrSubkey && pstrValue && pbData);
+ DBC_Require(phKey == NULL);
+ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
+ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
+
+ GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
+
+ /* We need to use regsup calls... */
+ /* ...for now we don't need the key handle or */
+ /* the subkey, all we need is the value to lookup. */
+ if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
+ status = DSP_SOK;
+ else
+ status = DSP_EFAIL;
+
+ return status;
+}
+
+/*
+ * ======== REG_Init ========
+ * Initialize the REG module's private state.
+ */
+bool REG_Init(void)
+{
+ bool fInit;
+
+ GT_create(&REG_debugMask, "RG"); /* RG for ReG */
+
+ fInit = regsupInit();
+
+ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
+
+ return fInit;
+}
+
+/*
+ * ======== REG_SetValue ========
+ * Set a value in the registry.
+ */
+DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue, IN CONST u32 dwType,
+ IN u8 *pbData, IN u32 dwDataSize)
+{
+ DSP_STATUS status;
+
+ DBC_Require(pstrValue && pbData);
+ DBC_Require(phKey == NULL);
+ DBC_Require(dwDataSize > 0);
+ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
+
+ /* We need to use regsup calls... */
+ /* ...for now we don't need the key handle or */
+ /* the subkey, all we need is the value to lookup. */
+ if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
+ status = DSP_SOK;
+ else
+ status = DSP_EFAIL;
+
+ return status;
+}
+
diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
new file mode 100644
index 000000000000..5251b68ea0ab
--- /dev/null
+++ b/drivers/dsp/bridge/services/regsup.c
@@ -0,0 +1,368 @@
+/*
+ * regsup.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== regsup.c ========
+ * Purpose:
+ * Provide registry support functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 28-May-2002 map: Integrated PSI's dspimage update mechanism
+ *! 11-May-2002 gp: Turned PERF "on".
+ *! 21-May-2002 map: Fixed bug in SetValue - if resizing datasize, set
+ *! new size too
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/csl.h>
+
+/* ----------------------------------- This */
+#include <regsup.h>
+
+struct RegValueStruct {
+ char name[BRIDGE_MAX_NAME_SIZE]; /* Name of a given value entry */
+ u32 dataSize; /* Size of the data */
+ void *pData; /* Pointer to the actual data */
+};
+
+struct RegKeyStruct {
+ /*The current number of value entries this key has*/
+ u32 numValueEntries;
+ /* Array of value entries */
+ struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
+};
+
+
+/* Pointer to the registry support key */
+static struct RegKeyStruct *pRegKey;
+
+#if GT_TRACE
+extern struct GT_Mask REG_debugMask; /* GT trace var. */
+/*
+ * ======== printS ========
+ * Purpose:
+ * Displays printable characters in pBuf, if any.
+ */
+static inline void printS(void *pBuf)
+{
+ int pos = 0;
+ if (*(REG_debugMask).flags & (GT_2CLASS)) {
+ while (*(u8 *)((pBuf)+pos) >= ' ' &&
+ *(u8 *)((pBuf)+pos) <= '~') {
+ GT_1trace(REG_debugMask, GT_2CLASS, "%c",
+ *(u8 *)((pBuf) + pos++));
+ }
+
+ GT_0trace(REG_debugMask, GT_2CLASS, "\n");
+ }
+}
+#else
+#define printS(pBuf)
+#endif
+
+/*
+ * ======== regsupInit ========
+ * Purpose:
+ * Initialize the Registry Support module's private state.
+ */
+bool regsupInit(void)
+{
+ if (pRegKey != NULL)
+ return true;
+
+ /* Need to allocate and setup our registry. */
+ pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
+ if (pRegKey == NULL)
+ return false;
+
+ return true;
+}
+
+/*
+ * ======== regsupExit ========
+ * Purpose:
+ * Release all registry support allocations.
+ */
+void regsupExit(void)
+{
+ u32 i;
+
+ /* Make sure data has actually been allocated. */
+ if (pRegKey == NULL) {
+ /* Nothing initialized.return! */
+ return;
+ }
+
+ GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
+ pRegKey->numValueEntries);
+
+ /* Now go through each entry and free all resources. */
+ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
+ (i < pRegKey->numValueEntries)); i++) {
+ if (pRegKey->values[i].name[0] != '\0') {
+ /* We have a valid entry.free it up! */
+ if (pRegKey->values[i].pData != NULL) {
+ GT_3trace(REG_debugMask, GT_2CLASS,
+ "E %d\t %s DATA %x ", i,
+ pRegKey->values[i].name,
+ *(u32 *)pRegKey->values[i].pData);
+ printS((u8 *)(pRegKey->values[i].pData));
+ MEM_Free(pRegKey->values[i].pData);
+ }
+ pRegKey->values[i].pData = NULL;
+ pRegKey->values[i].dataSize = 0;
+ pRegKey->values[i].name[0] = '\0';
+ }
+ }
+
+ /* Now that all of the resources are freed up, free the main one! */
+ MEM_Free(pRegKey);
+
+ /* Don't forget to NULL out the global entry! */
+ pRegKey = NULL;
+}
+
+/*
+ * ======== regsupGetValue ========
+ * Purpose:
+ * Get the value of the entry having the given name.
+ */
+DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
+{
+ DSP_STATUS retVal = DSP_EFAIL;
+ u32 i;
+
+ /* Need to search through the entries looking for the right one. */
+ for (i = 0; i < pRegKey->numValueEntries; i++) {
+ /* See if the name matches. */
+ if (strncmp(pRegKey->values[i].name, valName,
+ BRIDGE_MAX_NAME_SIZE) == 0) {
+
+ /* We have a match! Copy out the data. */
+ memcpy(pBuf, pRegKey->values[i].pData,
+ pRegKey->values[i].dataSize);
+
+ /* Get the size for the caller. */
+ *dataSize = pRegKey->values[i].dataSize;
+
+ /* Set our status to good and exit. */
+ retVal = DSP_SOK;
+ break;
+ }
+ }
+
+ if (DSP_SUCCEEDED(retVal)) {
+ GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
+ *(u32 *)pBuf);
+ printS((u8 *)pBuf);
+ } else {
+ GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
+ }
+
+ return retVal;
+}
+
+/*
+ * ======== regsupSetValue ========
+ * Purpose:
+ * Sets the value of the entry having the given name.
+ */
+DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
+{
+ DSP_STATUS retVal = DSP_EFAIL;
+ u32 i;
+
+ GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
+ *(u32 *)pBuf);
+ printS((u8 *)pBuf);
+
+ /* Need to search through the entries looking for the right one. */
+ for (i = 0; i < pRegKey->numValueEntries; i++) {
+ /* See if the name matches. */
+ if (strncmp(pRegKey->values[i].name, valName,
+ BRIDGE_MAX_NAME_SIZE) == 0) {
+ /* Make sure the new data size is the same. */
+ if (dataSize != pRegKey->values[i].dataSize) {
+ /* The caller needs a different data size! */
+ MEM_Free(pRegKey->values[i].pData);
+ pRegKey->values[i].pData = MEM_Alloc(dataSize,
+ MEM_NONPAGED);
+ if (pRegKey->values[i].pData == NULL)
+ break;
+
+ }
+
+ /* We have a match! Copy out the data. */
+ memcpy(pRegKey->values[i].pData, pBuf, dataSize);
+
+ /* Reset datasize - overwrite if new or same */
+ pRegKey->values[i].dataSize = dataSize;
+
+ /* Set our status to good and exit. */
+ retVal = DSP_SOK;
+ break;
+ }
+ }
+
+ /* See if we found a match or if this is a new entry */
+ if (i == pRegKey->numValueEntries) {
+ /* No match, need to make a new entry */
+ /* First check to see if we can make any more entries. */
+ if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
+ strncpy(pRegKey->values[pRegKey->numValueEntries].name,
+ valName, BRIDGE_MAX_NAME_SIZE);
+ pRegKey->values[pRegKey->numValueEntries].pData =
+ MEM_Alloc(dataSize, MEM_NONPAGED);
+ if (pRegKey->values[pRegKey->numValueEntries].pData !=
+ NULL) {
+ memcpy(pRegKey->
+ values[pRegKey->numValueEntries].pData,
+ pBuf, dataSize);
+ pRegKey->
+ values[pRegKey->numValueEntries].dataSize =
+ dataSize;
+ pRegKey->numValueEntries++;
+ retVal = DSP_SOK;
+ }
+ } else {
+ GT_0trace(REG_debugMask, GT_7CLASS,
+ "MAX NUM REG ENTRIES REACHED\n");
+ }
+ }
+
+ return retVal;
+}
+
+/*
+ * ======== regsupEnumValue ========
+ * Purpose:
+ * Returns registry "values" and their "data" under a (sub)key.
+ */
+DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
+ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
+ IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
+{
+ DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
+ u32 i;
+ u32 dwKeyLen;
+ u32 count = 0;
+
+ DBC_Require(pstrKey);
+ dwKeyLen = strlen(pstrKey);
+
+ /* Need to search through the entries looking for the right one. */
+ for (i = 0; i < pRegKey->numValueEntries; i++) {
+ /* See if the name matches. */
+ if ((strncmp(pRegKey->values[i].name, pstrKey,
+ dwKeyLen) == 0) && count++ == dwIndex) {
+ /* We have a match! Copy out the data. */
+ memcpy(pstrData, pRegKey->values[i].pData,
+ pRegKey->values[i].dataSize);
+ /* Get the size for the caller. */
+ *pdwDataSize = pRegKey->values[i].dataSize;
+ *pdwValueSize = strlen(&(pRegKey->
+ values[i].name[dwKeyLen]));
+ strncpy(pstrValue,
+ &(pRegKey->values[i].name[dwKeyLen]),
+ *pdwValueSize + 1);
+ GT_3trace(REG_debugMask, GT_2CLASS,
+ "E Key %s, Value %s, Data %x ",
+ pstrKey, pstrValue, *(u32 *)pstrData);
+ printS((u8 *)pstrData);
+ /* Set our status to good and exit. */
+ retVal = DSP_SOK;
+ break;
+ }
+ }
+
+ if (count && DSP_FAILED(retVal))
+ retVal = REG_E_NOMOREITEMS;
+
+ return retVal;
+}
+
+/*
+ * ======== regsupDeleteValue ========
+ */
+DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue)
+{
+ DSP_STATUS retVal = DSP_EFAIL;
+ u32 i;
+
+ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
+ (i < pRegKey->numValueEntries)); i++) {
+ /* See if the name matches... */
+ if (strncmp(pRegKey->values[i].name, pstrValue,
+ BRIDGE_MAX_NAME_SIZE) == 0) {
+ /* We have a match! Delete this key. To delete a
+ * key, we free all resources associated with this
+ * key and, if we're not already the last entry in
+ * the array, we copy that entry into this deleted
+ * key.
+ */
+ MEM_Free(pRegKey->values[i].pData);
+ if ((pRegKey->numValueEntries - 1) == i) {
+ /* we're deleting the last one */
+ pRegKey->values[i].name[0] = '\0';
+ pRegKey->values[i].dataSize = 0;
+ pRegKey->values[i].pData = NULL;
+ } else {
+ /* move the last one here */
+ strncpy(pRegKey->values[i].name, pRegKey->
+ values[pRegKey->numValueEntries - 1].name,
+ BRIDGE_MAX_NAME_SIZE);
+ pRegKey->values[i].dataSize =
+ pRegKey->
+ values[pRegKey->numValueEntries-1].dataSize;
+ pRegKey->values[i].pData =
+ pRegKey->
+ values[pRegKey->numValueEntries-1].pData;
+ /* don't have to do this, but for
+ * the paranoid... */
+ pRegKey->
+ values[pRegKey->numValueEntries-1].name[0] =
+ '\0';
+ }
+
+ /* another one bites the dust. */
+ pRegKey->numValueEntries--;
+
+ /* Set our status to good and exit... */
+ retVal = DSP_SOK;
+ break;
+ }
+ }
+ return retVal;
+
+}
+
diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
new file mode 100644
index 000000000000..011be5230c41
--- /dev/null
+++ b/drivers/dsp/bridge/services/regsup.h
@@ -0,0 +1,58 @@
+/*
+ * regsup.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== regsup.h ========
+ *
+ *! Revision History
+ *! ================
+ */
+
+#ifndef _REGSUP_H_
+#define _REGSUP_H_
+
+#define BRIDGE_MAX_NAME_SIZE MAXREGPATHLENGTH
+#define BRIDGE_MAX_NUM_REG_ENTRIES 52
+
+/* Init function. MUST be called BEFORE any calls are */
+/* made into this psuedo-registry!!! Returns TRUE/FALSE for SUCCESS/ERROR */
+extern bool regsupInit(void);
+
+/* Release all registry support allocations. */
+extern void regsupExit(void);
+
+/*
+ * ======== regsupDeleteValue ========
+ */
+extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
+ IN CONST char *pstrValue);
+/* Get the value of the entry having the given name. Returns DSP_SOK */
+/* if an entry was found and the value retrieved. Returns DSP_EFAIL
+ * otherwise.*/
+extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
+
+/* Sets the value of the entry having the given name. Returns DSP_SOK */
+/* if an entry was found and the value set. Returns DSP_EFAIL otherwise. */
+extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
+
+/* Returns registry "values" and their "data" under a (sub)key. */
+extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
+ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
+ IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
+
+#endif
+
diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
new file mode 100644
index 000000000000..4902b2fb6516
--- /dev/null
+++ b/drivers/dsp/bridge/services/services.c
@@ -0,0 +1,206 @@
+/*
+ * services.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== services.c ========
+ * Purpose:
+ * Provide SERVICES loading.
+ *
+ * Public Functions:
+ * SERVICES_Exit
+ * SERVICES_Init
+ *
+ *
+ *! Revision History
+ *! ================
+ *! 20-Nov-2000 rr: NTFY_Init/Exit added.
+ *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
+ *! 01-Feb-2000 kc: Created.
+ */
+
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/dbg.h>
+#include <dspbridge/dpc.h>
+#include <dspbridge/kfile.h>
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/reg.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/clk.h>
+#include <dspbridge/util.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/services.h>
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask SERVICES_debugMask = { NULL, NULL }; /* GT trace var. */
+#endif
+
+static u32 cRefs; /* SERVICES module reference count */
+
+/*
+ * ======== SERVICES_Exit ========
+ * Purpose:
+ * Discontinue usage of module; free resources when reference count
+ * reaches 0.
+ */
+void SERVICES_Exit(void)
+{
+ DBC_Require(cRefs > 0);
+
+ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
+ cRefs);
+
+ cRefs--;
+ if (cRefs == 0) {
+ /* Uninitialize all SERVICES modules here */
+ NTFY_Exit();
+ UTIL_Exit();
+ SYNC_Exit();
+#ifdef OMAP_3430
+ CLK_Exit();
+#endif
+ REG_Exit();
+ LST_Exit();
+ KFILE_Exit();
+ DPC_Exit();
+ DBG_Exit();
+ CSL_Exit();
+ CFG_Exit();
+ MEM_Exit();
+
+ GT_exit();
+ }
+
+ DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ * ======== SERVICES_Init ========
+ * Purpose:
+ * Initializes SERVICES modules.
+ */
+bool SERVICES_Init(void)
+{
+ bool fInit = true;
+ bool fCFG, fCSL, fDBG, fDPC, fKFILE, fLST, fMEM;
+ bool fREG, fSYNC, fUTIL, fNTFY;
+#ifdef OMAP_3430
+ bool fCLK;
+#endif
+
+ DBC_Require(cRefs >= 0);
+
+ if (cRefs == 0) {
+
+ GT_init();
+ GT_create(&SERVICES_debugMask, "OS"); /* OS for OSal */
+
+ GT_0trace(SERVICES_debugMask, GT_ENTER,
+ "SERVICES_Init: entered\n");
+
+ /* Perform required initialization of SERVICES modules. */
+ fMEM = MEM_Init();
+ fREG = REG_Init();
+ fCFG = CFG_Init();
+ fCSL = CSL_Init();
+ fDBG = DBG_Init();
+ fDPC = DPC_Init();
+ fKFILE = KFILE_Init();
+ fLST = LST_Init();
+ /* fREG = REG_Init(); */
+ fSYNC = SYNC_Init();
+#ifdef OMAP_3430
+ fCLK = CLK_Init();
+#endif
+ fUTIL = UTIL_Init();
+ fNTFY = NTFY_Init();
+
+ fInit = fCFG && fCSL && fDBG && fDPC && fKFILE &&
+#ifdef OMAP_3430
+ fLST && fMEM && fREG && fSYNC && fCLK && fUTIL;
+#else
+ fLST && fMEM && fREG && fSYNC && fUTIL;
+#endif
+
+ if (!fInit) {
+ if (fNTFY)
+ NTFY_Exit();
+
+ if (fUTIL)
+ UTIL_Exit();
+
+ if (fSYNC)
+ SYNC_Exit();
+
+#ifdef OMAP_3430
+ if (fCLK)
+ CLK_Exit();
+#endif
+
+ if (fREG)
+ REG_Exit();
+
+ if (fLST)
+ LST_Exit();
+
+ if (fKFILE)
+ KFILE_Exit();
+
+ if (fDPC)
+ DPC_Exit();
+
+ if (fDBG)
+ DBG_Exit();
+
+ if (fCSL)
+ CSL_Exit();
+
+ if (fCFG)
+ CFG_Exit();
+
+ if (fMEM)
+ MEM_Exit();
+
+ }
+ }
+
+ if (fInit)
+ cRefs++;
+
+ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
+ cRefs);
+
+ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
+
+ return fInit;
+}
+
diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
new file mode 100644
index 000000000000..7ab9347d6c22
--- /dev/null
+++ b/drivers/dsp/bridge/services/sync.c
@@ -0,0 +1,602 @@
+/*
+ * sync.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== sync.c ========
+ * Purpose:
+ * Synchronization services.
+ *
+ * Public Functions:
+ * SYNC_CloseEvent
+ * SYNC_DeleteCS
+ * SYNC_EnterCS
+ * SYNC_Exit
+ * SYNC_Init
+ * SYNC_InitializeCS
+ * SYNC_LeaveCS
+ * SYNC_OpenEvent
+ * SYNC_ResetEvent
+ * SYNC_SetEvent
+ * SYNC_WaitOnEvent
+ * SYNC_WaitOnMultipleEvents
+ *
+ *! Revision History:
+ *! ================
+ *! 05-Nov-2001 kc: Minor cosmetic changes.
+ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
+ *! 10-Aug-2000 rr: SYNC_PostMessage added.
+ *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
+ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
+ *! GT Changes.
+ *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
+ *! 22-Nov-1999 kc: Added changes from code review.
+ *! 22-Sep-1999 kc: Modified from sync95.c.
+ *! 05-Aug-1996 gp: Created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/gt.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/mem.h>
+
+/* ----------------------------------- This */
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define SIGNATURE 0x434e5953 /* "SYNC" (in reverse) */
+
+enum wait_state {
+ wo_waiting,
+ wo_signalled
+} ;
+
+enum sync_state {
+ so_reset,
+ so_signalled
+} ;
+
+struct WAIT_OBJECT {
+ enum wait_state state;
+ struct SYNC_OBJECT *signalling_event;
+ struct semaphore sem;
+};
+
+/* Generic SYNC object: */
+struct SYNC_OBJECT {
+ u32 dwSignature; /* Used for object validation. */
+ enum sync_state state;
+ spinlock_t sync_lock;
+ struct WAIT_OBJECT *pWaitObj;
+};
+
+struct SYNC_DPCCSOBJECT {
+ u32 dwSignature; /* used for object validation */
+ spinlock_t sync_dpccs_lock;
+ s32 count;
+} ;
+
+/* ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask SYNC_debugMask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+static int test_and_set(volatile void *ptr, int val)
+{
+ int ret = val;
+ asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
+ return ret;
+}
+
+static void timeout_callback(unsigned long hWaitObj);
+
+/*
+ * ======== SYNC_CloseEvent ========
+ * Purpose:
+ * Close an existing SYNC event object.
+ */
+DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
+
+ DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
+
+ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
+ hEvent);
+
+ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
+ if (pEvent->pWaitObj) {
+ status = DSP_EFAIL;
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_CloseEvent: Wait object not NULL\n");
+ }
+ MEM_FreeObject(pEvent);
+
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_CloseEvent: invalid "
+ "hEvent handle 0x%x\n", hEvent);
+ }
+
+ return status;
+}
+
+/*
+ * ======== SYNC_Exit ========
+ * Purpose:
+ * Cleanup SYNC module.
+ */
+void SYNC_Exit(void)
+{
+ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
+}
+
+/*
+ * ======== SYNC_Init ========
+ * Purpose:
+ * Initialize SYNC module.
+ */
+bool SYNC_Init(void)
+{
+ GT_create(&SYNC_debugMask, "SY"); /* SY for SYnc */
+
+ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
+
+ return true;
+}
+
+/*
+ * ======== SYNC_OpenEvent ========
+ * Purpose:
+ * Open a new synchronization event object.
+ */
+DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
+ IN OPTIONAL struct SYNC_ATTRS *pAttrs)
+{
+ struct SYNC_OBJECT *pEvent = NULL;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(phEvent != NULL);
+
+ GT_2trace(SYNC_debugMask, GT_ENTER,
+ "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
+ "0x%x\n", phEvent, pAttrs);
+
+ /* Allocate memory for sync object */
+ MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
+ if (pEvent != NULL) {
+ pEvent->state = so_reset;
+ pEvent->pWaitObj = NULL;
+ spin_lock_init(&pEvent->sync_lock);
+ } else {
+ status = DSP_EMEMORY;
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_OpenEvent: MEM_AllocObject failed\n");
+ }
+
+ *phEvent = pEvent;
+
+ return status;
+}
+
+/*
+ * ======== SYNC_ResetEvent ========
+ * Purpose:
+ * Reset an event to non-signalled.
+ */
+DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
+
+ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
+ hEvent);
+
+ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
+ pEvent->state = so_reset;
+ status = DSP_SOK;
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_ResetEvent: invalid hEvent "
+ "handle 0x%x\n", hEvent);
+ }
+
+ return status;
+}
+
+/*
+ * ======== SYNC_SetEvent ========
+ * Purpose:
+ * Set an event to signaled and unblock one waiting thread.
+ *
+ * This function is called from ISR, DPC and user context. Hence interrupts
+ * are disabled to ensure atomicity.
+ */
+
+DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
+ unsigned long flags;
+
+ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
+ hEvent);
+
+ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
+ spin_lock_irqsave(&hEvent->sync_lock, flags);
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_SetEvent: pEvent->pWaitObj "
+ "= 0x%x \n", pEvent->pWaitObj);
+ if (pEvent->pWaitObj)
+ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
+ "pEvent->pWaitObj->state = 0x%x \n",
+ pEvent->pWaitObj->state);
+ if (pEvent->pWaitObj != NULL &&
+ test_and_set(&pEvent->pWaitObj->state,
+ wo_signalled) == wo_waiting) {
+
+ pEvent->state = so_reset;
+ pEvent->pWaitObj->signalling_event = pEvent;
+ up(&pEvent->pWaitObj->sem);
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_SetEvent: Unlock "
+ "Semaphore for hEvent 0x%x\n", hEvent);
+ } else {
+ pEvent->state = so_signalled;
+ }
+ spin_unlock_irqrestore(&hEvent->sync_lock, flags);
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_SetEvent: invalid hEvent "
+ "handle 0x%x\n", hEvent);
+ }
+ return status;
+}
+
+/*
+ * ======== SYNC_WaitOnEvent ========
+ * Purpose:
+ * Wait for an event to be signalled, up to the specified timeout.
+ * Note: dwTimeOut must be 0xffffffff to signal infinite wait.
+ */
+DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
+ u32 temp;
+
+ GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
+ "dwTimeOut 0x%x", hEvent, dwTimeout);
+ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
+ status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
+ &temp);
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_WaitOnEvent: invalid hEvent"
+ "handle 0x%x\n", hEvent);
+ }
+ return status;
+}
+
+/*
+ * ======== SYNC_WaitOnMultipleEvents ========
+ * Purpose:
+ * Wait for any of an array of events to be signalled, up to the
+ * specified timeout.
+ */
+DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
+ u32 uCount, u32 dwTimeout,
+ OUT u32 *puIndex)
+{
+ u32 i;
+ DSP_STATUS status = DSP_SOK;
+ u32 curr;
+ struct WAIT_OBJECT *Wp;
+
+ DBC_Require(uCount > 0);
+ DBC_Require(hSyncEvents != NULL);
+ DBC_Require(puIndex != NULL);
+
+ for (i = 0; i < uCount; i++)
+ DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
+
+ GT_4trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_WaitOnMultipleEvents: hSyncEvents:"
+ "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
+ hSyncEvents, uCount, dwTimeout, puIndex);
+
+ Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
+ if (Wp == NULL)
+ return DSP_EMEMORY;
+
+ Wp->state = wo_waiting;
+ Wp->signalling_event = NULL;
+ init_MUTEX_LOCKED(&(Wp->sem));
+
+ for (curr = 0; curr < uCount; curr++) {
+ hSyncEvents[curr]->pWaitObj = Wp;
+ if (hSyncEvents[curr]->state == so_signalled) {
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "Detected signaled Event !!!\n");
+ if (test_and_set(&(Wp->state), wo_signalled) ==
+ wo_waiting) {
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "Setting Signal Event!!!\n");
+ hSyncEvents[curr]->state = so_reset;
+ Wp->signalling_event = hSyncEvents[curr];
+ }
+ curr++; /* Will try optimizing later */
+ break;
+ }
+ }
+
+ curr--; /* Will try optimizing later */
+ if (Wp->state != wo_signalled && dwTimeout > 0) {
+ struct timer_list timeout;
+ if (dwTimeout != SYNC_INFINITE) {
+ init_timer(&timeout);
+ timeout.function = timeout_callback;
+ timeout.data = (unsigned long)Wp;
+ timeout.expires = jiffies + dwTimeout * HZ / 1000;
+ add_timer(&timeout);
+ }
+ if (down_interruptible(&(Wp->sem))) {
+ GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
+ "WaitOnMultipleEvents Interrupted by signal\n");
+ status = DSP_EFAIL;
+ }
+ if (dwTimeout != SYNC_INFINITE) {
+ if (in_interrupt()) {
+ if (!del_timer(&timeout)) {
+ GT_0trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC: Timer expired\n");
+ }
+ } else {
+ if (!del_timer_sync(&timeout)) {
+ GT_0trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC: Timer expired\n");
+ }
+ }
+ }
+ }
+ for (i = 0; i <= curr; i++) {
+ if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
+ /* Memory corruption here if hSyncEvents[i] is
+ * freed before following statememt. */
+ hSyncEvents[i]->pWaitObj = NULL;
+ }
+ if (hSyncEvents[i] == Wp->signalling_event)
+ *puIndex = i;
+
+ }
+ if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
+ GT_0trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC:Signaling Event NULL!!!(:-\n");
+ status = DSP_ETIMEOUT;
+ }
+ if (Wp)
+ MEM_Free(Wp);
+ return status;
+}
+
+static void timeout_callback(unsigned long hWaitObj)
+{
+ struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
+ if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
+ up(&pWaitObj->sem);
+
+}
+
+/*
+ * ======== SYNC_DeleteCS ========
+ */
+DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
+
+ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
+
+ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
+ if (down_trylock(&pCSObj->sem) != 0) {
+ GT_1trace(SYNC_debugMask, GT_7CLASS,
+ "CS in use (locked) while "
+ "deleting! pCSObj=0x%X", pCSObj);
+ DBC_Assert(0);
+ }
+ MEM_FreeObject(hCSObj);
+ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
+ struct SYNC_DPCCSOBJECT *pDPCCSObj =
+ (struct SYNC_DPCCSOBJECT *)hCSObj;
+ if (pDPCCSObj->count != 1) {
+ GT_1trace(SYNC_debugMask, GT_7CLASS,
+ "DPC CS in use (locked) while "
+ "deleting! pCSObj=0x%X", pCSObj);
+ DBC_Assert(0);
+ }
+ MEM_FreeObject(pDPCCSObj);
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_DeleteCS: invalid hCSObj "
+ "handle 0x%x\n", hCSObj);
+ }
+
+ return status;
+}
+
+/*
+ * ======== SYNC_EnterCS ========
+ */
+DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
+
+ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
+ hCSObj);
+ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
+ if (in_interrupt()) {
+ status = DSP_EFAIL;
+ GT_0trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC_EnterCS called from "
+ "ISR/DPC or with ISR/DPC disabled!");
+ DBC_Assert(0);
+ } else if (down_interruptible(&pCSObj->sem)) {
+ GT_1trace(SYNC_debugMask, GT_7CLASS,
+ "CS interrupted by signal! "
+ "pCSObj=0x%X", pCSObj);
+ status = DSP_EFAIL;
+ }
+ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
+ struct SYNC_DPCCSOBJECT *pDPCCSObj =
+ (struct SYNC_DPCCSOBJECT *)hCSObj;
+ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
+ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
+ pDPCCSObj->count--;
+ if (pDPCCSObj->count != 0) {
+ /* FATAL ERROR : Failed to acquire DPC CS */
+ GT_2trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC_EnterCS DPCCS %x locked,"
+ "count %d", pDPCCSObj, pDPCCSObj->count);
+ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
+ DBC_Assert(0);
+ }
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_EnterCS: invalid hCSObj "
+ "handle 0x%x\n", hCSObj);
+ }
+
+ return status;
+}
+
+/*
+ * ======== SYNC_InitializeCS ========
+ */
+DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_CSOBJECT *pCSObj = NULL;
+
+ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
+
+ /* Allocate memory for sync CS object */
+ MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
+ if (pCSObj != NULL) {
+ init_MUTEX(&pCSObj->sem);
+ } else {
+ status = DSP_EMEMORY;
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_InitializeCS: MEM_AllocObject"
+ "failed\n");
+ }
+ /* return CS object */
+ *phCSObj = pCSObj;
+ DBC_Assert(DSP_FAILED(status) || (pCSObj));
+ return status;
+}
+
+DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_DPCCSOBJECT *pCSObj = NULL;
+
+ DBC_Require(phCSObj);
+
+ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
+
+ if (phCSObj) {
+ /* Allocate memory for sync CS object */
+ MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
+ SIGNATUREDPCCS);
+ if (pCSObj != NULL) {
+ pCSObj->count = 1;
+ spin_lock_init(&pCSObj->sync_dpccs_lock);
+ } else {
+ status = DSP_EMEMORY;
+ GT_0trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_InitializeDPCCS: "
+ "MEM_AllocObject failed\n");
+ }
+
+ /* return CS object */
+ *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
+ } else {
+ status = DSP_EPOINTER;
+ }
+
+ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
+ "pCSObj %p\n", pCSObj);
+ DBC_Assert(DSP_FAILED(status) || (pCSObj));
+
+ return status;
+}
+
+/*
+ * ======== SYNC_LeaveCS ========
+ */
+DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
+
+ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
+ hCSObj);
+
+ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
+ up(&pCSObj->sem);
+ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
+ struct SYNC_DPCCSOBJECT *pDPCCSObj =
+ (struct SYNC_DPCCSOBJECT *)hCSObj;
+ pDPCCSObj->count++;
+ if (pDPCCSObj->count != 1) {
+ /* FATAL ERROR : Invalid DPC CS count */
+ GT_2trace(SYNC_debugMask, GT_7CLASS,
+ "SYNC_LeaveCS DPCCS %x, "
+ "Invalid count %d", pDPCCSObj,
+ pDPCCSObj->count);
+ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
+ DBC_Assert(0);
+ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
+ }
+ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
+ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
+ } else {
+ status = DSP_EHANDLE;
+ GT_1trace(SYNC_debugMask, GT_6CLASS,
+ "SYNC_LeaveCS: invalid hCSObj "
+ "handle 0x%x\n", hCSObj);
+ }
+
+ return status;
+}
diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
new file mode 100644
index 000000000000..801b000e02ca
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_cmm.h
@@ -0,0 +1,59 @@
+/*
+ * _cmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _cmm.h ========
+ * Description:
+ * Private header file defining CMM manager objects and defines needed
+ * by IO manager to register shared memory regions when DSP base image
+ * is loaded(WMD_IO_OnLoaded).
+ *
+ * Public Functions:
+ * None.
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Aug-2001 ag Created.
+ */
+
+#ifndef _CMM_
+#define _CMM_
+
+/*
+ * These target side symbols define the beginning and ending addresses
+ * of the section of shared memory used for shared memory manager CMM.
+ * They are defined in the *cfg.cmd file by cdb code.
+ */
+#define SHM0_SHARED_BASE_SYM "_SHM0_BEG"
+#define SHM0_SHARED_END_SYM "_SHM0_END"
+#define SHM0_SHARED_RESERVED_BASE_SYM "_SHM0_RSVDSTRT"
+
+/*
+ * Shared Memory Region #0(SHMSEG0) is used in the following way:
+ *
+ * |(_SHM0_BEG) | (_SHM0_RSVDSTRT) | (_SHM0_END)
+ * V V V
+ * ------------------------------------------------------------
+ * | DSP-side allocations | GPP-side allocations |
+ * ------------------------------------------------------------
+ *
+ *
+ */
+
+#endif /* _CMM_ */
diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
new file mode 100644
index 000000000000..c9d1d8a6ad98
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_deh.h
@@ -0,0 +1,47 @@
+/*
+ * _deh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _deh.h ========
+ * Description:
+ * Private header for DEH module.
+ *
+ *! Revision History:
+ *! ================
+ *! 21-Sep-2001 kc: created.
+ */
+
+#ifndef _DEH_
+#define _DEH_
+
+#include <dspbridge/dpc.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/wmd.h>
+
+#define SIGNATURE 0x5f484544 /* "DEH_" backwards */
+extern struct notify_driver_object *handle;
+
+/* DEH Manager: only one created per board: */
+struct DEH_MGR {
+ u32 dwSignature; /* Used for object validation. */
+ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
+ struct NTFY_OBJECT *hNtfy; /* NTFY object */
+ struct DPC_OBJECT *hMmuFaultDpc; /* DPC object handle. */
+ struct DSP_ERRORINFO errInfo; /* DSP exception info. */
+} ;
+
+#endif /* _DEH_ */
diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
new file mode 100644
index 000000000000..fa5e9ee1cb62
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_msg_sm.h
@@ -0,0 +1,158 @@
+/*
+ * _msg_sm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _msg_sm.h ========
+ * Description:
+ * Private header file defining MSG manager objects and defines needed
+ * by IO manager.
+ *
+ * Public Functions:
+ * None.
+ *
+ * Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 09-May-2001 jeh Code Review cleanup.
+ *! 08-Nov-2000 jeh Created.
+ */
+
+#ifndef _MSG_SM_
+#define _MSG_SM_
+
+#include <dspbridge/list.h>
+#include <dspbridge/msgdefs.h>
+
+/*
+ * These target side symbols define the beginning and ending addresses
+ * of the section of shared memory used for messages. They are
+ * defined in the *cfg.cmd file by cdb code.
+ */
+#define MSG_SHARED_BUFFER_BASE_SYM "_MSG_BEG"
+#define MSG_SHARED_BUFFER_LIMIT_SYM "_MSG_END"
+
+#ifndef _CHNL_WORDSIZE
+#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
+#endif
+
+/*
+ * ======== MSG ========
+ * There is a control structure for messages to the DSP, and a control
+ * structure for messages from the DSP. The shared memory region for
+ * transferring messages is partitioned as follows:
+ *
+ * ----------------------------------------------------------
+ * |Control | Messages from DSP | Control | Messages to DSP |
+ * ----------------------------------------------------------
+ *
+ * MSG control structure for messages to the DSP is used in the following
+ * way:
+ *
+ * bufEmpty - This flag is set to FALSE by the GPP after it has output
+ * messages for the DSP. The DSP host driver sets it to
+ * TRUE after it has copied the messages.
+ * postSWI - Set to 1 by the GPP after it has written the messages,
+ * set the size, and set bufEmpty to FALSE.
+ * The DSP Host driver uses SWI_andn of the postSWI field
+ * when a host interrupt occurs. The host driver clears
+ * this after posting the SWI.
+ * size - Number of messages to be read by the DSP.
+ *
+ * For messages from the DSP:
+ * bufEmpty - This flag is set to FALSE by the DSP after it has output
+ * messages for the GPP. The DPC on the GPP sets it to
+ * TRUE after it has copied the messages.
+ * postSWI - Set to 1 the DPC on the GPP after copying the messages.
+ * size - Number of messages to be read by the GPP.
+ */
+struct MSG {
+ u32 bufEmpty; /* to/from DSP buffer is empty */
+ u32 postSWI; /* Set to "1" to post MSG SWI */
+ u32 size; /* Number of messages to/from the DSP */
+ u32 resvd;
+} ;
+
+/*
+ * ======== MSG_MGR ========
+ * The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
+ * have MSG_QUEUE to hold all messages that come up from the corresponding
+ * node on the DSP. The MSG_MGR also has a shared queue of messages
+ * ready to go to the DSP.
+ */
+struct MSG_MGR {
+ /* The first two fields must match those in msgobj.h */
+ u32 dwSignature;
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
+
+ struct IO_MGR *hIOMgr; /* IO manager */
+ struct LST_LIST *queueList; /* List of MSG_QUEUEs */
+ struct SYNC_CSOBJECT *hSyncCS; /* For critical sections */
+ /* Signalled when MsgFrame is available */
+ struct SYNC_OBJECT *hSyncEvent;
+ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
+ struct LST_LIST *msgUsedList; /* MsgFrames ready to go to DSP */
+ u32 uMsgsPending; /* # of queued messages to go to DSP */
+ u32 uMaxMsgs; /* Max # of msgs that fit in buffer */
+ MSG_ONEXIT onExit; /* called when RMS_EXIT is received */
+} ;
+
+/*
+ * ======== MSG_QUEUE ========
+ * Each NODE has a MSG_QUEUE for receiving messages from the
+ * corresponding node on the DSP. The MSG_QUEUE object maintains a list
+ * of messages that have been sent to the host, but not yet read (MSG_Get),
+ * and a list of free frames that can be filled when new messages arrive
+ * from the DSP.
+ * The MSG_QUEUE's hSynEvent gets posted when a message is ready.
+ */
+struct MSG_QUEUE {
+ struct LST_ELEM listElem;
+ u32 dwSignature;
+ struct MSG_MGR *hMsgMgr;
+ u32 uMaxMsgs; /* Node message depth */
+ u32 dwId; /* Node environment pointer */
+ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
+ /* Filled MsgFramess waiting to be read */
+ struct LST_LIST *msgUsedList;
+ HANDLE hArg; /* Handle passed to mgr onExit callback */
+ struct SYNC_OBJECT *hSyncEvent; /* Signalled when message is ready */
+ struct SYNC_OBJECT *hSyncDone; /* For synchronizing cleanup */
+ struct SYNC_OBJECT *hSyncDoneAck; /* For synchronizing cleanup */
+ struct NTFY_OBJECT *hNtfy; /* For notification of message ready */
+ bool fDone; /* TRUE <==> deleting the object */
+ u32 refCount; /* Number of pending MSG_get/put calls */
+};
+
+/*
+ * ======== MSG_DSPMSG ========
+ */
+struct MSG_DSPMSG {
+ struct DSP_MSG msg;
+ u32 dwId; /* Identifies the node the message goes to */
+} ;
+
+/*
+ * ======== MSG_FRAME ========
+ */
+struct MSG_FRAME {
+ struct LST_ELEM listElem;
+ struct MSG_DSPMSG msgData;
+} ;
+
+#endif /* _MSG_SM_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
new file mode 100644
index 000000000000..282d5fe1a0ff
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap.h
@@ -0,0 +1,418 @@
+/*
+ * _tiomap.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== _tiomap.h ========
+ * Description:
+ * Definitions and types private to this WMD.
+ *
+ *! Revision History
+ *! ================
+ *! 12-Apr-2004 hp: Removed the L4 entry of Dsp DMA , not needed
+ *! 08-Mar-2004 sb: Added the Dynamic Memory Mapping feature - PgTableAttrs
+ *! 21-Mar-2003 sb: Added numTLBEntries to struct WMD_DEV_CONTEXT
+ *! 20-Feb-2003 vp: Ported to Linux platform.
+ *! 30-Jul-2002 rr: Modified TBC_ID_VALUE to 0xb47002f.
+ *! 10-May-2002 sg: Added ARM_SYSST_OFFSET and IDLE_DSP_MASK.
+ *! 14-Mar-2002 rr: Added Boot vector field to pDevContext.
+ *! Added TBC Register defines and value for OMAP1510.
+ *! 12-Jan-2002 ag: wIntrVal2Dsp Added.
+ *! 05-Nov-2001 kc: Added MMU fault related definitions.
+ *! 03-Aug-2001 ag Added TLB table for OEM cofig of DSP-MMU.
+ *! 23-Aug-2001 rr: Added API_SIZE define.
+ *! 16-Aug-2001 rr: Added dwDspExtBaseAddr to access the Ext memory.
+ *! 24-Jul-2001 ag: Added Internal SRAM MMU table entry.
+ *! 27-Jun-2001 rr: Name changed to _tihelen.h.
+ *! 27-Jun-2001 ag: Added dwIntAddr in WMD_DEV_CONTEXT used for MB INTRs msk.
+ *! 07-May-2001 ag: Added DSP Clock Module CLKM2.
+ *! Added TIHEL_SDRAMPHYSBASE used for DSP MMU init.
+ *! Added ClearBit() MACRO.
+ *! 18-Jan-2001 rr: Created
+ */
+
+#ifndef _TIOMAP_
+#define _TIOMAP_
+
+#include <dspbridge/devdefs.h>
+#include <hw_defs.h>
+#include <hw_mbox.h>
+#include <dspbridge/wmdioctl.h> /* for WMDIOCTL_EXTPROC defn */
+#include <dspbridge/sync.h>
+#include <dspbridge/clk.h>
+
+struct MAP_L4PERIPHERAL {
+ u32 physAddr;
+ u32 dspVirtAddr;
+ u32 ulSize;
+} ;
+
+#define ARM_MAILBOX_START 0xfffcf000
+#define ARM_MAILBOX_LENGTH 0x800
+
+/* New Registers in OMAP3.1 */
+
+#define TESTBLOCK_ID_START 0xfffed400
+#define TESTBLOCK_ID_LENGTH 0xff
+
+/* ID Returned by OMAP1510 */
+#define TBC_ID_VALUE 0xB47002F
+
+#define SPACE_LENGTH 0x2000
+#define API_CLKM_DPLL_DMA 0xfffec000
+#define ARM_INTERRUPT_OFFSET 0xb00
+
+#define BIOS_24XX
+
+#define L4_PERIPHERAL_NULL 0x0
+#define DSPVA_PERIPHERAL_NULL 0x0
+
+#define MAX_LOCK_TLB_ENTRIES 15
+
+#define L4_PERIPHERAL_UART3 0x48020000
+#define DSPVA_PERIPHERAL_UART3 L4_PERIPHERAL_UART3
+
+#define L4_PERIPHERAL_GPIO2 0x48055000
+#define DSPVA_PERIPHERAL_GPIO2 L4_PERIPHERAL_GPIO2
+#define L4_PERIPHERAL_GPIO3 0x48057000
+#define DSPVA_PERIPHERAL_GPIO3 L4_PERIPHERAL_GPIO3
+#define L4_PERIPHERAL_GPIO4 0x48059000
+#define DSPVA_PERIPHERAL_GPIO4 L4_PERIPHERAL_GPIO4
+#define L4_PERIPHERAL_GPIO5 0x4805B000
+#define DSPVA_PERIPHERAL_GPIO5 L4_PERIPHERAL_GPIO5
+
+#define L4_PERIPHERAL_GPTIMER5 0x49038000
+#define DSPVA_PERIPHERAL_GPTIMER5 L4_PERIPHERAL_GPTIMER5
+#define L4_PERIPHERAL_GPTIMER6 0x4903A000
+#define DSPVA_PERIPHERAL_GPTIMER6 L4_PERIPHERAL_GPTIMER6
+#define L4_PERIPHERAL_GPTIMER7 0x4903C000
+#define DSPVA_PERIPHERAL_GPTIMER7 L4_PERIPHERAL_GPTIMER7
+#define L4_PERIPHERAL_GPTIMER8 0x4903E000
+#define DSPVA_PERIPHERAL_GPTIMER8 L4_PERIPHERAL_GPTIMER8
+
+#define L4_PERIPHERAL_UART1 0x4806A000
+#define DSPVA_PERIPHERAL_UART1 L4_PERIPHERAL_UART1
+#define L4_PERIPHERAL_UART2 0x4806C000
+#define DSPVA_PERIPHERAL_UART2 L4_PERIPHERAL_UART2
+#define L4_PERIPHERAL_UART4 0x4806E000
+#define DSPVA_PERIPHERAL_UART4 L4_PERIPHERAL_UART4
+
+#define L4_PERIPHERAL_MCBSP4 0x48074000
+#define DSPVA_PERIPHERAL_MCBSP4 L4_PERIPHERAL_MCBSP4
+#define L4_PERIPHERAL_MCBSP5 0x48096000
+#define DSPVA_PERIPHERAL_MCBSP5 L4_PERIPHERAL_MCBSP5
+
+#define L4_PERIPHERAL_MCSPI1 0x48098000
+#define DSPVA_PERIPHERAL_MCSPI1 L4_PERIPHERAL_MCSPI1
+#define L4_PERIPHERAL_MCSPI2 0x4809A000
+#define DSPVA_PERIPHERAL_MCSPI2 L4_PERIPHERAL_MCSPI2
+
+#define L4_PERIPHERAL_MCBSP1 0x49022000
+#define DSPVA_PERIPHERAL_MCBSP1 L4_PERIPHERAL_MCBSP1
+#define L4_PERIPHERAL_MCBSP2 0x49024000
+#define DSPVA_PERIPHERAL_MCBSP2 L4_PERIPHERAL_MCBSP2
+#define L4_PERIPHERAL_MCBSP3 0x49028000
+#define DSPVA_PERIPHERAL_MCBSP3 L4_PERIPHERAL_MCBSP3
+
+#define L4_PERIPHERAL_WDT3 0x49030000
+#define DSPVA_PERIPHERAL_WDT3 L4_PERIPHERAL_WDT3
+
+#define L4_PERIPHERAL_MBOX 0x4A0F4000
+#define DSPVA_PERIPHERAL_MBOX L4_PERIPHERAL_MBOX
+
+
+#define L4_PERIPHERAL_CM1 0x4A004000
+#define DSPVA_PERIPHERAL_CM1 L4_PERIPHERAL_CM1
+#define L4_PERIPHERAL_CM2_P1 0x4A008000 /*(4Kb)*/
+#define DSPVA_PERIPHERAL_CM2_P1 L4_PERIPHERAL_CM2_P1
+#define L4_PERIPHERAL_CM2_P2 0x4A009000 /*(4Kb)*/
+#define DSPVA_PERIPHERAL_CM2_P2 L4_PERIPHERAL_CM2_P2
+
+
+#define L4_PERIPHERAL_PRM_P1 0x4A306000 /*(4Kb)*/
+#define DSPVA_PERIPHERAL_PRM_P1 L4_PERIPHERAL_PRM_P1
+#define L4_PERIPHERAL_PRM_P2 0x4A307000 /*(4Kb)*/
+#define DSPVA_PERIPHERAL_PRM_P2 L4_PERIPHERAL_PRM_P2
+
+
+
+#define L4_PERIPHERAL_SCRM 0x4A30A000
+#define DSPVA_PERIPHERAL_SCRM L4_PERIPHERAL_SCRM
+
+#define L4_PERIPHERAL_GPIO1 0x4A310000
+#define DSPVA_PERIPHERAL_GPIO1 L4_PERIPHERAL_GPIO1
+
+#define NOTIFY_TESLA_EVENTNUMBER 0x00000000
+
+static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
+/* Mailbox 4KB */
+{L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX, HW_PAGE_SIZE_4KB},
+/* SCM 4KB */
+{L4_PERIPHERAL_SCRM, DSPVA_PERIPHERAL_SCRM, HW_PAGE_SIZE_4KB},
+/* PRM 8KB */
+{L4_PERIPHERAL_PRM_P1, DSPVA_PERIPHERAL_PRM_P1, HW_PAGE_SIZE_4KB},
+{L4_PERIPHERAL_PRM_P2, DSPVA_PERIPHERAL_PRM_P2, HW_PAGE_SIZE_4KB},
+
+/* CM1 4KB */
+{L4_PERIPHERAL_CM1, DSPVA_PERIPHERAL_CM1, HW_PAGE_SIZE_4KB},
+/* CM2 8KB */
+{L4_PERIPHERAL_CM2_P1, DSPVA_PERIPHERAL_CM2_P1, HW_PAGE_SIZE_4KB},
+{L4_PERIPHERAL_CM2_P2, DSPVA_PERIPHERAL_CM2_P2, HW_PAGE_SIZE_4KB},
+
+/* GP timer1 4KB */
+{L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5, HW_PAGE_SIZE_4KB},
+/* GP timer6 4KB */
+{L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6, HW_PAGE_SIZE_4KB},
+/* GP timer7 4KB */
+{L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7, HW_PAGE_SIZE_4KB},
+/* GP timer8 4KB */
+{L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8, HW_PAGE_SIZE_4KB},
+/* GPIO1 4KB */
+{L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1, HW_PAGE_SIZE_4KB},
+/* GPIO2 4KB */
+{L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2, HW_PAGE_SIZE_4KB},
+/* GPIO3 4KB */
+{L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3, HW_PAGE_SIZE_4KB},
+/* GPIO4 4KB */
+{L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4, HW_PAGE_SIZE_4KB},
+/* GPIO5 4KB */
+{L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5, HW_PAGE_SIZE_4KB},
+/* Watch dog timer 4KB */
+{L4_PERIPHERAL_WDT3, DSPVA_PERIPHERAL_WDT3, HW_PAGE_SIZE_4KB},
+/* Mcbsp1 4KB */
+{L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1, HW_PAGE_SIZE_4KB},
+/* Mcbsp2 4KB */
+{L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2, HW_PAGE_SIZE_4KB},
+/* Mcbsp3 4KB */
+{L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3, HW_PAGE_SIZE_4KB},
+/* Mcbsp4 4KB */
+{L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4, HW_PAGE_SIZE_4KB},
+/* Mcbsp5 4KB */
+{L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5, HW_PAGE_SIZE_4KB},
+/* UART1 4KB */
+{L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1, HW_PAGE_SIZE_4KB},
+/* UART2 4KB */
+{L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2, HW_PAGE_SIZE_4KB},
+/* UART3 4KB */
+{L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3, HW_PAGE_SIZE_4KB},
+/* SPI1 4KB */
+{L4_PERIPHERAL_MCSPI1, DSPVA_PERIPHERAL_MCSPI1, HW_PAGE_SIZE_4KB},
+/* SPI2 4KB */
+{L4_PERIPHERAL_MCSPI2, DSPVA_PERIPHERAL_MCSPI2, HW_PAGE_SIZE_4KB},
+
+{L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
+
+};
+
+
+/*
+ * 15 10 0
+ * ---------------------------------
+ * |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
+ * ---------------------------------
+ * | (class) | (module specific) |
+ *
+ * where c -> Externel Clock Command: Clk & Autoidle Disable/Enable
+ * i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
+ */
+
+/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
+#define MBX_PM_CLK_IDMASK 0x7F
+
+/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
+#define MBX_PM_CLK_CMDSHIFT 7
+
+/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
+#define MBX_PM_CLK_CMDMASK 7
+
+/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
+#define MBX_CORE1_RESOURCES 7
+
+/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
+#define MBX_CORE2_RESOURCES 1
+
+/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
+#define MBX_PM_MAX_RESOURCES 11
+
+/* Power Management Commands */
+enum BPWR_ExtClockCmd {
+ BPWR_DisableClock = 0,
+ BPWR_EnableClock,
+ BPWR_DisableAutoIdle,
+ BPWR_EnableAutoIdle
+} ;
+
+/* OMAP242x specific resources */
+enum BPWR_ExtClockId {
+ BPWR_GPTimer5 = 0x10,
+ BPWR_GPTimer6,
+ BPWR_GPTimer7,
+ BPWR_GPTimer8,
+ BPWR_WDTimer3,
+ BPWR_MCBSP1,
+ BPWR_MCBSP2,
+ BPWR_MCBSP3,
+ BPWR_MCBSP4,
+ BPWR_MCBSP5,
+ BPWR_SSI = 0x20
+} ;
+
+static const u32 BPWR_CLKID[] = {
+ (u32) BPWR_GPTimer5,
+ (u32) BPWR_GPTimer6,
+ (u32) BPWR_GPTimer7,
+ (u32) BPWR_GPTimer8,
+ (u32) BPWR_WDTimer3,
+ (u32) BPWR_MCBSP1,
+ (u32) BPWR_MCBSP2,
+ (u32) BPWR_MCBSP3,
+ (u32) BPWR_MCBSP4,
+ (u32) BPWR_MCBSP5,
+ (u32) BPWR_SSI
+};
+
+struct BPWR_Clk_t {
+ u32 clkId;
+ enum SERVICES_ClkId funClk;
+ enum SERVICES_ClkId intClk;
+} ;
+
+static const struct BPWR_Clk_t BPWR_Clks[] = {
+ {(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
+ {(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
+ {(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
+ {(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
+ {(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
+ {(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
+ {(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
+ {(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
+ {(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
+ {(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
+ {(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
+};
+
+/* Interrupt Register Offsets */
+#define INTH_IT_REG_OFFSET 0x00 /* Interrupt register offset */
+#define INTH_MASK_IT_REG_OFFSET 0x04 /* Mask Interrupt reg offset */
+
+#define DSP_MAILBOX1_INT 10
+
+/*
+ * INTH_InterruptKind_t
+ * Identify the kind of interrupt: either FIQ/IRQ
+ */
+enum INTH_InterruptKind_t {
+ INTH_IRQ = 0,
+ INTH_FIQ = 1
+} ;
+
+enum INTH_SensitiveEdge_t {
+ FALLING_EDGE_SENSITIVE = 0,
+ LOW_LEVEL_SENSITIVE = 1
+} ;
+
+/*
+ * Bit definition of Interrupt Level Registers
+ */
+
+/* Mail Box defines */
+#define MB_ARM2DSP1_REG_OFFSET 0x00
+
+#define MB_ARM2DSP1B_REG_OFFSET 0x04
+
+#define MB_DSP2ARM1B_REG_OFFSET 0x0C
+
+#define MB_ARM2DSP1_FLAG_REG_OFFSET 0x18
+
+#define MB_ARM2DSP_FLAG 0x0001
+
+#define MBOX_ARM2DSP HW_MBOX_ID_0
+#define MBOX_DSP2ARM HW_MBOX_ID_1
+#define MBOX_ARM HW_MBOX_U0_ARM
+#define MBOX_DSP HW_MBOX_U1_DSP1
+
+#define ENABLE true
+#define DISABLE false
+
+#define HIGH_LEVEL true
+#define LOW_LEVEL false
+
+/* Macro's */
+#define REG16(A) (*(REG_UWORD16 *)(A))
+
+#define ClearBit(reg, mask) (reg &= ~mask)
+#define SetBit(reg, mask) (reg |= mask)
+
+#define SetGroupBits16(reg, position, width, value) \
+ do {\
+ reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
+ reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
+ } while (0);
+
+#define ClearBitIndex(reg, index) (reg &= ~(1 << (index)))
+
+/* This mini driver's device context: */
+struct WMD_DEV_CONTEXT {
+ struct DEV_OBJECT *hDevObject; /* Handle to WCD device object. */
+ u32 dwDspBaseAddr; /* Arm's API to DSP virtual base addr */
+ /*
+ * DSP External memory prog address as seen virtually by the OS on
+ * the host side.
+ */
+ u32 dwDspExtBaseAddr; /* See the comment above */
+ u32 dwAPIRegBase; /* API memory mapped registers */
+ u32 dwDSPMmuBase; /* DSP MMU Mapped registers */
+ u32 dwMailBoxBase; /* Mail box mapped registers */
+ u32 dwAPIClkBase; /* CLK Registers */
+ u32 dwDSPClkM2Base; /* DSP Clock Module m2 */
+ u32 dwPublicRhea; /* Pub Rhea */
+ u32 dwIntAddr; /* MB INTR reg */
+ u32 dwTCEndianism; /* TC Endianism register */
+ u32 dwTestBase; /* DSP MMU Mapped registers */
+ u32 dwSelfLoop; /* Pointer to the selfloop */
+ u32 dwDSPStartAdd; /* API Boot vector */
+ u32 dwInternalSize; /* Internal memory size */
+
+ /*
+ * Processor specific info is set when prog loaded and read from DCD.
+ * [See WMD_BRD_Ctrl()] PROC info contains DSP-MMU TLB entries.
+ */
+ /* DMMU TLB entries */
+ struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
+ u32 dwBrdState; /* Last known board state. */
+ u32 ulIntMask; /* int mask */
+ u16 ioBase; /* Board I/O base */
+ u16 wIntrVal2Dsp; /* MBX value to DSP. See mbx_sh.h */
+ u32 numTLBEntries; /* DSP MMU TLB entry counter */
+ u32 fixedTLBEntries; /* Fixed DSPMMU TLB entry count */
+
+ /* TC Settings */
+ bool tcWordSwapOn; /* Traffic Controller Word Swap */
+ struct PgTableAttrs *pPtAttrs;
+ u32 uDspPerClks;
+} ;
+
+ /*
+ * ======== WMD_TLB_DspVAToMpuPA ========
+ * Given a DSP virtual address, traverse the page table and return
+ * a corresponding MPU physical address and size.
+ */
+extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u32 ulVirtAddr,
+ OUT u32 *ulPhysAddr,
+ OUT u32 *sizeTlb);
+
+#endif /* _TIOMAP_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
new file mode 100644
index 000000000000..6b21047ebdc3
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
@@ -0,0 +1,53 @@
+/*
+ * _tiomap_mmu.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _tiomap_mmu.h ========
+ * Description:
+ * Definitions and types for the DSP MMU modules
+ *
+ *! Revision History
+ *! ================
+ *! 19-Apr-2004 sb: Renamed HW types. Removed dspMmuTlbEntry
+ *! 05-Jan-2004 vp: Moved the file to a platform specific folder from common.
+ *! 21-Mar-2003 sb: Added macro definition TIHEL_LARGEPAGESIZE
+ *! 08-Oct-2002 rr: Created.
+ */
+
+#ifndef _TIOMAP_MMU_
+#define _TIOMAP_MMU_
+
+#include "_tiomap.h"
+
+/*
+ * ======== configureDspMmu ========
+ *
+ * Make DSP MMu page table entries.
+ * Note: Not utilizing Coarse / Fine page tables.
+ * SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
+ * DSP Byte address 0x40_0000 is word addr 0x20_0000.
+ */
+extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
+ u32 dataBasePhys,
+ u32 dspBaseVirt,
+ u32 sizeInBytes,
+ s32 nEntryStart,
+ enum HW_Endianism_t endianism,
+ enum HW_ElementSize_t elemSize,
+ enum HW_MMUMixedSize_t mixedSize);
+
+#endif /* _TIOMAP_MMU_ */
diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
new file mode 100644
index 000000000000..7ebd7b52520e
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
@@ -0,0 +1,102 @@
+/*
+ * _tiomap_pwr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _tiomap_pwr.h ========
+ * Description:
+ * Definitions and types for the DSP wake/sleep routines.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr: Created.
+ */
+
+#ifndef _TIOMAP_PWR_
+#define _TIOMAP_PWR_
+
+/*
+ * ======== WakeDSP =========
+ * Wakes up the DSP from DeepSleep
+ */
+extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+
+/*
+ * ======== SleepDSP =========
+ * Places the DSP in DeepSleep.
+ */
+extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u32 dwCmd, IN void *pArgs);
+/*
+ * ========InterruptDSP========
+ * Sends an interrupt to DSP unconditionally.
+ */
+extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
+
+/*
+ * ======== WakeDSP =========
+ * Wakes up the DSP from DeepSleep
+ */
+extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs);
+/*
+ * ======== handle_hibernation_fromDSP ========
+ * Handle Hibernation requested from DSP
+ */
+DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
+/*
+ * ======== PostScale_DSP ========
+ * Handle Post Scale notification to DSP
+ */
+DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+/*
+ * ======== PreScale_DSP ========
+ * Handle Pre Scale notification to DSP
+ */
+DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+/*
+ * ======== handle_constraints_set ========
+ * Handle constraints request from DSP
+ */
+DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs);
+/*
+ * ======== DSP_PeripheralClocks_Disable ========
+ * This function disables all the peripheral clocks that
+ * were enabled by DSP. Call this function only when
+ * DSP is entering Hibernation or when DSP is in
+ * Error state
+ */
+DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs);
+
+/*
+ * ======== DSP_PeripheralClocks_Enable ========
+ * This function enables all the peripheral clocks that
+ * were requested by DSP.
+ */
+DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs);
+
+/*
+ * ======== DSPClkWakeupEventCtrl ========
+ * This function sets the group selction bits for while
+ * enabling/disabling.
+ */
+void DSPClkWakeupEventCtrl(u32 ClkId, bool enable);
+
+#endif /* _TIOMAP_PWR_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
new file mode 100644
index 000000000000..47e1e5d001d9
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
@@ -0,0 +1,46 @@
+/*
+ * _tiomap_util.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _tiomap_util.h ========
+ * Description:
+ * Definitions and types for the utility routines.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr: Created.
+ */
+
+#ifndef _TIOMAP_UTIL_
+#define _TIOMAP_UTIL_
+
+/* Time out Values in uSeconds*/
+#define TIHELEN_ACKTIMEOUT 10000
+
+/* Time delay for HOM->SAM transition. */
+#define WAIT_SAM 1000000 /* in usec (1000 millisec) */
+
+/*
+ * ======== WaitForStart ========
+ * Wait for the singal from DSP that it has started, or time out.
+ * The argument dwSyncAddr is set to 1 before releasing the DSP.
+ * If the DSP starts running, it will clear this location.
+ */
+extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
+
+#endif /* _TIOMAP_UTIL_ */
+
diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
new file mode 100644
index 000000000000..e8ffb2f87783
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/chnl_sm.c
@@ -0,0 +1,1100 @@
+/*
+ * chnl_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== chnl_sm.c ========
+ * Description:
+ * Implements upper edge functions for WMD channel module.
+ *
+ * Public Functions:
+ * WMD_CHNL_AddIOReq
+ * WMD_CHNL_CancelIO
+ * WMD_CHNL_Close
+ * WMD_CHNL_Create
+ * WMD_CHNL_Destroy
+ * WMD_CHNL_FlushIO
+ * WMD_CHNL_GetInfo
+ * WMD_CHNL_GetIOC
+ * WMD_CHNL_GetMgrInfo
+ * WMD_CHNL_Idle
+ * WMD_CHNL_Open
+ *
+ * Notes:
+ * The lower edge functions must be implemented by the WMD writer, and
+ * are declared in chnl_sm.h.
+ *
+ * Care is taken in this code to prevent simulataneous access to channel
+ * queues from
+ * 1. Threads.
+ * 2. IO_DPC(), scheduled from the IO_ISR() as an event.
+ *
+ * This is done primarily by:
+ * - Semaphores.
+ * - state flags in the channel object; and
+ * - ensuring the IO_Dispatch() routine, which is called from both
+ * CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
+ *
+ * Channel Invariant:
+ * There is an important invariant condition which must be maintained per
+ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
+ * which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
+ * This invariant condition is:
+ *
+ * LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
+ * and
+ * !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
+ *
+ *! Revision History:
+ *! ================
+ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
+ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
+ *! 23-Apr-2003 sb: Fixed mailbox deadlock
+ *! 24-Feb-2003 vp: Code Review Updates.
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 29-Aug-2002 rr Changed the SYNC error code return to DSP error code return
+ * in WMD_CHNL_GetIOC.
+ *! 22-Jan-2002 ag Zero-copy support added.
+ *! CMM_CallocBuf() used for SM allocations.
+ *! 04-Feb-2001 ag DSP-DMA support added.
+ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
+ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
+ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
+ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
+ *! Remove #ifdef DEBUG from around channel cIOCs field.
+ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
+ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
+ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
+ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
+ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
+ *! 20-Jan-2000 ag: Incorporated code review comments.
+ *! 05-Jan-2000 ag: Text format cleanup.
+ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
+ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
+ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
+ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
+ *! SM addrs taken from COFF(IO) or host resource(SM).
+ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
+ *! address and length from symbols defined in the currently
+ *! loaded COFF file. See _chn_sm.h.
+ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
+ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
+ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
+ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
+ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
+ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
+ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
+ *! of the SHM window length reported by Windows CM.
+ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
+ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
+ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
+ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
+ *! 14-Jan-1997 gp: Updated based on code review feedback.
+ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
+ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
+ *! 13-Sep-1996 gp: Added performance statistics for channel.
+ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
+ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
+ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
+ *! 17-Jul-1996 gp: Started pseudo coding.
+ *! 11-Jul-1996 gp: Stubbed out.
+ */
+
+/* ----------------------------------- OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Mini-Driver */
+#include <dspbridge/wmd.h>
+#include <dspbridge/wmdchnl.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/io_sm.h>
+
+/* ----------------------------------- Define for This */
+#define USERMODE_ADDR PAGE_OFFSET
+
+#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
+
+/* ----------------------------------- Function Prototypes */
+static struct LST_LIST *CreateChirpList(u32 uChirps);
+
+static void FreeChirpList(struct LST_LIST *pList);
+
+static struct CHNL_IRP *MakeNewChirp(void);
+
+static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
+ OUT u32 *pdwChnl);
+
+/*
+ * ======== WMD_CHNL_AddIOReq ========
+ * Enqueue an I/O request for data transfer on a channel to the DSP.
+ * The direction (mode) is specified in the channel object. Note the DSP
+ * address is specified for channels opened in direct I/O mode.
+ */
+DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
+ u32 cBytes, u32 cBufSize,
+ OPTIONAL u32 dwDspAddr, u32 dwArg)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+ struct CHNL_IRP *pChirp = NULL;
+ u32 dwState;
+ bool fIsEOS;
+ struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
+ u8 *pHostSysBuf = NULL;
+ bool fSchedDPC = false;
+ u16 wMbVal = 0;
+
+ DBG_Trace(DBG_ENTER,
+ "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
+ "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
+ pChnl->uChnlType, pChnl->uId);
+
+ fIsEOS = (cBytes == 0) ? true : false;
+
+ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
+ if (!(pHostBuf < (void *)USERMODE_ADDR)) {
+ pHostSysBuf = pHostBuf;
+ goto func_cont;
+ }
+ /* if addr in user mode, then copy to kernel space */
+ pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
+ if (pHostSysBuf == NULL) {
+ status = DSP_EMEMORY;
+ DBG_Trace(DBG_LEVEL7,
+ "No memory to allocate kernel buffer\n");
+ goto func_cont;
+ }
+ if (CHNL_IsOutput(pChnl->uMode)) {
+ status = copy_from_user(pHostSysBuf, pHostBuf,
+ cBufSize);
+ if (status) {
+ DBG_Trace(DBG_LEVEL7,
+ "Error copying user buffer to "
+ "kernel, %d bytes remaining.\n",
+ status);
+ MEM_Free(pHostSysBuf);
+ pHostSysBuf = NULL;
+ status = DSP_EPOINTER;
+ }
+ }
+ }
+func_cont:
+ /* Validate args: */
+ if (pHostBuf == NULL) {
+ status = DSP_EPOINTER;
+ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
+ status = CHNL_E_NOEOS;
+ } else {
+ /* Check the channel state: only queue chirp if channel state
+ * allows */
+ dwState = pChnl->dwState;
+ if (dwState != CHNL_STATEREADY) {
+ if (dwState & CHNL_STATECANCEL) {
+ status = CHNL_E_CANCELLED;
+ } else if ((dwState & CHNL_STATEEOS)
+ && CHNL_IsOutput(pChnl->uMode)) {
+ status = CHNL_E_EOS;
+ } else {
+ /* No other possible states left: */
+ DBC_Assert(0);
+ }
+ }
+ }
+ /* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
+ * channels. DPCCS is held to avoid race conditions with PCPY channels.
+ * If DPC is scheduled in process context (IO_Schedule) and any
+ * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
+ * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
+ SYNC_EnterCS(pChnlMgr->hCSObj);
+ disable_irq(MAILBOX_IRQ);
+ if (pChnl->uChnlType == CHNL_PCPY) {
+ /* This is a processor-copy channel. */
+ if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
+ /* Check buffer size on output channels for fit. */
+ if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
+ status = CHNL_E_BUFSIZE;
+
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get a free chirp: */
+ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
+ if (pChirp == NULL)
+ status = CHNL_E_NOIORPS;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Enqueue the chirp on the chnl's IORequest queue: */
+ pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
+ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
+ pChirp->pHostSysBuf = pHostSysBuf;
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Note: for dma chans dwDspAddr contains dsp address
+ * of SM buffer.*/
+ DBC_Assert(pChnlMgr->uWordSize != 0);
+ /* DSP address */
+ pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
+ pChirp->cBytes = cBytes;
+ pChirp->cBufSize = cBufSize;
+ /* Only valid for output channel */
+ pChirp->dwArg = dwArg;
+ pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
+ CHNL_IOCSTATCOMPLETE);
+ LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
+ pChirp);
+ pChnl->cIOReqs++;
+ DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
+ /* If end of stream, update the channel state to prevent
+ * more IOR's: */
+ if (fIsEOS)
+ pChnl->dwState |= CHNL_STATEEOS;
+
+ {
+ /* Legacy DSM Processor-Copy */
+ DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
+ /* Request IO from the DSP */
+ IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
+ (CHNL_IsInput(pChnl->uMode) ?
+ IO_INPUT : IO_OUTPUT), &wMbVal);
+ fSchedDPC = true;
+ }
+ }
+ }
+ enable_irq(MAILBOX_IRQ);
+ SYNC_LeaveCS(pChnlMgr->hCSObj);
+ if (wMbVal != 0)
+ IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
+
+ if (fSchedDPC == true) {
+ /* Schedule a DPC, to do the actual data transfer: */
+ IO_Schedule(pChnlMgr->hIOMgr);
+ }
+ DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_CancelIO ========
+ * Return all I/O requests to the client which have not yet been
+ * transferred. The channel's I/O completion object is
+ * signalled, and all the I/O requests are queued as IOC's, with the
+ * status field set to CHNL_IOCSTATCANCEL.
+ * This call is typically used in abort situations, and is a prelude to
+ * CHNL_Close();
+ */
+DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+ u32 iChnl = -1;
+ CHNL_MODE uMode;
+ struct CHNL_IRP *pChirp;
+ struct CHNL_MGR *pChnlMgr = NULL;
+
+ /* Check args: */
+ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ iChnl = pChnl->uId;
+ uMode = pChnl->uMode;
+ pChnlMgr = pChnl->pChnlMgr;
+ } else {
+ status = DSP_EHANDLE;
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ /* Mark this channel as cancelled, to prevent further IORequests or
+ * IORequests or dispatching. */
+ SYNC_EnterCS(pChnlMgr->hCSObj);
+ pChnl->dwState |= CHNL_STATECANCEL;
+ if (LST_IsEmpty(pChnl->pIORequests))
+ goto func_cont;
+
+ if (pChnl->uChnlType == CHNL_PCPY) {
+ /* Indicate we have no more buffers available for transfer: */
+ if (CHNL_IsInput(pChnl->uMode)) {
+ IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
+ } else {
+ /* Record that we no longer have output buffers
+ * available: */
+ pChnlMgr->dwOutputMask &= ~(1 << iChnl);
+ }
+ }
+ /* Move all IOR's to IOC queue: */
+ while (!LST_IsEmpty(pChnl->pIORequests)) {
+ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
+ if (pChirp) {
+ pChirp->cBytes = 0;
+ pChirp->status |= CHNL_IOCSTATCANCEL;
+ LST_PutTail(pChnl->pIOCompletions,
+ (struct LST_ELEM *)pChirp);
+ pChnl->cIOCs++;
+ pChnl->cIOReqs--;
+ DBC_Assert(pChnl->cIOReqs >= 0);
+ }
+ }
+func_cont:
+ SYNC_LeaveCS(pChnlMgr->hCSObj);
+func_end:
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_Close ========
+ * Purpose:
+ * Ensures all pending I/O on this channel is cancelled, discards all
+ * queued I/O completion notifications, then frees the resources allocated
+ * for this channel, and makes the corresponding logical channel id
+ * available for subsequent use.
+ */
+DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
+{
+ DSP_STATUS status;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+
+ /* Check args: */
+ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto func_cont;
+ }
+ {
+ /* Cancel IO: this ensures no further IO requests or
+ * notifications.*/
+ status = WMD_CHNL_CancelIO(hChnl);
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status)) {
+ /* Assert I/O on this channel is now cancelled: Protects
+ * from IO_DPC. */
+ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
+ /* Invalidate channel object: Protects from
+ * CHNL_GetIOCompletion(). */
+ pChnl->dwSignature = 0x0000;
+ /* Free the slot in the channel manager: */
+ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
+ pChnl->pChnlMgr->cOpenChannels -= 1;
+ if (pChnl->hNtfy) {
+ NTFY_Delete(pChnl->hNtfy);
+ pChnl->hNtfy = NULL;
+ }
+ /* Reset channel event: (NOTE: hUserEvent freed in user
+ * context.). */
+ if (pChnl->hSyncEvent) {
+ SYNC_ResetEvent(pChnl->hSyncEvent);
+ SYNC_CloseEvent(pChnl->hSyncEvent);
+ pChnl->hSyncEvent = NULL;
+ }
+ /* Free I/O request and I/O completion queues: */
+ if (pChnl->pIOCompletions) {
+ FreeChirpList(pChnl->pIOCompletions);
+ pChnl->pIOCompletions = NULL;
+ pChnl->cIOCs = 0;
+ }
+ if (pChnl->pIORequests) {
+ FreeChirpList(pChnl->pIORequests);
+ pChnl->pIORequests = NULL;
+ pChnl->cIOReqs = 0;
+ }
+ if (pChnl->pFreeList) {
+ FreeChirpList(pChnl->pFreeList);
+ pChnl->pFreeList = NULL;
+ }
+ /* Release channel object. */
+ MEM_FreeObject(pChnl);
+ pChnl = NULL;
+ }
+ DBC_Ensure(DSP_FAILED(status) ||
+ !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_Create ========
+ * Create a channel manager object, responsible for opening new channels
+ * and closing old ones for a given board.
+ */
+DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_MGR *pChnlMgr = NULL;
+ s32 cChannels;
+#ifdef DEBUG
+ struct CHNL_MGR *hChnlMgr;
+#endif
+ /* Check DBC requirements: */
+ DBC_Require(phChnlMgr != NULL);
+ DBC_Require(pMgrAttrs != NULL);
+ DBC_Require(pMgrAttrs->cChannels > 0);
+ DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
+ DBC_Require(pMgrAttrs->uWordSize != 0);
+#ifdef DEBUG
+ /* This for the purposes of DBC_Require: */
+ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
+ DBC_Require(status != DSP_EHANDLE);
+ DBC_Require(hChnlMgr == NULL);
+#endif
+ if (DSP_SUCCEEDED(status)) {
+ /* Allocate channel manager object: */
+ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
+ if (pChnlMgr) {
+ /* The cChannels attr must equal the # of supported
+ * chnls for each transport(# chnls for PCPY = DDMA =
+ * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
+ * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */
+ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
+ cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
+ CHNL_PCPY));
+ /* Create array of channels: */
+ pChnlMgr->apChannel = MEM_Calloc(
+ sizeof(struct CHNL_OBJECT *) *
+ cChannels, MEM_NONPAGED);
+ if (pChnlMgr->apChannel) {
+ /* Initialize CHNL_MGR object: */
+ /* Shared memory driver. */
+ pChnlMgr->dwType = CHNL_TYPESM;
+ pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
+ /* total # chnls supported */
+ pChnlMgr->cChannels = cChannels;
+ pChnlMgr->cOpenChannels = 0;
+ pChnlMgr->dwOutputMask = 0;
+ pChnlMgr->dwLastOutput = 0;
+ pChnlMgr->hDevObject = hDevObject;
+ if (DSP_SUCCEEDED(status)) {
+ status = SYNC_InitializeDPCCS
+ (&pChnlMgr->hCSObj);
+ }
+ } else {
+ status = DSP_EMEMORY;
+ }
+ } else {
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_FAILED(status)) {
+ WMD_CHNL_Destroy(pChnlMgr);
+ *phChnlMgr = NULL;
+ } else {
+ /* Return channel manager object to caller... */
+ *phChnlMgr = pChnlMgr;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_Destroy ========
+ * Purpose:
+ * Close all open channels, and destroy the channel manager.
+ */
+DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_MGR *pChnlMgr = hChnlMgr;
+ u32 iChnl;
+
+ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+ /* Close all open channels: */
+ for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
+ if (DSP_SUCCEEDED
+ (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
+ DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
+ }
+ }
+ /* release critical section */
+ if (pChnlMgr->hCSObj)
+ SYNC_DeleteCS(pChnlMgr->hCSObj);
+
+ /* Free channel manager object: */
+ if (pChnlMgr->apChannel)
+ MEM_Free(pChnlMgr->apChannel);
+
+ /* Set hChnlMgr to NULL in device object. */
+ DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
+ /* Free this Chnl Mgr object: */
+ MEM_FreeObject(hChnlMgr);
+ } else {
+ status = DSP_EHANDLE;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_FlushIO ========
+ * purpose:
+ * Flushes all the outstanding data requests on a channel.
+ */
+DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+ CHNL_MODE uMode = -1;
+ struct CHNL_MGR *pChnlMgr;
+ struct CHNL_IOC chnlIOC;
+ /* Check args: */
+ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ if ((dwTimeOut == CHNL_IOCNOWAIT)
+ && CHNL_IsOutput(pChnl->uMode)) {
+ status = DSP_EINVALIDARG;
+ } else {
+ uMode = pChnl->uMode;
+ pChnlMgr = pChnl->pChnlMgr;
+ }
+ } else {
+ status = DSP_EHANDLE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Note: Currently, if another thread continues to add IO
+ * requests to this channel, this function will continue to
+ * flush all such queued IO requests. */
+ if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
+ /* Wait for IO completions, up to the specified
+ * timeout: */
+ while (!LST_IsEmpty(pChnl->pIORequests) &&
+ DSP_SUCCEEDED(status)) {
+ status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
+ &chnlIOC);
+ if (DSP_FAILED(status))
+ continue;
+
+ if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
+ status = CHNL_E_WAITTIMEOUT;
+
+ }
+ } else {
+ status = WMD_CHNL_CancelIO(hChnl);
+ /* Now, leave the channel in the ready state: */
+ pChnl->dwState &= ~CHNL_STATECANCEL;
+ }
+ }
+ DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_GetInfo ========
+ * Purpose:
+ * Retrieve information related to a channel.
+ */
+DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
+ OUT struct CHNL_INFO *pInfo)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+ if (pInfo != NULL) {
+ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ /* Return the requested information: */
+ pInfo->hChnlMgr = pChnl->pChnlMgr;
+ pInfo->hEvent = pChnl->hUserEvent;
+ pInfo->dwID = pChnl->uId;
+ pInfo->dwMode = pChnl->uMode;
+ pInfo->cPosition = pChnl->cBytesMoved;
+ pInfo->hProcess = pChnl->hProcess;
+ pInfo->hSyncEvent = pChnl->hSyncEvent;
+ pInfo->cIOCs = pChnl->cIOCs;
+ pInfo->cIOReqs = pChnl->cIOReqs;
+ pInfo->dwState = pChnl->dwState;
+ } else {
+ status = DSP_EHANDLE;
+ }
+ } else {
+ status = DSP_EPOINTER;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_GetIOC ========
+ * Optionally wait for I/O completion on a channel. Dequeue an I/O
+ * completion record, which contains information about the completed
+ * I/O request.
+ * Note: Ensures Channel Invariant (see notes above).
+ */
+DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
+ OUT struct CHNL_IOC *pIOC)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+ struct CHNL_IRP *pChirp;
+ DSP_STATUS statSync;
+ bool fDequeueIOC = true;
+ struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
+ u8 *pHostSysBuf = NULL;
+
+ DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
+ "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
+ pChnl->uChnlType);
+ /* Check args: */
+ if (pIOC == NULL) {
+ status = DSP_EPOINTER;
+ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else if (dwTimeOut == CHNL_IOCNOWAIT) {
+ if (LST_IsEmpty(pChnl->pIOCompletions))
+ status = CHNL_E_NOIOC;
+
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ ioc.status = CHNL_IOCSTATCOMPLETE;
+ if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
+ if (dwTimeOut == CHNL_IOCINFINITE)
+ dwTimeOut = SYNC_INFINITE;
+
+ statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
+ if (statSync == DSP_ETIMEOUT) {
+ /* No response from DSP */
+ ioc.status |= CHNL_IOCSTATTIMEOUT;
+ fDequeueIOC = false;
+ } else if (statSync == DSP_EFAIL) {
+ /* This can occur when the user mode thread is
+ * aborted (^C), or when _VWIN32_WaitSingleObject()
+ * fails due to unkown causes. */
+ /* Even though Wait failed, there may be something in
+ * the Q: */
+ if (LST_IsEmpty(pChnl->pIOCompletions)) {
+ ioc.status |= CHNL_IOCSTATCANCEL;
+ fDequeueIOC = false;
+ }
+ }
+ }
+ /* See comment in AddIOReq */
+ SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
+ disable_irq(MAILBOX_IRQ);
+ if (fDequeueIOC) {
+ /* Dequeue IOC and set pIOC; */
+ DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
+ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
+ /* Update pIOC from channel state and chirp: */
+ if (pChirp) {
+ pChnl->cIOCs--;
+ /* If this is a zero-copy channel, then set IOC's pBuf
+ * to the DSP's address. This DSP address will get
+ * translated to user's virtual addr later. */
+ {
+ pHostSysBuf = pChirp->pHostSysBuf;
+ ioc.pBuf = pChirp->pHostUserBuf;
+ }
+ ioc.cBytes = pChirp->cBytes;
+ ioc.cBufSize = pChirp->cBufSize;
+ ioc.dwArg = pChirp->dwArg;
+ ioc.status |= pChirp->status;
+ /* Place the used chirp on the free list: */
+ LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
+ pChirp);
+ } else {
+ ioc.pBuf = NULL;
+ ioc.cBytes = 0;
+ }
+ } else {
+ ioc.pBuf = NULL;
+ ioc.cBytes = 0;
+ ioc.dwArg = 0;
+ ioc.cBufSize = 0;
+ }
+ /* Ensure invariant: If any IOC's are queued for this channel... */
+ if (!LST_IsEmpty(pChnl->pIOCompletions)) {
+ /* Since DSPStream_Reclaim() does not take a timeout
+ * parameter, we pass the stream's timeout value to
+ * WMD_CHNL_GetIOC. We cannot determine whether or not
+ * we have waited in User mode. Since the stream's timeout
+ * value may be non-zero, we still have to set the event.
+ * Therefore, this optimization is taken out.
+ *
+ * if (dwTimeOut == CHNL_IOCNOWAIT) {
+ * ... ensure event is set..
+ * SYNC_SetEvent(pChnl->hSyncEvent);
+ * } */
+ SYNC_SetEvent(pChnl->hSyncEvent);
+ } else {
+ /* else, if list is empty, ensure event is reset. */
+ SYNC_ResetEvent(pChnl->hSyncEvent);
+ }
+ enable_irq(MAILBOX_IRQ);
+ SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
+ if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
+ if (!(ioc.pBuf < (void *) USERMODE_ADDR))
+ goto func_cont;
+
+ /* If the addr is in user mode, then copy it */
+ if (!pHostSysBuf || !ioc.pBuf) {
+ status = DSP_EPOINTER;
+ DBG_Trace(DBG_LEVEL7,
+ "System buffer NULL in IO completion.\n");
+ goto func_cont;
+ }
+ if (!CHNL_IsInput(pChnl->uMode))
+ goto func_cont1;
+
+ /*pHostUserBuf */
+ status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
+#ifndef RES_CLEANUP_DISABLE
+ if (status) {
+ if (current->flags & PF_EXITING) {
+ DBG_Trace(DBG_LEVEL7,
+ "\n2current->flags == PF_EXITING, "
+ " current->flags;0x%x\n",
+ current->flags);
+ status = 0;
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "\n2current->flags != PF_EXITING, "
+ " current->flags;0x%x\n",
+ current->flags);
+ }
+ }
+#endif
+ if (status) {
+ DBG_Trace(DBG_LEVEL7,
+ "Error copying kernel buffer to user, %d"
+ " bytes remaining. in_interupt %d\n",
+ status, in_interrupt());
+ status = DSP_EPOINTER;
+ }
+func_cont1:
+ MEM_Free(pHostSysBuf);
+ }
+func_cont:
+ /* Update User's IOC block: */
+ *pIOC = ioc;
+func_end:
+ DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_GetMgrInfo ========
+ * Retrieve information related to the channel manager.
+ */
+DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
+ OUT struct CHNL_MGRINFO *pMgrInfo)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
+
+ if (pMgrInfo != NULL) {
+ if (uChnlID <= CHNL_MAXCHANNELS) {
+ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+ /* Return the requested information: */
+ pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
+ pMgrInfo->cOpenChannels = pChnlMgr->
+ cOpenChannels;
+ pMgrInfo->dwType = pChnlMgr->dwType;
+ /* total # of chnls */
+ pMgrInfo->cChannels = pChnlMgr->cChannels;
+ } else {
+ status = DSP_EHANDLE;
+ }
+ } else {
+ status = CHNL_E_BADCHANID;
+ }
+ } else {
+ status = DSP_EPOINTER;
+ }
+
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_Idle ========
+ * Idles a particular channel.
+ */
+DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
+ bool fFlush)
+{
+ CHNL_MODE uMode;
+ struct CHNL_MGR *pChnlMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
+
+ uMode = hChnl->uMode;
+ pChnlMgr = hChnl->pChnlMgr;
+
+ if (CHNL_IsOutput(uMode) && !fFlush) {
+ /* Wait for IO completions, up to the specified timeout: */
+ status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
+ } else {
+ status = WMD_CHNL_CancelIO(hChnl);
+
+ /* Reset the byte count and put channel back in ready state. */
+ hChnl->cBytesMoved = 0;
+ hChnl->dwState &= ~CHNL_STATECANCEL;
+ }
+
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_Open ========
+ * Open a new half-duplex channel to the DSP board.
+ */
+DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
+ struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
+ u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct CHNL_MGR *pChnlMgr = hChnlMgr;
+ struct CHNL_OBJECT *pChnl = NULL;
+ struct SYNC_ATTRS *pSyncAttrs = NULL;
+ struct SYNC_OBJECT *hSyncEvent = NULL;
+ /* Ensure DBC requirements: */
+ DBC_Require(phChnl != NULL);
+ DBC_Require(pAttrs != NULL);
+ *phChnl = NULL;
+ /* Validate Args: */
+ if (pAttrs->uIOReqs == 0) {
+ status = DSP_EINVALIDARG;
+ } else {
+ if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+ status = DSP_EHANDLE;
+ } else {
+ if (uChnlId != CHNL_PICKFREE) {
+ if (uChnlId >= pChnlMgr->cChannels) {
+ status = CHNL_E_BADCHANID;
+ } else if (pChnlMgr->apChannel[uChnlId] !=
+ NULL) {
+ status = CHNL_E_CHANBUSY;
+ }
+ } else {
+ /* Check for free channel */
+ status = SearchFreeChannel(pChnlMgr, &uChnlId);
+ }
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_end;
+
+ DBC_Assert(uChnlId < pChnlMgr->cChannels);
+ /* Create channel object: */
+ MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
+ if (!pChnl) {
+ status = DSP_EMEMORY;
+ goto func_cont;
+ }
+ /* Protect queues from IO_DPC: */
+ pChnl->dwState = CHNL_STATECANCEL;
+ /* Allocate initial IOR and IOC queues: */
+ pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
+ pChnl->pIORequests = CreateChirpList(0);
+ pChnl->pIOCompletions = CreateChirpList(0);
+ pChnl->cChirps = pAttrs->uIOReqs;
+ pChnl->cIOCs = 0;
+ pChnl->cIOReqs = 0;
+ status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
+ if (DSP_SUCCEEDED(status)) {
+ status = NTFY_Create(&pChnl->hNtfy);
+ if (DSP_FAILED(status)) {
+ /* The only failure that could have occurred */
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ if (pChnl->pIOCompletions && pChnl->pIORequests &&
+ pChnl->pFreeList) {
+ /* Initialize CHNL object fields: */
+ pChnl->pChnlMgr = pChnlMgr;
+ pChnl->uId = uChnlId;
+ pChnl->uMode = uMode;
+ pChnl->hUserEvent = hSyncEvent; /* for Linux */
+ pChnl->hSyncEvent = hSyncEvent;
+ /* get the process handle */
+ pChnl->hProcess = current->pid;
+ pChnl->pCBArg = 0;
+ pChnl->cBytesMoved = 0;
+ /* Default to proc-copy */
+ pChnl->uChnlType = CHNL_PCPY;
+ } else {
+ status = DSP_EMEMORY;
+ }
+ } else {
+ status = DSP_EINVALIDARG;
+ }
+ if (DSP_FAILED(status)) {
+ /* Free memory */
+ if (pChnl->pIOCompletions) {
+ FreeChirpList(pChnl->pIOCompletions);
+ pChnl->pIOCompletions = NULL;
+ pChnl->cIOCs = 0;
+ }
+ if (pChnl->pIORequests) {
+ FreeChirpList(pChnl->pIORequests);
+ pChnl->pIORequests = NULL;
+ }
+ if (pChnl->pFreeList) {
+ FreeChirpList(pChnl->pFreeList);
+ pChnl->pFreeList = NULL;
+ }
+ if (hSyncEvent) {
+ SYNC_CloseEvent(hSyncEvent);
+ hSyncEvent = NULL;
+ }
+ if (pChnl->hNtfy) {
+ NTFY_Delete(pChnl->hNtfy);
+ pChnl->hNtfy = NULL;
+ }
+ MEM_FreeObject(pChnl);
+ }
+func_cont:
+ if (DSP_SUCCEEDED(status)) {
+ /* Insert channel object in channel manager: */
+ pChnlMgr->apChannel[pChnl->uId] = pChnl;
+ SYNC_EnterCS(pChnlMgr->hCSObj);
+ pChnlMgr->cOpenChannels++;
+ SYNC_LeaveCS(pChnlMgr->hCSObj);
+ /* Return result... */
+ pChnl->dwSignature = CHNL_SIGNATURE;
+ pChnl->dwState = CHNL_STATEREADY;
+ *phChnl = pChnl;
+ }
+func_end:
+ DBC_Ensure((DSP_SUCCEEDED(status) &&
+ MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
+ (*phChnl == NULL));
+ return status;
+}
+
+/*
+ * ======== WMD_CHNL_RegisterNotify ========
+ * Registers for events on a particular channel.
+ */
+DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
+
+ status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
+ uNotifyType);
+
+ return status;
+}
+
+/*
+ * ======== CreateChirpList ========
+ * Purpose:
+ * Initialize a queue of channel I/O Request/Completion packets.
+ * Parameters:
+ * uChirps: Number of Chirps to allocate.
+ * Returns:
+ * Pointer to queue of IRPs, or NULL.
+ * Requires:
+ * Ensures:
+ */
+static struct LST_LIST *CreateChirpList(u32 uChirps)
+{
+ struct LST_LIST *pChirpList;
+ struct CHNL_IRP *pChirp;
+ u32 i;
+
+ pChirpList = LST_Create();
+
+ if (pChirpList) {
+ /* Make N chirps and place on queue. */
+ for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
+ NULL); i++) {
+ LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
+ }
+
+ /* If we couldn't allocate all chirps, free those allocated: */
+ if (i != uChirps) {
+ FreeChirpList(pChirpList);
+ pChirpList = NULL;
+ }
+ }
+
+ return pChirpList;
+}
+
+/*
+ * ======== FreeChirpList ========
+ * Purpose:
+ * Free the queue of Chirps.
+ */
+static void FreeChirpList(struct LST_LIST *pChirpList)
+{
+ DBC_Require(pChirpList != NULL);
+
+ while (!LST_IsEmpty(pChirpList))
+ MEM_Free(LST_GetHead(pChirpList));
+
+ LST_Delete(pChirpList);
+}
+
+/*
+ * ======== MakeNewChirp ========
+ * Allocate the memory for a new channel IRP.
+ */
+static struct CHNL_IRP *MakeNewChirp(void)
+{
+ struct CHNL_IRP *pChirp;
+
+ pChirp = (struct CHNL_IRP *)MEM_Calloc(
+ sizeof(struct CHNL_IRP), MEM_NONPAGED);
+ if (pChirp != NULL) {
+ /* LST_InitElem only resets the list's member values. */
+ LST_InitElem(&pChirp->link);
+ }
+
+ return pChirp;
+}
+
+/*
+ * ======== SearchFreeChannel ========
+ * Search for a free channel slot in the array of channel pointers.
+ */
+static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
+ OUT u32 *pdwChnl)
+{
+ DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
+ u32 i;
+
+ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
+
+ for (i = 0; i < pChnlMgr->cChannels; i++) {
+ if (pChnlMgr->apChannel[i] == NULL) {
+ status = DSP_SOK;
+ *pdwChnl = i;
+ break;
+ }
+ }
+
+ return status;
+}
diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
new file mode 100755
index 000000000000..fd033aaf49fa
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/io_sm.c
@@ -0,0 +1,2136 @@
+/*
+ * io_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== io_sm.c ========
+ * Description:
+ * IO dispatcher for a shared memory channel driver.
+ *
+ * Public Functions:
+ * WMD_IO_Create
+ * WMD_IO_Destroy
+ * WMD_IO_OnLoaded
+ * IO_AndSetValue
+ * IO_BufSize
+ * IO_CancelChnl
+ * IO_DPC
+ * IO_ISR
+ * IO_IVAISR
+ * IO_OrSetValue
+ * IO_ReadValue
+ * IO_ReadValueLong
+ * IO_RequestChnl
+ * IO_Schedule
+ * IO_WriteValue
+ * IO_WriteValueLong
+ *
+ * Channel Invariant:
+ * There is an important invariant condition which must be maintained per
+ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
+ * which may cause timeouts and/or failure of the WIN32_WaitSingleObject
+ * function (SYNC_WaitOnEvent).
+ *
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+#include <linux/workqueue.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/cfg.h>
+#include <dspbridge/dpc.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/reg.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/* ----------------------------------- Mini Driver */
+#include <dspbridge/wmddeh.h>
+#include <dspbridge/wmdio.h>
+#include <dspbridge/wmdioctl.h>
+#include <_tiomap.h>
+#include <tiomap_io.h>
+#include <_tiomap_pwr.h>
+#include <tiomap_io.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/cod.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/chnl_sm.h>
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/rms_sh.h>
+#include <dspbridge/mgr.h>
+#include <dspbridge/drv.h>
+#include "_cmm.h"
+
+/* ----------------------------------- This */
+#include <dspbridge/io_sm.h>
+#include "_msg_sm.h"
+#include <dspbridge/gt.h>
+
+/*------------------------------------Notify */
+#include <syslink/notify.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/notify_tesladriver.h>
+#include <syslink/notify_shmdriver.h>
+#include <syslink/notify_driver.h>
+
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define OUTPUTNOTREADY 0xffff
+#define NOTENABLED 0xffff /* channel(s) not enabled */
+
+#define EXTEND "_EXT_END"
+
+#define SwapWord(x) (x)
+#define ulPageAlignSize 0x10000 /* Page Align Size */
+
+#define MAX_PM_REQS 32
+
+struct notify_driver_handle *handlePtr;
+struct notify_driver_object *handle;
+u32 eventNo;
+struct IO_MGR *ext_pIOMgr;
+extern irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+void * external_piomgr;
+
+
+/* IO Manager: only one created per board: */
+struct IO_MGR {
+ /* These four fields must be the first fields in a IO_MGR_ struct: */
+ u32 dwSignature; /* Used for object validation */
+ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context */
+ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
+ struct DEV_OBJECT *hDevObject; /* Device this board represents */
+
+ /* These fields initialized in WMD_IO_Create(): */
+ struct CHNL_MGR *hChnlMgr;
+ struct SHM *pSharedMem; /* Shared Memory control */
+ u8 *pInput; /* Address of input channel */
+ u8 *pOutput; /* Address of output channel */
+ struct MSG_MGR *hMsgMgr; /* Message manager */
+ struct MSG *pMsgInputCtrl; /* Msg control for from DSP messages */
+ struct MSG *pMsgOutputCtrl; /* Msg control for to DSP messages */
+ u8 *pMsgInput; /* Address of input messages */
+ u8 *pMsgOutput; /* Address of output messages */
+ u32 uSMBufSize; /* Size of a shared memory I/O channel */
+ bool fSharedIRQ; /* Is this IRQ shared? */
+ struct DPC_OBJECT *hDPC; /* DPC object handle */
+ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
+ u32 uWordSize; /* Size in bytes of DSP word */
+ u16 wIntrVal; /* interrupt value */
+ /* private extnd proc info; mmu setup */
+ struct MGR_PROCESSOREXTINFO extProcInfo;
+ struct CMM_OBJECT *hCmmMgr; /* Shared Mem Mngr */
+ struct work_struct io_workq; /*workqueue */
+ u32 dQuePowerMbxVal[MAX_PM_REQS];
+ u32 iQuePowerHead;
+ u32 iQuePowerTail;
+#ifndef DSP_TRACEBUF_DISABLED
+ u32 ulTraceBufferBegin; /* Trace message start address */
+ u32 ulTraceBufferEnd; /* Trace message end address */
+ u32 ulTraceBufferCurrent; /* Trace message current address */
+ u32 ulGPPReadPointer; /* GPP Read pointer to Trace buffer */
+ u8 *pMsg;
+ u32 ulGppVa;
+ u32 ulDspVa;
+#endif
+} ;
+
+/* ----------------------------------- Function Prototypes */
+static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
+ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
+static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static void IO_DispatchPM(struct work_struct *work);
+static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
+ struct CHNL_IRP *pChirp);
+static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+ u32 iMode);
+static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+ u32 iMode);
+static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
+ struct CHNL_OBJECT *pChnl, u32 dwMask);
+static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+ void *pSrc, u32 uSize);
+static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+ void *pSrc, u32 uSize);
+static struct workqueue_struct *bridge_workqueue;
+#ifndef DSP_TRACEBUF_DISABLED
+void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
+#endif
+
+/* Bus Addr (cached kernel)*/
+static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
+ struct COD_MANAGER *hCodMan,
+ u32 dwGPPBasePA);
+
+#ifdef CONFIG_BRIDGE_DVFS
+/* The maximum number of OPPs that are supported */
+extern s32 dsp_max_opps;
+/* The Vdd1 opp table information */
+extern u32 vdd1_dsp_freq[6][4] ;
+#endif
+
+#if GT_TRACE
+static struct GT_Mask dsp_trace_mask = { NULL, NULL }; /* GT trace variable */
+#endif
+
+/*
+ * ======== WMD_IO_Create ========
+ * Create an IO manager object.
+ */
+DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct IO_ATTRS *pMgrAttrs)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct IO_MGR *pIOMgr = NULL;
+ struct SHM *pSharedMem = NULL;
+ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
+ struct CFG_HOSTRES hostRes;
+ struct CFG_DEVNODE *hDevNode;
+ struct CHNL_MGR *hChnlMgr;
+ static int ref_count;
+ u32 devType;
+
+ struct notify_config ntfy_config;
+ struct notify_tesladrv_config tesla_cfg;
+ struct notify_tesladrv_params params;
+ dma_addr_t mem_pa;
+ void *mem_va = NULL;
+ char driverName[32] = "NOTIFYMBXDRV";
+ int ntfystatus;
+ irq_handler = (void *) IO_ISR;
+
+
+ /* Check DBC requirements: */
+ DBC_Require(phIOMgr != NULL);
+ DBC_Require(pMgrAttrs != NULL);
+ DBC_Require(pMgrAttrs->uWordSize != 0);
+ /* This for the purposes of DBC_Require: */
+ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
+ DBC_Require(status != DSP_EHANDLE);
+ DBC_Require(hChnlMgr != NULL);
+ DBC_Require(hChnlMgr->hIOMgr == NULL);
+ /* Message manager will be created when a file is loaded, since
+ * size of message buffer in shared memory is configurable in
+ * the base image. */
+ DEV_GetWMDContext(hDevObject, &hWmdContext);
+ DBC_Assert(hWmdContext);
+ DEV_GetDevType(hDevObject, &devType);
+ /* DSP shared memory area will get set properly when
+ * a program is loaded. They are unknown until a COFF file is
+ * loaded. I chose the value -1 because it was less likely to be
+ * a valid address than 0. */
+ pSharedMem = (struct SHM *) -1;
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+/*
+ * Create a Single Threaded Work Queue
+ */
+
+ if (ref_count == 0)
+ bridge_workqueue = create_workqueue("bridge_work-queue");
+
+ if (bridge_workqueue <= 0)
+ DBG_Trace(DBG_LEVEL1, "Workque Create"
+ " failed 0x%d \n", bridge_workqueue);
+
+
+ /* Allocate IO manager object: */
+ MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
+ if (pIOMgr == NULL) {
+ status = DSP_EMEMORY;
+ goto func_cont;
+ }
+ /*Intializing Work Element*/
+ if (ref_count == 0) {
+ INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
+ ref_count = 1;
+ } else
+ PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
+
+ /* Initialize CHNL_MGR object:*/
+#ifndef DSP_TRACEBUF_DISABLED
+ pIOMgr->pMsg = NULL;
+#endif
+ pIOMgr->hChnlMgr = hChnlMgr;
+ pIOMgr->uWordSize = pMgrAttrs->uWordSize;
+ pIOMgr->pSharedMem = pSharedMem;
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_InitializeCS(&pIOMgr->hCSObj);
+
+ if (devType == DSP_UNIT) {
+ /* Create a DPC object: */
+ status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
+ if (DSP_SUCCEEDED(status))
+ status = DEV_GetDevNode(hDevObject, &hDevNode);
+
+ pIOMgr->iQuePowerHead = 0;
+ pIOMgr->iQuePowerTail = 0;
+ }
+
+ notify_get_config(&ntfy_config);
+ ntfystatus = notify_setup(&ntfy_config);
+
+ if (ntfystatus != NOTIFY_SUCCESS) {
+ pr_err("Failed notify_setup ntfystatus\n");
+ goto func_cont;
+ }
+
+ notify_tesladrv_getconfig(&tesla_cfg);
+
+ ntfystatus = notify_tesladrv_setup(&tesla_cfg);
+
+ if (ntfystatus != 0) {
+ pr_err("Failed notify_tesladrv_setup\n");
+ goto func_cont;
+ }
+
+ notify_tesladrv_params_init(NULL, &params);
+
+ mem_va = dma_alloc_coherent(NULL, 0x4000, &mem_pa, GFP_ATOMIC);
+
+ if (mem_va == NULL)
+ pr_err("Memory allocation for communication failed\n");
+
+ params.num_events = 32;
+ params.num_reserved_events = 0;
+ params.send_event_poll_count = (int) -1;
+ params.recv_int_id = 26;
+ params.send_int_id = 55;
+ params.shared_addr_size = 0x4000;
+ params.shared_addr = (int)mem_va;
+ params.remote_proc_id = 0;
+
+ handle = notify_tesladrv_create(driverName, &params);
+ if (handle == NULL) {
+ pr_err("Failed notify_tesladrv_create\n");
+ goto func_cont;
+ }
+
+ eventNo = ((NOTIFY_SYSTEM_KEY<<16)|NOTIFY_TESLA_EVENTNUMBER);
+
+ ntfystatus = notify_register_event(handle, /*PROC_TESLA*/0,
+ eventNo, (void *)IO_ISR, NULL);
+
+ if (ntfystatus != NOTIFY_SUCCESS) {
+ pr_err("Failed notify_register_event\n");
+ goto func_cont;
+ }
+ notify_disable_event(handle, 0, eventNo);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = CFG_GetHostResources((struct CFG_DEVNODE *)
+ DRV_GetFirstDevExtension() , &hostRes);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pIOMgr->hWmdContext = hWmdContext;
+ pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
+#ifdef OMAP44XX
+ external_piomgr = pIOMgr;
+
+#else
+ IO_DisableInterrupt(hWmdContext);
+ if (devType == DSP_UNIT) {
+ /* Plug the channel ISR:. */
+ if ((request_irq(INT_MAIL_MPU_IRQ, IO_ISR, 0,
+ "DspBridge\tmailbox", (void *)pIOMgr)) == 0)
+ status = DSP_SOK;
+ else
+ status = DSP_EFAIL;
+ }
+#endif
+ if (DSP_SUCCEEDED(status))
+ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
+ pIOMgr);
+ else
+ status = CHNL_E_ISR;
+ } else
+ status = CHNL_E_ISR;
+func_cont:
+ if (DSP_FAILED(status)) {
+ /* Cleanup: */
+ WMD_IO_Destroy(pIOMgr);
+ *phIOMgr = NULL;
+ } else {
+ /* Return IO manager object to caller... */
+ hChnlMgr->hIOMgr = pIOMgr;
+ *phIOMgr = pIOMgr;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_IO_Destroy ========
+ * Purpose:
+ * Disable interrupts, destroy the IO manager.
+ */
+DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 notify_status;
+#ifdef OMAP44XX
+ notify_status = notify_tesladrv_delete(&handle);
+ notify_status = notify_tesladrv_destroy();
+ notify_status = notify_destroy();
+#else
+ struct WMD_DEV_CONTEXT *hWmdContext;
+ if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
+ /* Unplug IRQ: */
+ /* Disable interrupts from the board: */
+ if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject,
+ &hWmdContext)))
+ DBC_Assert(hWmdContext);
+ (void)CHNLSM_DisableInterrupt(hWmdContext);
+ destroy_workqueue(bridge_workqueue);
+ /* uninstall ISR */
+ free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr);
+ (void)DPC_Destroy(hIOMgr->hDPC);
+#ifndef DSP_TRACEBUF_DISABLED
+ if (hIOMgr->pMsg)
+ MEM_Free(hIOMgr->pMsg);
+#endif
+ SYNC_DeleteCS(hIOMgr->hCSObj); /* Leak Fix. */
+ /* Free this IO manager object: */
+ MEM_FreeObject(hIOMgr);
+ } else
+ status = DSP_EHANDLE;
+#endif
+ return status;
+}
+
+/*
+ * ======== WMD_IO_OnLoaded ========
+ * Purpose:
+ * Called when a new program is loaded to get shared memory buffer
+ * parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
+ * are in DSP address units.
+ */
+DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
+{
+ struct COD_MANAGER *hCodMan;
+ struct CHNL_MGR *hChnlMgr;
+ struct MSG_MGR *hMsgMgr;
+ u32 ulShmBase;
+ u32 ulShmBaseOffset;
+ u32 ulShmLimit;
+ u32 ulShmLength = -1;
+ u32 ulMemLength = -1;
+ u32 ulMsgBase;
+ u32 ulMsgLimit;
+ u32 ulMsgLength = -1;
+ u32 ulExtEnd;
+ u32 ulGppPa = 0;
+ u32 ulGppVa = 0;
+ u32 ulDspVa = 0;
+ u32 ulSegSize = 0;
+ u32 ulPadSize = 0;
+ u32 i;
+ DSP_STATUS status = DSP_SOK;
+ u32 uNumProcs = 0;
+ s32 ndx = 0;
+ /* DSP MMU setup table */
+ struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
+ struct CFG_HOSTRES hostRes;
+ u32 mapAttrs;
+ u32 ulShm0End;
+ u32 ulDynExtBase;
+ u32 ulSeg1Size = 0;
+ u32 paCurr = 0;
+ u32 vaCurr = 0;
+ u32 gppVaCurr = 0;
+ u32 numBytes = 0;
+ u32 allBits = 0;
+ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
+ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
+
+ status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ hChnlMgr = hIOMgr->hChnlMgr;
+ /* The message manager is destroyed when the board is stopped. */
+ DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
+ hMsgMgr = hIOMgr->hMsgMgr;
+ DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
+ DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+ if (hIOMgr->pSharedMem)
+ hIOMgr->pSharedMem = NULL;
+
+ /* Get start and length of channel part of shared memory */
+ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
+ &ulShmBase);
+ if (DSP_FAILED(status)) {
+ status = CHNL_E_NOMEMMAP;
+ goto func_cont1;
+ }
+ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
+ &ulShmLimit);
+ if (DSP_FAILED(status)) {
+ status = CHNL_E_NOMEMMAP;
+ goto func_cont1;
+ }
+ if (ulShmLimit <= ulShmBase) {
+ status = CHNL_E_INVALIDMEMBASE;
+ } else {
+ /* get total length in bytes */
+ ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
+ /* Calculate size of a PROCCOPY shared memory region */
+ DBG_Trace(DBG_LEVEL7,
+ "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
+ (ulShmLength - sizeof(struct SHM)));
+ }
+func_cont1:
+ if (DSP_SUCCEEDED(status)) {
+ /* Get start and length of message part of shared memory */
+ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
+ &ulMsgBase);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
+ &ulMsgLimit);
+ if (DSP_SUCCEEDED(status)) {
+ if (ulMsgLimit <= ulMsgBase) {
+ status = CHNL_E_INVALIDMEMBASE;
+ } else {
+ /* Length (bytes) of messaging part of shared
+ * memory */
+ ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
+ hIOMgr->uWordSize;
+ /* Total length (bytes) of shared memory:
+ * chnl + msg */
+ ulMemLength = ulShmLength + ulMsgLength;
+ }
+ } else {
+ status = CHNL_E_NOMEMMAP;
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+#ifndef DSP_TRACEBUF_DISABLED
+ status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
+ DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
+ ulShm0End);
+#else
+ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
+ &ulShm0End);
+ DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
+#endif
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Get memory reserved in host resources */
+ (void)MGR_EnumProcessorInfo(0,
+ (struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
+ sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
+ CFG_GetHostResources((
+ struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &hostRes);
+ /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
+ ndx = 0;
+ ulGppPa = hostRes.dwMemPhys[1];
+ ulGppVa = hostRes.dwMemBase[1];
+ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
+ /* Why can't we directly take the DSPVA from the symbols? */
+ ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
+ ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
+ ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
+ ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
+ ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
+ ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
+ ulPageAlignSize);
+ if (ulPadSize == ulPageAlignSize)
+ ulPadSize = 0x0;
+
+ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
+ "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
+ "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
+ ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
+ ulSeg1Size);
+
+ if ((ulSegSize + ulSeg1Size + ulPadSize) >
+ hostRes.dwMemLength[1]) {
+ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
+ "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
+ "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
+ ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
+ ulExtEnd, ulSegSize, ulSeg1Size);
+ DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
+ "Required 0x%x\n", hostRes.dwMemLength[1],
+ ulSegSize + ulSeg1Size + ulPadSize);
+ status = DSP_EMEMORY;
+ }
+ }
+ if (DSP_FAILED(status))
+ goto func_cont;
+
+ paCurr = ulGppPa;
+ vaCurr = ulDynExtBase * hIOMgr->uWordSize;
+ gppVaCurr = ulGppVa;
+ numBytes = ulSeg1Size;
+
+ /*
+ * Try to fit into TLB entries. If not possible, push them to page
+ * tables. It is quite possible that if sections are not on
+ * bigger page boundary, we may end up making several small pages.
+ * So, push them onto page tables, if that is the case.
+ */
+ mapAttrs = 0x00000000;
+ mapAttrs = DSP_MAPLITTLEENDIAN;
+ mapAttrs |= DSP_MAPPHYSICALADDR;
+ mapAttrs |= DSP_MAPELEMSIZE32;
+ mapAttrs |= DSP_MAPDONOTLOCK;
+
+ while (numBytes && DSP_SUCCEEDED(status)) {
+ /* To find the max. page size with which both PA & VA are
+ * aligned */
+ allBits = paCurr | vaCurr;
+ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
+ "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
+ for (i = 0; i < 4; i++) {
+ if ((numBytes >= pgSize[i]) && ((allBits &
+ (pgSize[i] - 1)) == 0)) {
+ status = hIOMgr->pIntfFxns->pfnBrdMemMap
+ (hIOMgr->hWmdContext, paCurr, vaCurr,
+ pgSize[i], mapAttrs);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ paCurr += pgSize[i];
+ vaCurr += pgSize[i];
+ gppVaCurr += pgSize[i];
+ numBytes -= pgSize[i];
+ /* Don't try smaller sizes. Hopefully we have
+ * reached an address aligned to a bigger page
+ * size*/
+ break;
+ }
+ }
+ }
+ paCurr += ulPadSize;
+ vaCurr += ulPadSize;
+ gppVaCurr += ulPadSize;
+
+ /* configure the TLB entries for the next cacheable segment */
+ numBytes = ulSegSize;
+ vaCurr = ulDspVa * hIOMgr->uWordSize;
+ allBits = 0x0;
+ while (numBytes && DSP_SUCCEEDED(status)) {
+ /* To find the max. page size with which both PA & VA are
+ * aligned*/
+ allBits = paCurr | vaCurr;
+ DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
+ "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
+ numBytes);
+ for (i = 0; i < 4; i++) {
+ if (!(numBytes >= pgSize[i]) ||
+ !((allBits & (pgSize[i]-1)) == 0))
+ continue;
+ if (ndx < MAX_LOCK_TLB_ENTRIES) {
+ /* This is the physical address written to
+ * DSP MMU */
+ aEProc[ndx].ulGppPa = paCurr;
+ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
+ * ADDRESS!!! */
+ aEProc[ndx].ulGppVa = gppVaCurr;
+ aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
+ uWordSize;
+ aEProc[ndx].ulSize = pgSize[i];
+ aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
+ aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
+ aEProc[ndx].mixedMode = HW_MMU_CPUES;
+ DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
+ " VA %lx DSP_VA %lx Size %lx\n",
+ aEProc[ndx].ulGppPa,
+ aEProc[ndx].ulGppVa,
+ aEProc[ndx].ulDspVa *
+ hIOMgr->uWordSize, pgSize[i]);
+ ndx++;
+ } else {
+ status = hIOMgr->pIntfFxns->pfnBrdMemMap(
+ hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
+ mapAttrs);
+ DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
+ " VA %lx DSP_VA %lx Size %lx\n",
+ aEProc[ndx].ulGppPa,
+ aEProc[ndx].ulGppVa,
+ aEProc[ndx].ulDspVa *
+ hIOMgr->uWordSize, pgSize[i]);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ }
+ paCurr += pgSize[i];
+ vaCurr += pgSize[i];
+ gppVaCurr += pgSize[i];
+ numBytes -= pgSize[i];
+ /* Don't try smaller sizes. Hopefully we have reached
+ an address aligned to a bigger page size*/
+ break;
+ }
+ }
+
+ /* Copy remaining entries from CDB. All entries are 1 MB and should not
+ * conflict with SHM entries on MPU or DSP side */
+ for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
+ DSP_SUCCEEDED(status); i++) {
+ if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
+ continue;
+
+ if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
+ && hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
+ ulGppPa + ulSegSize)
+ || (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
+ 0x100000 / hIOMgr->uWordSize && hIOMgr->
+ extProcInfo.tyTlb[i].ulDspVirt
+ <= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
+ DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
+ "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
+ "GppPa %x, DspVa %x, Bytes %x.\n", i,
+ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
+ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
+ ulGppPa, ulDspVa, ulSegSize);
+ status = DSP_EFAIL;
+ } else {
+ if (ndx < MAX_LOCK_TLB_ENTRIES) {
+ aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
+ tyTlb[i].ulDspVirt;
+ aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
+ tyTlb[i].ulGppPhys;
+ aEProc[ndx].ulGppVa = 0;
+ /* Can't convert, so set to zero*/
+ aEProc[ndx].ulSize = 0x100000; /* 1 MB*/
+ DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
+ "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
+ aEProc[ndx].ulDspVa);
+ ndx++;
+ } else {
+ status = hIOMgr->pIntfFxns->pfnBrdMemMap
+ (hIOMgr->hWmdContext,
+ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
+ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
+ 0x100000, mapAttrs);
+ }
+ }
+ }
+ if (i < 7 && DSP_SUCCEEDED(status)) {
+ /* All CDB entries could not be made*/
+ status = DSP_EFAIL;
+ }
+func_cont:
+ mapAttrs = 0x00000000;
+ mapAttrs = DSP_MAPLITTLEENDIAN;
+ mapAttrs |= DSP_MAPPHYSICALADDR;
+ mapAttrs |= DSP_MAPELEMSIZE32;
+ mapAttrs |= DSP_MAPDONOTLOCK;
+
+ /* Map the L4 peripherals */
+ i = 0;
+#ifdef OMAP_3430
+ while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
+ status = hIOMgr->pIntfFxns->pfnBrdMemMap
+ (hIOMgr->hWmdContext,
+ L4PeripheralTable[i].physAddr,
+ L4PeripheralTable[i].dspVirtAddr,
+ HW_PAGE_SIZE_4KB,
+ mapAttrs);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ i++;
+ }
+#else
+ while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
+ status = hIOMgr->pIntfFxns->pfnBrdMemMap
+ (hIOMgr->hWmdContext,
+ L4PeripheralTable[i].physAddr,
+ L4PeripheralTable[i].dspVirtAddr,
+ L4PeripheralTable[i].ulSize,
+ mapAttrs);
+ DBC_Assert(DSP_SUCCEEDED(status));
+ i++;
+ }
+#endif
+
+ if (DSP_SUCCEEDED(status)) {
+ for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
+ aEProc[i].ulDspVa = 0;
+ aEProc[i].ulGppPa = 0;
+ aEProc[i].ulGppVa = 0;
+ aEProc[i].ulSize = 0;
+ }
+ /* Set the SHM physical address entry (grayed out in CDB file)
+ * to the virtual uncached ioremapped address of SHM reserved
+ * on MPU */
+ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
+ ulPadSize);
+ DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
+ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
+ /* Need SHM Phys addr. IO supports only one DSP for now:
+ * uNumProcs=1 */
+ if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
+ (uNumProcs != 1)) {
+ status = CHNL_E_NOMEMMAP;
+ DBC_Assert(false);
+ } else {
+ DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
+ /* ulShmBase may not be at ulDspVa address */
+ ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
+ hIOMgr->uWordSize;
+ /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
+ * _BRD_Start() the MMU will be re-programed with MMU
+ * DSPVa-GPPPa pair info while DSP is in a known
+ * (reset) state. */
+ DBC_Assert(hIOMgr->pIntfFxns != NULL);
+ DBC_Assert(hIOMgr->hWmdContext != NULL);
+ status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
+ hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
+ ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
+ DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
+ "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
+ ulGppPhys);
+ ulShmBase += ulShmBaseOffset;
+ ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
+ ulMemLength);
+ DBC_Assert(ulShmBase != 0);
+ if (DSP_SUCCEEDED(status)) {
+ status = registerSHMSegs(hIOMgr, hCodMan,
+ aEProc[0].ulGppPa);
+ /* Register SM */
+ }
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
+ hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
+ sizeof(struct SHM);
+ hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
+ sizeof(struct SHM))/2;
+ hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
+ DBG_Trace(DBG_LEVEL3,
+ "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
+ hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
+ DBG_Trace(DBG_LEVEL3,
+ "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
+ hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
+ sizeof(struct SHM));
+ /* Set up Shared memory addresses for messaging. */
+ hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
+ hIOMgr->pSharedMem +
+ ulShmLength);
+ hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
+ sizeof(struct MSG);
+ hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
+ pMsgInputCtrl + ulMsgLength / 2);
+ hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
+ sizeof(struct MSG);
+ hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
+ hIOMgr->pMsgInput) /
+ sizeof(struct MSG_DSPMSG);
+ DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
+ "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
+ "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
+ "0x%x \n", (u8 *)hIOMgr->pSharedMem,
+ (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
+ (u8 *)hIOMgr->pMsgInputCtrl,
+ (u8 *)hIOMgr->pMsgInput,
+ (u8 *)hIOMgr->pMsgOutputCtrl,
+ (u8 *)hIOMgr->pMsgOutput);
+ DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
+ "0x%x\n", hMsgMgr->uMaxMsgs);
+ memset((void *) hIOMgr->pSharedMem, 0, sizeof(struct SHM));
+ }
+#ifndef DSP_TRACEBUF_DISABLED
+ if (DSP_SUCCEEDED(status)) {
+ /* Get the start address of trace buffer */
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
+ &hIOMgr->ulTraceBufferBegin);
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
+ (ulGppVa + ulSeg1Size + ulPadSize) +
+ (hIOMgr->ulTraceBufferBegin - ulDspVa);
+ /* Get the end address of trace buffer */
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
+ &hIOMgr->ulTraceBufferEnd);
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
+ (hIOMgr->ulTraceBufferEnd - ulDspVa);
+ /* Get the current address of DSP write pointer */
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMan,
+ BRIDGE_SYS_PUTC_current,
+ &hIOMgr->ulTraceBufferCurrent);
+ if (DSP_FAILED(status))
+ status = CHNL_E_NOMEMMAP;
+
+ }
+ hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
+ ulPadSize) + (hIOMgr->
+ ulTraceBufferCurrent - ulDspVa);
+ /* Calculate the size of trace buffer */
+ if (hIOMgr->pMsg)
+ MEM_Free(hIOMgr->pMsg);
+ hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
+ hIOMgr->ulTraceBufferBegin) *
+ hIOMgr->uWordSize) + 2, MEM_NONPAGED);
+ if (!hIOMgr->pMsg)
+ status = DSP_EMEMORY;
+
+ DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
+ hIOMgr->ulDspVa = ulDspVa;
+ hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
+ }
+#endif
+ IO_EnableInterrupt(hIOMgr->hWmdContext);
+ return status;
+}
+
+/*
+ * ======== IO_BufSize ========
+ * Size of shared memory I/O channel.
+ */
+u32 IO_BufSize(struct IO_MGR *hIOMgr)
+{
+ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+
+ return hIOMgr->uSMBufSize;
+}
+
+/*
+ * ======== IO_CancelChnl ========
+ * Cancel IO on a given PCPY channel.
+ */
+void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
+{
+ struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
+ struct SHM *sm;
+
+ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+ sm = hIOMgr->pSharedMem;
+
+ /* Inform DSP that we have no more buffers on this channel: */
+ IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
+ (~(1 << ulChnl)));
+
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
+}
+
+/*
+ * ======== IO_DispatchChnl ========
+ * Proc-copy chanl dispatch.
+ */
+static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
+ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
+{
+ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
+
+ /* See if there is any data available for transfer: */
+ DBC_Assert(iMode == IO_SERVICE);
+
+ /* Any channel will do for this mode: */
+ InputChnl(pIOMgr, pChnl, iMode);
+ OutputChnl(pIOMgr, pChnl, iMode);
+}
+
+/*
+ * ======== IO_DispatchMsg ========
+ * Performs I/O dispatch on message queues.
+ */
+static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
+
+ /* We are performing both input and output processing. */
+ InputMsg(pIOMgr, hMsgMgr);
+ OutputMsg(pIOMgr, hMsgMgr);
+}
+
+/*
+ * ======== IO_DispatchPM ========
+ * Performs I/O dispatch on PM related messages from DSP
+ */
+static void IO_DispatchPM(struct work_struct *work)
+{
+ struct IO_MGR *pIOMgr =
+ container_of(work, struct IO_MGR, io_workq);
+ DSP_STATUS status;
+ u32 pArg[2];
+
+ /*DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));*/
+
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
+
+ /* Perform Power message processing here */
+ while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
+ pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
+ iQuePowerTail]);
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
+ pArg[0]);
+ /* Send the command to the WMD clk/pwr manager to handle */
+ if (pArg[0] == MBX_PM_HIBERNATE_EN) {
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
+ "command\n");
+ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+ hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
+ "Hibernation command failed\n");
+ }
+ } else if (pArg[0] == MBX_PM_OPP_REQ) {
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+ pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
+ "value =0x%x \n", pArg[1]);
+ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+ hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
+ pArg);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
+ "to set constraint = 0x%x \n",
+ pArg[1]);
+ }
+#endif
+#endif
+
+ } else {
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
+ "value of msg = 0x%x: \n", pArg[0]);
+ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+ hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
+ "to control the DSP clk = 0x%x \n",
+ *pArg);
+ }
+ }
+ /* increment the tail count here */
+ pIOMgr->iQuePowerTail++;
+ if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
+ pIOMgr->iQuePowerTail = 0;
+
+ }
+
+}
+
+/*
+ * ======== IO_DPC ========
+ * Deferred procedure call for shared memory channel driver ISR. Carries
+ * out the dispatch of I/O as a non-preemptible event.It can only be
+ * pre-empted by an ISR.
+ */
+void IO_DPC(IN OUT void *pRefData)
+{
+ struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
+ struct CHNL_MGR *pChnlMgr;
+ struct MSG_MGR *pMsgMgr;
+ struct DEH_MGR *hDehMgr;
+
+ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+ pChnlMgr = pIOMgr->hChnlMgr;
+ DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
+ DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
+ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
+ DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
+ /* Check value of interrupt register to ensure it is a valid error */
+ if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
+ /* notify DSP/BIOS exception */
+ if (hDehMgr)
+ WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
+
+ }
+ IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
+#ifdef CHNL_MESSAGES
+ if (pMsgMgr) {
+ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
+ IO_DispatchMsg(pIOMgr, pMsgMgr);
+ }
+#endif
+#ifndef DSP_TRACEBUF_DISABLED
+ if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
+ /* notify DSP Trace message */
+ if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
+ PrintDSPDebugTrace(pIOMgr);
+ }
+#endif
+
+#ifndef DSP_TRACEBUF_DISABLED
+ PrintDSPDebugTrace(pIOMgr);
+#endif
+}
+
+
+/*
+ * ======== IO_ISR ========
+ * Main interrupt handler for the shared memory IO manager.
+ * Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
+ * schedules a DPC to dispatch I/O.
+ */
+
+void IO_ISR(IN unsigned long int procId,
+ IN void * pRefData,
+ struct pt_regs *reg)
+{
+ struct IO_MGR *hIOMgr;
+ pRefData = external_piomgr;
+ hIOMgr = (struct IO_MGR *)pRefData;
+
+#ifdef OMAP_3430
+ bool fSchedDPC;
+ DBC_Require(irq == INT_MAIL_MPU_IRQ);
+#endif
+ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+ DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
+
+#ifdef OMAP_3430
+ /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
+ if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
+ DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
+#endif
+ if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
+ hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
+ hIOMgr->wIntrVal;
+ hIOMgr->iQuePowerHead++;
+ if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
+ hIOMgr->iQuePowerHead = 0;
+
+ queue_work(bridge_workqueue, &hIOMgr->io_workq);
+ }
+ if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
+ DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
+ hIOMgr->wIntrVal = 0;
+#ifdef OMAP44XX
+ } else {
+#else
+ } else if (fSchedDPC) {
+#endif
+ /* PROC-COPY defer i/o */
+ DPC_Schedule(hIOMgr->hDPC);
+ }
+#ifdef OMAP_3430
+ } else
+ /* Ensure that, if WMD didn't claim it, the IRQ is shared. */
+ DBC_Ensure(hIOMgr->fSharedIRQ);
+ return IRQ_HANDLED;
+#endif
+}
+EXPORT_SYMBOL(IO_ISR);
+/*
+ * ======== IO_RequestChnl ========
+ * Purpose:
+ * Request chanenel I/O from the DSP. Sets flags in shared memory, then
+ * interrupts the DSP.
+ */
+void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+ u32 iMode, OUT u16 *pwMbVal)
+{
+ struct CHNL_MGR *pChnlMgr;
+ struct SHM *sm;
+ DBC_Require(pChnl != NULL);
+ DBC_Require(pwMbVal != NULL);
+ pChnlMgr = pIOMgr->hChnlMgr;
+ sm = pIOMgr->pSharedMem;
+ if (iMode == IO_INPUT) {
+ /* Assertion fires if CHNL_AddIOReq() called on a stream
+ * which was cancelled, or attached to a dead board: */
+ DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
+ (pChnl->dwState == CHNL_STATEEOS));
+ /* Indicate to the DSP we have a buffer available for input: */
+ IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
+ (1 << pChnl->uId));
+ *pwMbVal = MBX_PCPY_CLASS;
+ } else if (iMode == IO_OUTPUT) {
+ /* This assertion fails if CHNL_AddIOReq() was called on a
+ * stream which was cancelled, or attached to a dead board: */
+ DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
+ CHNL_STATEREADY);
+ /* Record the fact that we have a buffer available for
+ * output: */
+ pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
+ } else {
+ DBC_Assert(iMode); /* Shouldn't get here. */
+ }
+}
+
+/*
+ * ======== IO_Schedule ========
+ * Schedule DPC for IO.
+ */
+void IO_Schedule(struct IO_MGR *pIOMgr)
+{
+ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+ DPC_Schedule(pIOMgr->hDPC);
+}
+
+/*
+ * ======== FindReadyOutput ========
+ * Search for a host output channel which is ready to send. If this is
+ * called as a result of servicing the DPC, then implement a round
+ * robin search; otherwise, this was called by a client thread (via
+ * IO_Dispatch()), so just start searching from the current channel id.
+ */
+static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
+ struct CHNL_OBJECT *pChnl, u32 dwMask)
+{
+ u32 uRetval = OUTPUTNOTREADY;
+ u32 id, startId;
+ u32 shift;
+
+ id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
+ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
+ DBC_Assert(id < CHNL_MAXCHANNELS);
+ if (dwMask) {
+ shift = (1 << id);
+ startId = id;
+ do {
+ if (dwMask & shift) {
+ uRetval = id;
+ if (pChnl == NULL)
+ pChnlMgr->dwLastOutput = id;
+
+ break;
+ }
+ id = id + 1;
+ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
+ shift = (1 << id);
+ } while (id != startId);
+ }
+ DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
+ return uRetval;
+}
+
+/*
+ * ======== InputChnl ========
+ * Dispatch a buffer on an input channel.
+ */
+static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+ u32 iMode)
+{
+ struct CHNL_MGR *pChnlMgr;
+ struct SHM *sm;
+ u32 chnlId;
+ u32 uBytes;
+ struct CHNL_IRP *pChirp = NULL;
+ u32 dwArg;
+ bool fClearChnl = false;
+ bool fNotifyClient = false;
+
+ sm = pIOMgr->pSharedMem;
+ pChnlMgr = pIOMgr->hChnlMgr;
+
+ DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
+
+ /* Attempt to perform input.... */
+ if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
+ goto func_end;
+
+ uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
+ pChnlMgr->uWordSize;
+ chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
+ dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
+ if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
+ /* Shouldn't be here: would indicate corrupted SHM. */
+ DBC_Assert(chnlId);
+ goto func_end;
+ }
+ pChnl = pChnlMgr->apChannel[chnlId];
+ if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
+ if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
+ if (!pChnl->pIORequests)
+ goto func_end;
+ /* Get the I/O request, and attempt a transfer: */
+ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
+ pIORequests);
+ if (pChirp) {
+ pChnl->cIOReqs--;
+ DBC_Assert(pChnl->cIOReqs >= 0);
+ /* Ensure we don't overflow the client's
+ * buffer: */
+ uBytes = min(uBytes, pChirp->cBytes);
+ /* Transfer buffer from DSP side: */
+ uBytes = ReadData(pIOMgr->hWmdContext,
+ pChirp->pHostSysBuf,
+ pIOMgr->pInput, uBytes);
+ pChnl->cBytesMoved += uBytes;
+ pChirp->cBytes = uBytes;
+ pChirp->dwArg = dwArg;
+ pChirp->status = CHNL_IOCSTATCOMPLETE;
+ DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
+ "\n", *((RMS_WORD *)(pChirp->
+ pHostSysBuf)));
+ if (uBytes == 0) {
+ /* This assertion fails if the DSP
+ * sends EOS more than once on this
+ * channel: */
+ DBC_Assert(!(pChnl->dwState &
+ CHNL_STATEEOS));
+ /* Zero bytes indicates EOS. Update
+ * IOC status for this chirp, and also
+ * the channel state: */
+ pChirp->status |= CHNL_IOCSTATEOS;
+ pChnl->dwState |= CHNL_STATEEOS;
+ /* Notify that end of stream has
+ * occurred */
+ NTFY_Notify(pChnl->hNtfy,
+ DSP_STREAMDONE);
+ DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
+ "chnl = 0x%x\n", pChnl);
+ }
+ /* Tell DSP if no more I/O buffers available: */
+ if (!pChnl->pIORequests)
+ goto func_end;
+ if (LST_IsEmpty(pChnl->pIORequests)) {
+ IO_AndValue(pIOMgr->hWmdContext,
+ struct SHM, sm, hostFreeMask,
+ ~(1 << pChnl->uId));
+ }
+ fClearChnl = true;
+ fNotifyClient = true;
+ } else {
+ /* Input full for this channel, but we have no
+ * buffers available. The channel must be
+ * "idling". Clear out the physical input
+ * channel. */
+ fClearChnl = true;
+ }
+ } else {
+ /* Input channel cancelled: clear input channel. */
+ fClearChnl = true;
+ }
+ } else {
+ /* DPC fired after host closed channel: clear input channel. */
+ fClearChnl = true;
+ }
+ if (fClearChnl) {
+ /* Indicate to the DSP we have read the input: */
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
+ }
+ if (fNotifyClient) {
+ /* Notify client with IO completion record: */
+ NotifyChnlComplete(pChnl, pChirp);
+ }
+func_end:
+ DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
+}
+
+/*
+ * ======== InputMsg ========
+ * Copies messages from shared memory to the message queues.
+ */
+static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+ u32 uMsgs;
+ u32 i;
+ u8 *pMsgInput;
+ struct MSG_QUEUE *hMsgQueue;
+ struct MSG_FRAME *pMsg;
+ struct MSG_DSPMSG msg;
+ struct MSG *pCtrl;
+ u32 fInputEmpty;
+ u32 addr;
+
+ pCtrl = pIOMgr->pMsgInputCtrl;
+ /* Get the number of input messages to be read. */
+ fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ bufEmpty);
+ uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
+ if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
+ return;
+
+ pMsgInput = pIOMgr->pMsgInput;
+ for (i = 0; i < uMsgs; i++) {
+ /* Read the next message */
+ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
+ msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
+ msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
+ msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
+ msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+ pMsgInput += sizeof(struct MSG_DSPMSG);
+ if (!hMsgMgr->queueList)
+ goto func_end;
+
+ /* Determine which queue to put the message in */
+ hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
+ DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
+ "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
+ msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
+ /* Interrupt may occur before shared memory and message
+ * input locations have been set up. If all nodes were
+ * cleaned up, hMsgMgr->uMaxMsgs should be 0. */
+ if (hMsgQueue && uMsgs > hMsgMgr->uMaxMsgs)
+ goto func_end;
+
+ while (hMsgQueue != NULL) {
+ if (msg.dwId == hMsgQueue->dwId) {
+ /* Found it */
+ if (msg.msg.dwCmd == RMS_EXITACK) {
+ /* The exit message does not get
+ * queued */
+ /* Call the node exit notification */
+ /* Node handle */ /* status */
+ (*hMsgMgr->onExit)((HANDLE)hMsgQueue->
+ hArg, msg.msg.dwArg1);
+ } else {
+ /* Not an exit acknowledgement, queue
+ * the message */
+ if (!hMsgQueue->msgFreeList)
+ goto func_end;
+ pMsg = (struct MSG_FRAME *)LST_GetHead
+ (hMsgQueue->msgFreeList);
+ if (hMsgQueue->msgUsedList && pMsg) {
+ pMsg->msgData = msg;
+ LST_PutTail(hMsgQueue->
+ msgUsedList,
+ (struct LST_ELEM *)pMsg);
+ NTFY_Notify(hMsgQueue->hNtfy,
+ DSP_NODEMESSAGEREADY);
+ SYNC_SetEvent(hMsgQueue->
+ hSyncEvent);
+ } else {
+ /* No free frame to copy the
+ * message into */
+ DBG_Trace(DBG_LEVEL7, "NO FREE "
+ "MSG FRAMES, DISCARDING"
+ " MESSAGE\n");
+ }
+ }
+ break;
+ }
+
+ if (!hMsgMgr->queueList || !hMsgQueue)
+ goto func_end;
+ hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
+ queueList, (struct LST_ELEM *)hMsgQueue);
+ }
+ }
+ /* Set the post SWI flag */
+ if (uMsgs > 0) {
+ /* Tell the DSP we've read the messages */
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
+ true);
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
+ true);
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
+ }
+func_end:
+ return;
+
+}
+
+/*
+ * ======== NotifyChnlComplete ========
+ * Purpose:
+ * Signal the channel event, notifying the client that I/O has completed.
+ */
+static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
+ struct CHNL_IRP *pChirp)
+{
+ bool fSignalEvent;
+
+ DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
+ DBC_Require(pChnl->hSyncEvent != NULL);
+ /* Note: we signal the channel event only if the queue of IO
+ * completions is empty. If it is not empty, the event is sure to be
+ * signalled by the only IO completion list consumer:
+ * WMD_CHNL_GetIOC(). */
+ fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
+ /* Enqueue the IO completion info for the client: */
+ LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
+ pChnl->cIOCs++;
+ DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
+ /* Signal the channel event (if not already set) that IO is complete: */
+ if (fSignalEvent)
+ SYNC_SetEvent(pChnl->hSyncEvent);
+
+ /* Notify that IO is complete */
+ NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
+}
+
+/*
+ * ======== OutputChnl ========
+ * Purpose:
+ * Dispatch a buffer on an output channel.
+ */
+static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+ u32 iMode)
+{
+ struct CHNL_MGR *pChnlMgr;
+ struct SHM *sm;
+ u32 chnlId;
+ struct CHNL_IRP *pChirp;
+ u32 dwDspFMask;
+
+ pChnlMgr = pIOMgr->hChnlMgr;
+ sm = pIOMgr->pSharedMem;
+ DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
+ /* Attempt to perform output: */
+ if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
+ goto func_end;
+
+ if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
+ goto func_end;
+
+ /* Look to see if both a PC and DSP output channel are ready: */
+ dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
+ dspFreeMask);
+ chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
+ dwDspFMask));
+ if (chnlId == OUTPUTNOTREADY)
+ goto func_end;
+
+ pChnl = pChnlMgr->apChannel[chnlId];
+ if (!pChnl || !pChnl->pIORequests) {
+ /* Shouldn't get here: */
+ goto func_end;
+ }
+ /* Get the I/O request, and attempt a transfer: */
+ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
+ if (!pChirp)
+ goto func_end;
+
+ pChnl->cIOReqs--;
+ if (pChnl->cIOReqs < 0 || !pChnl->pIORequests)
+ goto func_end;
+
+ /* Record fact that no more I/O buffers available: */
+ if (LST_IsEmpty(pChnl->pIORequests))
+ pChnlMgr->dwOutputMask &= ~(1 << chnlId);
+
+ /* Transfer buffer to DSP side: */
+ pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
+ pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
+ cBytes));
+ pChnl->cBytesMoved += pChirp->cBytes;
+ /* Write all 32 bits of arg */
+ IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
+#if _CHNL_WORDSIZE == 2
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
+ (u16)chnlId);
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
+ (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
+ (u16)pChnlMgr->uWordSize);
+#else
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
+ (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
+ uWordSize);
+#endif
+ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
+ /* Indicate to the DSP we have written the output: */
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
+ /* Notify client with IO completion record (keep EOS) */
+ pChirp->status &= CHNL_IOCSTATEOS;
+ NotifyChnlComplete(pChnl, pChirp);
+ /* Notify if stream is done. */
+ if (pChirp->status & CHNL_IOCSTATEOS)
+ NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
+
+func_end:
+ DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
+}
+/*
+ * ======== OutputMsg ========
+ * Copies messages from the message queues to the shared memory.
+ */
+static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+ u32 uMsgs = 0;
+ u32 i;
+ u8 *pMsgOutput;
+ struct MSG_FRAME *pMsg;
+ struct MSG *pCtrl;
+ u32 fOutputEmpty;
+ u32 val;
+ u32 addr;
+
+ pCtrl = pIOMgr->pMsgOutputCtrl;
+
+ /* Check if output has been cleared */
+ fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ bufEmpty);
+ if (fOutputEmpty) {
+ uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
+ hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
+ pMsgOutput = pIOMgr->pMsgOutput;
+ /* Copy uMsgs messages into shared memory */
+ for (i = 0; i < uMsgs; i++) {
+ if (!hMsgMgr->msgUsedList) {
+ DBG_Trace(DBG_LEVEL3, "msgUsedList is NULL\n");
+ pMsg = NULL;
+ goto func_end;
+ } else
+ pMsg = (struct MSG_FRAME *)LST_GetHead(
+ hMsgMgr->msgUsedList);
+ if (pMsg != NULL) {
+ val = (pMsg->msgData).dwId;
+ addr = (u32)&(((struct MSG_DSPMSG *)
+ pMsgOutput)->dwId);
+ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+ val);
+ val = (pMsg->msgData).msg.dwCmd;
+ addr = (u32)&((((struct MSG_DSPMSG *)
+ pMsgOutput)->msg).dwCmd);
+ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+ val);
+ val = (pMsg->msgData).msg.dwArg1;
+ addr =
+ (u32)&((((struct MSG_DSPMSG *)
+ pMsgOutput)->msg).dwArg1);
+ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+ val);
+ val = (pMsg->msgData).msg.dwArg2;
+ addr =
+ (u32)&((((struct MSG_DSPMSG *)
+ pMsgOutput)->msg).dwArg2);
+ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+ val);
+ pMsgOutput += sizeof(struct MSG_DSPMSG);
+ if (!hMsgMgr->msgFreeList)
+ goto func_end;
+ LST_PutTail(hMsgMgr->msgFreeList,
+ (struct LST_ELEM *) pMsg);
+ SYNC_SetEvent(hMsgMgr->hSyncEvent);
+ } else {
+ DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
+ }
+ }
+
+ if (uMsgs > 0) {
+ hMsgMgr->uMsgsPending -= uMsgs;
+#if _CHNL_WORDSIZE == 2
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ size, (u16)uMsgs);
+#else
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ size, uMsgs);
+#endif
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ bufEmpty, false);
+ /* Set the post SWI flag */
+ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+ postSWI, true);
+ /* Tell the DSP we have written the output. */
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
+ }
+ }
+func_end:
+ return;
+
+}
+
+/*
+ * ======== registerSHMSegs ========
+ * purpose:
+ * Registers GPP SM segment with CMM.
+ */
+static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
+ struct COD_MANAGER *hCodMan,
+ u32 dwGPPBasePA)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 ulShm0_Base = 0;
+ u32 ulShm0_End = 0;
+ u32 ulShm0_RsrvdStart = 0;
+ u32 ulRsrvdSize = 0;
+ u32 ulGppPhys;
+ u32 ulDspVirt;
+ u32 ulShmSegId0 = 0;
+ u32 dwOffset, dwGPPBaseVA, ulDSPSize;
+
+ /* Read address and size info for first SM region.*/
+ /* Get start of 1st SM Heap region */
+ status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
+ DBC_Assert(ulShm0_Base != 0);
+ /* Get end of 1st SM Heap region */
+ if (DSP_SUCCEEDED(status)) {
+ /* Get start and length of message part of shared memory */
+ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
+ &ulShm0_End);
+ DBC_Assert(ulShm0_End != 0);
+ }
+ /* start of Gpp reserved region */
+ if (DSP_SUCCEEDED(status)) {
+ /* Get start and length of message part of shared memory */
+ status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
+ &ulShm0_RsrvdStart);
+ DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart 0x%x \n",
+ ulShm0_RsrvdStart);
+ DBC_Assert(ulShm0_RsrvdStart != 0);
+ }
+ /* Register with CMM */
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
+ if (DSP_SUCCEEDED(status)) {
+ status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
+ CMM_ALLSEGMENTS);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
+ "Un-Register SM segments \n");
+ }
+ } else {
+ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
+ "Handle \n");
+ }
+ }
+ /* Register new SM region(s) */
+ if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
+ /* calc size (bytes) of SM the GPP can alloc from */
+ ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
+ uWordSize;
+ DBC_Assert(ulRsrvdSize > 0);
+ /* calc size of SM DSP can alloc from */
+ ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
+ uWordSize;
+ DBC_Assert(ulDSPSize > 0);
+ /* First TLB entry reserved for Bridge SM use.*/
+ ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
+ /* get size in bytes */
+ ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
+ uWordSize;
+ /* Calc byte offset used to convert GPP phys <-> DSP byte
+ * address.*/
+ if (dwGPPBasePA > ulDspVirt)
+ dwOffset = dwGPPBasePA - ulDspVirt;
+ else
+ dwOffset = ulDspVirt - dwGPPBasePA;
+
+ DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
+ /* calc Gpp phys base of SM region */
+ /* Linux - this is actually uncached kernel virtual address*/
+ dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
+ - ulDspVirt;
+ /* calc Gpp phys base of SM region */
+ /* Linux - this is the physical address*/
+ dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
+ uWordSize - ulDspVirt;
+ /* Register SM Segment 0.*/
+ status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
+ ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
+ CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
+ (u32)(ulShm0_Base * hIOMgr->uWordSize),
+ ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
+ "Seg 0 \n");
+ }
+ /* first SM region is segId = 1 */
+ DBC_Assert(ulShmSegId0 == 1);
+ }
+ return status;
+}
+
+/*
+ * ======== ReadData ========
+ * Copies buffers from the shared memory to the host buffer.
+ */
+static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+ void *pSrc, u32 uSize)
+{
+ memcpy(pDest, pSrc, uSize);
+ return uSize;
+}
+
+/*
+ * ======== WriteData ========
+ * Copies buffers from the host side buffer to the shared memory.
+ */
+static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+ void *pSrc, u32 uSize)
+{
+ memcpy(pDest, pSrc, uSize);
+ return uSize;
+}
+
+/* ZCPY IO routines. */
+void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
+{
+ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
+}
+
+/*
+ * ======== IO_SHMcontrol ========
+ * Sets the requested SHM setting.
+ */
+DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
+ IN void *pArgs)
+{
+#ifdef CONFIG_BRIDGE_DVFS
+ u32 i;
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+
+ switch (desc) {
+ case SHM_CURROPP:
+ /* Update the shared memory with requested OPP information */
+ if (pArgs != NULL)
+ hIOMgr->pSharedMem->oppTableStruct.currOppPt =
+ *(u32 *)pArgs;
+ else
+ return DSP_EFAIL;
+ break;
+ case SHM_OPPINFO:
+ /* Update the shared memory with the voltage, frequency,
+ min and max frequency values for an OPP */
+ for (i = 0; i <= dsp_max_opps; i++) {
+ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
+ vdd1_dsp_freq[i][0];
+ DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
+ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+ oppPoint[i].voltage);
+ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
+ frequency = vdd1_dsp_freq[i][1];
+ DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
+ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+ oppPoint[i].frequency);
+ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
+ vdd1_dsp_freq[i][2];
+ DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
+ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+ oppPoint[i].minFreq);
+ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
+ vdd1_dsp_freq[i][3];
+ DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
+ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+ oppPoint[i].maxFreq);
+ }
+ hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
+ DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
+ "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
+ /* Update the current OPP number */
+ if (pdata->dsp_get_opp)
+ i = (*pdata->dsp_get_opp)();
+ hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
+ DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
+ "%d\n", i);
+ break;
+ case SHM_GETOPP:
+ /* Get the OPP that DSP has requested */
+ *(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
+ break;
+ default:
+ break;
+
+ }
+#endif
+ return DSP_SOK;
+}
+
+/*
+ * ======== WMD_IO_GetProcLoad ========
+ * Gets the Processor's Load information
+ */
+DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
+ OUT struct DSP_PROCLOADSTAT *pProcStat)
+{
+#ifdef OMAP_3430
+ pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
+ pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
+ pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
+ pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
+
+ DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
+ "Pred Freq = %d\n", pProcStat->uCurrLoad,
+ pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
+ pProcStat->uPredictedFreq);
+#endif
+ return DSP_SOK;
+}
+
+#ifndef DSP_TRACEBUF_DISABLED
+void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
+{
+ u32 ulNewMessageLength = 0, ulGPPCurPointer;
+ volatile unsigned int i;
+
+
+ while (true) {
+ /* Get the DSP current pointer */
+ ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
+ ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
+ hIOMgr->ulDspVa);
+
+ /* No new debug messages available yet */
+ if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
+ break;
+
+ /* Continuous data */
+ else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
+ ulNewMessageLength = ulGPPCurPointer - hIOMgr->
+ ulGPPReadPointer;
+
+ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
+ ulNewMessageLength);
+ hIOMgr->pMsg[ulNewMessageLength] = '\0';
+ /* Advance the GPP trace pointer to DSP current
+ * pointer */
+ hIOMgr->ulGPPReadPointer += ulNewMessageLength;
+ /* Print the trace messages */
+ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
+ }
+ /* Handle trace buffer wraparound */
+ else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
+ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
+ hIOMgr->ulTraceBufferEnd -
+ hIOMgr->ulGPPReadPointer);
+ ulNewMessageLength = ulGPPCurPointer -
+ hIOMgr->ulTraceBufferBegin;
+ memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
+ hIOMgr->ulGPPReadPointer],
+ (char *)hIOMgr->ulTraceBufferBegin,
+ ulNewMessageLength);
+ hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
+ hIOMgr->ulGPPReadPointer +
+ ulNewMessageLength] = '\0';
+ /* Advance the GPP trace pointer to DSP current
+ * pointer */
+ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
+ ulNewMessageLength;
+ /* Print the trace messages */
+ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
+ }
+ }
+#ifdef OMAP44XX
+ for (i = 0; i < 0x100; i++)
+ ;
+#endif
+}
+#endif
+
+/*
+ * ======== PackTraceBuffer ========
+ * Removes extra nulls from the trace buffer returned from the DSP.
+ * Works even on buffers that already are packed (null removed); but has
+ * one bug in that case -- loses the last character (replaces with '\0').
+ * Continues through conversion for full set of nBytes input characters.
+ * Parameters:
+ * lpBuf: Pointer to input/output buffer
+ * nBytes: Number of characters in the buffer
+ * ulNumWords: Number of DSP words in the buffer. Indicates potential
+ * number of extra carriage returns to generate.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Unable to allocate memory.
+ * Requires:
+ * lpBuf must be a fully allocated writable block of at least nBytes.
+ * There are no more than ulNumWords extra characters needed (the number of
+ * linefeeds minus the number of NULLS in the input buffer).
+ */
+#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
+static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
+{
+ DSP_STATUS status = DSP_SOK;
+ char *lpTmpBuf;
+ char *lpBufStart;
+ char *lpTmpStart;
+ u32 nCnt;
+ char thisChar;
+
+ /* tmp workspace, 1 KB longer than input buf */
+ lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
+ if (lpTmpBuf == NULL) {
+ DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
+ status = DSP_EMEMORY;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ lpBufStart = lpBuf;
+ lpTmpStart = lpTmpBuf;
+ for (nCnt = nBytes; nCnt > 0; nCnt--) {
+ thisChar = *lpBuf++;
+ switch (thisChar) {
+ case '\0': /* Skip null bytes */
+ break;
+ case '\n': /* Convert \n to \r\n */
+ /* NOTE: do not reverse order; Some OS */
+ /* editors control doesn't understand "\n\r" */
+ *lpTmpBuf++ = '\r';
+ *lpTmpBuf++ = '\n';
+ break;
+ default: /* Copy in the actual ascii byte */
+ *lpTmpBuf++ = thisChar;
+ break;
+ }
+ }
+ *lpTmpBuf = '\0'; /* Make sure tmp buf is null terminated */
+ /* Cut output down to input buf size */
+ strncpy(lpBufStart, lpTmpStart, nBytes);
+ /*Make sure output is null terminated */
+ lpBufStart[nBytes - 1] = '\0';
+ MEM_Free(lpTmpStart);
+ }
+
+ return status;
+}
+#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+
+/*
+ * ======== PrintDspTraceBuffer ========
+ * Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
+ * Parameters:
+ * hDehMgr: Handle to DEH manager object
+ * number of extra carriage returns to generate.
+ * Returns:
+ * DSP_SOK: Success.
+ * DSP_EMEMORY: Unable to allocate memory.
+ * Requires:
+ * hDehMgr muse be valid. Checked in WMD_DEH_Notify.
+ */
+DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT *hWmdContext)
+{
+ DSP_STATUS status = DSP_SOK;
+
+#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
+ struct COD_MANAGER *hCodMgr;
+ u32 ulTraceEnd;
+ u32 ulTraceBegin;
+ u32 ulNumBytes = 0;
+ u32 ulNumWords = 0;
+ u32 ulWordSize = 2;
+ CONST u32 uMaxSize = 512;
+ char *pszBuf;
+ u16 *lpszBuf;
+
+ struct WMD_DEV_CONTEXT *pWmdContext = (struct WMD_DEV_CONTEXT *)
+ hWmdContext;
+ struct WMD_DRV_INTERFACE *pIntfFxns;
+ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)
+ pWmdContext->hDevObject;
+
+ status = DEV_GetCodMgr(pDevObject, &hCodMgr);
+ if (DSP_FAILED(status))
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
+ status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
+ GT_1trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
+ ulTraceBegin);
+ if (DSP_FAILED(status))
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: Failed on "
+ "COD_GetSymValue.\n");
+ }
+ if (DSP_SUCCEEDED(status)) {
+ status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
+ GT_1trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
+ ulTraceEnd);
+ if (DSP_FAILED(status))
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: Failed on "
+ "COD_GetSymValue.\n");
+ }
+ if (DSP_SUCCEEDED(status)) {
+ ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
+ /* If the chip type is 55 then the addresses will be
+ * byte addresses; convert them to word addresses. */
+ if (ulNumBytes > uMaxSize)
+ ulNumBytes = uMaxSize;
+
+ /* make sure the data we request fits evenly */
+ ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
+ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
+ "ulNumBytes 0x%x\n", ulNumBytes);
+ ulNumWords = ulNumBytes * ulWordSize;
+ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
+ "ulNumWords 0x%x\n", ulNumWords);
+ status = DEV_GetIntfFxns(pDevObject, &pIntfFxns);
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
+ lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
+ if (pszBuf != NULL) {
+ /* Read bytes from the DSP trace buffer... */
+ status = (*pIntfFxns->pfnBrdRead)(hWmdContext,
+ (u8 *)pszBuf, (u32)ulTraceBegin,
+ ulNumBytes, 0);
+ if (DSP_FAILED(status))
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: "
+ "Failed to Read Trace Buffer.\n");
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Pack and do newline conversion */
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: "
+ "before pack and unpack.\n");
+ PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
+ GT_1trace(dsp_trace_mask, GT_1CLASS,
+ "DSP Trace Buffer:\n%s\n", pszBuf);
+ }
+ MEM_Free(pszBuf);
+ MEM_Free(lpszBuf);
+ } else {
+ GT_0trace(dsp_trace_mask, GT_2CLASS,
+ "PrintDspTraceBuffer: Failed to "
+ "allocate trace buffer.\n");
+ status = DSP_EMEMORY;
+ }
+ }
+#endif
+ return status;
+}
+
+void IO_SM_init(void)
+{
+
+ GT_create(&dsp_trace_mask, "DT"); /* DSP Trace Mask */
+
+}
diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
new file mode 100644
index 000000000000..5585cdb4c8ce
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/mmu_fault.c
@@ -0,0 +1,172 @@
+/*
+ * mmu_fault.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== mmu_fault.c ========
+ * Description:
+ * Implements DSP MMU fault handling functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Dec-2004 hn: Support for IVA MMU exception.
+ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
+ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
+ *! 05-Jan-2004 vp: Updated support for 24xx silicon
+ *! 19-Feb-2003 vp: Code review updates.
+ *! - Cosmetic changes.
+ *! 18-Oct-2002 sb: Ported to Linux platform.
+ *! 10-Sep-2001 kc: created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/host_os.h>
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/dpc.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/drv.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmddeh.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/* ----------------------------------- This */
+#include "_deh.h"
+#include <dspbridge/cfg.h>
+#include "_tiomap_mmu.h"
+#include "_tiomap.h"
+#include "mmu_fault.h"
+
+static u32 dmmuEventMask;
+u32 faultAddr;
+
+static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ * ======== MMU_FaultDpc ========
+ * Deferred procedure call to handle DSP MMU fault.
+ */
+void MMU_FaultDpc(IN void *pRefData)
+{
+ struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
+
+ if (pDehMgr)
+ WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
+
+ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
+}
+
+/*
+ * ======== MMU_FaultIsr ========
+ * ISR to be triggered by a DSP MMU fault interrupt.
+ */
+irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData)
+{
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
+ struct WMD_DEV_CONTEXT *pDevContext;
+ struct CFG_HOSTRES resources;
+ DSP_STATUS status = DSP_SOK;
+
+
+ DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
+ DBC_Require(irq == INT_DSP_MMU_IRQ);
+ DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
+
+ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+
+ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ if (DSP_FAILED(status))
+ DBG_Trace(DBG_LEVEL7,
+ "**Failed to get Host Resources "
+ "in MMU ISR **\n");
+ if (MMU_CheckIfFault(pDevContext)) {
+ printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
+ "0x%x\n", dmmuEventMask);
+ printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
+ "0x%x\n", faultAddr);
+ /* Disable the MMU events, else once we clear it will
+ * start to raise INTs again */
+ /*
+ * Schedule a DPC directly. In the future, it may be
+ * necessary to check if DSP MMU fault is intended for
+ * Bridge.
+ */
+ DPC_Schedule(pDehMgr->hMmuFaultDpc);
+ /* Reset errInfo structure before use. */
+ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
+ pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
+ pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
+ pDehMgr->errInfo.dwVal3 = 0L;
+ /* Disable the MMU events, else once we clear it will
+ * start to raise INTs again */
+ HW_MMU_EventDisable(resources.dwDmmuBase,
+ HW_MMU_TRANSLATION_FAULT);
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "***** MMU FAULT ***** faultcode 0x%x\n",
+ dmmuEventMask);
+ HW_MMU_EventDisable(resources.dwDmmuBase,
+ HW_MMU_ALL_INTERRUPTS);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * ======== MMU_CheckIfFault ========
+ * Check to see if MMU Fault is valid TLB miss from DSP
+ * Note: This function is called from an ISR
+ */
+static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
+{
+
+
+ bool retVal = false;
+ DSP_STATUS status = DSP_SOK;
+ HW_STATUS hwStatus;
+ struct CFG_HOSTRES resources;
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
+ "MMU_CheckIfFault **\n");
+
+ hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
+ if (dmmuEventMask == HW_MMU_TRANSLATION_FAULT) {
+ HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
+ DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
+ "address = 0x%x\n", faultAddr);
+ retVal = true;
+ }
+ return retVal;
+}
diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
new file mode 100644
index 000000000000..be59333d0190
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/mmu_fault.h
@@ -0,0 +1,45 @@
+/*
+ * mmu_fault.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== mmu_fault.h ========
+ * Description:
+ * Defines DSP MMU fault handling functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Dec-2004 hn: IVA MMU handlers.
+ *! 10-Sep-2001 kc: created.
+ */
+
+#ifndef MMU_FAULT_
+#define MMU_FAULT_
+
+/*
+ * ======== MMU_FaultDpc ========
+ * Deferred procedure call to handle DSP MMU fault.
+ */
+ void MMU_FaultDpc(IN void *pRefData);
+
+/*
+ * ======== MMU_FaultIsr ========
+ * ISR to be triggered by a DSP MMU fault interrupt.
+ */
+irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData);
+
+#endif /* MMU_FAULT_ */
+
diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
new file mode 100644
index 000000000000..b9b2bec175cd
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/msg_sm.c
@@ -0,0 +1,643 @@
+/*
+ * msg_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== msg_sm.c ========
+ * Description:
+ * Implements upper edge functions for WMD message module.
+ *
+ * Public Functions:
+ * WMD_MSG_Create
+ * WMD_MSG_CreateQueue
+ * WMD_MSG_Delete
+ * WMD_MSG_DeleteQueue
+ * WMD_MSG_Get
+ * WMD_MSG_Put
+ * WMD_MSG_RegisterNotify
+ * WMD_MSG_SetQueueId
+ *
+ *! Revision History:
+ *! =================
+ *! 24-Jul-2002 jeh Release critical section in WMD_MSG_Put() before
+ *! scheduling DPC.
+ *! 09-May-2001 jeh Free MSG queue NTFY object, remove unnecessary set/
+ *! reset of events.
+ *! 10-Jan-2001 jeh Set/Reset message manager and message queue events
+ *! correctly.
+ *! 04-Dec-2000 jeh Bug fixes.
+ *! 12-Sep-2000 jeh Created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/list.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/sync.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+
+/* ----------------------------------- Others */
+#include <dspbridge/io_sm.h>
+
+/* ----------------------------------- This */
+#include <_msg_sm.h>
+#include <dspbridge/wmdmsg.h>
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#define MSGQ_SIGNATURE 0x5147534d /* "QGSM" */
+
+/* ----------------------------------- Function Prototypes */
+static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
+static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
+static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
+static void FreeMsgList(struct LST_LIST *msgList);
+
+/*
+ * ======== WMD_MSG_Create ========
+ * Create an object to manage message queues. Only one of these objects
+ * can exist per device object.
+ */
+DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
+ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
+{
+ struct MSG_MGR *pMsgMgr;
+ struct IO_MGR *hIOMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(phMsgMgr != NULL);
+ DBC_Require(msgCallback != NULL);
+ DBC_Require(hDevObject != NULL);
+ DEV_GetIOMgr(hDevObject, &hIOMgr);
+ DBC_Assert(hIOMgr != NULL);
+ *phMsgMgr = NULL;
+ /* Allocate MSG manager object */
+ MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
+
+ if (pMsgMgr) {
+ pMsgMgr->onExit = msgCallback;
+ pMsgMgr->hIOMgr = hIOMgr;
+ /* List of MSG_QUEUEs */
+ pMsgMgr->queueList = LST_Create();
+ /* Queues of message frames for messages to the DSP. Message
+ * frames will only be added to the free queue when a
+ * MSG_QUEUE object is created. */
+ pMsgMgr->msgFreeList = LST_Create();
+ pMsgMgr->msgUsedList = LST_Create();
+ if (pMsgMgr->queueList == NULL ||
+ pMsgMgr->msgFreeList == NULL ||
+ pMsgMgr->msgUsedList == NULL)
+ status = DSP_EMEMORY;
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
+
+ /* Create an event to be used by WMD_MSG_Put() in waiting
+ * for an available free frame from the message manager. */
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
+
+ if (DSP_SUCCEEDED(status))
+ *phMsgMgr = pMsgMgr;
+ else
+ DeleteMsgMgr(pMsgMgr);
+
+ } else {
+ status = DSP_EMEMORY;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_MSG_CreateQueue ========
+ * Create a MSG_QUEUE for sending/receiving messages to/from a node
+ * on the DSP.
+ */
+DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
+ OUT struct MSG_QUEUE **phMsgQueue,
+ u32 dwId, u32 uMaxMsgs, HANDLE hArg)
+{
+ u32 i;
+ u32 uNumAllocated = 0;
+ struct MSG_QUEUE *pMsgQ;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+ DBC_Require(phMsgQueue != NULL);
+
+ *phMsgQueue = NULL;
+ /* Allocate MSG_QUEUE object */
+ MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
+ if (!pMsgQ) {
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ LST_InitElem((struct LST_ELEM *) pMsgQ);
+ pMsgQ->uMaxMsgs = uMaxMsgs;
+ pMsgQ->hMsgMgr = hMsgMgr;
+ pMsgQ->hArg = hArg; /* Node handle */
+ pMsgQ->dwId = dwId; /* Node env (not valid yet) */
+ /* Queues of Message frames for messages from the DSP */
+ pMsgQ->msgFreeList = LST_Create();
+ pMsgQ->msgUsedList = LST_Create();
+ if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
+ status = DSP_EMEMORY;
+
+ /* Create event that will be signalled when a message from
+ * the DSP is available. */
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
+
+ /* Create a notification list for message ready notification. */
+ if (DSP_SUCCEEDED(status))
+ status = NTFY_Create(&pMsgQ->hNtfy);
+
+ /* Create events that will be used to synchronize cleanup
+ * when the object is deleted. hSyncDone will be set to
+ * unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
+ * will be set by the unblocked thread to signal that it
+ * is unblocked and will no longer reference the object. */
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
+
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
+
+ if (DSP_SUCCEEDED(status)) {
+ if (!hMsgMgr->msgFreeList) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+ /* Enter critical section */
+ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+ /* Initialize message frames and put in appropriate queues */
+ for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
+ status = AddNewMsg(hMsgMgr->msgFreeList);
+ if (DSP_SUCCEEDED(status)) {
+ uNumAllocated++;
+ status = AddNewMsg(pMsgQ->msgFreeList);
+ }
+ }
+ if (DSP_FAILED(status)) {
+ /* Stay inside CS to prevent others from taking any
+ * of the newly allocated message frames. */
+ DeleteMsgQueue(pMsgQ, uNumAllocated);
+ } else {
+ LST_PutTail(hMsgMgr->queueList,
+ (struct LST_ELEM *)pMsgQ);
+ *phMsgQueue = pMsgQ;
+ /* Signal that free frames are now available */
+ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
+ SYNC_SetEvent(hMsgMgr->hSyncEvent);
+
+ }
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ } else {
+ DeleteMsgQueue(pMsgQ, 0);
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== WMD_MSG_Delete ========
+ * Delete a MSG manager allocated in WMD_MSG_Create().
+ */
+void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
+{
+ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+
+ DeleteMsgMgr(hMsgMgr);
+}
+
+/*
+ * ======== WMD_MSG_DeleteQueue ========
+ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
+ */
+void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
+{
+ struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
+ u32 refCount;
+
+ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+ hMsgQueue->fDone = true;
+ /* Unblock all threads blocked in MSG_Get() or MSG_Put(). */
+ refCount = hMsgQueue->refCount;
+ while (refCount) {
+ /* Unblock thread */
+ SYNC_SetEvent(hMsgQueue->hSyncDone);
+ /* Wait for acknowledgement */
+ SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
+ refCount = hMsgQueue->refCount;
+ }
+ /* Remove message queue from hMsgMgr->queueList */
+ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+ LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
+ /* Free the message queue object */
+ DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
+ if (!hMsgMgr->msgFreeList)
+ goto func_cont;
+ if (LST_IsEmpty(hMsgMgr->msgFreeList))
+ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
+func_cont:
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+}
+
+/*
+ * ======== WMD_MSG_Get ========
+ * Get a message from a MSG queue.
+ */
+DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
+ struct DSP_MSG *pMsg, u32 uTimeout)
+{
+ struct MSG_FRAME *pMsgFrame;
+ struct MSG_MGR *hMsgMgr;
+ bool fGotMsg = false;
+ struct SYNC_OBJECT *hSyncs[2];
+ u32 uIndex;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+ DBC_Require(pMsg != NULL);
+
+ hMsgMgr = hMsgQueue->hMsgMgr;
+ if (!hMsgQueue->msgUsedList) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+
+ /* Enter critical section */
+ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+ /* If a message is already there, get it */
+ if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
+ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
+ msgUsedList);
+ if (pMsgFrame != NULL) {
+ *pMsg = pMsgFrame->msgData.msg;
+ LST_PutTail(hMsgQueue->msgFreeList,
+ (struct LST_ELEM *)pMsgFrame);
+ if (LST_IsEmpty(hMsgQueue->msgUsedList))
+ SYNC_ResetEvent(hMsgQueue->hSyncEvent);
+
+ fGotMsg = true;
+ }
+ } else {
+ if (hMsgQueue->fDone)
+ status = DSP_EFAIL;
+ else
+ hMsgQueue->refCount++;
+
+ }
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ if (DSP_SUCCEEDED(status) && !fGotMsg) {
+ /* Wait til message is available, timeout, or done. We don't
+ * have to schedule the DPC, since the DSP will send messages
+ * when they are available. */
+ hSyncs[0] = hMsgQueue->hSyncEvent;
+ hSyncs[1] = hMsgQueue->hSyncDone;
+ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
+ &uIndex);
+ /* Enter critical section */
+ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+ if (hMsgQueue->fDone) {
+ hMsgQueue->refCount--;
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ /* Signal that we're not going to access hMsgQueue
+ * anymore, so it can be deleted. */
+ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
+ status = DSP_EFAIL;
+ } else {
+ if (DSP_SUCCEEDED(status)) {
+ DBC_Assert(!LST_IsEmpty(hMsgQueue->
+ msgUsedList));
+ /* Get msg from used list */
+ pMsgFrame = (struct MSG_FRAME *)
+ LST_GetHead(hMsgQueue->msgUsedList);
+ /* Copy message into pMsg and put frame on the
+ * free list */
+ if (pMsgFrame != NULL) {
+ *pMsg = pMsgFrame->msgData.msg;
+ LST_PutTail(hMsgQueue->msgFreeList,
+ (struct LST_ELEM *)pMsgFrame);
+ }
+ }
+ hMsgQueue->refCount--;
+ /* Reset the event if there are still queued messages */
+ if (!LST_IsEmpty(hMsgQueue->msgUsedList))
+ SYNC_SetEvent(hMsgQueue->hSyncEvent);
+
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== WMD_MSG_Put ========
+ * Put a message onto a MSG queue.
+ */
+DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
+ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
+{
+ struct MSG_FRAME *pMsgFrame;
+ struct MSG_MGR *hMsgMgr;
+ bool fPutMsg = false;
+ struct SYNC_OBJECT *hSyncs[2];
+ u32 uIndex;
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+ DBC_Require(pMsg != NULL);
+
+ hMsgMgr = hMsgQueue->hMsgMgr;
+
+ if (!hMsgMgr->msgFreeList) {
+ status = DSP_EHANDLE;
+ goto func_end;
+ }
+
+
+ (void) SYNC_EnterCS(hMsgMgr->hSyncCS);
+
+ /* If a message frame is available, use it */
+ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
+ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
+ msgFreeList);
+ if (pMsgFrame != NULL) {
+ pMsgFrame->msgData.msg = *pMsg;
+ pMsgFrame->msgData.dwId = hMsgQueue->dwId;
+ LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
+ pMsgFrame);
+ hMsgMgr->uMsgsPending++;
+ fPutMsg = true;
+ }
+ if (LST_IsEmpty(hMsgMgr->msgFreeList))
+ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
+
+ /* Release critical section before scheduling DPC */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ /* Schedule a DPC, to do the actual data transfer: */
+ IO_Schedule(hMsgMgr->hIOMgr);
+ } else {
+ if (hMsgQueue->fDone)
+ status = DSP_EFAIL;
+ else
+ hMsgQueue->refCount++;
+
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ }
+ if (DSP_SUCCEEDED(status) && !fPutMsg) {
+ /* Wait til a free message frame is available, timeout,
+ * or done */
+ hSyncs[0] = hMsgMgr->hSyncEvent;
+ hSyncs[1] = hMsgQueue->hSyncDone;
+ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
+ &uIndex);
+ /* Enter critical section */
+ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+ if (hMsgQueue->fDone) {
+ hMsgQueue->refCount--;
+ /* Exit critical section */
+ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ /* Signal that we're not going to access hMsgQueue
+ * anymore, so it can be deleted. */
+ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
+ status = DSP_EFAIL;
+ } else {
+ if (DSP_SUCCEEDED(status)) {
+ if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
+ status = DSP_EPOINTER;
+ goto func_cont;
+ }
+ /* Get msg from free list */
+ pMsgFrame = (struct MSG_FRAME *)
+ LST_GetHead(hMsgMgr->msgFreeList);
+ /* Copy message into pMsg and put frame on the
+ * used list */
+ if (pMsgFrame != NULL) {
+ pMsgFrame->msgData.msg = *pMsg;
+ pMsgFrame->msgData.dwId =
+ hMsgQueue->dwId;
+ LST_PutTail(hMsgMgr->msgUsedList,
+ (struct LST_ELEM *)
+ pMsgFrame);
+ hMsgMgr->uMsgsPending++;
+ /* Schedule a DPC, to do the actual
+ * data transfer: */
+ IO_Schedule(hMsgMgr->hIOMgr);
+ }
+ }
+ hMsgQueue->refCount--;
+ /* Reset event if there are still frames available */
+ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
+ SYNC_SetEvent(hMsgMgr->hSyncEvent);
+func_cont:
+ /* Exit critical section */
+ (void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== WMD_MSG_RegisterNotify ========
+ */
+DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification)
+{
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+ DBC_Require(hNotification != NULL);
+ DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
+ DBC_Require(uNotifyType == DSP_SIGNALEVENT);
+
+ status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
+ uNotifyType);
+
+ if (status == DSP_EVALUE) {
+ /* Not registered. Ok, since we couldn't have known. Node
+ * notifications are split between node state change handled
+ * by NODE, and message ready handled by MSG. */
+ status = DSP_SOK;
+ }
+
+ return status;
+}
+
+/*
+ * ======== WMD_MSG_SetQueueId ========
+ */
+void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
+{
+ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+ /* DBC_Require(dwId != 0); */
+
+ /*
+ * A message queue must be created when a node is allocated,
+ * so that NODE_RegisterNotify() can be called before the node
+ * is created. Since we don't know the node environment until the
+ * node is created, we need this function to set hMsgQueue->dwId
+ * to the node environment, after the node is created.
+ */
+ hMsgQueue->dwId = dwId;
+}
+
+/*
+ * ======== AddNewMsg ========
+ * Must be called in message manager critical section.
+ */
+static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
+{
+ struct MSG_FRAME *pMsg;
+ DSP_STATUS status = DSP_SOK;
+
+ pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
+ MEM_PAGED);
+ if (pMsg != NULL) {
+ LST_InitElem((struct LST_ELEM *) pMsg);
+ LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
+ } else {
+ status = DSP_EMEMORY;
+ }
+
+ return status;
+}
+
+/*
+ * ======== DeleteMsgMgr ========
+ */
+static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
+{
+ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+
+ if (hMsgMgr->queueList) {
+ if (LST_IsEmpty(hMsgMgr->queueList)) {
+ LST_Delete(hMsgMgr->queueList);
+ hMsgMgr->queueList = NULL;
+ }
+ }
+
+ if (hMsgMgr->msgFreeList) {
+ FreeMsgList(hMsgMgr->msgFreeList);
+ hMsgMgr->msgFreeList = NULL;
+ }
+
+ if (hMsgMgr->msgUsedList) {
+ FreeMsgList(hMsgMgr->msgUsedList);
+ hMsgMgr->msgUsedList = NULL;
+ }
+
+ if (hMsgMgr->hSyncEvent)
+ SYNC_CloseEvent(hMsgMgr->hSyncEvent);
+
+ if (hMsgMgr->hSyncCS)
+ SYNC_DeleteCS(hMsgMgr->hSyncCS);
+
+ MEM_FreeObject(hMsgMgr);
+}
+
+/*
+ * ======== DeleteMsgQueue ========
+ */
+static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
+{
+ struct MSG_MGR *hMsgMgr;
+ struct MSG_FRAME *pMsg;
+ u32 i;
+
+ if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE)
+ || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList)
+ goto func_end;
+ hMsgMgr = hMsgQueue->hMsgMgr;
+
+
+ /* Pull off uNumToDSP message frames from Msg manager and free */
+ for (i = 0; i < uNumToDSP; i++) {
+
+ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
+ pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
+ msgFreeList);
+ MEM_Free(pMsg);
+ } else {
+ /* Cannot free all of the message frames */
+ break;
+ }
+ }
+
+ if (hMsgQueue->msgFreeList) {
+ FreeMsgList(hMsgQueue->msgFreeList);
+ hMsgQueue->msgFreeList = NULL;
+ }
+
+ if (hMsgQueue->msgUsedList) {
+ FreeMsgList(hMsgQueue->msgUsedList);
+ hMsgQueue->msgUsedList = NULL;
+ }
+
+
+ if (hMsgQueue->hNtfy)
+ NTFY_Delete(hMsgQueue->hNtfy);
+
+ if (hMsgQueue->hSyncEvent)
+ SYNC_CloseEvent(hMsgQueue->hSyncEvent);
+
+ if (hMsgQueue->hSyncDone)
+ SYNC_CloseEvent(hMsgQueue->hSyncDone);
+
+ if (hMsgQueue->hSyncDoneAck)
+ SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
+
+ MEM_FreeObject(hMsgQueue);
+func_end:
+ return;
+
+}
+
+/*
+ * ======== FreeMsgList ========
+ */
+static void FreeMsgList(struct LST_LIST *msgList)
+{
+ struct MSG_FRAME *pMsg;
+
+ if (!msgList)
+ goto func_end;
+
+ while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
+ MEM_Free(pMsg);
+
+ DBC_Assert(LST_IsEmpty(msgList));
+
+ LST_Delete(msgList);
+func_end:
+ return;
+}
+
diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
new file mode 100644
index 000000000000..537c7c976e43
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap3430.c
@@ -0,0 +1,2238 @@
+/*
+ * tiomap.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/*
+ * ======== tiomap.c ========
+ * Processor Manager Driver for TI OMAP3430 EVM.
+ *
+ * Public Function:
+ * WMD_DRV_Entry
+ *
+ *! Revision History:
+ *! ================
+ * 26-March-2008 HK and AL: Added WMD_DEV_WalkTbl funciton.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <mach-omap2/prm.h>
+#include <mach-omap2/cm.h>
+#include <mach-omap2/prm-regbits-34xx.h>
+#include <mach-omap2/cm-regbits-34xx.h>
+#include <mach/control.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/util.h>
+#include <dspbridge/reg.h>
+#include <dspbridge/dbreg.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/csl.h>
+#include <dspbridge/sync.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_dspssC64P.h>
+#include <hw_prcm.h>
+#include <hw_mmu.h>
+#include <hw_mbox.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmd.h>
+#include <dspbridge/wmdchnl.h>
+#include <dspbridge/wmddeh.h>
+#include <dspbridge/wmdio.h>
+#include <dspbridge/wmdmsg.h>
+#include <dspbridge/pwr.h>
+#include <dspbridge/chnl_sm.h>
+#include <dspbridge/io_sm.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/wcd.h>
+#include <dspbridge/dmm.h>
+
+/* ----------------------------------- Local */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "_tiomap_mmu.h"
+#include "_tiomap_util.h"
+#include "tiomap_io.h"
+
+
+/* Offset in shared mem to write to in order to synchronize start with DSP */
+#define SHMSYNCOFFSET 4 /* GPP byte offset */
+
+#define BUFFERSIZE 1024
+
+#define MMU_SECTION_ADDR_MASK 0xFFF00000
+#define MMU_SSECTION_ADDR_MASK 0xFF000000
+#define MMU_LARGE_PAGE_MASK 0xFFFF0000
+#define MMU_SMALL_PAGE_MASK 0xFFFFF000
+#define PAGES_II_LVL_TABLE 512
+#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
+
+#define MMU_GFLUSH 0x60
+
+/* Forward Declarations: */
+static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
+static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
+ OUT u8 *pbHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
+ u32 dwDSPAddr);
+static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
+ OUT BRD_STATUS *pdwState);
+static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
+static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u8 *pbHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulBrdState);
+static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulDspDestAddr, u32 ulDspSrcAddr,
+ u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
+ u32 ulMapAttr);
+static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulVirtAddr, u32 ulNumBytes);
+static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CFG_HOSTRES *pConfig,
+ IN CONST struct CFG_DSPRES *pDspConfig);
+static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
+ IN OUT void *pArgs);
+static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
+static u32 user_va2pa(struct mm_struct *mm, u32 address);
+static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
+ u32 va, u32 size,
+ struct HW_MMUMapAttrs_t *mapAttrs);
+static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
+ u32 size, struct HW_MMUMapAttrs_t *attrs);
+static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulMpuAddr, u32 ulVirtAddr,
+ u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);
+#ifdef OMAP44XX
+void GetHWRegs(void __iomem *prm_base, u32 cm1_base, u32 cm2_base);
+#endif
+
+/* ----------------------------------- Globals */
+
+/* Attributes of L2 page tables for DSP MMU */
+struct PageInfo {
+ u32 numEntries; /* Number of valid PTEs in the L2 PT */
+} ;
+
+/* Attributes used to manage the DSP MMU page tables */
+struct PgTableAttrs {
+ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
+
+ u32 L1BasePa; /* Physical address of the L1 PT */
+ u32 L1BaseVa; /* Virtual address of the L1 PT */
+ u32 L1size; /* Size of the L1 PT */
+ u32 L1TblAllocPa;
+ /* Physical address of Allocated mem for L1 table. May not be aligned */
+ u32 L1TblAllocVa;
+ /* Virtual address of Allocated mem for L1 table. May not be aligned */
+ u32 L1TblAllocSz;
+ /* Size of consistent memory allocated for L1 table.
+ * May not be aligned */
+
+ u32 L2BasePa; /* Physical address of the L2 PT */
+ u32 L2BaseVa; /* Virtual address of the L2 PT */
+ u32 L2size; /* Size of the L2 PT */
+ u32 L2TblAllocPa;
+ /* Physical address of Allocated mem for L2 table. May not be aligned */
+ u32 L2TblAllocVa;
+ /* Virtual address of Allocated mem for L2 table. May not be aligned */
+ u32 L2TblAllocSz;
+ /* Size of consistent memory allocated for L2 table.
+ * May not be aligned */
+
+ u32 L2NumPages; /* Number of allocated L2 PT */
+ struct PageInfo *pgInfo; /* Array [L2NumPages] of L2 PT info structs */
+} ;
+
+/*
+ * If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
+ * to boot
+ */
+extern s32 dsp_debug;
+
+/*
+ * This mini driver's function interface table.
+ */
+static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
+ WCD_MAJOR_VERSION, /* WCD ver. for which this mini driver is built. */
+ WCD_MINOR_VERSION,
+ WMD_DEV_Create,
+ WMD_DEV_Destroy,
+ WMD_DEV_Ctrl,
+ WMD_BRD_Monitor,
+ WMD_BRD_Start,
+ WMD_BRD_Stop,
+ WMD_BRD_Status,
+ WMD_BRD_Read,
+ WMD_BRD_Write,
+ WMD_BRD_SetState,
+ WMD_BRD_MemCopy,
+ WMD_BRD_MemWrite,
+ WMD_BRD_MemMap,
+ WMD_BRD_MemUnMap,
+ /* The following CHNL functions are provided by chnl_io.lib: */
+ WMD_CHNL_Create,
+ WMD_CHNL_Destroy,
+ WMD_CHNL_Open,
+ WMD_CHNL_Close,
+ WMD_CHNL_AddIOReq,
+ WMD_CHNL_GetIOC,
+ WMD_CHNL_CancelIO,
+ WMD_CHNL_FlushIO,
+ WMD_CHNL_GetInfo,
+ WMD_CHNL_GetMgrInfo,
+ WMD_CHNL_Idle,
+ WMD_CHNL_RegisterNotify,
+ /* The following DEH functions are provided by tihelen_ue_deh.c */
+ WMD_DEH_Create,
+ WMD_DEH_Destroy,
+ WMD_DEH_Notify,
+ WMD_DEH_RegisterNotify,
+ WMD_DEH_GetInfo,
+ /* The following IO functions are provided by chnl_io.lib: */
+ WMD_IO_Create,
+ WMD_IO_Destroy,
+ WMD_IO_OnLoaded,
+ WMD_IO_GetProcLoad,
+ /* The following MSG functions are provided by chnl_io.lib: */
+ WMD_MSG_Create,
+ WMD_MSG_CreateQueue,
+ WMD_MSG_Delete,
+ WMD_MSG_DeleteQueue,
+ WMD_MSG_Get,
+ WMD_MSG_Put,
+ WMD_MSG_RegisterNotify,
+ WMD_MSG_SetQueueId,
+};
+
+static inline void tlb_flush_all(const void __iomem *base)
+{
+ __raw_writeb(__raw_readb(base + MMU_GFLUSH) | 1, base + MMU_GFLUSH);
+}
+
+static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)
+{
+ struct CFG_HOSTRES resources;
+#ifdef OMAP_3430
+ u32 temp = 0;
+#endif
+
+ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+#ifdef OMAP_3430
+ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
+
+ if ((temp & HW_PWR_STATE_ON) == HW_PWR_STATE_OFF ||
+ (temp & HW_PWR_STATE_ON) == HW_PWR_STATE_RET) {
+ CLK_Enable(SERVICESCLK_iva2_ck);
+ WakeDSP(pDevContext, NULL);
+ tlb_flush_all(pDevContext->dwDSPMmuBase);
+ CLK_Disable(SERVICESCLK_iva2_ck);
+ } else
+ tlb_flush_all(pDevContext->dwDSPMmuBase);
+#else
+ tlb_flush_all((void __iomem *)pDevContext->dwDSPMmuBase);
+#endif
+}
+
+static void bad_page_dump(u32 pa, struct page *pg)
+{
+ pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
+ pr_emerg("Bad page state in process '%s'\n"
+ "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
+ "Backtrace:\n",
+ current->comm, pg, (int)(2*sizeof(unsigned long)),
+ (unsigned long)pg->flags, pg->mapping,
+ page_mapcount(pg), page_count(pg));
+ BUG();
+}
+
+/*
+ * ======== WMD_DRV_Entry ========
+ * purpose:
+ * Mini Driver entry point.
+ */
+void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
+ IN CONST char *pstrWMDFileName)
+{
+
+ DBC_Require(pstrWMDFileName != NULL);
+ DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
+
+ IO_SM_init(); /* Initialization of io_sm module */
+
+ if (strcmp(pstrWMDFileName, "UMA") == 0)
+ *ppDrvInterface = &drvInterfaceFxns;
+ else
+ DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
+
+}
+
+/*
+ * ======== WMD_BRD_Monitor ========
+ * purpose:
+ * This WMD_BRD_Monitor puts DSP into a Loadable state.
+ * i.e Application can load and start the device.
+ *
+ * Preconditions:
+ * Device in 'OFF' state.
+ */
+static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ struct CFG_HOSTRES resources;
+#ifdef OMAP_3430
+ u32 temp;
+ enum HW_PwrState_t pwrState;
+#endif
+
+ DBG_Trace(DBG_ENTER, "Board in the monitor state \n");
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ goto error_return;
+
+#ifdef OMAP44XX
+ printk(KERN_ERR "Disabling Clocks... and resources.dwCm1Base = 0x%x\n"
+ "resources.dwCm2Base= 0x%x\n"
+ "resources.dwPrmBase = 0x%x\n",
+ (unsigned int)resources.dwCm1Base,
+ (unsigned int)resources.dwCm2Base,
+ (unsigned int)resources.dwPrmBase);
+
+ HW_CLK_Disable(resources.dwCm1Base, HW_CLK_TESLA);
+ printk("Resetting DSP...");
+ HW_RST_Reset(resources.dwPrmBase, HW_RST1_TESLA);
+ HW_RST_Reset(resources.dwPrmBase, HW_RST2_TESLA);
+ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_TESLA);
+ printk("Enabling Clocks...");
+ HW_CLK_Enable(resources.dwCm1Base, HW_CLK_TESLA);
+ *((REG_UWORD32 *)((u32)(resources.dwDmmuBase)+0x50)) = 0x400;
+#else
+ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+ HW_PWRST_RegGet(resources.dwPrmBase, HW_PWR_DOMAIN_TESLA, &temp);
+
+ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
+
+ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
+ /* IVA2 is not in ON state */
+ /* Read and set PM_PWSTCTRL_IVA2 to ON */
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
+ HW_PWR_DOMAIN_DSP,
+ HW_PWR_STATE_ON);
+ /* Set the SW supervised state transition */
+ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_SW_SUP_WAKEUP);
+ /* Wait until the state has moved to ON */
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ /* Disable Automatic transition */
+ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
+ }
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
+ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
+ CLK_Enable(SERVICESCLK_iva2_ck);
+#endif
+ if (DSP_SUCCEEDED(status)) {
+ /* set the device state to IDLE */
+ pDevContext->dwBrdState = BRD_IDLE;
+ }
+error_return:
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
+#ifdef OMAP44XX
+ GetHWRegs(resources.dwPrmBase, resources.dwCm1Base, resources.dwCm2Base);
+#endif
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_Read ========
+ * purpose:
+ * Reads buffers for DSP memory.
+ */
+static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
+ OUT u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ u32 offset;
+ u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
+
+ DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
+ " 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
+ "ulMemType: 0x%x\n", pDevContext, pbHostBuf,
+ dwDSPAddr, ulNumBytes, ulMemType);
+ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Read: DSP address < start address \n ");
+ status = DSP_EFAIL;
+ return status;
+ }
+ /* change here to account for the 3 bands of the DSP internal memory */
+ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
+ pDevContext->dwInternalSize) {
+ offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
+ } else {
+ DBG_Trace(DBG_LEVEL1,
+ "**** Reading From external memory **** \n ");
+ status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
+ ulNumBytes, ulMemType);
+ return status;
+ }
+ /* copy the data from DSP memory, */
+ memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_SetState ========
+ * purpose:
+ * This routine updates the Board status.
+ */
+static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulBrdState)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+ DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
+ ulBrdState);
+ pDevContext->dwBrdState = ulBrdState;
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_Start ========
+ * purpose:
+ * Initializes DSP MMU and Starts DSP.
+ *
+ * Preconditions:
+ * a) DSP domain is 'ACTIVE'.
+ * b) DSP_RST1 is asserted.
+ * b) DSP_RST2 is released.
+ */
+static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 dwDSPAddr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ u32 dwSyncAddr = 0;
+ u32 ulShmBase; /* Gpp Phys SM base addr(byte) */
+ u32 ulShmBaseVirt; /* Dsp Virt SM base addr */
+ u32 ulTLBBaseVirt; /* Base of MMU TLB entry */
+ u32 ulShmOffsetVirt; /* offset of ulShmBaseVirt from ulTLBBaseVirt */
+ u32 temp;
+ struct CFG_HOSTRES resources;
+ s32 iEntryNdx;
+ s32 itmpEntryNdx = 0; /* DSP-MMU TLB entry base address */
+#ifdef OMAP_3430
+ u32 ulDspClkRate;
+ u32 ulDspClkAddr;
+ u32 ulBiosGpTimer;
+ u32 uClkCmd;
+ u32 ulLoadMonitorTimer;
+ u32 extClkId = 0;
+ u32 tmpIndex;
+ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
+#endif
+ struct IO_MGR *hIOMgr;
+ register u32 newAdress = ((u32)(dwDSPAddr));
+
+ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
+ "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
+#ifdef OMAP44XX
+ printk(KERN_ERR "Please break Virtio by typing 'y' in console and start CCS"
+ "set DSP PC adress to below DSP Start address and Run using CCS\n");
+ printk(KERN_ERR "- - - DSP Start Address [0x%x]- - -\n", dwDSPAddr) ;
+#endif
+ /* The device context contains all the mmu setup info from when the
+ * last dsp base image was loaded. The first entry is always
+ * SHMMEM base. */
+ /* Get SHM_BEG - convert to byte address */
+ (void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
+ &ulShmBaseVirt);
+ ulShmBaseVirt *= DSPWORDSIZE;
+ DBC_Assert(ulShmBaseVirt != 0);
+ /* DSP Virtual address */
+ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
+ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+ ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
+ /* Kernel logical address */
+ ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
+
+ DBC_Assert(ulShmBase != 0);
+ /* 2nd wd is used as sync field */
+ dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
+ /* Write a signature into the SHM base + offset; this will
+ * get cleared when the DSP program starts. */
+ if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
+ status = DSP_EFAIL;
+ } else
+ *((volatile u32 *)dwSyncAddr) = 0xffffffff;
+
+ if (DSP_SUCCEEDED(status)) {
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ newAdress &= 0xFFFFFC00;
+ *((REG_UWORD32 *)((u32)(resources.dwSysCtrlBase)+0x304)) =
+ newAdress;
+ /* Assert RST1 i.e only the RST only for DSP megacell */
+ /* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
+ if (DSP_SUCCEEDED(status)) {
+#ifdef OMAP44XX
+ /*HW_RST_Reset(resources.dwPrmBase,
+ HW_RST1_TESLA);*/
+#else
+ HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
+ if (dsp_debug) {
+ /* Set the bootmode to self loop */
+ DBG_Trace(DBG_LEVEL7,
+ "Set boot mode to self loop"
+ " for IVA2 Device\n");
+ HW_DSPSS_BootModeSet(
+ resources.dwSysCtrlBase,
+ HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
+ } else {
+ /* Set the bootmode to '0'
+ - direct boot */
+ DBG_Trace(DBG_LEVEL7,
+ "Set boot mode to direct"
+ " boot for IVA2 Device \n");
+ HW_DSPSS_BootModeSet(
+ resources.dwSysCtrlBase,
+ HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
+ }
+#endif
+ }
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Reset and Unreset the RST2, so that BOOTADDR is copied to
+ * IVA2 SYSC register */
+#ifdef OMAP44XX
+ udelay(100);
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
+ GetHWRegs(resources.dwPrmBase, resources.dwCm1Base,
+ resources.dwCm2Base);
+#else
+ HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
+ udelay(100);
+ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
+ udelay(100);
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
+ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+#endif
+ /* Disbale the DSP MMU */
+ HW_MMU_Disable(resources.dwDmmuBase);
+ /* Disable TWL */
+ HW_MMU_TWLDisable(resources.dwDmmuBase);
+
+ /* Only make TLB entry if both addresses are non-zero */
+ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
+ iEntryNdx++) {
+ if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
+ (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
+ DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
+ " 0x%x DspVa 0x%x Size 0x%x\n",
+ itmpEntryNdx,
+ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
+ pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
+ pDevContext->aTLBEntry[iEntryNdx].ulSize);
+ configureDspMmu(pDevContext,
+ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
+ pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
+ DSPWORDSIZE,
+ pDevContext->aTLBEntry[iEntryNdx].ulSize,
+ itmpEntryNdx,
+ pDevContext->aTLBEntry[iEntryNdx].endianism,
+ pDevContext->aTLBEntry[iEntryNdx].elemSize,
+ pDevContext->aTLBEntry[iEntryNdx].
+ mixedMode);
+ itmpEntryNdx++;
+ }
+ } /* end for */
+ }
+
+ /* Lock the above TLB entries and get the BIOS and load monitor timer
+ * information*/
+ if (DSP_SUCCEEDED(status)) {
+ HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
+ HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
+ HW_MMU_TTBSet(resources.dwDmmuBase,
+ pDevContext->pPtAttrs->L1BasePa);
+ HW_MMU_TWLEnable(resources.dwDmmuBase);
+ /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
+
+
+#ifdef OMAP_3430
+ temp = __raw_readl((resources.dwDmmuBase) + 0x10);
+ temp = (temp & 0xFFFFFFEF) | 0x11;
+ __raw_writel(temp, (resources.dwDmmuBase) + 0x10);
+#endif
+ /* Let the DSP MMU run */
+ temp = __raw_readl((resources.dwDmmuBase) + 0x10);
+ temp = (temp & 0xFFFFFFEF) | 0x11;
+ __raw_writel(temp, (resources.dwDmmuBase) + 0x10);
+
+ HW_MMU_Enable(resources.dwDmmuBase);
+ (void)CHNLSM_EnableInterrupt(pDevContext);
+
+
+#ifdef OMAP_3430
+ /* Enable the BIOS clock */
+ (void)DEV_GetSymbol(pDevContext->hDevObject,
+ BRIDGEINIT_BIOSGPTIMER,
+ &ulBiosGpTimer);
+ DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
+ (void)DEV_GetSymbol(pDevContext->hDevObject,
+ BRIDGEINIT_LOADMON_GPTIMER,
+ &ulLoadMonitorTimer);
+ DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
+ ulLoadMonitorTimer);
+#endif
+ }
+#ifdef OMAP_3430
+ if (DSP_SUCCEEDED(status)) {
+ if (ulLoadMonitorTimer != 0xFFFF) {
+ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
+ ulLoadMonitorTimer;
+ DBG_Trace(DBG_LEVEL7,
+ "encoded LoadMonitor cmd for Disable: 0x%x\n",
+ uClkCmd);
+ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
+ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
+ tmpIndex++) {
+ if (extClkId == BPWR_CLKID[tmpIndex]) {
+ clkIdIndex = tmpIndex;
+ break;
+ }
+ }
+
+ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
+ status = CLK_Set_32KHz(
+ BPWR_Clks[clkIdIndex].funClk);
+ else
+ status = DSP_EFAIL;
+
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7, " Error while setting"
+ "LM Timer to 32KHz\n");
+ }
+ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
+ ulLoadMonitorTimer;
+ DBG_Trace(DBG_LEVEL7,
+ "encoded LoadMonitor cmd for Enable : 0x%x\n",
+ uClkCmd);
+ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "Not able to get the symbol for Load "
+ "Monitor Timer\n");
+ }
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ if (ulBiosGpTimer != 0xFFFF) {
+ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
+ ulBiosGpTimer;
+ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
+ "Disable: 0x%x\n", uClkCmd);
+ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
+
+ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
+ tmpIndex++) {
+ if (extClkId == BPWR_CLKID[tmpIndex]) {
+ clkIdIndex = tmpIndex;
+ break;
+ }
+ }
+
+ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
+ status = CLK_Set_32KHz(
+ BPWR_Clks[clkIdIndex].funClk);
+ else
+ status = DSP_EFAIL;
+
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ " Error while setting BIOS Timer to 32KHz\n");
+ }
+
+ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
+ ulBiosGpTimer;
+ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
+ "0x%x\n", uClkCmd);
+ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "Not able to get the symbol for BIOS Timer\n");
+ }
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Set the DSP clock rate */
+ (void)DEV_GetSymbol(pDevContext->hDevObject,
+ "_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
+ /*Set Autoidle Mode for IVA2 PLL */
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x34));
+ temp = (temp & 0xFFFFFFFE) | 0x1;
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
+ (u32) temp;
+ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
+ "0x%x \n", ulDspClkAddr);
+ if ((unsigned int *)ulDspClkAddr != NULL) {
+ /* Get the clock rate */
+ status = CLK_GetRate(SERVICESCLK_iva2_ck,
+ &ulDspClkRate);
+ DBG_Trace(DBG_LEVEL5,
+ "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
+ ulDspClkRate);
+ (void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
+ ulDspClkAddr, sizeof(u32), 0);
+ }
+/*PM_IVA2GRPSEL_PER = 0xC0;*/
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ temp = (temp & 0xFFFFFF30) | 0xC0;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8)) =
+ (u32) temp;
+
+/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F;*/
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ temp = (temp & 0xFFFFFF3F);
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4)) =
+ (u32) temp;
+/*CM_SLEEPDEP_PER |= 0x04;*/
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerBase) + 0x44));
+ temp = (temp & 0xFFFFFFFB) | 0x04;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerBase) + 0x44)) =
+ (u32) temp;
+
+/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions*/
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x48));
+ temp = (temp & 0xFFFFFFFC) | 0x03;
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x48)) =
+ (u32) temp;
+
+ /* Enable Mailbox events and also drain any pending
+ * stale messages */
+ (void)CHNLSM_EnableInterrupt(pDevContext);
+ }
+#endif
+ if (DSP_SUCCEEDED(status)) {
+#ifdef OMAP_3430
+ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
+ temp);
+ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
+ temp);
+#else
+ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_TESLA, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
+ temp);
+ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_TESLA, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
+ temp);
+ /* Let DSP go */
+#endif
+ /* Let DSP go */
+ DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
+ /* Enable DSP MMU Interrupts */
+ HW_MMU_EventEnable(resources.dwDmmuBase,
+ HW_MMU_ALL_INTERRUPTS);
+ /* release the RST1, DSP starts executing now .. */
+#ifdef OMAP44XX
+ HW_RST_UnReset(resources.dwPrmBase, HW_RST1_TESLA);
+ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_TESLA, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
+ temp);
+ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_TESLA, &temp);
+#else
+ HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
+ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
+ temp);
+ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+#endif
+ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
+ temp);
+ DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
+ dwSyncAddr);
+ DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address = 0x%x \n",
+ dwDSPAddr);
+ if (dsp_debug)
+ while (*((volatile u16 *)dwSyncAddr))
+ ;;
+ }
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Wait for DSP to clear word in shared memory */
+ /* Read the Location */
+ if (!WaitForStart(pDevContext, dwSyncAddr)) {
+ status = WMD_E_TIMEOUT;
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Start Failed to Synchronize\n");
+ }
+ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+ if (DSP_SUCCEEDED(status)) {
+ IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Start: OPP information initialzed\n");
+ /* Write the synchronization bit to indicate the
+ * completion of OPP table update to DSP
+ */
+ *((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* update board state */
+ pDevContext->dwBrdState = BRD_RUNNING;
+ /* (void)CHNLSM_EnableInterrupt(pDevContext);*/
+ DBG_Trace(DBG_LEVEL7, "Device Started \n ");
+ } else {
+ pDevContext->dwBrdState = BRD_UNKNOWN;
+ DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
+ }
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_Stop ========
+ * purpose:
+ * Puts DSP in self loop.
+ *
+ * Preconditions :
+ * a) None
+ */
+static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ struct CFG_HOSTRES resources;
+#ifdef OMAP_3430
+ struct PgTableAttrs *pPtAttrs;
+ u32 dspPwrState;
+ DSP_STATUS clk_status;
+#endif
+ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
+ hDevContext);
+
+ /* Disable the mail box interrupts */
+ (void)CHNLSM_DisableInterrupt(pDevContext);
+
+ if (pDevContext->dwBrdState == BRD_STOPPED)
+ return status;
+
+ /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
+ * before turning off the clocks.. This is to ensure that there are no
+ * pending L3 or other transactons from IVA2 */
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Stop: Get Host resources failed \n");
+ DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
+ return DSP_EFAIL;
+ }
+
+#ifdef OMAP44XX
+ DBG_Trace(DBG_LEVEL7, "Resetting DSP...");
+ HW_CLK_Disable (resources.dwCm1Base, HW_CLK_TESLA) ;
+ HW_RST_Reset(resources.dwPrmBase, HW_RST1_TESLA);
+ /* Enable DSP */
+ HW_CLK_Enable (resources.dwCm1Base, HW_CLK_TESLA) ;
+ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
+#else
+ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
+ if (dspPwrState != HW_PWR_STATE_OFF) {
+ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
+ mdelay(10);
+ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+ udelay(50);
+
+ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+ if (DSP_FAILED(clk_status)) {
+ DBG_Trace(DBG_LEVEL6,
+ "\n WMD_BRD_Stop: CLK_Disable failed "
+ "for iva2_fck\n");
+ }
+ /* IVA2 is not in OFF state */
+ /* Set PM_PWSTCTRL_IVA2 to OFF */
+ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
+ HW_PWR_DOMAIN_DSP,
+ HW_PWR_STATE_OFF);
+ /* Set the SW supervised state transition for Sleep */
+ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_SW_SUP_SLEEP);
+ } else {
+ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+ if (DSP_FAILED(clk_status)) {
+ DBG_Trace(DBG_LEVEL6,
+ "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
+ " for iva2_fck\n");
+ }
+ }
+ udelay(10);
+ /* Release the Ext Base virtual Address as the next DSP Program
+ * may have a different load address */
+ if (pDevContext->dwDspExtBaseAddr)
+ pDevContext->dwDspExtBaseAddr = 0;
+
+ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
+ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
+ /* This is a good place to clear the MMU page tables as well */
+ if (pDevContext->pPtAttrs) {
+ pPtAttrs = pDevContext->pPtAttrs;
+ memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
+ memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
+ memset((u8 *) pPtAttrs->pgInfo, 0x00,
+ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
+ }
+#endif
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
+ return status;
+}
+
+
+/*
+ * ======== WMD_BRD_Delete ========
+ * purpose:
+ * Puts DSP in Low power mode
+ *
+ * Preconditions :
+ * a) None
+ */
+static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ struct CFG_HOSTRES resources;
+ struct PgTableAttrs *pPtAttrs;
+#ifdef OMAP_3430
+ DSP_STATUS clk_status;
+#endif
+
+ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
+ hDevContext);
+
+ /* Disable the mail box interrupts */
+ (void) CHNLSM_DisableInterrupt(pDevContext);
+
+ if (pDevContext->dwBrdState == BRD_STOPPED)
+ return status;
+
+ /* as per TRM, it is advised to first drive
+ * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
+ * to ensure that there are no pending L3 or other transactons from
+ * IVA2 */
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Stop: Get Host resources failed \n");
+ DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
+ return DSP_EFAIL;
+ }
+#ifdef OMAP44XX
+ HW_CLK_Disable (resources.dwCm1Base, HW_CLK_TESLA) ;
+#else
+
+ status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
+ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+ if (DSP_FAILED(clk_status)) {
+ DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
+ " iva2_fck\n");
+ }
+#endif
+ /* Release the Ext Base virtual Address as the next DSP Program
+ * may have a different load address */
+ if (pDevContext->dwDspExtBaseAddr)
+ pDevContext->dwDspExtBaseAddr = 0;
+
+ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
+ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
+ /* This is a good place to clear the MMU page tables as well */
+ if (pDevContext->pPtAttrs) {
+ pPtAttrs = pDevContext->pPtAttrs;
+ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
+ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
+ memset((u8 *)pPtAttrs->pgInfo, 0x00,
+ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
+ }
+ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
+#ifdef OMAP_3430
+ HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
+ HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
+#endif
+
+ return status;
+}
+
+
+/*
+ * ======== WMD_BRD_Status ========
+ * Returns the board status.
+ */
+static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
+ OUT BRD_STATUS *pdwState)
+{
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ *pdwState = pDevContext->dwBrdState;
+ return DSP_SOK;
+}
+
+/*
+ * ======== WMD_BRD_Write ========
+ * Copies the buffers to DSP internal or external memory.
+ */
+static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
+ IN u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
+ "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
+ "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
+ dwDSPAddr, ulNumBytes, ulMemType);
+ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_Write: DSP address < start address \n ");
+ status = DSP_EFAIL;
+ return status;
+ }
+ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
+ pDevContext->dwInternalSize) {
+ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
+ ulNumBytes, ulMemType);
+ } else {
+ status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
+ ulNumBytes, ulMemType, false);
+ }
+
+ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy : DspLogicAddr=0x%x \n",
+ pDevContext->dwDspBaseAddr);
+ return status;
+}
+
+/*
+ * ======== WMD_DEV_Create ========
+ * Creates a driver object. Puts DSP in self loop.
+ */
+static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
+ struct DEV_OBJECT *hDevObject,
+ IN CONST struct CFG_HOSTRES *pConfig,
+ IN CONST struct CFG_DSPRES *pDspConfig)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = NULL;
+ s32 iEntryNdx;
+ s32 tcWordSwap;
+ u32 tcWordSwapSize = sizeof(tcWordSwap);
+ struct CFG_HOSTRES resources;
+ struct PgTableAttrs *pPtAttrs;
+ u32 pg_tbl_pa;
+ u32 pg_tbl_va;
+ u32 align_size;
+
+ enum HW_PwrState_t pwrState;
+ u32 PwrCtrl;
+ u32 iIterations = 0;
+ DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
+ "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
+ ppDevContext, hDevObject, pConfig, pDspConfig);
+ /* Allocate and initialize a data structure to contain the mini driver
+ * state, which becomes the context for later calls into this WMD. */
+ pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
+ if (!pDevContext) {
+ DBG_Trace(DBG_ENTER, "Failed to allocate mem \n");
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_ENTER, "Failed to get host resources \n");
+ status = DSP_EMEMORY;
+ goto func_end;
+ }
+
+ pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
+ pDevContext->dwSelfLoop = (u32)NULL;
+ pDevContext->uDspPerClks = 0;
+ pDevContext->dwInternalSize = OMAP_DSP_SIZE;
+ /* Clear dev context MMU table entries.
+ * These get set on WMD_BRD_IOCTL() call after program loaded. */
+ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
+ pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
+ pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
+ }
+ pDevContext->numTLBEntries = 0;
+ pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
+ (pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
+ if (!pDevContext->dwDspBaseAddr) {
+ status = DSP_EFAIL;
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_DEV_Create: failed to Map the API memory\n");
+ }
+ pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
+ if (pPtAttrs != NULL) {
+ /* Assuming that we use only DSP's memory map
+ * until 0x4000:0000 , we would need only 1024
+ * L1 enties i.e L1 size = 4K */
+ pPtAttrs->L1size = 0x4000;
+ align_size = pPtAttrs->L1size;
+ /* Align sizes are expected to be power of 2 */
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
+ align_size, &pg_tbl_pa);
+
+ /* Check if the PA is aligned for us */
+ if ((pg_tbl_pa) & (align_size-1)) {
+ /* PA not aligned to page table size ,
+ * try with more allocation and align */
+ MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa,
+ pPtAttrs->L1size);
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
+ align_size, &pg_tbl_pa);
+ /* We should be able to get aligned table now */
+ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
+ pPtAttrs->L1TblAllocVa = pg_tbl_va;
+ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
+ /* Align the PA to the next 'align' boundary */
+ pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
+ (~(align_size-1));
+ pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
+ pg_tbl_pa);
+ } else {
+ /* We got aligned PA, cool */
+ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
+ pPtAttrs->L1TblAllocVa = pg_tbl_va;
+ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
+ pPtAttrs->L1BasePa = pg_tbl_pa;
+ pPtAttrs->L1BaseVa = pg_tbl_va;
+ }
+ if (pPtAttrs->L1BaseVa)
+ memset((u8 *)pPtAttrs->L1BaseVa, 0x00,
+ pPtAttrs->L1size);
+
+ /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
+ * L4 pages */
+ pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
+ pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
+ pPtAttrs->L2NumPages;
+ align_size = 4; /* Make it u32 aligned */
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
+ align_size, &pg_tbl_pa);
+ pPtAttrs->L2TblAllocPa = pg_tbl_pa;
+ pPtAttrs->L2TblAllocVa = pg_tbl_va;
+ pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
+ pPtAttrs->L2BasePa = pg_tbl_pa;
+ pPtAttrs->L2BaseVa = pg_tbl_va;
+
+ if (pPtAttrs->L2BaseVa)
+ memset((u8 *)pPtAttrs->L2BaseVa, 0x00,
+ pPtAttrs->L2size);
+
+ pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
+ sizeof(struct PageInfo), MEM_NONPAGED);
+ DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
+ "%x, size %x\n", pPtAttrs->L1BasePa,
+ pPtAttrs->L1BaseVa, pPtAttrs->L1size,
+ pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
+ pPtAttrs->L2size);
+ DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
+ pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
+ }
+ if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
+ (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
+ pDevContext->pPtAttrs = pPtAttrs;
+ else
+ status = DSP_EMEMORY;
+
+ if (DSP_SUCCEEDED(status))
+ status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Set the Endianism Register */ /* Need to set this */
+ pDevContext->wIntrVal2Dsp = MBX_PCPY_CLASS;
+ /* Retrieve the TC u16 SWAP Option */
+ status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
+ (u8 *)&tcWordSwap, &tcWordSwapSize);
+ /* Save the value */
+ pDevContext->tcWordSwapOn = tcWordSwap;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ /* Set the Clock Divisor for the DSP module */
+ DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
+ "enable the clock \n");
+#ifdef OMAP44XX
+ HW_PWR_PowerStateSet((u32)resources.dwPrmBase,
+ HW_PWR_DOMAIN_TESLA, HW_PWR_STATE_ON);
+
+ HW_CLK_Enable(resources.dwCm1Base, HW_CLK_TESLA);
+
+ HW_PWR_ForceStateSet((u32)resources.dwCm1Base,
+ HW_PWR_DOMAIN_TESLA, HW_SW_SUP_WAKEUP);
+
+ HW_PWR_PowerStateGet((u32)resources.dwPrmBase,
+ HW_PWR_DOMAIN_TESLA, &pwrState);
+ while (HW_PWR_STATE_ON != pwrState) {
+ iIterations++;
+ if (iIterations >= 500) {
+ HW_PWRSTCTRL_RegGet((u32)
+ resources.dwPrmBase,
+ &PwrCtrl);
+ printk("Error: Failed to put"
+ " the DSP domain in ON"
+ "state"
+ " PRM_TESLA_PWRSTCTRL ="
+ " 0x%x", PwrCtrl);
+ return DSP_EFAIL;
+ }
+ HW_PWR_PowerStateGet((u32)
+ resources.dwPrmBase,
+ HW_PWR_DOMAIN_TESLA, &pwrState);
+ }
+#else
+ status = CLK_Enable(SERVICESCLK_mailbox_ick);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_DEV_create:Reset mail box and "
+ "enable the clock Fail\n");
+ }
+ udelay(5);
+ /* 24xx-Linux MMU address is obtained from the host
+ * resources struct */
+#endif
+ pDevContext->dwDSPMmuBase = (u32)resources.dwDmmuBase;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pDevContext->hDevObject = hDevObject;
+ pDevContext->ulIntMask = 0;
+ /* Store current board state. */
+ pDevContext->dwBrdState = BRD_STOPPED;
+ /* Return this ptr to our device state to the WCD for storage:*/
+ *ppDevContext = pDevContext;
+ DBG_Trace(DBG_ENTER, "Device Created \n");
+ } else {
+ if (pPtAttrs != NULL) {
+ if (pPtAttrs->hCSObj)
+ SYNC_DeleteCS(pPtAttrs->hCSObj);
+
+ if (pPtAttrs->pgInfo)
+ MEM_Free(pPtAttrs->pgInfo);
+
+ if (pPtAttrs->L2TblAllocVa) {
+ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
+ pPtAttrs->L2TblAllocPa,
+ pPtAttrs->L2TblAllocSz);
+ }
+ if (pPtAttrs->L1TblAllocVa) {
+ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
+ pPtAttrs->L1TblAllocPa,
+ pPtAttrs->L1TblAllocSz);
+ }
+ }
+ if (pPtAttrs)
+ MEM_Free(pPtAttrs);
+
+ if (pDevContext)
+ MEM_Free(pDevContext);
+
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_DEV_Create Error Device not created\n");
+ }
+func_end:
+ return status;
+}
+
+/*
+ * ======== WMD_DEV_Ctrl ========
+ * Receives device specific commands.
+ */
+static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
+ IN OUT void *pArgs)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
+ s32 ndx;
+
+ DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext: 0x%x\n\t\t dwCmd: "
+ "0x%x\n\t\tpArgs: 0x%x\n", pDevContext, dwCmd, pArgs);
+ switch (dwCmd) {
+ case WMDIOCTL_CHNLREAD:
+ break;
+ case WMDIOCTL_CHNLWRITE:
+ break;
+ case WMDIOCTL_SETMMUCONFIG:
+ /* store away dsp-mmu setup values for later use */
+ for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
+ pDevContext->aTLBEntry[ndx] = *paExtProc;
+ break;
+ case WMDIOCTL_DEEPSLEEP:
+ case WMDIOCTL_EMERGENCYSLEEP:
+ /* Currently only DSP Idle is supported Need to update for
+ * later releases */
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
+ status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
+ break;
+ case WMDIOCTL_WAKEUP:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
+ status = WakeDSP(pDevContext, pArgs);
+ break;
+ case WMDIOCTL_CLK_CTRL:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
+ status = DSP_SOK;
+ /* Looking For Baseport Fix for Clocks */
+ status = DSPPeripheralClkCtrl(pDevContext, pArgs);
+ break;
+ case WMDIOCTL_PWR_HIBERNATE:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
+ status = handle_hibernation_fromDSP(pDevContext);
+ break;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+ case WMDIOCTL_PRESCALE_NOTIFY:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
+ status = PreScale_DSP(pDevContext, pArgs);
+ break;
+ case WMDIOCTL_POSTSCALE_NOTIFY:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
+ status = PostScale_DSP(pDevContext, pArgs);
+ break;
+ case WMDIOCTL_CONSTRAINT_REQUEST:
+ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
+ status = handle_constraints_set(pDevContext, pArgs);
+ break;
+#endif
+#endif
+ default:
+ status = DSP_EFAIL;
+ DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
+ break;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_DEV_Destroy ========
+ * Destroys the driver object.
+ */
+static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
+{
+ struct PgTableAttrs *pPtAttrs;
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
+ hDevContext;
+ DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
+ hDevContext);
+ /* first put the device to stop state */
+ WMD_BRD_Delete(pDevContext);
+ if (pDevContext && pDevContext->pPtAttrs) {
+ pPtAttrs = pDevContext->pPtAttrs;
+ if (pPtAttrs->hCSObj)
+ SYNC_DeleteCS(pPtAttrs->hCSObj);
+
+ if (pPtAttrs->pgInfo)
+ MEM_Free(pPtAttrs->pgInfo);
+
+ if (pPtAttrs->L2TblAllocVa) {
+ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
+ pPtAttrs->L2TblAllocPa, pPtAttrs->
+ L2TblAllocSz);
+ }
+ if (pPtAttrs->L1TblAllocVa) {
+ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
+ pPtAttrs->L1TblAllocPa, pPtAttrs->
+ L1TblAllocSz);
+ }
+ if (pPtAttrs)
+ MEM_Free(pPtAttrs);
+
+ }
+ /* Free the driver's device context: */
+ MEM_Free((void *) hDevContext);
+ return status;
+}
+
+static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulDspDestAddr, u32 ulDspSrcAddr,
+ u32 ulNumBytes, u32 ulMemType)
+{
+ DSP_STATUS status = DSP_SOK;
+ u32 srcAddr = ulDspSrcAddr;
+ u32 destAddr = ulDspDestAddr;
+ u32 copyBytes = 0;
+ u32 totalBytes = ulNumBytes;
+ u8 hostBuf[BUFFERSIZE];
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
+ copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
+ /* Read from External memory */
+ status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
+ copyBytes, ulMemType);
+ if (DSP_SUCCEEDED(status)) {
+ if (destAddr < (pDevContext->dwDSPStartAdd +
+ pDevContext->dwInternalSize)) {
+ /* Write to Internal memory */
+ status = WriteDspData(hDevContext, hostBuf,
+ destAddr, copyBytes, ulMemType);
+ } else {
+ /* Write to External memory */
+ status = WriteExtDspData(hDevContext, hostBuf,
+ destAddr, copyBytes, ulMemType, false);
+ }
+ }
+ totalBytes -= copyBytes;
+ srcAddr += copyBytes;
+ destAddr += copyBytes;
+ }
+ return status;
+}
+
+/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
+static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
+ IN u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ u32 ulRemainBytes = 0;
+ u32 ulBytes = 0;
+ ulRemainBytes = ulNumBytes;
+ while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
+ ulBytes =
+ ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
+ if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
+ pDevContext->dwInternalSize)) {
+ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
+ ulBytes, ulMemType);
+ } else {
+ status = WriteExtDspData(hDevContext, pbHostBuf,
+ dwDSPAddr, ulBytes, ulMemType, true);
+ }
+ ulRemainBytes -= ulBytes;
+ dwDSPAddr += ulBytes;
+ pbHostBuf = pbHostBuf + ulBytes;
+ }
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_MemMap ========
+ * This function maps MPU buffer to the DSP address space. It performs
+ * linear to physical address translation if required. It translates each
+ * page since linear addresses can be physically non-contiguous
+ * All address & size arguments are assumed to be page aligned (in proc.c)
+ *
+ * TODO: Disable MMU while updating the page tables (but that'll stall DSP)
+ */
+static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulMpuAddr, u32 ulVirtAddr,
+ u32 ulNumBytes, u32 ulMapAttr)
+{
+ u32 attrs;
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ struct HW_MMUMapAttrs_t hwAttrs;
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ u32 write = 0;
+ u32 numUsrPgs = 0;
+ struct page *mappedPage, *pg;
+ s32 pgNum;
+ u32 va = ulVirtAddr;
+ struct task_struct *curr_task = current;
+ u32 pgI = 0;
+ u32 mpuAddr, pa;
+
+ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
+ "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
+ ulNumBytes, ulMapAttr);
+ if (ulNumBytes == 0)
+ return DSP_EINVALIDARG;
+
+ if (ulMapAttr != 0) {
+ attrs = ulMapAttr;
+ } else {
+ /* Assign default attributes */
+ attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
+ }
+ /* Take mapping properties */
+ if (attrs & DSP_MAPBIGENDIAN)
+ hwAttrs.endianism = HW_BIG_ENDIAN;
+ else
+ hwAttrs.endianism = HW_LITTLE_ENDIAN;
+
+ hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
+ ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
+ /* Ignore elementSize if mixedSize is enabled */
+ if (hwAttrs.mixedSize == 0) {
+ if (attrs & DSP_MAPELEMSIZE8) {
+ /* Size is 8 bit */
+ hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
+ } else if (attrs & DSP_MAPELEMSIZE16) {
+ /* Size is 16 bit */
+ hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
+ } else if (attrs & DSP_MAPELEMSIZE32) {
+ /* Size is 32 bit */
+ hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
+ } else if (attrs & DSP_MAPELEMSIZE64) {
+ /* Size is 64 bit */
+ hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
+ } else {
+ /*
+ * Mixedsize isn't enabled, so size can't be
+ * zero here
+ */
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_MemMap: MMU element size is zero\n");
+ return DSP_EINVALIDARG;
+ }
+ }
+ if (attrs & DSP_MAPDONOTLOCK)
+ hwAttrs.donotlockmpupage = 1;
+ else
+ hwAttrs.donotlockmpupage = 0;
+
+ if (attrs & DSP_MAPVMALLOCADDR) {
+ return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
+ ulNumBytes, &hwAttrs);
+ }
+ /*
+ * Do OS-specific user-va to pa translation.
+ * Combine physically contiguous regions to reduce TLBs.
+ * Pass the translated pa to PteUpdate.
+ */
+ if ((attrs & DSP_MAPPHYSICALADDR)) {
+ status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
+ ulNumBytes, &hwAttrs);
+ goto func_cont;
+ }
+
+ /*
+ * Important Note: ulMpuAddr is mapped from user application process
+ * to current process - it must lie completely within the current
+ * virtual memory address space in order to be of use to us here!
+ */
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, ulMpuAddr);
+ if (vma)
+ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
+ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
+ ulMpuAddr, ulNumBytes, vma->vm_start,
+ vma->vm_end, vma->vm_flags);
+
+ /*
+ * It is observed that under some circumstances, the user buffer is
+ * spread across several VMAs. So loop through and check if the entire
+ * user buffer is covered
+ */
+ while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
+ /* jump to the next VMA region */
+ vma = find_vma(mm, vma->vm_end + 1);
+ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
+ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
+ ulMpuAddr, ulNumBytes, vma->vm_start,
+ vma->vm_end, vma->vm_flags);
+ }
+ if (!vma) {
+ DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
+ "MPU Buffer !!! \n");
+ status = DSP_EINVALIDARG;
+ up_read(&mm->mmap_sem);
+ goto func_cont;
+ }
+
+ if (vma->vm_flags & VM_IO) {
+ numUsrPgs = ulNumBytes / PG_SIZE_4K;
+ mpuAddr = ulMpuAddr;
+ DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"
+ "ulNumBytes= %d\n", numUsrPgs, ulNumBytes);
+ /* Get the physical addresses for user buffer */
+ for (pgI = 0; pgI < numUsrPgs; pgI++) {
+ pa = user_va2pa(mm, mpuAddr);
+ if (!pa) {
+ status = DSP_EFAIL;
+ pr_err("DSPBRIDGE: VM_IO mapping physical"
+ "address is invalid\n");
+ break;
+ }
+ if (pfn_valid(__phys_to_pfn(pa))) {
+ pg = phys_to_page(pa);
+ get_page(pg);
+ if (page_count(pg) < 1) {
+ pr_err("Bad page in VM_IO buffer\n");
+ bad_page_dump(pa, pg);
+ }
+ }
+ status = PteSet(pDevContext->pPtAttrs, pa,
+ va, HW_PAGE_SIZE_4KB, &hwAttrs);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_MemMap: FAILED IN VM_IO"
+ "PTESET \n");
+ break;
+ }
+ va += HW_PAGE_SIZE_4KB;
+ mpuAddr += HW_PAGE_SIZE_4KB;
+ pa += HW_PAGE_SIZE_4KB;
+ }
+ } else {
+ numUsrPgs = ulNumBytes / PG_SIZE_4K;
+ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
+ write = 1;
+
+ for (pgI = 0; pgI < numUsrPgs; pgI++) {
+ pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,
+ write, 1, &mappedPage, NULL);
+ if (pgNum > 0) {
+ if (page_count(mappedPage) < 1) {
+ pr_err("Bad page count after doing"
+ "get_user_pages on"
+ "user buffer\n");
+ bad_page_dump(page_to_phys(mappedPage),
+ mappedPage);
+ }
+ status = PteSet(pDevContext->pPtAttrs,
+ page_to_phys(mappedPage), va,
+ HW_PAGE_SIZE_4KB, &hwAttrs);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "WMD_BRD_MemMap: FAILED IN PTESET \n");
+ break;
+ }
+ va += HW_PAGE_SIZE_4KB;
+ ulMpuAddr += HW_PAGE_SIZE_4KB;
+ } else {
+ pr_err("DSPBRIDGE: get_user_pages FAILED,"
+ "MPU addr = 0x%x,"
+ "vma->vm_flags = 0x%lx,"
+ "get_user_pages Err"
+ "Value = %d, Buffer"
+ "size=0x%x\n", ulMpuAddr,
+ vma->vm_flags, pgNum,
+ ulNumBytes);
+ status = DSP_EFAIL;
+ break;
+ }
+ }
+ }
+ up_read(&mm->mmap_sem);
+func_cont:
+ /* Don't propogate Linux or HW status to upper layers */
+ if (DSP_SUCCEEDED(status)) {
+ status = DSP_SOK;
+ } else {
+ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
+ /*
+ * Roll out the mapped pages incase it failed in middle of
+ * mapping
+ */
+ if (pgI) {
+ WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,
+ (pgI * PG_SIZE_4K));
+ }
+ status = DSP_EFAIL;
+ }
+ /*
+ * In any case, flush the TLB
+ * This is called from here instead from PteUpdate to avoid unnecessary
+ * repetition while mapping non-contiguous physical regions of a virtual
+ * region
+ */
+ flush_all(pDevContext);
+ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
+ return status;
+}
+
+/*
+ * ======== WMD_BRD_MemUnMap ========
+ * Invalidate the PTEs for the DSP VA block to be unmapped.
+ *
+ * PTEs of a mapped memory block are contiguous in any page table
+ * So, instead of looking up the PTE address for every 4K block,
+ * we clear consecutive PTEs until we unmap all the bytes
+ */
+static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
+ u32 ulVirtAddr, u32 ulNumBytes)
+{
+ u32 L1BaseVa;
+ u32 L2BaseVa;
+ u32 L2BasePa;
+ u32 L2PageNum;
+ u32 pteVal;
+ u32 pteSize;
+ u32 pteCount;
+ u32 pteAddrL1;
+ u32 pteAddrL2 = 0;
+ u32 remBytes;
+ u32 remBytesL2;
+ u32 vaCurr;
+ struct page *pg = NULL;
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ struct PgTableAttrs *pt = pDevContext->pPtAttrs;
+ u32 pacount = 0;
+ u32 *pPhysAddrPageTbl = NULL;
+ u32 temp;
+ u32 patemp = 0;
+ u32 pAddr;
+ u32 numof4KPages = 0;
+
+ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
+ "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
+ pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
+ vaCurr = ulVirtAddr;
+ remBytes = ulNumBytes;
+ remBytesL2 = 0;
+ L1BaseVa = pt->L1BaseVa;
+ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
+ DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
+ "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
+ vaCurr, remBytes);
+ while (remBytes && (DSP_SUCCEEDED(status))) {
+ u32 vaCurrOrig = vaCurr;
+ /* Find whether the L1 PTE points to a valid L2 PT */
+ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
+ pteVal = *(u32 *)pteAddrL1;
+ pteSize = HW_MMU_PteSizeL1(pteVal);
+ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
+ /*
+ * Get the L2 PA from the L1 PTE, and find
+ * corresponding L2 VA
+ */
+ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
+ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
+ L2PageNum = (L2BasePa - pt->L2BasePa) /
+ HW_MMU_COARSE_PAGE_SIZE;
+ /*
+ * Find the L2 PTE address from which we will start
+ * clearing, the number of PTEs to be cleared on this
+ * page, and the size of VA space that needs to be
+ * cleared on this L2 page
+ */
+ pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
+ pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
+ pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
+ sizeof(u32);
+ if (remBytes < (pteCount * PG_SIZE_4K))
+ pteCount = remBytes / PG_SIZE_4K;
+
+ remBytesL2 = pteCount * PG_SIZE_4K;
+ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
+ "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
+ L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
+ /*
+ * Unmap the VA space on this L2 PT. A quicker way
+ * would be to clear pteCount entries starting from
+ * pteAddrL2. However, below code checks that we don't
+ * clear invalid entries or less than 64KB for a 64KB
+ * entry. Similar checking is done for L1 PTEs too
+ * below
+ */
+ while (remBytesL2 && (DSP_SUCCEEDED(status))) {
+ pteVal = *(u32 *)pteAddrL2;
+ pteSize = HW_MMU_PteSizeL2(pteVal);
+ /* vaCurr aligned to pteSize? */
+ if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
+ !(vaCurr & (pteSize - 1))) {
+ /* Collect Physical addresses from VA */
+ pAddr = (pteVal & ~(pteSize - 1));
+ if (pteSize == HW_PAGE_SIZE_64KB)
+ numof4KPages = 16;
+ else
+ numof4KPages = 1;
+ temp = 0;
+ while (temp++ < numof4KPages) {
+ pPhysAddrPageTbl[pacount++] =
+ pAddr;
+ pAddr += HW_PAGE_SIZE_4KB;
+ }
+ if (HW_MMU_PteClear(pteAddrL2,
+ vaCurr, pteSize) == RET_OK) {
+ status = DSP_SOK;
+ remBytesL2 -= pteSize;
+ vaCurr += pteSize;
+ pteAddrL2 += (pteSize >> 12) *
+ sizeof(u32);
+ } else {
+ status = DSP_EFAIL;
+ goto EXIT_LOOP;
+ }
+ } else {
+ status = DSP_EFAIL;
+ }
+ }
+ SYNC_EnterCS(pt->hCSObj);
+ if (remBytesL2 == 0) {
+ pt->pgInfo[L2PageNum].numEntries -= pteCount;
+ if (pt->pgInfo[L2PageNum].numEntries == 0) {
+ /*
+ * Clear the L1 PTE pointing to the
+ * L2 PT
+ */
+ if (RET_OK == HW_MMU_PteClear(L1BaseVa,
+ vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))
+ status = DSP_SOK;
+ else {
+ status = DSP_EFAIL;
+ SYNC_LeaveCS(pt->hCSObj);
+ goto EXIT_LOOP;
+ }
+ }
+ remBytes -= pteCount * PG_SIZE_4K;
+ } else {
+ status = DSP_EFAIL;
+ }
+ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
+ "numEntries %x, pteCount %x, status: 0x%x\n",
+ L2PageNum, pt->pgInfo[L2PageNum].numEntries,
+ pteCount, status);
+ SYNC_LeaveCS(pt->hCSObj);
+ } else
+ /* vaCurr aligned to pteSize? */
+ /* pteSize = 1 MB or 16 MB */
+ if ((pteSize != 0) && (remBytes >= pteSize) &&
+ !(vaCurr & (pteSize - 1))) {
+ if (pteSize == HW_PAGE_SIZE_1MB)
+ numof4KPages = 256;
+ else
+ numof4KPages = 4096;
+ temp = 0;
+ /* Collect Physical addresses from VA */
+ pAddr = (pteVal & ~(pteSize - 1));
+ while (temp++ < numof4KPages) {
+ pPhysAddrPageTbl[pacount++] = pAddr;
+ pAddr += HW_PAGE_SIZE_4KB;
+ }
+ if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)
+ == RET_OK) {
+ status = DSP_SOK;
+ remBytes -= pteSize;
+ vaCurr += pteSize;
+ } else {
+ status = DSP_EFAIL;
+ goto EXIT_LOOP;
+ }
+ } else {
+ status = DSP_EFAIL;
+ }
+ }
+ /*
+ * It is better to flush the TLB here, so that any stale old entries
+ * get flushed
+ */
+EXIT_LOOP:
+ flush_all(pDevContext);
+ for (temp = 0; temp < pacount; temp++) {
+ patemp = pPhysAddrPageTbl[temp];
+ if (pfn_valid(__phys_to_pfn(patemp))) {
+ pg = phys_to_page(patemp);
+ if (page_count(pg) < 1) {
+ pr_info("DSPBRIDGE:UNMAP function: COUNT 0"
+ "FOR PA 0x%x, size = 0x%x\n",
+ patemp, ulNumBytes);
+ bad_page_dump(patemp, pg);
+ }
+ SetPageDirty(pg);
+ page_cache_release(pg);
+ }
+ }
+ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
+ "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
+ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
+ "remBytesL2 %x\n", status, remBytes, remBytesL2);
+ return status;
+}
+
+/*
+ * ======== user_va2pa ========
+ * Purpose:
+ * This function walks through the Linux page tables to convert a userland
+ * virtual address to physical address
+ */
+static u32 user_va2pa(struct mm_struct *mm, u32 address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ pgd = pgd_offset(mm, address);
+ if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
+ pmd = pmd_offset(pgd, address);
+ if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
+ ptep = pte_offset_map(pmd, address);
+ if (ptep) {
+ pte = *ptep;
+ if (pte_present(pte))
+ return pte & PAGE_MASK;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * ======== PteUpdate ========
+ * This function calculates the optimum page-aligned addresses and sizes
+ * Caller must pass page-aligned values
+ */
+static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
+ u32 va, u32 size,
+ struct HW_MMUMapAttrs_t *mapAttrs)
+{
+ u32 i;
+ u32 allBits;
+ u32 paCurr = pa;
+ u32 vaCurr = va;
+ u32 numBytes = size;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ DSP_STATUS status = DSP_SOK;
+ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
+ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
+ DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
+ "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
+ while (numBytes && DSP_SUCCEEDED(status)) {
+ /* To find the max. page size with which both PA & VA are
+ * aligned */
+ allBits = paCurr | vaCurr;
+ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
+ "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
+ for (i = 0; i < 4; i++) {
+ if ((numBytes >= pgSize[i]) && ((allBits &
+ (pgSize[i] - 1)) == 0)) {
+ DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
+ status = PteSet(pDevContext->pPtAttrs, paCurr,
+ vaCurr, pgSize[i], mapAttrs);
+ paCurr += pgSize[i];
+ vaCurr += pgSize[i];
+ numBytes -= pgSize[i];
+ /* Don't try smaller sizes. Hopefully we have
+ * reached an address aligned to a bigger page
+ * size */
+ break;
+ }
+ }
+ }
+ DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
+ numBytes);
+ return status;
+}
+
+/*
+ * ======== PteSet ========
+ * This function calculates PTE address (MPU virtual) to be updated
+ * It also manages the L2 page tables
+ */
+static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
+ u32 size, struct HW_MMUMapAttrs_t *attrs)
+{
+ u32 i;
+ u32 pteVal;
+ u32 pteAddrL1;
+ u32 pteSize;
+ u32 pgTblVa; /* Base address of the PT that will be updated */
+ u32 L1BaseVa;
+ /* Compiler warns that the next three variables might be used
+ * uninitialized in this function. Doesn't seem so. Working around,
+ * anyways. */
+ u32 L2BaseVa = 0;
+ u32 L2BasePa = 0;
+ u32 L2PageNum = 0;
+ DSP_STATUS status = DSP_SOK;
+ DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
+ "size %x, attrs %x\n", pt, pa, va, size, attrs);
+ L1BaseVa = pt->L1BaseVa;
+ pgTblVa = L1BaseVa;
+ if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
+ /* Find whether the L1 PTE points to a valid L2 PT */
+ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
+ if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
+ pteVal = *(u32 *)pteAddrL1;
+ pteSize = HW_MMU_PteSizeL1(pteVal);
+ } else {
+ return DSP_EFAIL;
+ }
+ SYNC_EnterCS(pt->hCSObj);
+ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
+ /* Get the L2 PA from the L1 PTE, and find
+ * corresponding L2 VA */
+ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
+ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
+ L2PageNum = (L2BasePa - pt->L2BasePa) /
+ HW_MMU_COARSE_PAGE_SIZE;
+ } else if (pteSize == 0) {
+ /* L1 PTE is invalid. Allocate a L2 PT and
+ * point the L1 PTE to it */
+ /* Find a free L2 PT. */
+ for (i = 0; (i < pt->L2NumPages) &&
+ (pt->pgInfo[i].numEntries != 0); i++)
+ ;;
+ if (i < pt->L2NumPages) {
+ L2PageNum = i;
+ L2BasePa = pt->L2BasePa + (L2PageNum *
+ HW_MMU_COARSE_PAGE_SIZE);
+ L2BaseVa = pt->L2BaseVa + (L2PageNum *
+ HW_MMU_COARSE_PAGE_SIZE);
+ /* Endianness attributes are ignored for
+ * HW_MMU_COARSE_PAGE_SIZE */
+ status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
+ HW_MMU_COARSE_PAGE_SIZE, attrs);
+ } else {
+ status = DSP_EMEMORY;
+ }
+ } else {
+ /* Found valid L1 PTE of another size.
+ * Should not overwrite it. */
+ status = DSP_EFAIL;
+ }
+ if (DSP_SUCCEEDED(status)) {
+ pgTblVa = L2BaseVa;
+ if (size == HW_PAGE_SIZE_64KB)
+ pt->pgInfo[L2PageNum].numEntries += 16;
+ else
+ pt->pgInfo[L2PageNum].numEntries++;
+ DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
+ "PageNum %x numEntries %x\n", L2BaseVa,
+ L2BasePa, L2PageNum,
+ pt->pgInfo[L2PageNum].numEntries);
+ }
+ SYNC_LeaveCS(pt->hCSObj);
+ }
+ if (DSP_SUCCEEDED(status)) {
+ DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
+ pgTblVa, pa, va, size);
+ DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
+ "mixedSize %x\n", attrs->endianism,
+ attrs->elementSize, attrs->mixedSize);
+ status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
+ }
+ DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
+ return status;
+}
+
+/* Memory map kernel VA -- memory allocated with vmalloc */
+static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,
+ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
+ struct HW_MMUMapAttrs_t *hwAttrs)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct page *pPage[1];
+ u32 i;
+ u32 paCurr;
+ u32 paNext;
+ u32 vaCurr;
+ u32 sizeCurr;
+ u32 numPages;
+ u32 pa;
+ u32 numOf4KPages;
+ u32 temp = 0;
+
+ DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
+ "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);
+
+ /*
+ * Do Kernel va to pa translation.
+ * Combine physically contiguous regions to reduce TLBs.
+ * Pass the translated pa to PteUpdate.
+ */
+ numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
+ i = 0;
+ vaCurr = ulMpuAddr;
+ pPage[0] = vmalloc_to_page((void *)vaCurr);
+ paNext = page_to_phys(pPage[0]);
+ while (DSP_SUCCEEDED(status) && (i < numPages)) {
+ /*
+ * Reuse paNext from the previous iteraion to avoid
+ * an extra va2pa call
+ */
+ paCurr = paNext;
+ sizeCurr = PAGE_SIZE;
+ /*
+ * If the next page is physically contiguous,
+ * map it with the current one by increasing
+ * the size of the region to be mapped
+ */
+ while (++i < numPages) {
+ pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
+ paNext = page_to_phys(pPage[0]);
+ DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
+ "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
+ if (paNext == (paCurr + sizeCurr))
+ sizeCurr += PAGE_SIZE;
+ else
+ break;
+
+ }
+ if (paNext == 0) {
+ status = DSP_EMEMORY;
+ break;
+ }
+ pa = paCurr;
+ numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;
+ while (temp++ < numOf4KPages) {
+ get_page(phys_to_page(pa));
+ pa += HW_PAGE_SIZE_4KB;
+ }
+ status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
+ (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);
+ vaCurr += sizeCurr;
+ }
+ /* Don't propogate Linux or HW status to upper layers */
+ if (DSP_SUCCEEDED(status)) {
+ status = DSP_SOK;
+ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
+ status);
+ } else {
+ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
+ status = DSP_EFAIL;
+ }
+ /*
+ * In any case, flush the TLB
+ * This is called from here instead from PteUpdate to avoid unnecessary
+ * repetition while mapping non-contiguous physical regions of a virtual
+ * region
+ */
+ flush_all(pDevContext);
+ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);
+ return status;
+}
+#ifdef OMAP44XX
+void GetHWRegs(void __iomem *prm_base, u32 cm1_base, u32 cm2_base) { }
+
+#else
+static void GetHWRegs(void __iomem *prm_base, void __iomem *cm_base)
+{
+
+ u32 temp;
+ temp = __raw_readl((cm_base) + 0x00);
+ DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((cm_base) + 0x10);
+ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((cm_base) + 0x20);
+ DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((cm_base) + 0x48);
+ DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((cm_base) + 0x4c);
+ DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((prm_base) + 0x50);
+ DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((prm_base) + 0x58);
+ DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((prm_base) + 0xE0);
+ DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((prm_base) + 0xE4);
+ DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
+ temp = __raw_readl((cm_base) + 0xA10);
+ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
+}
+#endif
+
+/*
+ * ======== configureDspMmu ========
+ * Make DSP MMU page table entries.
+ */
+void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
+ u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
+ enum HW_Endianism_t endianism,
+ enum HW_ElementSize_t elemSize,
+ enum HW_MMUMixedSize_t mixedSize)
+{
+ struct CFG_HOSTRES resources;
+ struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
+ DSP_STATUS status = DSP_SOK;
+
+ DBC_Require(sizeInBytes > 0);
+ DBG_Trace(DBG_LEVEL1,
+ "configureDspMmu entry %x pa %x, va %x, bytes %x ",
+ nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
+
+ DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
+ endianism, elemSize, mixedSize);
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ status = HW_MMU_TLBAdd((const void __iomem *)pDevContext->dwDSPMmuBase,
+ dataBasePhys, dspBaseVirt, sizeInBytes,
+ nEntryStart, &mapAttrs, HW_SET, HW_SET);
+}
+
+/*
+ * ======== WaitForStart ========
+ * Wait for the singal from DSP that it has started, or time out.
+ */
+bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
+{
+ u16 usCount = TIHELEN_ACKTIMEOUT;
+
+ /* Wait for response from board */
+ while (*((volatile u16 *)dwSyncAddr) && --usCount)
+ udelay(10);
+
+ /* If timed out: return FALSE */
+ if (!usCount) {
+ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
new file mode 100644
index 000000000000..914474fb1659
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
@@ -0,0 +1,738 @@
+/*
+ * tiomap_pwr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007-2008 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.
+ */
+
+/*
+ * ======== _tiomap_pwr.c ========
+ * Description:
+ * Implementation of DSP wake/sleep routines.
+ *
+ *! Revision History
+ *! ================
+ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
+ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
+ *! code.
+ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
+ *! 06-Dec-2002 cring: Added Palm support.
+ *! 08-Oct-2002 rr: Created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/io_sm.h>
+#include <dspbridge/chnl_sm.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/util.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/brddefs.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/iodefs.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_dspssC64P.h>
+#include <hw_prcm.h>
+#include <hw_mmu.h>
+
+#include <dspbridge/pwr_sh.h>
+
+/* ----------------------------------- Mini Driver */
+#include <dspbridge/wmddeh.h>
+
+/* ----------------------------------- specific to this file */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "_tiomap_util.h"
+#include <mach-omap2/prm-regbits-34xx.h>
+#include <mach-omap2/cm-regbits-34xx.h>
+
+#ifdef CONFIG_PM
+#include <mach/board-3430sdp.h>
+#endif
+extern struct MAILBOX_CONTEXT mboxsetting;
+extern unsigned short enable_off_mode;
+
+/*
+ * ======== handle_constraints_set ========
+ * Sets new DSP constraint
+ */
+DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs)
+{
+#ifdef CONFIG_BRIDGE_DVFS
+ u32 *pConstraintVal;
+ DSP_STATUS status = DSP_SOK;
+ struct CFG_HOSTRES resources;
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+
+ pConstraintVal = (u32 *)(pArgs);
+ /* Read the target value requested by DSP */
+ DBG_Trace(DBG_LEVEL7, "handle_constraints_set:"
+ "opp requested = 0x%x\n", (u32)*(pConstraintVal+1));
+ status = HW_MBOX_saveSettings(resources.dwMboxBase);
+
+ /* Set the new opp value */
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp)((u32)*(pConstraintVal+1));
+ return DSP_SOK;
+#endif /* #ifdef CONFIG_BRIDGE_DVFS */
+ return DSP_SOK;
+}
+
+/*
+ * ======== handle_hibernation_fromDSP ========
+ * Handle Hibernation requested from DSP
+ */
+DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
+{
+ DSP_STATUS status = DSP_SOK;
+#ifdef CONFIG_PM
+ u16 usCount = TIHELEN_ACKTIMEOUT;
+ struct CFG_HOSTRES resources;
+ enum HW_PwrState_t pwrState;
+#ifdef CONFIG_BRIDGE_DVFS
+ u32 opplevel;
+ struct IO_MGR *hIOMgr;
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+#endif
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ return status;
+
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ /* Wait for DSP to move into Off state, how much time should
+ * we wait? */
+ while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
+ udelay(500);
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ }
+ if (usCount == 0) {
+ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
+ status = WMD_E_TIMEOUT;
+ return status;
+ } else {
+
+ /* Save mailbox settings */
+ status = HW_MBOX_saveSettings(resources.dwMboxBase);
+ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
+ mboxsetting.sysconfig);
+ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
+ mboxsetting.irqEnable0);
+ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
+ mboxsetting.irqEnable1);
+ /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
+ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Update the Bridger Driver state */
+ pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
+#ifdef CONFIG_BRIDGE_DVFS
+ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+ if (DSP_FAILED(status))
+ return status;
+ IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
+ /* Set the OPP to low level before moving to OFF mode */
+ if (opplevel != VDD1_OPP1) {
+ DBG_Trace(DBG_LEVEL5,
+ "Tiomap_pwr.c - DSP requested"
+ " OPP = %d, MPU requesting low"
+ " OPP %d instead\n", opplevel,
+ VDD1_OPP1);
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp)(VDD1_OPP1);
+ status = DSP_SOK;
+ }
+#endif /* CONFIG_BRIDGE_DVFS */
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "handle_hibernation_fromDSP- FAILED\n");
+ }
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== SleepDSP ========
+ * Put DSP in low power consuming state.
+ */
+DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
+ IN void *pArgs)
+{
+ DSP_STATUS status = DSP_SOK;
+#ifdef CONFIG_PM
+ struct CFG_HOSTRES resources;
+ struct DEH_MGR *hDehMgr;
+ u16 usCount = TIHELEN_ACKTIMEOUT;
+ enum HW_PwrState_t pwrState;
+ enum HW_PwrState_t targetPwrState;
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ return status;
+ DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
+
+ /* next, check if sleep code is valid... */
+ if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
+ DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
+ return DSP_EINVALIDARG;
+ }
+ switch (pDevContext->dwBrdState) {
+ case BRD_RUNNING:
+ status = HW_MBOX_saveSettings(resources.dwMboxBase);
+ if (enable_off_mode) {
+ CHNLSM_InterruptDSP2(pDevContext,
+ MBX_PM_DSPHIBERNATE);
+ DBG_Trace(DBG_LEVEL7,
+ "SleepDSP - Sent hibernate "
+ "command to DSP\n");
+ targetPwrState = HW_PWR_STATE_OFF;
+ } else {
+ CHNLSM_InterruptDSP2(pDevContext,
+ MBX_PM_DSPRETENTION);
+ targetPwrState = HW_PWR_STATE_RET;
+ }
+ break;
+ case BRD_RETENTION:
+ status = HW_MBOX_saveSettings(resources.dwMboxBase);
+ if (enable_off_mode) {
+ CHNLSM_InterruptDSP2(pDevContext,
+ MBX_PM_DSPHIBERNATE);
+ targetPwrState = HW_PWR_STATE_OFF;
+ } else
+ return DSP_SOK;
+ break;
+ case BRD_HIBERNATION:
+ case BRD_DSP_HIBERNATION:
+ status = HW_MBOX_saveSettings(resources.dwMboxBase);
+ /* Already in Hibernation, so just return */
+ DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
+ "hibernation\n");
+ return DSP_SOK;
+ case BRD_STOPPED:
+ DBG_Trace(DBG_LEVEL7,
+ "SleepDSP- Board in STOP state \n");
+ return DSP_SALREADYASLEEP;
+ default:
+ DBG_Trace(DBG_LEVEL7,
+ "SleepDSP- Bridge in Illegal state\n");
+ return DSP_EFAIL;
+ }
+ /* Get the PRCM DSP power domain status */
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ /* Wait for DSP to move into Standby state, how much time
+ * should we wait?*/
+ while ((pwrState != targetPwrState) && --usCount) {
+ udelay(500);
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ }
+ if (usCount == 0) {
+ DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
+ " STANDBY %x \n", pwrState);
+ DEV_GetDehMgr(pDevContext->hDevObject, &hDehMgr);
+ WMD_DEH_Notify(hDehMgr, DSP_PWRERROR, 0);
+ return WMD_E_TIMEOUT;
+ } else {
+ DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
+ pwrState);
+ /* Update the Bridger Driver state */
+ if (enable_off_mode)
+ pDevContext->dwBrdState = BRD_HIBERNATION;
+ else
+ pDevContext->dwBrdState = BRD_RETENTION;
+ /* Turn off DSP Peripheral clocks */
+ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
+ if (DSP_FAILED(status))
+ DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
+ }
+#endif
+ return status;
+}
+
+
+/*
+ * ======== WakeDSP ========
+ * Wake up DSP from sleep.
+ */
+DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+ DSP_STATUS status = DSP_SOK;
+#ifdef CONFIG_PM
+ struct CFG_HOSTRES resources;
+ enum HW_PwrState_t pwrState;
+ u32 temp;
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ return status;
+ /* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
+ if (pDevContext->dwBrdState == BRD_RUNNING ||
+ pDevContext->dwBrdState == BRD_STOPPED ||
+ pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
+ /* The Device is in 'RET' or 'OFF' state and WMD state is not
+ * 'SLEEP', this means state inconsistency, so return */
+ status = DSP_SOK;
+ return status;
+ }
+ /* Enable the DSP peripheral clocks and load monitor timer
+ * before waking the DSP */
+ DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
+ pDevContext->uDspPerClks);
+ status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
+
+ /* Enabling Dppll in lock mode */
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x34));
+ temp = (temp & 0xFFFFFFFE) | 0x1;
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
+ (u32) temp;
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x4));
+ temp = (temp & 0xFFFFFC8) | 0x37;
+
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
+ (u32) temp;
+
+ udelay(10);
+ if (DSP_SUCCEEDED(status)) {
+ /* Send a message to DSP to wake up */
+ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
+ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+ &pwrState);
+ DBG_Trace(DBG_LEVEL7,
+ "\nWakeDSP: Power State After sending Interrupt "
+ "to DSP %x\n", pwrState);
+ /* set the device state to RUNNIG */
+ pDevContext->dwBrdState = BRD_RUNNING;
+ } else {
+ DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== DSPPeripheralClkCtrl ========
+ * Enable/Disable the DSP peripheral clocks as needed..
+ */
+DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs)
+{
+ u32 extClk = 0;
+ u32 extClkId = 0;
+ u32 extClkCmd = 0;
+ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
+ u32 tmpIndex;
+ u32 dspPerClksBefore;
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_SOK;
+
+ DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
+ dspPerClksBefore = pDevContext->uDspPerClks;
+ DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
+ dspPerClksBefore);
+
+ extClk = (u32)*((u32 *)pArgs);
+
+ DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
+ extClk);
+
+ extClkId = extClk & MBX_PM_CLK_IDMASK;
+
+ /* process the power message -- TODO, keep it in a separate function */
+ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
+ if (extClkId == BPWR_CLKID[tmpIndex]) {
+ clkIdIndex = tmpIndex;
+ break;
+ }
+ }
+ /* TODO -- Assert may be a too hard restriction here.. May be we should
+ * just return with failure when the CLK ID does not match */
+ /* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
+ if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
+ DBG_Trace(DBG_LEVEL7,
+ "DSPPeripheralClkCtrl : Could n't get clock Id for"
+ "clkid 0x%x \n", clkIdIndex);
+ /* return with a more meaningfull error code */
+ return DSP_EFAIL;
+ }
+ extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
+ switch (extClkCmd) {
+ case BPWR_DisableClock:
+ /* Call BP to disable the needed clock */
+ DBG_Trace(DBG_LEVEL3,
+ "DSPPeripheralClkCtrl : Disable CLK for \n");
+ status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
+ status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
+ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, false);
+ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
+ (pDevContext->uDspPerClks) &=
+ (~((u32) (1 << clkIdIndex)));
+ } else {
+ DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
+ "to disable clk\n");
+ }
+ break;
+ case BPWR_EnableClock:
+ DBG_Trace(DBG_LEVEL3,
+ "DSPPeripheralClkCtrl : Enable CLK for \n");
+ status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
+ status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
+ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, true);
+ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
+ (pDevContext->uDspPerClks) |= (1 << clkIdIndex);
+ } else {
+ DBG_Trace(DBG_LEVEL7,
+ "DSPPeripheralClkCtrl:Failed to Enable clk\n");
+ }
+ break;
+ default:
+ DBG_Trace(DBG_LEVEL3,
+ "DSPPeripheralClkCtrl : Unsupported CMD \n");
+ /* unsupported cmd */
+ /* TODO -- provide support for AUTOIDLE Enable/Disable
+ * commands */
+ }
+ return status;
+}
+
+/*
+ * ========PreScale_DSP========
+ * Sends prescale notification to DSP
+ *
+ */
+DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+#ifdef CONFIG_BRIDGE_DVFS
+ u32 level;
+ u32 voltage_domain;
+
+ voltage_domain = *((u32 *)pArgs);
+ level = *((u32 *)pArgs + 1);
+
+ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
+ "0x%x\n", voltage_domain, level);
+ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
+ (pDevContext->dwBrdState == BRD_RETENTION) ||
+ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
+ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
+ "No notification to DSP\n");
+ return DSP_SOK;
+ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
+ /* Send a prenotificatio to DSP */
+ DBG_Trace(DBG_LEVEL7,
+ "PreScale_DSP: Sent notification to DSP\n");
+ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
+ return DSP_SOK;
+ } else {
+ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
+ " state in wrong state");
+ return DSP_EFAIL;
+ }
+#endif /* #ifdef CONFIG_BRIDGE_DVFS */
+ return DSP_SOK;
+}
+
+/*
+ * ========PostScale_DSP========
+ * Sends postscale notification to DSP
+ *
+ */
+DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+#ifdef CONFIG_BRIDGE_DVFS
+ u32 level;
+ u32 voltage_domain;
+ struct IO_MGR *hIOMgr;
+ DSP_STATUS status = DSP_SOK;
+
+ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+
+ voltage_domain = *((u32 *)pArgs);
+ level = *((u32 *)pArgs + 1);
+ DBG_Trace(DBG_LEVEL7,
+ "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
+ voltage_domain, level);
+ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
+ (pDevContext->dwBrdState == BRD_RETENTION) ||
+ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
+ /* Update the OPP value in shared memory */
+ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
+ DBG_Trace(DBG_LEVEL7,
+ "PostScale_DSP: IVA in sleep. Wrote to shared "
+ "memory \n");
+ return DSP_SOK;
+ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
+ /* Update the OPP value in shared memory */
+ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
+ /* Send a post notification to DSP */
+ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
+ DBG_Trace(DBG_LEVEL7,
+ "PostScale_DSP: Wrote to shared memory Sent post"
+ " notification to DSP\n");
+ return DSP_SOK;
+ } else {
+ DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
+ "in wrong state");
+ return DSP_EFAIL;
+ }
+#endif /* #ifdef CONFIG_BRIDGE_DVFS */
+ return DSP_SOK;
+}
+
+/*
+ * ========DSP_PeripheralClocks_Disable========
+ * Disables all the peripheral clocks that were requested by DSP
+ */
+DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs)
+{
+
+ u32 clkIdx;
+ DSP_STATUS status = DSP_SOK;
+
+ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
+ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
+ /* Disables the interface clock of the peripheral */
+ status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "Failed to Enable the DSP Peripheral"
+ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+ }
+ /* Disables the functional clock of the periphearl */
+ status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
+ if (DSP_FAILED(status)) {
+ DBG_Trace(DBG_LEVEL7,
+ "Failed to Enable the DSP Peripheral"
+ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+ }
+ }
+ }
+ return status;
+}
+
+/*
+ * ========DSP_PeripheralClocks_Enable========
+ * Enables all the peripheral clocks that were requested by DSP
+ */
+DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
+ IN void *pArgs)
+{
+ u32 clkIdx;
+ DSP_STATUS int_clk_status = DSP_EFAIL, fun_clk_status = DSP_EFAIL;
+
+ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
+ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
+ /* Enable the interface clock of the peripheral */
+ int_clk_status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
+ /* Enable the functional clock of the periphearl */
+ fun_clk_status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
+ }
+ }
+ if ((int_clk_status | fun_clk_status) != DSP_SOK)
+ return DSP_EFAIL;
+ return DSP_SOK;
+}
+
+void DSPClkWakeupEventCtrl(u32 ClkId, bool enable)
+{
+ struct CFG_HOSTRES resources;
+ DSP_STATUS status = DSP_SOK;
+ u32 iva2_grpsel;
+ u32 mpu_grpsel;
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+ if (DSP_FAILED(status))
+ return;
+
+ switch (ClkId) {
+ case BPWR_GPTimer5:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT5;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT5;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_GPTimer6:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT6;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT6;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_GPTimer7:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT7;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT7;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_GPTimer8:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT8;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT8;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_MCBSP1:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCorePmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCorePmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_MCBSP2:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_MCBSP3:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_MCBSP4:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwPerPmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ case BPWR_MCBSP5:
+ iva2_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCorePmBase) + 0xA8));
+ mpu_grpsel = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCorePmBase) + 0xA4));
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
+ }
+ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
+ = iva2_grpsel;
+ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
+ = mpu_grpsel;
+ break;
+ }
+}
diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
new file mode 100755
index 000000000000..97d08a3423f0
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_io.c
@@ -0,0 +1,434 @@
+/*
+ * tiomap_io.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _tiomap_io.c ========
+ * Description:
+ * Implementation for the io read/write routines.
+ *
+ *! Revision History
+ *! ================
+ *! 16-Feb-2004 vp: Fixed warning in WriteDspData function.
+ *! 16-Apr-2003 vp: Added support for TC word swap
+ *! 26-Feb-2003 vp: Fixed issue with EXT_BEG and EXT_END address.
+ *! 24-Feb-2003 vp: Ported to Linux platform
+ *! 08-Oct-2002 rr: Created.
+ */
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/drv.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/util.h>
+#include <dspbridge/cfg.h>
+
+/* ----------------------------------- specific to this file */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "tiomap_io.h"
+
+static u32 ulExtBase;
+static u32 ulExtEnd;
+
+static u32 ulShm0End;
+static u32 ulDynExtBase;
+static u32 ulTraceSecBeg;
+static u32 ulTraceSecEnd;
+static u32 ulShmBaseVirt;
+static u32 ulshmBeg;
+
+bool bSymbolsReloaded = true;
+
+/*
+ * ======== ReadExtDspData ========
+ * Copies DSP external memory buffers to the host side buffers.
+ */
+DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
+ OUT u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+ u32 offset;
+ u32 ulTLBBaseVirt = 0;
+ u32 ulShmOffsetVirt = 0;
+ u32 dwExtProgVirtMem;
+ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
+ bool bTraceRead = false;
+
+ DBG_Trace(DBG_ENTER, "ReadExtDspData,"
+ "hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
+ "\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
+ "ulMemType: 0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
+ ulNumBytes, ulMemType);
+
+ if (!ulShmBaseVirt) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ SHMBASENAME, &ulShmBaseVirt);
+ }
+ DBC_Assert(ulShmBaseVirt != 0);
+
+ /* Check if it is a read of Trace section */
+ if (!ulTraceSecBeg) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ DSP_TRACESEC_BEG, &ulTraceSecBeg);
+ }
+ DBC_Assert(ulTraceSecBeg != 0);
+
+ if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ DSP_TRACESEC_END, &ulTraceSecEnd);
+ }
+ DBC_Assert(ulTraceSecEnd != 0);
+
+ if (DSP_SUCCEEDED(status)) {
+ if ((dwDSPAddr <= ulTraceSecEnd) &&
+ (dwDSPAddr >= ulTraceSecBeg)) {
+ DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
+ "section 0x%x \n", dwDSPAddr);
+ bTraceRead = true;
+ }
+ }
+
+ /* If reading from TRACE, force remap/unmap */
+ if ((bTraceRead) && dwBaseAddr) {
+ dwBaseAddr = 0;
+ pDevContext->dwDspExtBaseAddr = 0;
+ }
+
+ if (!dwBaseAddr) {
+ /* Initialize ulExtBase and ulExtEnd */
+ ulExtBase = 0;
+ ulExtEnd = 0;
+
+ /* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
+ if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ DYNEXTBASE, &ulDynExtBase);
+ }
+ DBC_Assert(ulDynExtBase != 0);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ EXTBASE, &ulExtBase);
+ }
+ DBC_Assert(ulExtBase != 0);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = DEV_GetSymbol(pDevContext->hDevObject,
+ EXTEND, &ulExtEnd);
+ }
+ DBC_Assert(ulExtEnd != 0);
+
+ /* Trace buffer is right after the SHM SEG0,
+ * so set the base address to SHMBASE */
+ if (bTraceRead) {
+ ulExtBase = ulShmBaseVirt;
+ ulExtEnd = ulTraceSecEnd;
+ }
+
+ DBC_Assert(ulExtEnd != 0);
+ DBC_Assert(ulExtEnd > ulExtBase);
+
+ if (ulExtEnd < ulExtBase)
+ status = DSP_EFAIL;
+
+ if (DSP_SUCCEEDED(status)) {
+ ulTLBBaseVirt =
+ pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
+ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+ dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
+
+ if (bTraceRead) {
+ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+ "GPP VA pointing to SHMMEMBASE 0x%x \n",
+ dwExtProgVirtMem);
+ } else {
+ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
+ ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
+ ulDynExtBase + 1,
+ HW_PAGE_SIZE_64KB);
+ dwExtProgVirtMem -= ulShmOffsetVirt;
+ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
+ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+ "GPP VA pointing to EXTMEMBASE 0x%x \n",
+ dwExtProgVirtMem);
+ pDevContext->dwDspExtBaseAddr =
+ dwExtProgVirtMem;
+
+ /* This dwDspExtBaseAddr will get cleared only when the board is
+ * stopped. */
+ if (!pDevContext->dwDspExtBaseAddr) {
+ status = DSP_EFAIL;
+ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+ "failed to Map the program memory\n");
+ }
+ }
+
+ dwBaseAddr = dwExtProgVirtMem;
+ }
+ }
+
+ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
+ DBG_Trace(DBG_LEVEL7,
+ "Symbols missing for Ext Prog reading \n");
+ status = DSP_EFAIL;
+ }
+
+ offset = dwDSPAddr - ulExtBase;
+
+ if (DSP_SUCCEEDED(status))
+ memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
+
+ return status;
+}
+/*
+ * ======== WriteDspData ========
+ * purpose:
+ * Copies buffers to the DSP internal/external memory.
+ */
+DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
+ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
+{
+ u32 offset;
+ u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
+ struct CFG_HOSTRES resources;
+ DSP_STATUS status;
+ u32 base1, base2, base3;
+ base1 = OMAP_DSP_MEM1_SIZE;
+ base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
+ base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
+ DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+
+ offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
+ if (offset < base1) {
+ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
+ resources.dwMemLength[2]);
+ } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
+ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
+ resources.dwMemLength[3]);
+ offset = offset - base2;
+ } else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
+ offset < base3 + OMAP_DSP_MEM3_SIZE) {
+ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
+ resources.dwMemLength[4]);
+ offset = offset - base3;
+ } else{
+ status = DSP_EFAIL;
+ return status;
+ }
+ if (ulNumBytes)
+ memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
+ else
+ *((u32 *) pbHostBuf) = dwBaseAddr+offset;
+
+ return status;
+}
+
+/*
+ * ======== WriteExtDspData ========
+ * purpose:
+ * Copies buffers to the external memory.
+ *
+ */
+DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
+ u32 ulMemType, bool bDynamicLoad)
+{
+ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
+ u32 dwOffset = 0;
+ u8 bTempByte1, bTempByte2;
+ u8 remainByte[4];
+ s32 i;
+ DSP_STATUS retVal = DSP_SOK;
+ u32 dwExtProgVirtMem;
+ u32 ulTLBBaseVirt = 0;
+ u32 ulShmOffsetVirt = 0;
+ struct CFG_HOSTRES hostRes;
+ bool bTraceLoad = false;
+ bTempByte1 = 0x0;
+ bTempByte2 = 0x0;
+
+ DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
+ "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
+ if (bSymbolsReloaded) {
+ /* Check if it is a load to Trace section */
+#ifndef DSP_TRACEBUF_DISABLED
+ retVal = DEV_GetSymbol(pDevContext->hDevObject,
+ DSP_TRACESEC_BEG, &ulTraceSecBeg);
+#endif
+ if (DSP_SUCCEEDED(retVal))
+#ifndef DSP_TRACEBUF_DISABLED
+ retVal = DEV_GetSymbol(pDevContext->hDevObject,
+ DSP_TRACESEC_END, &ulTraceSecEnd);
+#endif
+ retVal = DEV_GetSymbol(pDevContext->hDevObject,
+ SHMBASENAME, &ulshmBeg);
+ }
+ if (DSP_SUCCEEDED(retVal)) {
+ if ((dwDSPAddr <= ulTraceSecEnd) &&
+ (dwDSPAddr >= ulshmBeg)) {
+ DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
+ "section 0x%x \n", dwDSPAddr);
+ bTraceLoad = true;
+ }
+ }
+
+ /* If dynamic, force remap/unmap */
+ if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
+ dwBaseAddr = 0;
+ MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
+ pDevContext->dwDspExtBaseAddr = 0x0;
+ }
+ if (!dwBaseAddr) {
+ if (bSymbolsReloaded)
+ /* Get SHM_BEG EXT_BEG and EXT_END. */
+ retVal = DEV_GetSymbol(pDevContext->hDevObject,
+ SHMBASENAME, &ulShmBaseVirt);
+ DBC_Assert(ulShmBaseVirt != 0);
+ if (bDynamicLoad) {
+ if (DSP_SUCCEEDED(retVal)) {
+ if (bSymbolsReloaded)
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, DYNEXTBASE,
+ &ulExtBase);
+ }
+ DBC_Assert(ulExtBase != 0);
+ if (DSP_SUCCEEDED(retVal)) {
+ /* DR OMAPS00013235 : DLModules array may be
+ * in EXTMEM. It is expected that DYNEXTMEM and
+ * EXTMEM are contiguous, so checking for the
+ * upper bound at EXTEND should be Ok. */
+ if (bSymbolsReloaded)
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, EXTEND, &ulExtEnd);
+ }
+ } else {
+ if (bSymbolsReloaded) {
+ if (DSP_SUCCEEDED(retVal))
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, EXTBASE,
+ &ulExtBase);
+ DBC_Assert(ulExtBase != 0);
+ if (DSP_SUCCEEDED(retVal))
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, EXTEND, &ulExtEnd);
+ }
+ }
+ /* Trace buffer it right after the SHM SEG0, so set the
+ * base address to SHMBASE */
+ if (bTraceLoad)
+ ulExtBase = ulShmBaseVirt;
+
+ DBC_Assert(ulExtEnd != 0);
+ DBC_Assert(ulExtEnd > ulExtBase);
+ if (ulExtEnd < ulExtBase)
+ retVal = DSP_EFAIL;
+
+ if (DSP_SUCCEEDED(retVal)) {
+ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
+ DSPWORDSIZE;
+ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+
+ if (bSymbolsReloaded) {
+ if (DSP_SUCCEEDED(retVal)) {
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, DSP_TRACESEC_END,
+ &ulShm0End);
+ }
+ if (DSP_SUCCEEDED(retVal)) {
+ retVal = DEV_GetSymbol(pDevContext->
+ hDevObject, DYNEXTBASE,
+ &ulDynExtBase);
+ }
+ }
+ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
+ if (bTraceLoad) {
+ dwExtProgVirtMem = pDevContext->aTLBEntry[0].
+ ulGppVa;
+ } else {
+ CFG_GetHostResources(
+ (struct CFG_DEVNODE *)
+ DRV_GetFirstDevExtension(), &hostRes);
+ dwExtProgVirtMem = hostRes.dwMemBase[1];
+ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
+ }
+ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
+ "pointing to EXTMEMBASE 0x%x \n",
+ dwExtProgVirtMem);
+
+ pDevContext->dwDspExtBaseAddr =
+ (u32)MEM_LinearAddress((void *)
+ TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
+ - ulExtBase);
+ dwBaseAddr += pDevContext->dwDspExtBaseAddr;
+ /* This dwDspExtBaseAddr will get cleared only when
+ * the board is stopped. */
+ if (!pDevContext->dwDspExtBaseAddr) {
+ retVal = DSP_EFAIL;
+ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
+ "to Map the program memory\n");
+ }
+ }
+ }
+ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
+ DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
+ retVal = DSP_EFAIL;
+ }
+ if (DSP_SUCCEEDED(retVal)) {
+ for (i = 0; i < 4; i++)
+ remainByte[i] = 0x0;
+
+ dwOffset = dwDSPAddr - ulExtBase;
+ /* Also make sure the dwDSPAddr is < ulExtEnd */
+ if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
+ DBG_Trace(DBG_LEVEL7, "We can not load at this address "
+ "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
+ "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
+ ulExtEnd);
+ retVal = DSP_EFAIL;
+ }
+ }
+ if (DSP_SUCCEEDED(retVal)) {
+ if (ulNumBytes)
+ memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
+ ulNumBytes);
+ else
+ *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
+ }
+ /* Unmap here to force remap for other Ext loads */
+ if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
+ MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
+ pDevContext->dwDspExtBaseAddr = 0x0;
+ }
+ bSymbolsReloaded = false;
+ return retVal;
+}
+
diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
new file mode 100644
index 000000000000..84a75533969b
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_io.h
@@ -0,0 +1,112 @@
+/*
+ * tiomap_io.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== _tiomap_io.h ========
+ * Description:
+ * Definitions, types and function prototypes for the io
+ * (r/w external mem).
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr: Created.
+ */
+
+#ifndef _TIOMAP_IO_
+#define _TIOMAP_IO_
+
+/*
+ * Symbol that defines beginning of shared memory.
+ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
+ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
+ * (see dspMmuTlbEntry()).
+ */
+#define SHMBASENAME "SHM_BEG"
+#define EXTBASE "EXT_BEG"
+#define EXTEND "_EXT_END"
+#define DYNEXTBASE "_DYNEXT_BEG"
+#define DYNEXTEND "_DYNEXT_END"
+#define IVAEXTMEMBASE "_IVAEXTMEM_BEG"
+#define IVAEXTMEMEND "_IVAEXTMEM_END"
+
+
+#define DSP_TRACESEC_BEG "_BRIDGE_TRACE_BEG"
+#define DSP_TRACESEC_END "_BRIDGE_TRACE_END"
+
+#define SYS_PUTCBEG "_SYS_PUTCBEG"
+#define SYS_PUTCEND "_SYS_PUTCEND"
+#define BRIDGE_SYS_PUTC_current "_BRIDGE_SYS_PUTC_current"
+
+
+#define WORDSWAP_ENABLE 0x3 /* Enable word swap */
+
+/*
+ * ======== ReadExtDspData ========
+ * Reads it from DSP External memory. The external memory for the DSP
+ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
+ */
+extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+ OUT u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType);
+
+/*
+ * ======== WriteDspData ========
+ */
+extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
+ OUT u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType);
+
+/*
+ * ======== WriteExtDspData ========
+ * Writes to the DSP External memory for external program.
+ * The ext mem for progra is configured by the combination of DSP MMU and
+ * SHM Memory manager in the CDB
+ */
+extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+ IN u8 *pbHostBuf, u32 dwDSPAddr,
+ u32 ulNumBytes, u32 ulMemType,
+ bool bDynamicLoad);
+
+/*
+ * ======== WriteExt32BitDspData ========
+ * Writes 32 bit data to the external memory
+ */
+extern inline void WriteExt32BitDspData(IN const
+ struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
+ IN u32 val)
+{
+ *(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
+ 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
+}
+
+/*
+ * ======== ReadExt32BitDspData ========
+ * Reads 32 bit data from the external memory
+ */
+extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
+ *pDevContext, IN u32 dwDSPAddr)
+{
+ u32 retVal;
+ retVal = *(u32 *)dwDSPAddr;
+
+ retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
+ & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
+ return retVal;
+}
+
+#endif /* _TIOMAP_IO_ */
+
diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
new file mode 100644
index 000000000000..573d54b476e9
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
@@ -0,0 +1,257 @@
+/*
+ * tiomap_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+#include <dspbridge/cfg.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/dev.h>
+
+#include <dspbridge/dbg.h>
+
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include <hw_defs.h>
+#include <hw_mbox.h>
+
+
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#ifndef CONFIG_OMAP3_PM
+#include <mach/omap-pm.h>
+#else
+#include <mach/resource.h>
+extern struct constraint_handle *dsp_constraint_handle;
+#endif
+#endif
+#endif
+/*------------------------------------- Noitfy */
+#include <syslink/notify.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/notify_tesladriver.h>
+extern struct notify_driver_object *handle;
+
+/* ----------------------------------- Defines, Data Structures, Typedefs */
+#ifndef DEBUG
+#define TIHELEN_INT_TIMEOUT 1
+#define LOOP_COUNT 1000000
+#endif
+
+#ifdef OMAP44XX
+#define PROCESSOR_TESLA 0
+#define KEY 0
+#endif
+
+
+extern struct MAILBOX_CONTEXT mboxsetting;
+
+extern DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT
+ *pDevContext, IN void *pArgs);
+
+
+
+#define MAILBOX_FIFOSTATUS(m) (0x80 + 4 * (m))
+
+static inline unsigned int fifo_full(void __iomem *mbox_base, int mbox_id)
+{
+ return __raw_readl(mbox_base + MAILBOX_FIFOSTATUS(mbox_id)) & 0x1;
+}
+
+DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
+{
+ DSP_STATUS status = DSP_SOK;
+#ifdef OMAP_3430
+ u32 numMbxMsg;
+ u32 mbxValue;
+ u32 hwStatus;
+#endif
+ struct CFG_HOSTRES resources;
+ u32 devType;
+ struct IO_MGR *hIOMgr;
+ u32 eventNo;
+
+ DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
+
+ /* Read the messages in the mailbox until the message queue is empty */
+
+ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ DEV_GetDevType(pDevContext->hDevObject, &devType);
+ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+
+#ifdef OMAP44XX
+ eventNo = ((NOTIFY_SYSTEM_KEY<<16)|NOTIFY_TESLA_EVENTNUMBER);
+
+ notify_enable_event(handle, 0, eventNo);
+
+ if (devType == DSP_UNIT) {
+ notify_restore(KEY, PROCESSOR_TESLA);
+ }
+
+#else
+ if (devType == DSP_UNIT) {
+ hwStatus = HW_MBOX_EventDisable(resources.dwMboxBase,
+ MBOX_DSP2ARM,
+ MBOX_ARM,
+ HW_MBOX_INT_NEW_MSG);
+ }
+#endif
+ return status;
+}
+
+
+DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
+{
+ u32 eventNo;
+ struct CFG_HOSTRES resources;
+
+ DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext);
+
+ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+#ifdef OMAP44XX
+
+ eventNo = ((NOTIFY_SYSTEM_KEY<<16)|NOTIFY_TESLA_EVENTNUMBER);
+ notify_disable_event(handle, 0, eventNo);
+ notify_disable(PROCESSOR_TESLA);
+#else
+
+ HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
+ MBOX_ARM, HW_MBOX_INT_NEW_MSG);
+#endif
+ return DSP_SOK;
+}
+
+DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext,
+ u16 wMbVal)
+{
+ struct CFG_HOSTRES resources;
+ DSP_STATUS status = DSP_SOK;
+ int notifyStatus;
+
+#ifdef OMAP_3430
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifdef CONFIG_BRIDGE_DVFS
+ struct dspbridge_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+ u32 opplevel = 0;
+#endif
+#endif
+ unsigned long timeout;
+ u32 temp;
+#endif
+
+ status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ if (DSP_FAILED(status))
+ return DSP_EFAIL;
+#ifdef OMAP_3430
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifdef CONFIG_BRIDGE_DVFS
+ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
+ pDevContext->dwBrdState == BRD_HIBERNATION) {
+ if (pdata->dsp_get_opp)
+ opplevel = (*pdata->dsp_get_opp)();
+ if (opplevel == 1) {
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp)(opplevel+1);
+ }
+ }
+#endif
+#endif
+
+ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
+ pDevContext->dwBrdState == BRD_HIBERNATION) {
+ /* Restore mailbox settings */
+ /* Restart the peripheral clocks that were disabled only
+ * in DSP initiated Hibernation case.*/
+ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
+ DSP_PeripheralClocks_Enable(pDevContext, NULL);
+ /* Enabling Dpll in lock mode*/
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x34));
+ temp = (temp & 0xFFFFFFFE) | 0x1;
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
+ (u32) temp;
+ temp = (u32) *((REG_UWORD32 *)
+ ((u32) (resources.dwCmBase) + 0x4));
+ temp = (temp & 0xFFFFFC8) | 0x37;
+
+ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
+ (u32) temp;
+ }
+ HW_MBOX_restoreSettings(resources.dwMboxBase);
+
+ /* Access MMU SYS CONFIG register to generate a short wakeup */
+ temp = (u32) *((REG_UWORD32 *) ((u32)
+ (resources.dwDmmuBase) + 0x10));
+
+ pDevContext->dwBrdState = BRD_RUNNING;
+ }
+ timeout = jiffies + msecs_to_jiffies(1);
+ while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n");
+ return WMD_E_TIMEOUT;
+ }
+ }
+#else
+ DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
+ wMbVal);
+
+
+ notifyStatus = notify_sendevent(handle,/*PROC_TESLA*/0,
+ ((NOTIFY_SYSTEM_KEY<<16)|NOTIFY_TESLA_EVENTNUMBER),
+ pDevContext->wIntrVal2Dsp, true);
+#endif
+
+ return DSP_SOK;
+}
+
+bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC,
+ u16 *pwIntrVal)
+{
+
+ bool fMyInterrupt = true;
+#ifdef OMAP_3430
+ struct CFG_HOSTRES resources;
+ u32 numMbxMsg;
+ u32 mbxValue;
+
+ CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+
+ HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
+
+ if (numMbxMsg > 0) {
+ HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
+
+ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
+ HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
+
+ DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
+ *pwIntrVal = (u16) mbxValue;
+ }
+ /* Set *pfSchedDPC to true; */
+ *pfSchedDPC = true;
+#endif
+ return fMyInterrupt;
+
+
+
+}
diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
new file mode 100644
index 000000000000..1034641c380d
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/ue_deh.c
@@ -0,0 +1,385 @@
+/*
+ * ue_deh.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== ue_deh.c ========
+ * Description:
+ * Implements upper edge DSP exception handling (DEH) functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 03-Jan-2005 hn: Support for IVA DEH.
+ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
+ *! 19-Feb-2003 vp: Code review updates.
+ *! - Cosmetic changes.
+ *! 18-Oct-2002 sb: Ported to Linux platform.
+ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
+ *! 10-Sep-2001 kc: created.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/csl.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/dpc.h>
+#include <dspbridge/mem.h>
+#include <dspbridge/ntfy.h>
+#include <dspbridge/drv.h>
+
+/* ----------------------------------- Link Driver */
+#include <dspbridge/wmddeh.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/wcd.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/*--------------------------------------Notify*/
+#include <syslink/notify.h>
+#include <syslink/notify_driverdefs.h>
+
+
+/* ----------------------------------- This */
+#include "mmu_fault.h"
+#include "_tiomap.h"
+#include "_deh.h"
+#include "_tiomap_mmu.h"
+#include "_tiomap_pwr.h"
+#include <dspbridge/io_sm.h>
+
+static struct HW_MMUMapAttrs_t mapAttrs = { HW_LITTLE_ENDIAN,
+ HW_ELEM_SIZE_16BIT,
+ HW_MMU_CPUES} ;
+#define VirtToPhys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+
+static u32 dummyVaAddr;
+/*
+ * ======== WMD_DEH_Create ========
+ * Creates DEH manager object.
+ */
+DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
+ struct DEV_OBJECT *hDevObject)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEH_MGR *pDehMgr = NULL;
+ struct CFG_HOSTRES cfgHostRes;
+ struct CFG_DEVNODE *hDevNode;
+ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
+
+ DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
+ /* Message manager will be created when a file is loaded, since
+ * size of message buffer in shared memory is configurable in
+ * the base image. */
+ /* Get WMD context info. */
+ DEV_GetWMDContext(hDevObject, &hWmdContext);
+ DBC_Assert(hWmdContext);
+ dummyVaAddr = 0;
+ /* Allocate IO manager object: */
+ MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
+ if (pDehMgr == NULL) {
+ status = DSP_EMEMORY;
+ } else {
+ /* Create an NTFY object to manage notifications */
+ if (DSP_SUCCEEDED(status))
+ status = NTFY_Create(&pDehMgr->hNtfy);
+
+ /* Create a DPC object. */
+ status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
+ (void *)pDehMgr);
+ if (DSP_SUCCEEDED(status))
+ status = DEV_GetDevNode(hDevObject, &hDevNode);
+
+ if (DSP_SUCCEEDED(status))
+ status = CFG_GetHostResources(hDevNode, &cfgHostRes);
+
+ if (DSP_SUCCEEDED(status)) {
+ /* Fill in context structure */
+ pDehMgr->hWmdContext = hWmdContext;
+ pDehMgr->errInfo.dwErrMask = 0L;
+ pDehMgr->errInfo.dwVal1 = 0L;
+ pDehMgr->errInfo.dwVal2 = 0L;
+ pDehMgr->errInfo.dwVal3 = 0L;
+ /* Install ISR function for DSP MMU fault */
+ if ((request_irq(INT_DSP_MMU_IRQ, MMU_FaultIsr, 0,
+ "DspBridge\tiommu fault", (void *)pDehMgr)) == 0)
+ status = DSP_SOK;
+ else
+ status = DSP_EFAIL;
+ }
+ }
+ if (DSP_FAILED(status)) {
+ /* If create failed, cleanup */
+ WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
+ *phDehMgr = NULL;
+ } else {
+ *phDehMgr = (struct DEH_MGR *)pDehMgr;
+ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
+ pDehMgr);
+ }
+ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
+ return status;
+}
+
+/*
+ * ======== WMD_DEH_Destroy ========
+ * Destroys DEH manager object.
+ */
+DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+ DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
+ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+ /* Release dummy VA buffer */
+ WMD_DEH_ReleaseDummyMem();
+ /* If notification object exists, delete it */
+ if (pDehMgr->hNtfy)
+ (void)NTFY_Delete(pDehMgr->hNtfy);
+ /* Disable DSP MMU fault */
+ free_irq(INT_DSP_MMU_IRQ, pDehMgr);
+ (void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
+ /* Deallocate the DEH manager object */
+ MEM_FreeObject(pDehMgr);
+ }
+ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
+ return status;
+}
+
+/*
+ * ======== WMD_DEH_RegisterNotify ========
+ * Registers for DEH notifications.
+ */
+DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
+ u32 uNotifyType,
+ struct DSP_NOTIFICATION *hNotification)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
+ pDehMgr);
+
+ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+ status = NTFY_Register(pDehMgr->hNtfy, hNotification,
+ uEventMask, uNotifyType);
+ }
+ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
+ return status;
+}
+
+
+/*
+ * ======== WMD_DEH_Notify ========
+ * DEH error notification function. Informs user about the error.
+ */
+void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
+ u32 dwErrInfo)
+{
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+ struct WMD_DEV_CONTEXT *pDevContext;
+ DSP_STATUS status = DSP_SOK;
+ DSP_STATUS status1 = DSP_EFAIL;
+ u32 memPhysical = 0;
+ u32 HW_MMU_MAX_TLB_COUNT = 31;
+ u32 extern faultAddr;
+ struct CFG_HOSTRES resources;
+ HW_STATUS hwStatus;
+ u32 NotifyStatus;
+
+ status = CFG_GetHostResources(
+ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+ &resources);
+ if (DSP_FAILED(status))
+ DBG_Trace(DBG_LEVEL7,
+ "**Failed to get Host Resources in MMU ISR **\n");
+
+ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
+ ulEventMask);
+ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+ printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
+ "**********\n");
+ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
+
+ switch (ulEventMask) {
+ case DSP_SYSERROR:
+ /* reset errInfo structure before use */
+ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
+ pDehMgr->errInfo.dwVal1 = 0L;
+ pDehMgr->errInfo.dwVal2 = 0L;
+ pDehMgr->errInfo.dwVal3 = 0L;
+ pDehMgr->errInfo.dwVal1 = dwErrInfo;
+ printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
+ "= 0x%x\n", dwErrInfo);
+ break;
+ case DSP_MMUFAULT:
+ /* MMU fault routine should have set err info
+ * structure */
+ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
+ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
+ "errInfo = 0x%x\n", dwErrInfo);
+ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
+ "Address = 0x%x\n",
+ (unsigned int)pDehMgr->errInfo.dwVal1);
+ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
+ "Address = 0x%x\n",
+ (unsigned int)pDehMgr->errInfo.dwVal2);
+ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
+ "address = 0x%x\n", (unsigned int)faultAddr);
+ dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
+ MEM_PAGED);
+ memPhysical = VirtToPhys(PG_ALIGN_LOW((u32)dummyVaAddr,
+ PG_SIZE_4K));
+DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
+ "mem Physical= 0x%x\n", memPhysical);
+ pDevContext = (struct WMD_DEV_CONTEXT *)
+ pDehMgr->hWmdContext;
+ /* Reset the dynamic mmu index to fixed count if it
+ * exceeds 31. So that the dynmmuindex is always
+ * between the range of standard/fixed entries
+ * and 31. */
+ if (pDevContext->numTLBEntries >
+ HW_MMU_MAX_TLB_COUNT) {
+ pDevContext->numTLBEntries = pDevContext->
+ fixedTLBEntries;
+ }
+ DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
+ "PA: 0x%x\n", pDevContext->
+ numTLBEntries, faultAddr, memPhysical);
+ if (DSP_SUCCEEDED(status)) {
+ hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
+ memPhysical, faultAddr,
+ HW_PAGE_SIZE_4KB, 1, &mapAttrs,
+ HW_SET, HW_SET);
+ }
+ /* send an interrupt to DSP */
+#ifdef OMAP_3430
+ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
+ MBX_DEH_CLASS | MBX_DEH_EMMU);
+
+#else
+ NotifyStatus = notify_sendevent(handle,/*PROC_TESLA*/0,
+ /*eventNo*/4,MBX_DEH_CLASS | MBX_DEH_EMMU,true);
+#endif
+
+
+ /* Clear MMU interrupt */
+ HW_MMU_EventAck(resources.dwDmmuBase,
+ HW_MMU_TRANSLATION_FAULT);
+ break;
+ case DSP_PWRERROR:
+ /* reset errInfo structure before use */
+ pDehMgr->errInfo.dwErrMask = DSP_PWRERROR;
+ pDehMgr->errInfo.dwVal1 = 0L;
+ pDehMgr->errInfo.dwVal2 = 0L;
+ pDehMgr->errInfo.dwVal3 = 0L;
+ pDehMgr->errInfo.dwVal1 = dwErrInfo;
+ printk(KERN_ERR "WMD_DEH_Notify: DSP_PWRERROR, errInfo "
+ "= 0x%x\n", dwErrInfo);
+ break;
+ default:
+ DBG_Trace(DBG_LEVEL6,
+ "WMD_DEH_Notify: Unknown Error, errInfo = "
+ "0x%x\n", dwErrInfo);
+ break;
+ }
+
+ /* Filter subsequent notifications when an error occurs */
+ if (pDevContext->dwBrdState != BRD_ERROR) {
+ /* Use it as a flag to send notifications the
+ * first time and error occurred, next time
+ * state will be BRD_ERROR */
+ status1 = DSP_EFAIL;
+ }
+
+ /* Filter subsequent notifications when an error occurs */
+ if (pDevContext->dwBrdState != BRD_ERROR)
+ status1 = DSP_SOK;
+
+ /* Set the Board state as ERROR */
+ pDevContext->dwBrdState = BRD_ERROR;
+ /* Disable all the clocks that were enabled by DSP */
+ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
+ /* Call DSP Trace Buffer */
+ PrintDspTraceBuffer(hDehMgr->hWmdContext);
+
+ if (DSP_SUCCEEDED(status1)) {
+ /* Signal DSP error/exception event. */
+ NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
+ }
+
+ }
+ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
+
+}
+
+/*
+ * ======== WMD_DEH_GetInfo ========
+ * Retrieves error information.
+ */
+DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
+ struct DSP_ERRORINFO *pErrInfo)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+ DBC_Require(pDehMgr);
+ DBC_Require(pErrInfo);
+
+ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
+
+ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+ /* Copy DEH error info structure to PROC error info
+ * structure. */
+ pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
+ pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
+ pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
+ pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
+ }
+
+ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
+
+ return status;
+}
+
+
+/*
+ * ======== WMD_DEH_ReleaseDummyMem ========
+ * Releases memory allocated for dummy page
+ */
+void WMD_DEH_ReleaseDummyMem(void)
+{
+ if (dummyVaAddr) {
+ MEM_Free((void *)dummyVaAddr);
+ dummyVaAddr = 0;
+ }
+}
+
diff --git a/drivers/dsp/syslink/Kconfig b/drivers/dsp/syslink/Kconfig
new file mode 100755
index 000000000000..7ff387959600
--- /dev/null
+++ b/drivers/dsp/syslink/Kconfig
@@ -0,0 +1,60 @@
+
+
+menuconfig Sys_Link
+ bool "Sys_Link"
+ default y
+
+if Sys_Link
+
+config SYSLINK_PROC
+ tristate "Syslink ProcMgr"
+ default m
+ help
+ Syslink Proc manager
+
+config SYSLINK_PROC4430
+ tristate "Proc 4430"
+ depends on SYSLINK_PROC && OMAP_IOMMU
+ default m
+ help
+ Ducati Proc implementation
+
+config MPU_BRIDGE_NOTIFY
+ tristate "OMAP Notify Module"
+ default m
+ help
+ Notify Module
+
+
+config NOTIFY_TESLA
+ tristate "OMAP Notify Tesla Module"
+ depends on MPU_BRIDGE_NOTIFY
+ default m
+ help
+ Notify Tesla Module
+
+config NOTIFY_DUCATI
+ tristate "OMAP Notify Ducati Module"
+ depends on MPU_BRIDGE_NOTIFY && SYSLINK_PROC4430
+ default m
+ help
+ Notify Ducati Module
+
+config MPU_SYSLINK_IPC
+ tristate "Syslink IPC Module"
+ depends on MPU_BRIDGE_NOTIFY && NOTIFY_DUCATI
+ default m
+ help
+ Syslink IPC Module
+
+config SYSLINK_USE_SYSMGR
+ bool "Enable SYS MGR setup"
+ depends on MPU_SYSLINK_IPC && SYSLINK_PROC
+ default y
+ help
+ This is the experimental option to enable SYS manager setup
+endif
+
+
+
+
diff --git a/drivers/dsp/syslink/multicore_ipc/Kbuild b/drivers/dsp/syslink/multicore_ipc/Kbuild
new file mode 100644
index 000000000000..2377e20c76b1
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/Kbuild
@@ -0,0 +1,25 @@
+libsyslink_ipc = multiproc.o multiproc_ioctl.o nameserver.o \
+nameserver_ioctl.o heap.o heapbuf.o heapbuf_ioctl.o \
+gatepeterson.o gatepeterson_ioctl.o sharedregion.o sharedregion_ioctl.o \
+nameserver_remote.o nameserver_remotenotify.o listmp_sharedmemory.o \
+listmp.o listmp_sharedmemory_ioctl.o messageq.o messageq_ioctl.o \
+messageq_transportshm.o messageq_transportshm_ioctl.o \
+nameserver_remotenotify_ioctl.o platform_mem.o sysmgr.o sysmgr_ioctl.o \
+sysmemmgr.o sysmemmgr_ioctl.o platformcfg.o platform.o ipc_ioctl.o ipc_drv.o
+
+obj-$(CONFIG_MPU_SYSLINK_IPC) += syslink_ipc.o
+syslink_ipc-objs = $(libservices) $(libsyslink_ipc)
+
+ccflags-y += -Wno-strict-prototypes
+
+#Machine dependent
+ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
+ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
+ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS \
+ -DCONFIG_DISABLE_BRIDGE_PM -DDSP_TRACEBUF_DISABLED
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include
+ccflags-y += -Iarch/arm/plat-omap/include/syslink
+ccflags-y += -Iarch/arm/plat-omap/include/dspbridge
+
diff --git a/drivers/dsp/syslink/multicore_ipc/_listmp.h b/drivers/dsp/syslink/multicore_ipc/_listmp.h
new file mode 100644
index 000000000000..13223dc2610b
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/_listmp.h
@@ -0,0 +1,48 @@
+/*
+ * _listmp.h
+ *
+ * Internal definitions for Internal Defines for shared memory
+ * doubly linked list.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#ifndef __LISTMP_H_
+#define __LISTMP_H_
+
+/* Standard headers */
+#include <linux/types.h>
+
+/*!
+ * @brief Structure defining attribute parameters for the
+ * ListMP module.
+ */
+struct listmp_attrs {
+ u32 version;
+ /*!< Version of module */
+ u32 status;
+ /*!< Status of module */
+ u32 shared_addr_size;
+ /*!< Shared address size of module */
+};
+
+/*!
+ * @brief Structure defining processor related information for the
+ * ListMP module.
+ */
+struct listmp_proc_attrs {
+ bool creator; /*!< Creator or opener */
+ u16 proc_id; /*!< Processor Identifier */
+ u32 open_count; /*!< How many times it is opened on a processor */
+};
+
+#endif /* __LISTMP_H_ */
diff --git a/drivers/dsp/syslink/multicore_ipc/gate_remote.c b/drivers/dsp/syslink/multicore_ipc/gate_remote.c
new file mode 100644
index 000000000000..b5cf6871c8b9
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/gate_remote.c
@@ -0,0 +1,40 @@
+/*
+ * gate_remote.c
+ *
+ * This includes the functions to handle remote gates
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/types.h>
+
+/*
+ * ======== gate_remote_enter ========
+ * Purpose:
+ * This function is used to enter in to a remote gate
+ */
+int gate_remote_enter(void *ghandle)
+{
+ return 0;
+}
+
+/*
+ * ======== gate_remote_leave ========
+ * Purpose:
+ * This function is used to leave from a remote gate
+ */
+int gate_remote_leave(void *ghandle, u32 key)
+{
+ key = 0;
+ return 0;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/gatepeterson.c b/drivers/dsp/syslink/multicore_ipc/gatepeterson.c
new file mode 100755
index 000000000000..11fdbb87a068
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/gatepeterson.c
@@ -0,0 +1,961 @@
+/*
+ * gatepeterson.c
+ *
+ * The Gate Peterson Algorithm for mutual exclusion of shared memory.
+ * Current implementation works for 2 processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <syslink/atomic_linux.h>
+#include <multiproc.h>
+#include <nameserver.h>
+#include <sharedregion.h>
+#include <gatepeterson.h>
+
+
+/* IPC stubs */
+
+/*
+ * Name of the reserved NameServer used for gatepeterson
+ */
+#define GATEPETERSON_NAMESERVER "GatePeterson"
+#define GATEPETERSON_BUSY 1
+#define GATEPETERSON_FREE 0
+#define GATEPETERSON_VERSION 1
+#define GATEPETERSON_CREATED 0x08201997 /* Stamp to indicate GP
+ was created here */
+#define MAX_GATEPETERSON_NAME_LEN 32
+
+/* Cache line size */
+#define GATEPETERSON_CACHESIZE 128
+
+/* Macro to make a correct module magic number with ref_count */
+#define GATEPETERSON_MAKE_MAGICSTAMP(x) ((GATEPETERSON_MODULEID << 12) | (x))
+
+/*
+ * structure for gatepeterson module state
+ */
+struct gatepeterson_moduleobject {
+ atomic_t ref_count; /* Reference count */
+ void *nshandle;
+ struct list_head obj_list;
+ struct mutex *mod_lock; /* Lock for obj list */
+ struct gatepeterson_config cfg;
+ struct gatepeterson_config default_cfg;
+ struct gatepeterson_params def_inst_params; /* default instance
+ paramters */
+};
+
+/*
+ * Structure defining attribute parameters for the Gate Peterson module
+ */
+struct gatepeterson_attrs {
+ VOLATILE u32 version;
+ VOLATILE u32 status;
+ VOLATILE u16 creator_proc_id;
+ VOLATILE u16 opener_proc_id;
+};
+
+/*
+ * Structure defining internal object for the Gate Peterson
+ */
+struct gatepeterson_obj {
+ struct list_head elem;
+ VOLATILE struct gatepeterson_attrs *attrs; /* Instance attr */
+ VOLATILE u32 *flag[2]; /* Falgs for processors */
+ VOLATILE u32 *turn; /* Indicates whoes turn it is now? */
+ u8 self_id; /* Self identifier */
+ u8 other_id; /* Other's identifier */
+ u32 nested; /* Counter to track nesting */
+ void *local_gate; /* Local lock handle */
+ void *ns_key; /* NameServer key received in create */
+ enum gatepeterson_protect local_protection; /* Type of local protection
+ to be used */
+ struct gatepeterson_params params;
+ void *top; /* Pointer to the top Object */
+ u32 ref_count; /* Local reference count */
+};
+
+/*
+ * Structure defining object for the Gate Peterson
+ */
+struct gatepeterson_object {
+ void *(*lock_get_knl_handle)(void **handle); /* Pointer to
+ Kernl object will be returned */
+ u32 (*enter)(void *handle); /* Function to enter GP */
+ void (*leave)(void *handle, u32 key); /* Function to leave GP */
+ struct gatepeterson_obj *obj; /* Pointer to GP internal object */
+};
+
+/*
+ * Variable for holding state of the gatepeterson module
+ */
+struct gatepeterson_moduleobject gatepeterson_state = {
+ .obj_list = LIST_HEAD_INIT(gatepeterson_state.obj_list),
+ .default_cfg.max_name_len = MAX_GATEPETERSON_NAME_LEN,
+ .default_cfg.default_protection = GATEPETERSON_PROTECT_PROCESS,
+ .default_cfg.use_nameserver = true,
+ .def_inst_params.shared_addr = 0x0,
+ .def_inst_params.shared_addr_size = 0x0,
+ .def_inst_params.name = NULL,
+ .def_inst_params.local_protection = GATEPETERSON_PROTECT_DEFAULT
+
+};
+
+static void *_gatepeterson_create(const struct gatepeterson_params *params,
+ bool create_flag);
+
+/*
+ * ======== gatepeterson_get_config ========
+ * Purpose:
+ * This will get the default configuration parameters for gatepeterson
+ * module
+ */
+void gatepeterson_get_config(struct gatepeterson_config *config)
+{
+ if (WARN_ON(config == NULL))
+ goto exit;
+
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true)
+ memcpy(config, &gatepeterson_state.default_cfg,
+ sizeof(struct gatepeterson_config));
+ else
+ memcpy(config, &gatepeterson_state.cfg,
+ sizeof(struct gatepeterson_config));
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(gatepeterson_get_config);
+
+/*
+ * ======== gatepeterson_setup ========
+ * Purpose:
+ * This will setup the gatepeterson module
+ */
+int gatepeterson_setup(const struct gatepeterson_config *config)
+{
+ struct nameserver_params params;
+ struct gatepeterson_config tmp_cfg;
+ void *nshandle = NULL;
+ s32 retval = 0;
+ s32 ret;
+
+ /* This sets the ref_count variable not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable
+ */
+ atomic_cmpmask_and_set(&gatepeterson_state.ref_count,
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&gatepeterson_state.ref_count)
+ != GATEPETERSON_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (config == NULL) {
+ gatepeterson_get_config(&tmp_cfg);
+ config = &tmp_cfg;
+ }
+
+ if (WARN_ON(config->max_name_len == 0)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (likely((config->use_nameserver == true))) {
+ retval = nameserver_params_init(&params);
+ params.max_value_len = sizeof(u32);
+ params.max_name_len = config->max_name_len;
+ /* Create the nameserver for modules */
+ nshandle = nameserver_create(GATEPETERSON_NAMESERVER, &params);
+ if (nshandle == NULL)
+ goto exit;
+
+ gatepeterson_state.nshandle = nshandle;
+ }
+
+ memcpy(&gatepeterson_state.cfg, config,
+ sizeof(struct gatepeterson_config));
+ gatepeterson_state.mod_lock = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+ if (gatepeterson_state.mod_lock == NULL) {
+ retval = -ENOMEM;
+ goto lock_create_fail;
+ }
+
+ mutex_init(gatepeterson_state.mod_lock);
+ return 0;
+
+lock_create_fail:
+ if ((likely(config->use_nameserver == true)))
+ ret = nameserver_delete(&gatepeterson_state.nshandle);
+
+exit:
+ atomic_set(&gatepeterson_state.ref_count,
+ GATEPETERSON_MAKE_MAGICSTAMP(0));
+
+ printk(KERN_ERR "gatepeterson_setup failed status: %x\n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_setup);
+
+/*
+ * ======== gatepeterson_destroy ========
+ * Purpose:
+ * This will destroy the gatepeterson module
+ */
+int gatepeterson_destroy(void)
+
+{
+ struct gatepeterson_obj *obj = NULL;
+ struct mutex *lock = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!(atomic_dec_return(&gatepeterson_state.ref_count)
+ == GATEPETERSON_MAKE_MAGICSTAMP(0))) {
+ retval = 1;
+ goto exit;
+ }
+
+ /* Temporarily increment ref_count here. */
+ atomic_set(&gatepeterson_state.ref_count,
+ GATEPETERSON_MAKE_MAGICSTAMP(1));
+ /* Check if any gatepeterson instances have not been
+ * ideleted/closed so far, if there any, delete or close them
+ */
+ list_for_each_entry(obj, &gatepeterson_state.obj_list, elem) {
+ if (obj->attrs->creator_proc_id ==
+ multiproc_get_id(NULL))
+ gatepeterson_delete(&obj->top);
+ else
+ gatepeterson_close(&obj->top);
+
+ if (list_empty(&gatepeterson_state.obj_list))
+ break;
+ }
+
+ /* Again reset ref_count. */
+ atomic_set(&gatepeterson_state.ref_count,
+ GATEPETERSON_MAKE_MAGICSTAMP(0));
+
+ retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
+ if (retval != 0)
+ goto exit;
+
+ if (likely(gatepeterson_state.cfg.use_nameserver == true)) {
+ retval = nameserver_delete(&gatepeterson_state.nshandle);
+ if (unlikely(retval != 0))
+ goto exit;
+ }
+
+ lock = gatepeterson_state.mod_lock;
+ gatepeterson_state.mod_lock = NULL;
+ memset(&gatepeterson_state.cfg, 0, sizeof(struct gatepeterson_config));
+ mutex_unlock(lock);
+ kfree(lock);
+ /* Decrease the ref_count */
+ atomic_set(&gatepeterson_state.ref_count,
+ GATEPETERSON_MAKE_MAGICSTAMP(0));
+ return 0;
+
+exit:;
+ if (retval < 0) {
+ printk(KERN_ERR "gatepeterson_destroy failed status:%x\n",
+ retval);
+ }
+ return retval;
+
+}
+EXPORT_SYMBOL(gatepeterson_destroy);
+
+/*
+ * ======== gatepeterson_params_init ========
+ * Purpose:
+ * This will Initialize this config-params structure with
+ * supplier-specified defaults before instance creation
+ */
+void gatepeterson_params_init(void *handle,
+ struct gatepeterson_params *params)
+{
+ if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(params == NULL))
+ goto exit;
+
+ if (handle == NULL)
+ memcpy(params, &(gatepeterson_state.def_inst_params),
+ sizeof(struct gatepeterson_params));
+ else {
+ struct gatepeterson_obj *obj =
+ (struct gatepeterson_obj *)handle;
+ /* Return updated gatepeterson instance specific parameters. */
+ memcpy(params, &(obj->params),
+ sizeof(struct gatepeterson_params));
+ }
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(gatepeterson_params_init);
+
+/*
+ * ======== gatepeterson_create ========
+ * Purpose:
+ * This will creates a new instance of gatepeterson module
+ */
+void *gatepeterson_create(const struct gatepeterson_params *params)
+{
+ void *handle = NULL;
+ s32 retval = 0;
+ u32 shaddrsize;
+
+ BUG_ON(params == NULL);
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ shaddrsize = gatepeterson_shared_memreq(params);
+ if (WARN_ON(params->shared_addr == NULL ||
+ params->shared_addr_size < shaddrsize)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (params->local_protection >= GATEPETERSON_PROTECT_END_VALUE) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ handle = _gatepeterson_create(params, true);
+ return handle;
+
+exit:
+ return NULL;
+}
+EXPORT_SYMBOL(gatepeterson_create);
+
+/*
+ * ======== gatepeterson_delete ========
+ * Purpose:
+ * This will deletes an instance of gatepeterson module
+ */
+int gatepeterson_delete(void **gphandle)
+
+{
+ struct gatepeterson_object *handle = NULL;
+ struct gatepeterson_obj *obj = NULL;
+ struct gatepeterson_params *params = NULL;
+ s32 retval;
+
+ BUG_ON(gphandle == NULL);
+ BUG_ON(*gphandle == NULL);
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ handle = (struct gatepeterson_object *)(*gphandle);
+ obj = (struct gatepeterson_obj *)handle->obj;
+ if (unlikely(obj == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (unlikely(obj->attrs == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ /* Check if we have created the GP or not */
+ if (unlikely(obj->attrs->creator_proc_id != multiproc_get_id(NULL))) {
+ retval = -EACCES;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(obj->local_gate);
+ if (retval)
+ goto exit;
+
+ if (obj->ref_count != 0) {
+ retval = -EBUSY;
+ goto error_handle;
+ }
+
+ obj->attrs->status = !GATEPETERSON_CREATED;
+ retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
+ if (retval)
+ goto exit;
+
+ list_del(&obj->elem); /* Remove the GP instance from the GP list */
+ mutex_unlock(gatepeterson_state.mod_lock);
+ params = &obj->params;
+ /* Remove from the name server */
+ if (likely(gatepeterson_state.cfg.use_nameserver) &&
+ params->name != NULL) {
+ retval = nameserver_remove_entry(gatepeterson_state.nshandle,
+ obj->ns_key);
+ if (unlikely(retval != 0))
+ goto error_handle;
+ kfree(params->name);
+ obj->ns_key = NULL;
+ }
+
+ mutex_unlock(obj->local_gate);
+ /* If the lock handle was created internally */
+ switch (obj->params.local_protection) {
+ case GATEPETERSON_PROTECT_NONE: /* Fall through */
+ obj->local_gate = NULL; /* TBD: Fixme */
+ break;
+ case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
+ /* FIXME: Add a spinlock protection */
+ case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
+ case GATEPETERSON_PROTECT_THREAD: /* Fall through */
+ case GATEPETERSON_PROTECT_PROCESS:
+ kfree(obj->local_gate);
+ break;
+ default:
+ /* An invalid protection level was supplied, FIXME */
+ break;
+ }
+
+ kfree(obj);
+ kfree(handle);
+ *gphandle = NULL;
+ return 0;
+
+error_handle:
+ mutex_unlock(obj->local_gate);
+
+exit:
+ printk(KERN_ERR "gatepeterson_create failed status: %x\n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_delete);
+
+/*
+ * ======== gatepeterson_inc_refcount ========
+ * Purpose:
+ * This will increment the reference count while opening
+ * a GP instance if it is already opened from local processor
+ */
+static bool gatepeterson_inc_refcount(const struct gatepeterson_params *params,
+ void **handle)
+{
+ struct gatepeterson_obj *obj = NULL;
+ s32 retval = 0;
+ bool done = false;
+
+ list_for_each_entry(obj, &gatepeterson_state.obj_list, elem) {
+ if (params->shared_addr != NULL) {
+ if (obj->params.shared_addr == params->shared_addr) {
+ retval = mutex_lock_interruptible(
+ gatepeterson_state.mod_lock);
+ if (retval)
+ break;
+
+ obj->ref_count++;
+ *handle = obj->top;
+ mutex_unlock(gatepeterson_state.mod_lock);
+ done = true;
+ break;
+ }
+ } else if (params->name != NULL && obj->params.name != NULL) {
+ if (strcmp(obj->params.name, params->name) == 0) {
+ retval = mutex_lock_interruptible(
+ gatepeterson_state.mod_lock);
+ if (retval)
+ break;
+
+ obj->ref_count++;
+ *handle = obj->top;
+ mutex_unlock(gatepeterson_state.mod_lock);
+ done = true;
+ break;
+ }
+ }
+ }
+
+ return done;
+}
+
+/*
+ * ======== gatepeterson_open ========
+ * Purpose:
+ * This will opens a created instance of gatepeterson
+ * module.
+ */
+int gatepeterson_open(void **gphandle,
+ struct gatepeterson_params *params)
+{
+ void *temp = NULL;
+ s32 retval = 0;
+ u32 sharedaddr;
+
+ BUG_ON(params == NULL);
+ BUG_ON(gphandle == NULL);
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (gatepeterson_state.cfg.use_nameserver == false &&
+ params->shared_addr == NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (gatepeterson_state.cfg.use_nameserver == true &&
+ params->shared_addr == NULL && params->name == NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+ if (params->shared_addr != NULL && params->shared_addr_size <
+ gatepeterson_shared_memreq(params)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (gatepeterson_inc_refcount(params, &temp))
+ goto exit; /* It's already opened from local processor */
+
+ if (unlikely(params->shared_addr == NULL)) {
+ if (likely(gatepeterson_state.cfg.use_nameserver == true &&
+ params->name != NULL)) {
+ /* Find in name server */
+ retval = nameserver_get(gatepeterson_state.nshandle,
+ params->name, &sharedaddr,
+ sizeof(u32), NULL);
+ if (retval < 0)
+ goto noentry_fail; /* Entry not found */
+
+ params->shared_addr = sharedregion_get_ptr(
+ (u32 *)sharedaddr);
+ if (params->shared_addr == NULL)
+ goto noentry_fail;
+ }
+ } else
+ sharedaddr = (u32) params->shared_addr;
+
+ if (unlikely(((struct gatepeterson_attrs *)sharedaddr)->status !=
+ GATEPETERSON_CREATED)) {
+ retval = -ENXIO; /* Not created */
+ goto noentry_fail;
+ }
+
+ if (unlikely(((struct gatepeterson_attrs *)sharedaddr)->version !=
+ GATEPETERSON_VERSION)) {
+ retval = -ENXIO; /* FIXME Version mismatch,
+ need to change retval */
+ goto noentry_fail;
+ }
+
+ *gphandle = _gatepeterson_create(params, false);
+ return 0;
+
+noentry_fail: /* Fall through */
+exit:
+ printk(KERN_ERR "gatepeterson_open failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_open);
+
+/*
+ * ======== gatepeterson_close ========
+ * Purpose:
+ * This will closes previously opened/created instance
+ * of gatepeterson module
+ */
+int gatepeterson_close(void **gphandle)
+{
+ struct gatepeterson_object *handle = NULL;
+ struct gatepeterson_obj *obj = NULL;
+ struct gatepeterson_params *params = NULL;
+ s32 retval = 0;
+
+ BUG_ON(gphandle == NULL);
+ if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(*gphandle == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct gatepeterson_object *)(*gphandle);
+ obj = (struct gatepeterson_obj *) handle->obj;
+ if (unlikely(obj == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(obj->local_gate);
+ if (retval)
+ goto exit;
+
+ if (obj->ref_count > 1) {
+ obj->ref_count--;
+ mutex_unlock(obj->local_gate);
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
+ if (retval)
+ goto error_handle;
+
+ list_del(&obj->elem);
+ mutex_unlock(gatepeterson_state.mod_lock);
+ params = &obj->params;
+ if (likely(params->name != NULL))
+ kfree(params->name);
+
+ mutex_unlock(obj->local_gate);
+ /* If the lock handle was created internally */
+ switch (obj->params.local_protection) {
+ case GATEPETERSON_PROTECT_NONE: /* Fall through */
+ obj->local_gate = NULL; /* TBD: Fixme */
+ break;
+ case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
+ /* FIXME: Add a spinlock protection */
+ case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
+ case GATEPETERSON_PROTECT_THREAD: /* Fall through */
+ case GATEPETERSON_PROTECT_PROCESS:
+ kfree(obj->local_gate);
+ break;
+ default:
+ /* An invalid protection level was supplied */
+ break;
+ }
+
+ kfree(obj);
+ kfree(handle);
+ *gphandle = NULL;
+ return 0;
+
+error_handle:
+ mutex_unlock(obj->local_gate);
+
+exit:
+ printk(KERN_ERR "gatepeterson_close failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_close);
+
+/*
+ * ======== gatepeterson_enter ========
+ * Purpose:
+ * This will enters the gatepeterson instance
+ */
+u32 gatepeterson_enter(void *gphandle)
+{
+ struct gatepeterson_object *handle = NULL;
+ struct gatepeterson_obj *obj = NULL;
+ s32 retval = 0;
+
+ BUG_ON(gphandle == NULL);
+ if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true)) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+
+ handle = (struct gatepeterson_object *)gphandle;
+ obj = (struct gatepeterson_obj *) handle->obj;
+ if (obj->local_gate != NULL)
+ retval = mutex_lock_interruptible(obj->local_gate);
+ if (retval)
+ goto exit;
+
+ obj->nested++;
+ if (obj->nested == 1) {
+ /* indicate, needs to use the resource. */
+ *((u32 *)obj->flag[obj->self_id]) = GATEPETERSON_BUSY ;
+ /* Give away the turn. */
+ *((u32 *)(obj->turn)) = obj->other_id;
+ /* Wait while other processor is using the resource and has
+ * the turn
+ */
+ while ((*((VOLATILE u32 *) obj->flag[obj->other_id])
+ == GATEPETERSON_BUSY) &&
+ (*((VOLATILE u32 *)obj->turn) == obj->other_id))
+ ; /* Empty body loop */
+ }
+
+ return 0;
+
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_enter);
+
+/*
+ * ======== gatepeterson_leave ========
+ * Purpose:
+ * This will leaves the gatepeterson instance
+ */
+void gatepeterson_leave(void *gphandle, u32 flag)
+{
+ struct gatepeterson_object *handle = NULL;
+ struct gatepeterson_obj *obj = NULL;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
+ GATEPETERSON_MAKE_MAGICSTAMP(0),
+ GATEPETERSON_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ BUG_ON(gphandle == NULL);
+
+ handle = (struct gatepeterson_object *)gphandle;
+ (void) flag;
+ obj = (struct gatepeterson_obj *)handle->obj;
+ obj->nested--;
+ if (obj->nested == 0)
+ *((VOLATILE u32 *)obj->flag[obj->self_id]) = GATEPETERSON_FREE;
+
+ if (obj->local_gate != NULL)
+ mutex_unlock(obj->local_gate);
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(gatepeterson_leave);
+
+/*
+ * ======== gatepeterson_get_knl_handle ========
+ * Purpose:
+ * This will gatepeterson kernel object pointer
+ */
+void *gatepeterson_get_knl_handle(void **gphandle)
+{
+ BUG_ON(gphandle == NULL);
+ return gphandle;
+}
+EXPORT_SYMBOL(gatepeterson_get_knl_handle);
+
+/*
+ * ======== gatepeterson_shared_memreq ========
+ * Purpose:
+ * This will give the amount of shared memory required
+ * for creation of each instance
+ */
+u32 gatepeterson_shared_memreq(const struct gatepeterson_params *params)
+{
+ u32 retval = 0;
+
+ retval = (GATEPETERSON_CACHESIZE * 4) ;
+ return retval;
+}
+EXPORT_SYMBOL(gatepeterson_shared_memreq);
+
+/*
+ * ======== gatepeterson_create ========
+ * Purpose:
+ * Creates a new instance of gatepeterson module.
+ * This is an internal function because both
+ * gatepeterson_create and gatepeterson_open
+ * call use the same functionality.
+ */
+static void *_gatepeterson_create(const struct gatepeterson_params *params,
+ bool create_flag)
+{
+ int status = 0;
+ struct gatepeterson_object *handle = NULL;
+ struct gatepeterson_obj *obj = NULL;
+ u32 len;
+ u32 shm_index;
+ u32 shared_shm_base;
+ s32 retval = 0;
+
+
+ handle = kmalloc(sizeof(struct gatepeterson_object), GFP_KERNEL);
+ if (handle == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ obj = kmalloc(sizeof(struct gatepeterson_obj), GFP_KERNEL);
+ if (obj == NULL) {
+ retval = -ENOMEM;
+ goto obj_alloc_fail;
+ }
+
+ if (likely(gatepeterson_state.cfg.use_nameserver == true &&
+ params->name != NULL)) {
+ len = strlen(params->name) + 1;
+ obj->params.name = kmalloc(len, GFP_KERNEL);
+ if (obj->params.name == NULL) {
+ retval = -ENOMEM;
+ goto name_alloc_fail;
+ }
+
+ if (create_flag == true) {
+ shm_index = sharedregion_get_index(
+ params->shared_addr);
+ shared_shm_base = (u32)sharedregion_get_srptr(
+ (void *)params->shared_addr,
+ shm_index);
+ obj->ns_key = nameserver_add_uint32(
+ gatepeterson_state.nshandle,
+ params->name,
+ (u32) (shared_shm_base));
+ if (obj->ns_key == NULL) {
+ status = -ENOMEM; /* FIXME */
+ goto ns_add32_fail;
+ }
+ }
+
+ }
+
+ handle->obj = obj;
+ handle->enter = &gatepeterson_enter;
+ handle->leave = &gatepeterson_leave;
+ handle->lock_get_knl_handle = &gatepeterson_get_knl_handle;
+ /* assign the memory with proper cache line padding */
+ obj->attrs = (struct gatepeterson_attrs *) params->shared_addr;
+ obj->flag[0] = ((void *)(((u32) obj->attrs) +
+ GATEPETERSON_CACHESIZE));
+ obj->flag[1] = ((void *)(((u32) obj->flag[0]) +
+ GATEPETERSON_CACHESIZE));
+ obj->turn = ((void *)(((u32) obj->flag[1])
+ + GATEPETERSON_CACHESIZE)); /* TBD: Fixme */
+
+ /* Creator always has selfid set to 0 */
+ if (create_flag == true) {
+ obj->self_id = 0;
+ obj->other_id = 1;
+ obj->attrs->creator_proc_id = multiproc_get_id(NULL);
+ obj->attrs->opener_proc_id = MULTIPROC_INVALIDID;
+ obj->attrs->status = GATEPETERSON_CREATED;
+ obj->attrs->version = GATEPETERSON_VERSION;
+
+ /* Set up shared memory */
+ *(obj->turn) = 0x0;
+ *(obj->flag[0]) = 0x0;
+ *(obj->flag[1]) = 0x0;
+ obj->ref_count = 0;
+ } else {
+ obj->self_id = 1;
+ obj->other_id = 0;
+ obj->attrs->opener_proc_id = multiproc_get_id(NULL);
+ obj->ref_count = 1;
+ }
+ obj->nested = 0;
+ obj->top = handle;
+
+ /* Populate the params member */
+ memcpy(&obj->params, params, sizeof(struct gatepeterson_params));
+
+ /* Create the local lock if not provided */
+ if (likely(params->local_protection == GATEPETERSON_PROTECT_DEFAULT))
+ obj->params.local_protection =
+ gatepeterson_state.cfg.default_protection;
+ else
+ obj->params.local_protection = params->local_protection;
+
+ switch (obj->params.local_protection) {
+ case GATEPETERSON_PROTECT_NONE: /* Fall through */
+ obj->local_gate = NULL; /* TBD: Fixme */
+ break;
+ /* In syslink ; for interrupt protect gatespinlock is used, that
+ * internally uses the mutex. So we added mutex for interrupt
+ * protection here also
+ */
+ case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
+ /* FIXME: Add a spinlock protection */
+ case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
+ case GATEPETERSON_PROTECT_THREAD: /* Fall through */
+ case GATEPETERSON_PROTECT_PROCESS:
+ obj->local_gate = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (obj->local_gate == NULL) {
+ retval = -ENOMEM;
+ goto gate_create_fail;
+ }
+
+ mutex_init(obj->local_gate);
+ break;
+ default:
+ /* An invalid protection level was supplied, FIXME */
+ obj->local_gate = NULL;
+ break;
+ }
+
+ /* Put in the local list */
+ retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
+ if (retval)
+ goto mod_lock_fail;
+
+ list_add_tail(&obj->elem, &gatepeterson_state.obj_list);
+ mutex_unlock(gatepeterson_state.mod_lock);
+ return (void *)handle;
+
+mod_lock_fail:
+ kfree(obj->local_gate);
+
+gate_create_fail:
+ status = nameserver_remove_entry(gatepeterson_state.nshandle,
+ obj->ns_key);
+
+ns_add32_fail:
+ kfree(obj->params.name);
+
+name_alloc_fail:
+ kfree(obj);
+
+obj_alloc_fail:
+ kfree(handle);
+ handle = NULL;
+
+exit:
+ if (create_flag == true)
+ printk(KERN_ERR "gatepeterson_create failed status: %x\n",
+ retval);
+ else
+ printk(KERN_ERR "gatepeterson_open failed status: %x\n",
+ retval);
+
+ return NULL;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/gatepeterson_ioctl.c b/drivers/dsp/syslink/multicore_ipc/gatepeterson_ioctl.c
new file mode 100644
index 000000000000..586c2a9ae25e
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/gatepeterson_ioctl.c
@@ -0,0 +1,386 @@
+/*
+ * gatepeterson_ioctl.c
+ *
+ * The Gate Peterson Algorithm for mutual exclusion of shared memory.
+ * Current implementation works for 2 processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <gatepeterson.h>
+#include <gatepeterson_ioctl.h>
+#include <sharedregion.h>
+
+/*
+ * ======== gatepeterson_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_get_config function
+ */
+static int gatepeterson_ioctl_get_config(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_config config;
+ s32 status = 0;
+ s32 size;
+
+ gatepeterson_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct gatepeterson_config));
+ if (size)
+ status = -EFAULT;
+
+ cargs->api_status = 0;
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_setup function
+ */
+static int gatepeterson_ioctl_setup(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_config config;
+ s32 status = 0;
+ s32 size;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct gatepeterson_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = gatepeterson_setup(&config);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_destroy function
+ */
+static int gatepeterson_ioctl_destroy(
+ struct gatepeterson_cmd_args *cargs)
+{
+ cargs->api_status = gatepeterson_destroy();
+ return 0;
+}
+
+/*
+ * ======== gatepeterson_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_params_init function
+ */
+static int gatepeterson_ioctl_params_init(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_params params;
+ s32 status = 0;
+ s32 size;
+
+ gatepeterson_params_init(cargs->args.params_init.handle,
+ &params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct gatepeterson_params));
+ if (size)
+ status = -EFAULT;
+
+ cargs->api_status = 0;
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl_create ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_create function
+ */
+static int gatepeterson_ioctl_create(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_params params;
+ void *handle = NULL;
+ s32 status = 0;
+ s32 size;
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct gatepeterson_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ if (cargs->args.create.name_len > 0) {
+ params.name = kmalloc(cargs->args.create.name_len + 1,
+ GFP_KERNEL);
+ if (params.name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ params.name[cargs->args.create.name_len] = '\0';
+ size = copy_from_user(params.name,
+ cargs->args.create.params->name,
+ cargs->args.create.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ }
+
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.create.shared_addr_srptr);
+ handle = gatepeterson_create(&params);
+ /* Here we are not validating the return from the module.
+ Even it is nul, we pass it to user and user has to pass
+ proper return to application
+ */
+ cargs->args.create.handle = handle;
+ cargs->api_status = 0;
+
+name_from_usr_error:
+ if (cargs->args.open.name_len > 0)
+ kfree(params.name);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_ioctl_delete function
+ */
+static int gatepeterson_ioctl_delete(struct gatepeterson_cmd_args *cargs)
+
+{
+ cargs->api_status = gatepeterson_delete(&cargs->args.delete.handle);
+ return 0;
+}
+
+/*
+ * ======== gatepeterson_ioctl_open ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_open function
+ */
+static int gatepeterson_ioctl_open(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_params params;
+ void *handle = NULL;
+ s32 status = 0;
+ s32 size;
+
+ size = copy_from_user(&params, cargs->args.open.params,
+ sizeof(struct gatepeterson_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ if (cargs->args.open.name_len > 0) {
+ params.name = kmalloc(cargs->args.open.name_len + 1,
+ GFP_KERNEL);
+ if (params.name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ params.name[cargs->args.open.name_len] = '\0';
+ size = copy_from_user(params.name,
+ cargs->args.open.params->name,
+ cargs->args.open.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+ }
+
+ /* For open by name, the shared_add_srptr may be invalid */
+ if (cargs->args.open.shared_addr_srptr != \
+ (u32) SHAREDREGION_INVALIDSRPTR) {
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.open.shared_addr_srptr);
+ }
+ cargs->api_status = gatepeterson_open(&handle, &params);
+ cargs->args.open.handle = handle;
+
+name_from_usr_error:
+ if (cargs->args.open.name_len > 0)
+ kfree(params.name);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl_close ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_close function
+ */
+static int gatepeterson_ioctl_close(struct gatepeterson_cmd_args *cargs)
+{
+ cargs->api_status = gatepeterson_close(&cargs->args.close.handle);
+ return 0;
+}
+
+/*
+ * ======== gatepeterson_ioctl_enter ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_enter function
+ */
+static int gatepeterson_ioctl_enter(struct gatepeterson_cmd_args *cargs)
+{
+ cargs->api_status = gatepeterson_enter(cargs->args.enter.handle);
+ return 0;
+}
+
+/*
+ * ======== gatepeterson_ioctl_leave ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_leave function
+ */
+static int gatepeterson_ioctl_leave(struct gatepeterson_cmd_args *cargs)
+{
+ gatepeterson_leave(cargs->args.enter.handle,
+ cargs->args.enter.flags);
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== gatepeterson_ioctl_shared_memreq ========
+ * Purpose:
+ * This ioctl interface to gatepeterson_shared_memreq function
+ */
+static int gatepeterson_ioctl_shared_memreq(struct gatepeterson_cmd_args *cargs)
+{
+ struct gatepeterson_params params;
+ s32 status = 0;
+ s32 size;
+
+
+ size = copy_from_user(&params, cargs->args.shared_memreq.params,
+ sizeof(struct gatepeterson_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->args.shared_memreq.bytes =
+ gatepeterson_shared_memreq(cargs->args.shared_memreq.params);
+ cargs->api_status = 0;
+
+exit:
+ return status;
+}
+
+/*
+ * ======== gatepeterson_ioctl ========
+ * Purpose:
+ * This ioctl interface for gatepeterson module
+ */
+int gatepeterson_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct gatepeterson_cmd_args __user *uarg =
+ (struct gatepeterson_cmd_args __user *)args;
+ struct gatepeterson_cmd_args cargs;
+
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct gatepeterson_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_GATEPETERSON_GETCONFIG:
+ status = gatepeterson_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_SETUP:
+ status = gatepeterson_ioctl_setup(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_DESTROY:
+ status = gatepeterson_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_PARAMS_INIT:
+ status = gatepeterson_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_CREATE:
+ status = gatepeterson_ioctl_create(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_DELETE:
+ status = gatepeterson_ioctl_delete(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_OPEN:
+ status = gatepeterson_ioctl_open(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_CLOSE:
+ status = gatepeterson_ioctl_close(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_ENTER:
+ status = gatepeterson_ioctl_enter(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_LEAVE:
+ status = gatepeterson_ioctl_leave(&cargs);
+ break;
+
+ case CMD_GATEPETERSON_SHAREDMEMREQ:
+ status = gatepeterson_ioctl_shared_memreq(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs,
+ sizeof(struct gatepeterson_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/heap.c b/drivers/dsp/syslink/multicore_ipc/heap.c
new file mode 100755
index 000000000000..11df26c11c88
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/heap.c
@@ -0,0 +1,101 @@
+/*
+ * heap.c
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+#include <linux/types.h>
+#include <linux/bug.h>
+
+
+#include <heap.h>
+
+
+/*
+ * ======== heap_alloc ========
+ * Purpose:
+ * This will allocate a block of memory of specified
+ * size
+ */
+void *heap_alloc(void *hphandle, u32 size, u32 align)
+{
+ char *block = NULL;
+ struct heap_object *obj = NULL;
+
+ BUG_ON(hphandle == NULL);
+
+ obj = (struct heap_object *)hphandle;
+ BUG_ON(obj->alloc == NULL);
+ block = obj->alloc(hphandle, size, align);
+ return block;
+}
+
+/*
+ * ======== heap_free ========
+ * Purpose:
+ * This will frees a block of memory allocated
+ * rom heap
+ */
+int heap_free(void *hphandle, void *block, u32 size)
+{
+ struct heap_object *obj = NULL;
+ s32 retval = 0;
+
+ BUG_ON(hphandle == NULL);
+
+ obj = (struct heap_object *)hphandle;
+ BUG_ON(obj->free == NULL);
+ retval = obj->free(hphandle, block, size);
+ return retval;
+}
+
+/*
+ * ======== heap_get_stats ========
+ * Purpose:
+ * This will get the heap memory statistics
+ */
+int heap_get_stats(void *hphandle, struct memory_stats *stats)
+{
+ struct heap_object *obj = NULL;
+ s32 retval = 0;
+
+ BUG_ON(hphandle == NULL);
+ BUG_ON(stats == NULL);
+
+ obj = (struct heap_object *)hphandle;
+ BUG_ON(obj->get_stats == NULL);
+ retval = obj->get_stats(hphandle, stats);
+ return retval;
+}
+
+/*
+ * ======== heap_get_extended_stats ========
+ * Purpose:
+ * This will get the heap memory extended statistics
+ */
+int heap_get_extended_stats(void *hphandle,
+ struct heap_extended_stats *stats)
+{
+ struct heap_object *obj = NULL;
+ s32 retval = 0;
+
+ BUG_ON(hphandle == NULL);
+ BUG_ON(stats == NULL);
+
+ obj = (struct heap_object *)hphandle;
+ BUG_ON(obj->get_extended_stats == NULL);
+ retval = obj->get_extended_stats(hphandle, stats);
+ return retval;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/heapbuf.c b/drivers/dsp/syslink/multicore_ipc/heapbuf.c
new file mode 100755
index 000000000000..8c076dd7e90c
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/heapbuf.c
@@ -0,0 +1,1171 @@
+/*
+ * heapbuf.c
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <atomic_linux.h>
+#include <multiproc.h>
+#include <nameserver.h>
+#include <sharedregion.h>
+#include <gatepeterson.h>
+#include <heapbuf.h>
+#include <listmp.h>
+#include <listmp_sharedmemory.h>
+
+/*
+ * Name of the reserved nameserver used for heapbuf.
+ */
+#define HEAPBUF_NAMESERVER "HeapBuf"
+#define HEAPBUF_MAX_NAME_LEN 32
+#define HEAPBUF_CACHESIZE 128
+/* brief Macro to make a correct module magic number with refCount */
+#define HEAPBUF_MAKE_MAGICSTAMP(x) ((HEAPBUF_MODULEID << 12) | (x))
+
+
+/*
+ * Structure defining attribute parameters for the heapbuf module
+ */
+struct heapbuf_attrs {
+ VOLATILE u32 version;
+ VOLATILE u32 status;
+ VOLATILE u32 num_free_blocks;
+ VOLATILE u32 min_free_blocks;
+ VOLATILE u32 block_size;
+ VOLATILE u32 align;
+ VOLATILE u32 num_blocks;
+ VOLATILE u32 buf_size;
+ VOLATILE char *buf;
+};
+
+/*
+ * Structure defining processor related information for the
+ * heapbuf module
+ */
+struct heapbuf_proc_attrs {
+ bool creator; /* Creator or opener */
+ u16 proc_id; /* Processor identifier */
+ u32 open_count; /* open count in a processor */
+};
+
+/*
+ * Structure for heapbuf module state
+ */
+struct heapbuf_module_object {
+ atomic_t ref_count; /* Reference count */
+ void *ns_handle;
+ struct list_head obj_list; /* List holding created objects */
+ struct mutex *local_lock; /* lock for protecting obj_list */
+ struct heapbuf_config cfg;
+ struct heapbuf_config default_cfg; /* Default config values */
+ struct heapbuf_params default_inst_params; /* Default instance
+ creation parameters */
+};
+
+struct heapbuf_module_object heapbuf_state = {
+ .obj_list = LIST_HEAD_INIT(heapbuf_state.obj_list),
+ .default_cfg.max_name_len = HEAPBUF_MAX_NAME_LEN,
+ .default_cfg.use_nameserver = true,
+ .default_cfg.track_max_allocs = false,
+ .default_inst_params.gate = NULL,
+ .default_inst_params.exact = false,
+ .default_inst_params.name = NULL,
+ .default_inst_params.resource_id = 0,
+ .default_inst_params.cache_flag = false,
+ .default_inst_params.align = 1,
+ .default_inst_params.num_blocks = 0,
+ .default_inst_params.block_size = 0,
+ .default_inst_params.shared_addr = NULL,
+ .default_inst_params.shared_addr_size = 0,
+ .default_inst_params.shared_buf = NULL,
+ .default_inst_params.shared_buf_size = 0
+};
+
+/*
+ * Structure for the handle for the heapbuf
+ */
+struct heapbuf_obj {
+ struct list_head list_elem; /* Used for creating a linked list */
+ struct heapbuf_params params; /* The creation parameter structure */
+ struct heapbuf_attrs *attrs; /* The shared attributes structure */
+ void *free_list; /* List of free buffers */
+ struct mutex *gate; /* Lock used for critical region management */
+ void *ns_key; /* nameserver key required for remove */
+ struct heapbuf_proc_attrs owner; /* owner processor info */
+ void *top; /* Pointer to the top object */
+ bool cacheFlag; /* added for future use */
+};
+
+/*
+ * ======== heapbuf_get_config ========
+ * Purpose:
+ * This will get default configuration for the
+ * heapbuf module
+ */
+int heapbuf_get_config(struct heapbuf_config *cfgparams)
+{
+ BUG_ON(cfgparams == NULL);
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true)
+ memcpy(cfgparams, &heapbuf_state.default_cfg,
+ sizeof(struct heapbuf_config));
+ else
+ memcpy(cfgparams, &heapbuf_state.cfg,
+ sizeof(struct heapbuf_config));
+ return 0;
+}
+EXPORT_SYMBOL(heapbuf_get_config);
+
+/*
+ * ======== heapbuf_setup ========
+ * Purpose:
+ * This will setup the heapbuf module
+ *
+ * This function sets up the HeapBuf module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then heapbuf_getconfig can be called to get
+ * the configuration filled with the default values. After this,
+ * only the required configuration values can be changed. If the
+ * user does not wish to make any change in the default parameters,
+ * the application can simply call HeapBuf_setup with NULL
+ * parameters. The default parameters would get automatically used.
+ */
+int heapbuf_setup(const struct heapbuf_config *cfg)
+{
+ struct nameserver_params params;
+ struct heapbuf_config tmp_cfg;
+ void *ns_handle = NULL;
+ s32 retval = 0;
+
+ /* This sets the ref_count variable not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable
+ */
+ atomic_cmpmask_and_set(&heapbuf_state.ref_count,
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&heapbuf_state.ref_count)
+ != HEAPBUF_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (cfg == NULL) {
+ heapbuf_get_config(&tmp_cfg);
+ cfg = &tmp_cfg;
+ }
+
+ if (cfg->max_name_len == 0 ||
+ cfg->max_name_len > HEAPBUF_MAX_NAME_LEN) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ heapbuf_state.local_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (heapbuf_state.local_lock == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ if (likely((cfg->use_nameserver == true))) {
+ retval = nameserver_get_params(NULL, &params);
+ params.max_value_len = sizeof(u32);
+ params.max_name_len = cfg->max_name_len;
+ ns_handle = nameserver_create(HEAPBUF_NAMESERVER, &params);
+ if (ns_handle == NULL) {
+ retval = -EFAULT;
+ goto ns_create_fail;
+ }
+ heapbuf_state.ns_handle = ns_handle;
+ }
+
+ memcpy(&heapbuf_state.cfg, cfg, sizeof(struct heapbuf_config));
+ mutex_init(heapbuf_state.local_lock);
+ return 0;
+
+ns_create_fail:
+ kfree(heapbuf_state.local_lock);
+
+error:
+ atomic_set(&heapbuf_state.ref_count,
+ HEAPBUF_MAKE_MAGICSTAMP(0));
+
+ printk(KERN_ERR "heapbuf_setup failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_setup);
+
+/*
+ * ======== heapbuf_destroy ========
+ * Purpose:
+ * This will destroy the heapbuf module
+ */
+int heapbuf_destroy(void)
+{
+ s32 retval = 0;
+ struct mutex *lock = NULL;
+ struct heapbuf_obj *obj = NULL;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (atomic_dec_return(&heapbuf_state.ref_count)
+ == HEAPBUF_MAKE_MAGICSTAMP(0)) {
+ /* Temporarily increment ref_count here. */
+ atomic_set(&heapbuf_state.ref_count,
+ HEAPBUF_MAKE_MAGICSTAMP(1));
+
+ /* Check if any heapbuf instances have not been deleted/closed
+ * so far. if there any, delete or close them
+ */
+ list_for_each_entry(obj, &heapbuf_state.obj_list, list_elem) {
+ if (obj->owner.proc_id == multiproc_get_id(NULL))
+ heapbuf_delete(&obj->top);
+ else
+ heapbuf_close(obj->top);
+
+ if (list_empty(&heapbuf_state.obj_list))
+ break;
+ }
+
+ /* Again reset ref_count. */
+ atomic_set(&heapbuf_state.ref_count,
+ HEAPBUF_MAKE_MAGICSTAMP(0));
+
+ if (likely(heapbuf_state.cfg.use_nameserver == true)) {
+ retval = nameserver_delete(&heapbuf_state.ns_handle);
+ if (unlikely(retval != 0))
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
+ if (retval)
+ goto error;
+
+ lock = heapbuf_state.local_lock;
+ heapbuf_state.local_lock = NULL;
+ mutex_unlock(lock);
+ kfree(lock);
+ memset(&heapbuf_state.cfg, 0, sizeof(struct heap_config));
+
+ atomic_set(&heapbuf_state.ref_count,
+ HEAPBUF_MAKE_MAGICSTAMP(0));
+ }
+
+ return 0;
+
+error:
+ printk(KERN_ERR "heapbuf_destroy failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_destroy);
+
+/*
+ * ======== heapbuf_params_init ========
+ * Purpose:
+ * This will get the intialization prams for a heapbuf
+ * module instance
+ */
+void heapbuf_params_init(void *handle,
+ struct heapbuf_params *params)
+{
+ struct heapbuf_obj *obj = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ BUG_ON(params == NULL);
+
+ if (handle == NULL)
+ memcpy(params, &heapbuf_state.default_inst_params,
+ sizeof(struct heapbuf_params));
+ else {
+ obj = (struct heapbuf_obj *)handle;
+ memcpy(params, (void *)&obj->params,
+ sizeof(struct heapbuf_params));
+ }
+ return;
+error:
+ printk(KERN_ERR "heapbuf_params_init failed status: %x\n", retval);
+}
+EXPORT_SYMBOL(heapbuf_params_init);
+
+/*
+ * ======== _heapbuf_create ========
+ * Purpose:
+ * This will create a new instance of heapbuf module
+ * This is an internal function as both heapbuf_create
+ * and heapbuf_open use the functionality
+ *
+ * NOTE: The lock to protect the shared memory area
+ * used by heapbuf is provided by the consumer of
+ * heapbuf module
+ */
+int _heapbuf_create(void **handle_ptr, const struct heapbuf_params *params,
+ u32 create_flag)
+{
+ struct heap_object *handle = NULL;
+ struct heapbuf_obj *obj = NULL;
+ char *buf = NULL;
+ listmp_sharedmemory_params listmp_params;
+ s32 retval = 0;
+ u32 i;
+ s32 align;
+ s32 shm_index;
+ u32 shared_shm_base;
+ void *entry = NULL;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ BUG_ON(handle_ptr == NULL);
+
+ BUG_ON(params == NULL);
+
+ /* No need for parameter checks, since this is an internal function. */
+
+ /* Initialize return parameter. */
+ *handle_ptr = NULL;
+
+ handle = kmalloc(sizeof(struct heap_object), GFP_KERNEL);
+ if (handle == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ obj = kmalloc(sizeof(struct heapbuf_obj), GFP_KERNEL);
+ if (obj == NULL) {
+ retval = -ENOMEM;
+ goto obj_alloc_error;
+ }
+
+ handle->obj = (struct heapbuf_obj *)obj;
+ handle->alloc = &heapbuf_alloc;
+ handle->free = &heapbuf_free;
+ handle->get_stats = &heapbuf_get_stats;
+ /* FIXME: handle->is_blocking = &heapbuf_isblocking; */
+ /* Create the shared list */
+ listmp_sharedmemory_params_init(NULL, &listmp_params);
+ listmp_params.shared_addr = (u32 *)((u32) (params->shared_addr)
+ + ((sizeof(struct heapbuf_attrs)
+ + (HEAPBUF_CACHESIZE - 1))
+ & ~(HEAPBUF_CACHESIZE - 1)));
+ listmp_params.shared_addr_size =
+ listmp_sharedmemory_shared_memreq(&listmp_params);
+ listmp_params.gate = NULL;
+ /* Assign the memory with proper cache line padding */
+ obj->attrs = (struct heapbuf_attrs *) params->shared_addr;
+
+ if (create_flag == false)
+ listmp_sharedmemory_open(&obj->free_list, &listmp_params);
+ else {
+ obj->free_list = listmp_sharedmemory_create(&listmp_params);
+
+ if (obj->free_list == NULL) {
+ retval = -ENOMEM;
+ goto listmp_error;
+ }
+
+ obj->attrs->version = HEAPBUF_VERSION;
+ obj->attrs->num_free_blocks = params->num_blocks;
+ obj->attrs->min_free_blocks = params->num_blocks;
+ obj->attrs->block_size = params->block_size;
+ obj->attrs->align = params->align;
+ obj->attrs->num_blocks = params->num_blocks;
+ obj->attrs->buf_size = params->shared_buf_size;
+ buf = params->shared_buf;
+ align = obj->attrs->align;
+ buf = (char *)(((u32)buf + (align - 1)) & ~(align - 1));
+ obj->attrs->buf = buf;
+
+ /*
+ * Split the buffer into blocks that are length
+ * block_size" and add into the free_list Queue
+ */
+ for (i = 0; i < obj->attrs->num_blocks; i++) {
+ listmp_put_tail((struct listmp_object *)
+ obj->free_list,
+ (struct listmp_elem *)buf);
+ buf += obj->attrs->block_size;
+ }
+ }
+
+ obj->gate = params->gate;
+
+ /* Populate the params member */
+ memcpy(&obj->params, params, sizeof(struct heapbuf_params));
+ if (params->name != NULL) {
+ obj->params.name = kmalloc(strlen(params->name) + 1,
+ GFP_KERNEL);
+ if (obj->params.name == NULL) {
+ retval = -ENOMEM;
+ goto name_alloc_error;
+ }
+ strncpy(obj->params.name, params->name,
+ strlen(params->name) + 1);
+ }
+
+ if (create_flag == true) {
+ obj->owner.creator = true;
+ obj->owner.open_count = 1;
+ obj->owner.proc_id = multiproc_get_id(NULL);
+ obj->top = handle;
+ obj->attrs->status = HEAPBUF_CREATED;
+ } else {
+ obj->owner.creator = false;
+ obj->owner.open_count = 0;
+ obj->owner.proc_id = MULTIPROC_INVALIDID;
+ obj->top = handle;
+ }
+
+ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
+ if (retval)
+ goto lock_error;
+
+ INIT_LIST_HEAD(&obj->list_elem);
+ list_add_tail(&obj->list_elem, &heapbuf_state.obj_list);
+ mutex_unlock(heapbuf_state.local_lock);
+
+ if ((likely(heapbuf_state.cfg.use_nameserver == true))
+ && (create_flag == true)) {
+ /* We will store a shared pointer in the nameserver */
+ shm_index = sharedregion_get_index(params->shared_addr);
+ shared_shm_base = (u32)sharedregion_get_srptr(
+ params->shared_addr, shm_index);
+ if (obj->params.name != NULL) {
+ entry = nameserver_add_uint32(heapbuf_state.ns_handle,
+ params->name,
+ (u32)(shared_shm_base));
+ if (entry == NULL) {
+ retval = -EFAULT;
+ goto ns_add_error;
+ }
+ }
+ }
+
+ *handle_ptr = (void *)handle;
+ return retval;
+
+ns_add_error:
+ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
+ list_del(&obj->list_elem);
+ mutex_unlock(heapbuf_state.local_lock);
+
+lock_error:
+ if (obj->params.name != NULL) {
+ if (obj->ns_key != NULL) {
+ nameserver_remove_entry(heapbuf_state.ns_handle,
+ obj->ns_key);
+ obj->ns_key = NULL;
+ }
+ kfree(obj->params.name);
+ }
+
+name_alloc_error: /* Fall through */
+ if (create_flag == true)
+ listmp_sharedmemory_delete((listmp_sharedmemory_handle *)
+ &obj->free_list);
+ else
+ listmp_sharedmemory_close((listmp_sharedmemory_handle *)
+ &obj->free_list);
+
+listmp_error:
+ kfree(obj);
+
+obj_alloc_error:
+ kfree(handle);
+
+error:
+ printk(KERN_ERR "_heapbuf_create failed status: %x\n", retval);
+ return retval;
+}
+
+/*
+ * ======== heapbuf_create ========
+ * Purpose:
+ * This will create a new instance of heapbuf module
+ */
+void *heapbuf_create(const struct heapbuf_params *params)
+{
+ s32 retval = 0;
+ void *handle = NULL;
+ u32 buf_size;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ BUG_ON(params == NULL);
+
+ if ((params->shared_addr) == NULL ||
+ params->shared_buf == NULL) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if ((params->shared_addr_size)
+ < heapbuf_shared_memreq(params, &buf_size)) {
+ /* if Shared memory size is less than required */
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (params->shared_buf_size < buf_size) {
+ /* if shared memory size is less than required */
+ retval = -EINVAL;
+ goto error;
+ }
+
+ retval = _heapbuf_create((void **)&handle, params, true);
+ if (retval < 0)
+ goto error;
+
+ return (void *)handle;
+
+error:
+ printk(KERN_ERR "heapbuf_create failed status: %x\n", retval);
+ return (void *)handle;
+}
+EXPORT_SYMBOL(heapbuf_create);
+
+/*
+ * ======== heapbuf_delete ========
+ * Purpose:
+ * This will delete an instance of heapbuf module
+ */
+int heapbuf_delete(void **handle_ptr)
+{
+ int status = 0;
+ struct heap_object *handle = NULL;
+ struct heapbuf_obj *obj = NULL;
+ struct heapbuf_params *params = NULL;
+ s32 retval = 0;
+ u16 myproc_id;
+
+ BUG_ON(handle_ptr == NULL);
+ handle = (struct heap_object *)(*handle_ptr);
+ if (WARN_ON(handle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ obj = (struct heapbuf_obj *)handle->obj;
+ if (obj == NULL) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ myproc_id = multiproc_get_id(NULL);
+
+ if (obj->owner.proc_id != myproc_id) {
+ retval = -EPERM;
+ goto error;
+ }
+
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto gate_error;
+ }
+ }
+
+ if (obj->owner.open_count > 1) {
+ retval = -EBUSY;
+ goto device_busy_error;;
+ }
+
+ if (obj->owner.open_count != 1) {
+ retval = -EBUSY;
+ goto device_busy_error;;
+ }
+
+ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
+ if (retval)
+ goto local_lock_error;
+
+ list_del(&obj->list_elem);
+ mutex_unlock(heapbuf_state.local_lock);
+ params = (struct heapbuf_params *) &obj->params;
+ if (likely(params->name != NULL)) {
+ if (likely(heapbuf_state.cfg.use_nameserver == true)) {
+ retval = nameserver_remove(heapbuf_state.ns_handle,
+ params->name);
+ if (retval != 0)
+ goto ns_remove_error;
+ obj->ns_key = NULL;
+ }
+ kfree(params->name);
+ }
+
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+ retval = listmp_sharedmemory_delete(&obj->free_list);
+ kfree(obj);
+ kfree(handle);
+ *handle_ptr = NULL;
+ return 0;
+
+ns_remove_error: /* Fall through */
+gate_error: /* Fall through */
+local_lock_error: /* Fall through */
+device_busy_error:
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+
+error:
+ printk(KERN_ERR "heapbuf_delete failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_delete);
+
+/*
+ * ======== heapbuf_open ========
+ * Purpose:
+ * This will opens a created instance of heapbuf
+ * module
+ */
+int heapbuf_open(void **handle_ptr,
+ struct heapbuf_params *params)
+{
+ struct heapbuf_obj *obj = NULL;
+ bool found = false;
+ s32 retval = 0;
+ u16 myproc_id;
+ u32 shared_shm_base;
+ struct heapbuf_attrs *attrs;
+
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if ((heapbuf_state.cfg.use_nameserver == false)
+ && (params->shared_addr == (u32)NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if ((heapbuf_state.cfg.use_nameserver == true)
+ && (params->shared_addr == (u32)NULL)
+ && (params->name == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ myproc_id = multiproc_get_id(NULL);
+ list_for_each_entry(obj, &heapbuf_state.obj_list, list_elem) {
+ if (obj->params.shared_addr == params->shared_addr)
+ found = true;
+ else if (params->name != NULL) {
+ if (strcmp(obj->params.name, params->name) == 0)
+ found = true;
+ }
+
+ if (found == true) {
+ retval = mutex_lock_interruptible(
+ heapbuf_state.local_lock);
+ if (obj->owner.proc_id == myproc_id)
+ obj->owner.open_count++;
+ *handle_ptr = obj->top;
+ mutex_unlock(heapbuf_state.local_lock);
+ }
+ }
+
+ if (likely(found == false)) {
+ if (unlikely(params->shared_addr == NULL)) {
+ if (likely(heapbuf_state.cfg.use_nameserver == true)) {
+ /* Find in name server */
+ retval = nameserver_get(heapbuf_state.ns_handle,
+ params->name,
+ &shared_shm_base,
+ sizeof(u32),
+ NULL);
+ if (retval < 0)
+ goto error;
+
+ /*
+ * Convert from shared region pointer
+ * to local address
+ */
+ params->shared_addr = sharedregion_get_ptr
+ (&shared_shm_base);
+ if (params->shared_addr == NULL) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+ }
+
+ attrs = (struct heapbuf_attrs *)(params->shared_addr);
+ if (unlikely(attrs->status != (HEAPBUF_CREATED)))
+ retval = -ENXIO; /* Not created */
+ else if (unlikely(attrs->version != (HEAPBUF_VERSION))) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ retval = _heapbuf_create((void **)handle_ptr, params, false);
+ if (retval < 0)
+ goto error;
+
+ }
+
+ return 0;
+
+error:
+ printk(KERN_ERR "heapbuf_open failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_open);
+
+/*
+ * ======== heapbuf_close ========
+ * Purpose:
+ * This will closes previously opened/created instance
+ * of heapbuf module
+ */
+int heapbuf_close(void *handle_ptr)
+{
+ int status = 0;
+ struct heap_object *handle = NULL;
+ struct heapbuf_obj *obj = NULL;
+ struct heapbuf_params *params = NULL;
+ s32 retval = 0;
+ u16 myproc_id = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (WARN_ON(handle_ptr == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ handle = (struct heap_object *)(handle_ptr);
+ obj = (struct heapbuf_obj *)handle->obj;
+
+ if (obj != NULL) {
+ retval = mutex_lock_interruptible(heapbuf_state.local_lock);
+ if (retval)
+ goto error;
+
+ myproc_id = multiproc_get_id(NULL);
+ /* opening an instance created locally */
+ if (obj->owner.proc_id == myproc_id) {
+ if (obj->owner.open_count > 1)
+ obj->owner.open_count--;
+ }
+
+ /* Check if HeapBuf is opened on same processor*/
+ if ((((struct heapbuf_obj *)obj)->owner.creator == false)
+ && (obj->owner.open_count == 0)) {
+ list_del(&obj->list_elem);
+
+ /* Take the local lock */
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+
+ params = (struct heapbuf_params *)&obj->params;
+ if (likely((params->name) != NULL))
+ kfree(params->name); /* Free memory */
+
+ /* Release the local lock */
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+
+ /* Delete the list */
+ listmp_sharedmemory_close((listmp_sharedmemory_handle *)
+ obj->free_list);
+ kfree(obj);
+ kfree(handle);
+ handle = NULL;
+ }
+ mutex_unlock(heapbuf_state.local_lock);
+ }
+ return 0;
+
+error:
+ printk(KERN_ERR "heapbuf_close failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_close);
+
+/*
+ * ======== heapbuf_alloc ========
+ * Purpose:
+ * This will allocs a block of memory
+ */
+void *heapbuf_alloc(void *hphandle, u32 size, u32 align)
+{
+ int status = 0;
+ struct heap_object *handle = NULL;
+ struct heapbuf_obj *obj = NULL;
+ char *block = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (WARN_ON(hphandle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (WARN_ON(size == 0)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ handle = (struct heap_object *)(hphandle);
+ obj = (struct heapbuf_obj *)handle->obj;
+
+ if ((obj->params.exact == true)
+ && (size != obj->attrs->block_size)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (size > obj->attrs->block_size) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+
+ block = listmp_get_head((void *)obj->free_list);
+ if (block == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ obj->attrs->num_free_blocks--;
+ /*
+ * Keep track of the min number of free for this heapbuf, if user
+ * has set the config variable trackMaxAllocs to true.
+ *
+ * The min number of free blocks, 'min_free_blocks', will be used to
+ * compute the "all time" maximum number of allocated blocks in
+ * getExtendedStats().
+ */
+ if (heapbuf_state.cfg.track_max_allocs) {
+ if (obj->attrs->num_free_blocks < obj->attrs->min_free_blocks)
+ /* save the new minimum */
+ obj->attrs->min_free_blocks =
+ obj->attrs->num_free_blocks;
+ }
+
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+ return block;
+error:
+ printk(KERN_ERR "heapbuf_alloc failed status: %x\n", retval);
+ return NULL;
+}
+EXPORT_SYMBOL(heapbuf_alloc);
+
+/*
+ * ======== heapbuf_free ========
+ * Purpose:
+ * This will free a block of memory
+ */
+int heapbuf_free(void *hphandle, void *block, u32 size)
+{
+ int status = 0;
+ struct heap_object *handle = NULL;
+ struct heapbuf_obj *obj = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (WARN_ON(hphandle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (WARN_ON(block == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ handle = (struct heap_object *)(hphandle);
+ obj = (struct heapbuf_obj *)handle->obj;
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+
+ retval = listmp_put_tail((void *)obj->free_list, block);
+ obj->attrs->num_free_blocks++;
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+ return 0;
+
+error:
+ printk(KERN_ERR "heapbuf_free failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_free);
+
+/*
+ * ======== heapbuf_get_stats ========
+ * Purpose:
+ * This will get memory statistics
+ */
+int heapbuf_get_stats(void *hphandle, struct memory_stats *stats)
+{
+ int status = 0;
+ struct heap_object *object = NULL;
+ struct heapbuf_obj *obj = NULL;
+ u32 block_size;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ BUG_ON(stats == NULL);
+
+ if (WARN_ON(hphandle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ object = (struct heap_object *)(hphandle);
+ obj = (struct heapbuf_obj *)object->obj;
+
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+
+ block_size = obj->attrs->block_size;
+ stats->total_size = (u32 *)(block_size * obj->attrs->num_blocks);
+ stats->total_free_size = (u32 *)(block_size *
+ obj->attrs->num_free_blocks);
+ if (obj->attrs->num_free_blocks)
+ stats->largest_free_size = (u32 *)block_size;
+ else
+ stats->largest_free_size = (u32 *)0;
+
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+ return 0;
+
+error:
+ printk(KERN_ERR "heapbuf_get_stats failed status: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_get_stats);
+
+/*
+ * ======== heapbuf_isblocking ========
+ * Purpose:
+ * Indicate whether the heap may block during an alloc or free call
+ */
+bool heapbuf_isblocking(void *handle)
+{
+ bool isblocking = false;
+ s32 retval = 0;
+
+ if (WARN_ON(handle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ /* TBD: Figure out how to determine whether the gate is blocking */
+ isblocking = true;
+
+ /* retval true Heap blocks during alloc/free calls */
+ /* retval false Heap does not block during alloc/free calls */
+ return isblocking;
+
+error:
+ printk(KERN_ERR "heapbuf_isblocking status: %x\n", retval);
+ return isblocking;
+}
+EXPORT_SYMBOL(heapbuf_isblocking);
+
+/*
+ * ======== heapbuf_get_extended_stats ========
+ * Purpose:
+ * This will get extended statistics
+ */
+int heapbuf_get_extended_stats(void *hphandle,
+ struct heapbuf_extended_stats *stats)
+{
+ int status = 0;
+ struct heap_object *object = NULL;
+ struct heapbuf_obj *obj = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(heapbuf_state.ref_count),
+ HEAPBUF_MAKE_MAGICSTAMP(0),
+ HEAPBUF_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ BUG_ON(stats == NULL);
+ if (WARN_ON(heapbuf_state.ns_handle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ if (WARN_ON(hphandle == NULL)) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ object = (struct heap_object *)(hphandle);
+ obj = (struct heapbuf_obj *)object->obj;
+ if (likely(obj->gate != NULL)) {
+ status = gatepeterson_enter(obj->gate);
+ if (status < 0) {
+ retval = -EINVAL;
+ goto error;
+ }
+ }
+
+ /*
+ * The maximum number of allocations for this heapbuf (for any given
+ * instance of time during its liftime) is computed as follows:
+ *
+ * max_allocated_blocks = obj->num_blocks - obj->min_free_blocks
+ *
+ * Note that max_allocated_blocks is *not* the maximum allocation count,
+ * but rather the maximum allocations seen at any snapshot of time in
+ * the heapbuf instance.
+ */
+ /* if nothing has been alloc'ed yet, return 0 */
+ if ((u32)(obj->attrs->min_free_blocks) == -1) /* FIX THIS */
+ stats->max_allocated_blocks = 0;
+ else
+ stats->max_allocated_blocks = obj->attrs->num_blocks
+ - obj->attrs->min_free_blocks;
+ /* current number of alloc'ed blocks is computed using curr # free
+ * blocks
+ */
+ stats->num_allocated_blocks = obj->attrs->num_blocks
+ - obj->attrs->num_free_blocks;
+ if (likely(obj->gate != NULL))
+ gatepeterson_leave(obj->gate, 0);
+
+error:
+ printk(KERN_ERR "heapbuf_get_extended_stats status: %x\n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(heapbuf_get_extended_stats);
+
+/*
+ * ======== heapbuf_shared_memreq ========
+ * Purpose:
+ * This will get amount of shared memory required for
+ * creation of each instance
+ */
+int heapbuf_shared_memreq(const struct heapbuf_params *params, u32 *buf_size)
+{
+ int state_size = 0;
+ listmp_sharedmemory_params listmp_params;
+
+ BUG_ON(params == NULL);
+
+ /* Size for attrs */
+ state_size = (sizeof(struct heapbuf_attrs) + (HEAPBUF_CACHESIZE - 1))
+ & ~(HEAPBUF_CACHESIZE - 1);
+
+ listmp_params_init(NULL, &listmp_params);
+ listmp_params.resource_id = params->resource_id;
+ state_size += listmp_shared_memreq(&listmp_params);
+
+ /* Determine size for the buffer */
+ *buf_size = params->num_blocks * params->block_size;
+
+ return state_size;
+}
+EXPORT_SYMBOL(heapbuf_shared_memreq);
diff --git a/drivers/dsp/syslink/multicore_ipc/heapbuf_ioctl.c b/drivers/dsp/syslink/multicore_ipc/heapbuf_ioctl.c
new file mode 100755
index 000000000000..cdb6189e81d8
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/heapbuf_ioctl.c
@@ -0,0 +1,479 @@
+/*
+ * heapbuf_ioctl.c
+ *
+ * Heap module manages fixed size buffers that can be used
+ * in a multiprocessor system with shared memory.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <heap.h>
+#include <heapbuf.h>
+#include <heapbuf_ioctl.h>
+#include <sharedregion.h>
+
+/*
+ * ======== heapbuf_ioctl_alloc ========
+ * Purpose:
+ * This ioctl interface to heapbuf_alloc function
+ */
+static int heapbuf_ioctl_alloc(struct heapbuf_cmd_args *cargs)
+{
+ u32 *block_srptr = SHAREDREGION_INVALIDSRPTR;
+ void *block;
+ s32 index;
+ s32 status = 0;
+
+ block = heapbuf_alloc(cargs->args.alloc.handle,
+ cargs->args.alloc.size,
+ cargs->args.alloc.align);
+ if (block != NULL) {
+ index = sharedregion_get_index(block);
+ block_srptr = sharedregion_get_srptr(block, index);
+ }
+ /* The error on above fn will be a null ptr. We are not
+ checking that condition here. We are passing whatever
+ we are getting from the heapbuf module. So IOCTL will succed,
+ but the actual fn might be failed inside heapbuf
+ */
+ cargs->args.alloc.block_srptr = block_srptr;
+ cargs->api_status = 0;
+ return status;
+}
+
+/*
+ * ======== heapbuf_ioctl_free ========
+ * Purpose:
+ * This ioctl interface to heapbuf_free function
+ */
+static int heapbuf_ioctl_free(struct heapbuf_cmd_args *cargs)
+{
+ char *block;
+
+ block = sharedregion_get_ptr(cargs->args.free.block_srptr);
+ cargs->api_status = heapbuf_free(cargs->args.free.handle, block,
+ cargs->args.free.size);
+ return 0;
+}
+
+/*
+ * ======== heapbuf_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to heapbuf_params_init function
+ */
+static int heapbuf_ioctl_params_init(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_params params;
+ s32 status = 0;
+ u32 size;
+
+ heapbuf_params_init(cargs->args.params_init.handle, &params);
+ cargs->api_status = 0;
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct heapbuf_params));
+ if (size)
+ status = -EFAULT;
+
+ return status;
+}
+
+/*
+ * ======== heapbuf_ioctl_create ========
+ * Purpose:
+ * This ioctl interface to heapbuf_create function
+ */
+static int heapbuf_ioctl_create(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_params params;
+ s32 status = 0;
+ u32 size;
+ void *handle = NULL;
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct heapbuf_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ if (cargs->args.create.name_len > 0) {
+ params.name = kmalloc(cargs->args.create.name_len, GFP_KERNEL);
+ if (params.name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ params.name[cargs->args.create.name_len] = '\0';
+ size = copy_from_user(params.name,
+ cargs->args.create.params->name,
+ cargs->args.create.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+ }
+
+ params.shared_addr = sharedregion_get_ptr((u32 *)
+ cargs->args.create.shared_addr_srptr);
+ params.shared_buf = sharedregion_get_ptr((u32 *)
+ cargs->args.create.shared_buf_srptr);
+ params.gate = cargs->args.create.knl_gate;
+ handle = heapbuf_create(&params);
+ cargs->args.create.handle = handle;
+ cargs->api_status = 0;
+
+name_from_usr_error:
+ if (cargs->args.open.name_len > 0)
+ kfree(params.name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== heapbuf_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to heapbuf_delete function
+ */
+static int heapbuf_ioctl_delete(struct heapbuf_cmd_args *cargs)
+{
+ cargs->api_status = heapbuf_delete(&cargs->args.delete.handle);
+ return 0;
+}
+
+/*
+ * ======== heapbuf_ioctl_open ========
+ * Purpose:
+ * This ioctl interface to heapbuf_open function
+ */
+static int heapbuf_ioctl_open(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_params params;
+ void *handle = NULL;
+ s32 status = 0;
+ ulong size;
+
+ size = copy_from_user(&params, cargs->args.open.params,
+ sizeof(struct heapbuf_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ if (cargs->args.open.name_len > 0) {
+ params.name = kmalloc(cargs->args.open.name_len, GFP_KERNEL);
+ if (params.name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ params.name[cargs->args.create.name_len] = '\0';
+ size = copy_from_user(params.name,
+ cargs->args.open.params->name,
+ cargs->args.open.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto free_name;
+ }
+ }
+
+ /* For open by name, the shared_add_srptr may be invalid */
+ if (cargs->args.open.shared_addr_srptr != SHAREDREGION_INVALIDSRPTR) {
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.open.shared_addr_srptr);
+ }
+ params.gate = cargs->args.open.knl_gate;
+
+ cargs->api_status = heapbuf_open(&handle, &params);
+ if (cargs->api_status < 0)
+ goto free_name;
+
+ cargs->args.open.handle = handle;
+ size = copy_to_user(cargs->args.open.params, &params,
+ sizeof(struct heapbuf_params));
+ if (size) {
+ status = -EFAULT;
+ goto copy_to_usr_error;
+ }
+
+ goto free_name;
+
+copy_to_usr_error:
+ if (handle) {
+ heapbuf_close(handle);
+ cargs->args.open.handle = NULL;
+ }
+
+free_name:
+ if (cargs->args.open.name_len > 0)
+ kfree(params.name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== heapbuf_ioctl_close ========
+ * Purpose:
+ * This ioctl interface to heapbuf_close function
+ */
+static int heapbuf_ioctl_close(struct heapbuf_cmd_args *cargs)
+{
+ cargs->api_status = heapbuf_close(cargs->args.close.handle);
+ return 0;
+}
+
+/*
+ * ======== heapbuf_ioctl_shared_memreq ========
+ * Purpose:
+ * This ioctl interface to heapbuf_shared_memreq function
+ */
+static int heapbuf_ioctl_shared_memreq(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_params params;
+ s32 status = 0;
+ ulong size;
+ u32 bytes;
+
+ size = copy_from_user(&params, cargs->args.shared_memreq.params,
+ sizeof(struct heapbuf_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ bytes = heapbuf_shared_memreq(&params,
+ &cargs->args.shared_memreq.buf_size);
+ cargs->args.shared_memreq.bytes = bytes;
+ cargs->api_status = 0;
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== heapbuf_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to heapbuf_get_config function
+ */
+static int heapbuf_ioctl_get_config(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_config config;
+ s32 status = 0;
+ ulong size;
+
+ cargs->api_status = heapbuf_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct heapbuf_config));
+ if (size)
+ status = -EFAULT;
+
+ return status;
+}
+
+/*
+ * ======== heapbuf_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to heapbuf_setup function
+ */
+static int heapbuf_ioctl_setup(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_config config;
+ s32 status = 0;
+ ulong size;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct heapbuf_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = heapbuf_setup(&config);
+
+exit:
+ return status;
+}
+/*
+ * ======== heapbuf_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to heapbuf_destroy function
+ */
+static int heapbuf_ioctl_destroy(struct heapbuf_cmd_args *cargs)
+{
+ cargs->api_status = heapbuf_destroy();
+ return 0;
+}
+
+
+/*
+ * ======== heapbuf_ioctl_get_stats ========
+ * Purpose:
+ * This ioctl interface to heapbuf_get_stats function
+ */
+static int heapbuf_ioctl_get_stats(struct heapbuf_cmd_args *cargs)
+{
+ struct memory_stats stats;
+ s32 status = 0;
+ ulong size;
+
+ cargs->api_status = heapbuf_get_stats(cargs->args.get_stats.handle,
+ &stats);
+ if (status)
+ goto exit;
+
+ size = copy_to_user(cargs->args.get_stats.stats, &stats,
+ sizeof(struct memory_stats));
+ if (size)
+ status = -EFAULT;
+
+exit:
+ return status;
+}
+
+/*
+ * ======== heapbuf_ioctl_get_extended_stats ========
+ * Purpose:
+ * This ioctl interface to heapbuf_get_extended_stats function
+ */
+static int heapbuf_ioctl_get_extended_stats(struct heapbuf_cmd_args *cargs)
+{
+ struct heapbuf_extended_stats stats;
+ s32 status = 0;
+ ulong size;
+
+ cargs->api_status = heapbuf_get_extended_stats(
+ cargs->args.get_extended_stats.handle, &stats);
+ if (cargs->api_status != 0)
+ goto exit;
+
+ size = copy_to_user(cargs->args.get_extended_stats.stats, &stats,
+ sizeof(struct heapbuf_extended_stats));
+ if (size)
+ status = -EFAULT;
+
+exit:
+ return status;
+}
+
+/*
+ * ======== heapbuf_ioctl ========
+ * Purpose:
+ * This ioctl interface for heapbuf module
+ */
+int heapbuf_ioctl(struct inode *pinode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct heapbuf_cmd_args __user *uarg =
+ (struct heapbuf_cmd_args __user *)args;
+ struct heapbuf_cmd_args cargs;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct heapbuf_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_HEAPBUF_ALLOC:
+ status = heapbuf_ioctl_alloc(&cargs);
+ break;
+
+ case CMD_HEAPBUF_FREE:
+ status = heapbuf_ioctl_free(&cargs);
+ break;
+
+ case CMD_HEAPBUF_PARAMS_INIT:
+ status = heapbuf_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_HEAPBUF_CREATE:
+ status = heapbuf_ioctl_create(&cargs);
+ break;
+
+ case CMD_HEAPBUF_DELETE:
+ status = heapbuf_ioctl_delete(&cargs);
+ break;
+
+ case CMD_HEAPBUF_OPEN:
+ status = heapbuf_ioctl_open(&cargs);
+ break;
+
+ case CMD_HEAPBUF_CLOSE:
+ status = heapbuf_ioctl_close(&cargs);
+ break;
+
+ case CMD_HEAPBUF_SHAREDMEMREQ:
+ status = heapbuf_ioctl_shared_memreq(&cargs);
+ break;
+
+ case CMD_HEAPBUF_GETCONFIG:
+ status = heapbuf_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_HEAPBUF_SETUP:
+ status = heapbuf_ioctl_setup(&cargs);
+ break;
+
+ case CMD_HEAPBUF_DESTROY:
+ status = heapbuf_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_HEAPBUF_GETSTATS:
+ status = heapbuf_ioctl_get_stats(&cargs);
+ break;
+
+ case CMD_HEAPBUF_GETEXTENDEDSTATS:
+ status = heapbuf_ioctl_get_extended_stats(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs,
+ sizeof(struct heapbuf_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/ipc_drv.c b/drivers/dsp/syslink/multicore_ipc/ipc_drv.c
new file mode 100755
index 000000000000..2e9a36f53592
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/ipc_drv.c
@@ -0,0 +1,242 @@
+/*
+ * ipc_drv.c
+ *
+ * IPC driver module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/*#ifdef MODULE*/
+#include <linux/module.h>
+/*#endif*/
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+
+#include <ipc_ioctl.h>
+#include <nameserver.h>
+
+#define IPC_NAME "syslink_ipc"
+#define IPC_MAJOR 0
+#define IPC_MINOR 0
+#define IPC_DEVICES 1
+
+struct ipc_device {
+ struct cdev cdev;
+};
+
+struct ipc_device *ipc_device;
+static struct class *ipc_class;
+
+s32 ipc_major = IPC_MAJOR;
+s32 ipc_minor = IPC_MINOR;
+char *ipc_name = IPC_NAME;
+
+module_param(ipc_name, charp, 0);
+MODULE_PARM_DESC(ipc_name, "Device name, default = syslink_ipc");
+
+module_param(ipc_major, int, 0); /* Driver's major number */
+MODULE_PARM_DESC(ipc_major, "Major device number, default = 0 (auto)");
+
+module_param(ipc_minor, int, 0); /* Driver's minor number */
+MODULE_PARM_DESC(ipc_minor, "Minor device number, default = 0 (auto)");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
+
+/*
+ * ======== ipc_open ========
+ * This function is invoked when an application
+ * opens handle to the ipc driver
+ */
+int ipc_open(struct inode *inode, struct file *filp)
+{
+ s32 retval = 0;
+ struct ipc_device *dev;
+
+ dev = container_of(inode->i_cdev, struct ipc_device, cdev);
+ filp->private_data = dev;
+ return retval;
+}
+
+/*
+ * ======== ipc_release ========
+ * This function is invoked when an application
+ * closes handle to the ipc driver
+ */
+int ipc_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/*
+ * ======== ipc_ioctl ========
+ * This function provides IO interface to the
+ * ipc driver
+ */
+int ipc_ioctl(struct inode *ip, struct file *filp, u32 cmd, ulong arg)
+{
+ s32 retval = 0;
+ void __user *argp = (void __user *)arg;
+
+ /* Verify the memory and ensure that it is not is kernel
+ address space
+ */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ retval = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ retval = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+
+ if (retval) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ retval = ipc_ioc_router(cmd, (ulong)argp);
+ return retval;
+
+exit:
+ return retval;
+}
+
+const struct file_operations ipc_fops = {
+open: ipc_open,
+release : ipc_release,
+ioctl : ipc_ioctl,
+};
+
+/*
+ * ======== ipc_modules_Init ========
+ * IPC Initialization routine. will initialize various
+ * sub components (modules) of IPC.
+ */
+static int ipc_modules_init(void)
+{
+ return 0;
+}
+
+/*
+ * ======== ipc_modules_Init ========
+ * IPC cleanup routine. will cleanup of various
+ * sub components (modules) of IPC.
+ */
+static void ipc_modules_exit(void)
+{
+
+}
+
+/*
+ * ======== ipc_init ========
+ * Initialization routine. Executed when the driver is
+ * loaded (as a kernel module), or when the system
+ * is booted (when included as part of the kernel
+ * image).
+ */
+static int __init ipc_init(void)
+{
+ dev_t dev ;
+ s32 retval = 0;
+
+ /* 2.6 device model */
+ if (ipc_major) {
+ dev = MKDEV(ipc_major, ipc_minor);
+ retval = register_chrdev_region(dev, IPC_DEVICES, ipc_name);
+ } else {
+ retval = alloc_chrdev_region(&dev, ipc_minor, IPC_DEVICES,
+ ipc_name);
+ ipc_major = MAJOR(dev);
+ }
+
+ if (retval < 0) {
+ printk(KERN_ERR "ipc_init: can't get major %x \n", ipc_major);
+ goto exit;
+ }
+
+ ipc_device = kmalloc(sizeof(struct ipc_device), GFP_KERNEL);
+ if (!ipc_device) {
+ printk(KERN_ERR "ipc_init: memory allocation failed for "
+ "ipc_device \n");
+ retval = -ENOMEM;
+ goto unreg_exit;
+ }
+
+ memset(ipc_device, 0, sizeof(struct ipc_device));
+ retval = ipc_modules_init();
+ if (retval) {
+ printk(KERN_ERR "ipc_init: ipc initialization failed \n");
+ goto unreg_exit;
+
+ }
+ /* TO DO : NEED TO LOOK IN TO THIS */
+ ipc_class = class_create(THIS_MODULE, "syslink_ipc");
+ if (IS_ERR(ipc_class)) {
+ printk(KERN_ERR "ipc_init: error creating ipc class \n");
+ retval = PTR_ERR(ipc_class);
+ goto unreg_exit;
+ }
+
+ device_create(ipc_class, NULL, MKDEV(ipc_major, ipc_minor), NULL,
+ ipc_name);
+ cdev_init(&ipc_device->cdev, &ipc_fops);
+ ipc_device->cdev.owner = THIS_MODULE;
+ retval = cdev_add(&ipc_device->cdev, dev, IPC_DEVICES);
+ if (retval) {
+ printk(KERN_ERR "ipc_init: failed to add the ipc device \n");
+ goto class_exit;
+ }
+ return retval;
+
+class_exit:
+ class_destroy(ipc_class);
+
+unreg_exit:
+ unregister_chrdev_region(dev, IPC_DEVICES);
+ kfree(ipc_device);
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== ipc_init ========
+ * This function is invoked during unlinking of ipc
+ * module from the kernel. ipc resources are
+ * freed in this function.
+ */
+static void __exit ipc_exit(void)
+{
+ dev_t devno;
+
+ ipc_modules_exit();
+ devno = MKDEV(ipc_major, ipc_minor);
+ if (ipc_device) {
+ cdev_del(&ipc_device->cdev);
+ kfree(ipc_device);
+ }
+ unregister_chrdev_region(devno, IPC_DEVICES);
+ if (ipc_class) {
+ /* remove the device from sysfs */
+ device_destroy(ipc_class, MKDEV(ipc_major, ipc_minor));
+ class_destroy(ipc_class);
+ }
+}
+
+/*
+ * ipc driver initialization and de-initialization functions
+ */
+module_init(ipc_init);
+module_exit(ipc_exit);
diff --git a/drivers/dsp/syslink/multicore_ipc/ipc_ioctl.c b/drivers/dsp/syslink/multicore_ipc/ipc_ioctl.c
new file mode 100755
index 000000000000..b40a1e192e76
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/ipc_ioctl.c
@@ -0,0 +1,80 @@
+/*
+ * ipc_ioctl.c
+ *
+ * This is the collection of ioctl functions that will invoke various ipc
+ * module level functions based on user comands
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/uaccess.h>
+
+#include <ipc_ioctl.h>
+#include <multiproc_ioctl.h>
+#include <nameserver_ioctl.h>
+#include <heapbuf_ioctl.h>
+#include <sharedregion_ioctl.h>
+#include <gatepeterson_ioctl.h>
+#include <listmp_sharedmemory_ioctl.h>
+#include <messageq_ioctl.h>
+#include <messageq_transportshm_ioctl.h>
+#include <nameserver_remotenotify_ioctl.h>
+#include <sysmgr_ioctl.h>
+#include <sysmemmgr_ioctl.h>
+
+/*
+ * ======== ipc_ioctl_router ========
+ * Purpose:
+ * This will route the ioctl commands to proper
+ * modules
+ */
+int ipc_ioc_router(u32 cmd, ulong arg)
+{
+ s32 retval = 0;
+ u32 ioc_nr = _IOC_NR(cmd);
+
+ if (ioc_nr >= MULTIPROC_BASE_CMD && ioc_nr <= MULTIPROC_END_CMD)
+ retval = multiproc_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= NAMESERVER_BASE_CMD &&
+ ioc_nr <= NAMESERVER_END_CMD)
+ retval = nameserver_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= HEAPBUF_BASE_CMD && ioc_nr <= HEAPBUF_END_CMD)
+ retval = heapbuf_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= SHAREDREGION_BASE_CMD &&
+ ioc_nr <= SHAREDREGION_END_CMD)
+ retval = sharedregion_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= GATEPETERSON_BASE_CMD &&
+ ioc_nr <= GATEPETERSON_END_CMD)
+ retval = gatepeterson_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= LISTMP_SHAREDMEMORY_BASE_CMD &&
+ ioc_nr <= LISTMP_SHAREDMEMORY_END_CMD)
+ retval = listmp_sharedmemory_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= MESSAGEQ_BASE_CMD &&
+ ioc_nr <= MESSAGEQ_END_CMD)
+ retval = messageq_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= MESSAGEQ_TRANSPORTSHM_BASE_CMD &&
+ ioc_nr <= MESSAGEQ_TRANSPORTSHM_END_CMD)
+ retval = messageq_transportshm_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= NAMESERVERREMOTENOTIFY_BASE_CMD &&
+ ioc_nr <= NAMESERVERREMOTENOTIFY_END_CMD)
+ retval = nameserver_remotenotify_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= SYSMGR_BASE_CMD &&
+ ioc_nr <= SYSMGR_END_CMD)
+ retval = sysmgr_ioctl(NULL, NULL, cmd, arg);
+ else if (ioc_nr >= SYSMEMMGR_BASE_CMD &&
+ ioc_nr <= SYSMEMMGR_END_CMD)
+ retval = sysmemmgr_ioctl(NULL, NULL, cmd, arg);
+ else
+ retval = -ENOTTY;
+
+ return retval;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/listmp.c b/drivers/dsp/syslink/multicore_ipc/listmp.c
new file mode 100644
index 000000000000..742c67f58f4c
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/listmp.c
@@ -0,0 +1,440 @@
+/*
+ * listmp_sharedmemory.c
+ *
+ * The listmp_sharedmemory is a linked-list based module designed to be
+ * used in a multi-processor environment. It is designed to
+ * provide a means of communication between different processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/*!
+ *
+ * This module implements the ListMP.
+ * This module is instance based. Each instance requires a small
+ * piece of shared memory. This is specified via the #shared_addr
+ * parameter to the create. The proper #shared_addr_size parameter
+ * can be determined via the #sharedMemReq call. Note: the
+ * parameters to this function must be the same that will used to
+ * create or open the instance.
+ * The ListMP module uses a #ti.sdo.utils.NameServer instance
+ * to store instance information when an instance is created and
+ * the name parameter is non-NULL. If a name is supplied, it must
+ * be unique for all ListMP instances.
+ * The #create also initializes the shared memory as needed. The
+ * shared memory must be initialized to 0 or all ones
+ * (e.g. 0xFFFFFFFFF) before the ListMP instance is created.
+ * Once an instance is created, an open can be performed. The #open
+ * is used to gain access to the same ListMP instance.
+ * Generally an instance is created on one processor and opened
+ * on the other processor.
+ * The open returns a ListMP instance handle like the create,
+ * however the open does not modify the shared memory. Generally an
+ * instance is created on one processor and opened on the other
+ * processor.
+ * There are two options when opening the instance:
+ * @li Supply the same name as specified in the create. The
+ * ListMP module queries the NameServer to get the needed
+ * information.
+ * @li Supply the same #shared_addr value as specified in the
+ * create. If the open is called before the instance is created,
+ * open returns NULL.
+ * There is currently a list of restrictions for the module:
+ * @li Both processors must have the same endianness. Endianness
+ * conversion may supported in a future version of ListMP.
+ * @li The module will be made a gated module
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Utilities headers */
+#include <linux/string.h>
+#include <linux/list.h>
+
+/* Module level headers */
+#include <nameserver.h>
+#include <listmp.h>
+#include <listmp_sharedmemory.h>
+
+
+/*
+ * ======== listmp_params_init ========
+ * Purpose:
+ * Function initializes listmp parameters
+ */
+void listmp_params_init(void *listmp_handle, struct listmp_params *params)
+{
+ BUG_ON(params == NULL);
+ listmp_sharedmemory_params_init(listmp_handle, params);
+}
+
+/*
+ * ======== listmp_shared_memreq ========
+ * Purpose:
+ * Function to get shared memory requirement for the module
+ */
+int listmp_shared_memreq(struct listmp_params *params)
+{
+ int shared_memreq = 0;
+
+ if (WARN_ON(params == NULL))
+ goto exit;
+
+ shared_memreq = listmp_sharedmemory_shared_memreq(params);
+exit:
+ return shared_memreq;
+}
+
+/*
+ * ======== listmp_create ========
+ * Purpose:
+ * Creates a new instance of listmp_sharedmemory module.
+ */
+void *listmp_create(struct listmp_params *params)
+{
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(params == NULL))
+ goto exit;
+
+ if (params->list_type == listmp_type_SHARED)
+ handle = (struct listmp_object *)
+ listmp_sharedmemory_create(params);
+ return (void *)handle;
+
+exit:
+ printk(KERN_ERR "listmp_create: listmp_params passed are NULL!\n");
+ return NULL;
+}
+
+/*
+ * ======== listmp_delete ========
+ * Purpose:
+ * Deletes an instance of listmp_sharedmemory module.
+ */
+int listmp_delete(void **listmp_handle_ptr)
+{
+ int status = 0;
+
+ if (WARN_ON(*listmp_handle_ptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (((struct listmp_object *)(*listmp_handle_ptr))->list_type == \
+ listmp_type_SHARED)
+ status = listmp_sharedmemory_delete(listmp_handle_ptr);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_delete failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_open ========
+ * Purpose:
+ * Opens an instance ofa previously created listmp_sharedmemory module.
+ */
+int listmp_open(void **listmp_handle_ptr, struct listmp_params *params)
+{
+ int status = 0;
+
+ if (WARN_ON(listmp_handle_ptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (params->list_type == listmp_type_SHARED)
+ status = listmp_sharedmemory_open(listmp_handle_ptr, params);
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "listmp_open failed! status = 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== listmp_close ========
+ * Purpose:
+ * Closes an instance of a previously opened listmp_sharedmemory module.
+ */
+int listmp_close(void *listmp_handle)
+{
+ int status = 0;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (((struct listmp_object *)listmp_handle)->list_type == \
+ listmp_type_SHARED)
+ status = listmp_sharedmemory_close(listmp_handle);
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "listmp_close failed! status = 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== listmp_empty ========
+ * Purpose:
+ * Function to check if list is empty
+ */
+bool listmp_empty(void *listmp_handle)
+{
+ bool isEmpty = false;
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(listmp_handle == NULL))
+ goto exit;
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->empty == NULL);
+ isEmpty = handle->empty(listmp_handle);
+
+exit:
+ return isEmpty;
+}
+
+/*
+ * ======== listmp_get_head ========
+ * Purpose:
+ * Function to get head element from a listmp_sharedmemory list
+ */
+void *listmp_get_head(void *listmp_handle)
+{
+ struct listmp_object *handle = NULL;
+ struct listmp_elem *elem = NULL;
+
+ if (WARN_ON(listmp_handle == NULL))
+ goto exit;
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->get_head == NULL);
+ elem = handle->get_head(listmp_handle);
+
+exit:
+ return elem;
+}
+
+/*
+ * ======== listmp_get_tail =====
+ * Purpose:
+ * Function to get tailement from a listmp_sharedmemory list
+ */
+void *listmp_get_tail(void *listmp_handle)
+{
+ struct listmp_object *handle = NULL;
+ struct listmp_elem *elem = NULL;
+
+ if (WARN_ON(listmp_handle == NULL))
+ goto exit;
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->get_tail == NULL);
+ elem = handle->get_tail(listmp_handle);
+
+exit:
+ return elem;
+}
+
+/*
+ * ======== listmp_put_head ========
+ * Purpose:
+ * Function to put head element into a listmp_sharedmemory list
+ */
+int listmp_put_head(void *listmp_handle, struct listmp_elem *elem)
+{
+ int status = 0;
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct listmp_object *) listmp_handle;
+
+ BUG_ON(handle->put_head == NULL);
+ status = handle->put_head(listmp_handle, elem);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_put_head failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_put_tail ========
+ * Purpose:
+ * Function to put tail element into a listmp_sharedmemory list
+ */
+int listmp_put_tail(void *listmp_handle, struct listmp_elem *elem)
+{
+ int status = 0;
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->put_tail == NULL);
+ status = handle->put_tail(listmp_handle, elem);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_put_tail failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_insert ========
+ * Purpose:
+ * Function to insert element into a listmp_sharedmemory list
+ */
+int listmp_insert(void *listmp_handle, struct listmp_elem *elem,
+ struct listmp_elem *curElem)
+{
+ int status = 0;
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(curElem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->insert == NULL);
+ status = handle->insert(listmp_handle, elem, curElem);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_insert failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_remove ========
+ * Purpose:
+ * Function to remove an element from a listmp_sharedmemory list
+ */
+int listmp_remove(void *listmp_handle, struct listmp_elem *elem)
+{
+ int status = LISTMP_SUCCESS;
+ struct listmp_object *handle = NULL;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->remove == NULL);
+ status = handle->remove(listmp_handle, elem);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_remove failed! status = 0x%x\n",
+ status);
+ }
+ return status ;
+}
+
+/*
+ * ======== listmp_next ========
+ * Purpose:
+ * Function to return the next element from a listmp_sharedmemory list
+ */
+void *listmp_next(void *listmp_handle, struct listmp_elem *elem)
+{
+ struct listmp_object *handle = NULL;
+ struct listmp_elem *nextElem = NULL;
+
+ if (WARN_ON(listmp_handle == NULL))
+ goto exit;
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->next == NULL);
+ nextElem = handle->next(listmp_handle, elem);
+
+exit:
+ return nextElem;
+}
+
+/*
+ * ======== listmp_next ========
+ * Purpose:
+ * Function to return the prev element from a listmp_sharedmemory list
+ */
+void *listmp_prev(void *listmp_handle, struct listmp_elem *elem)
+{
+ struct listmp_object *handle = NULL;
+ struct listmp_elem *prevElem = NULL;
+
+ if (WARN_ON(listmp_handle == NULL))
+ goto exit;
+
+ handle = (struct listmp_object *)listmp_handle;
+
+ BUG_ON(handle->prev == NULL);
+ prevElem = handle->prev(listmp_handle, elem);
+
+exit:
+ return prevElem;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory.c b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory.c
new file mode 100755
index 000000000000..6b18a11f5a5f
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory.c
@@ -0,0 +1,1473 @@
+/*
+ * listmp_sharedmemory.c
+ *
+ * The listmp_sharedmemory is a linked-list based module designed to be
+ * used in a multi-processor environment. It is designed to
+ * provide a means of communication between different processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/*!
+ * This module is instance based. Each instance requires a small
+ * piece of shared memory. This is specified via the #shared_addr
+ * parameter to the create. The proper #shared_addr_size parameter
+ * can be determined via the #shared_memreq call. Note: the
+ * parameters to this function must be the same that will used to
+ * create or open the instance.
+ * The listmp_sharedmemory module uses a #NameServer instance
+ * to store instance information when an instance is created and
+ * the name parameter is non-NULL. If a name is supplied, it must
+ * be unique for all listmp_sharedmemory instances.
+ * The #create also initializes the shared memory as needed. The
+ * shared memory must be initialized to 0 or all ones
+ * (e.g. 0xFFFFFFFFF) before the listmp_sharedmemory instance
+ * is created.
+ * Once an instance is created, an open can be performed. The #open
+ * is used to gain access to the same listmp_sharedmemory instance.
+ * Generally an instance is created on one processor and opened
+ * on the other processor.
+ * The open returns a listmp_sharedmemory instance handle like the
+ * create, however the open does not modify the shared memory.
+ * Generally an instance is created on one processor and opened
+ * on the other processor.
+ * There are two options when opening the instance:
+ * @li Supply the same name as specified in the create. The
+ * listmp_sharedmemory module queries the NameServer to get the
+ * needed information.
+ * @li Supply the same #shared_addr value as specified in the
+ * create.
+ * If the open is called before the instance is created, open
+ * returns NULL.
+ * There is currently a list of restrictions for the module:
+ * @li Both processors must have the same endianness. Endianness
+ * conversion may supported in a future version of
+ * listmp_sharedmemory.
+ * @li The module will be made a gated module
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Utilities headers */
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+/* Syslink headers */
+#include <syslink/atomic_linux.h>
+
+/* Module level headers */
+#include <nameserver.h>
+#include <sharedregion.h>
+#include <multiproc.h>
+#include "_listmp.h"
+#include <listmp.h>
+#include <gatepeterson.h>
+#include <listmp_sharedmemory.h>
+
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/*! @brief Macro to make a correct module magic number with refCount */
+#define LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(x) \
+ ((LISTMPSHAREDMEMORY_MODULEID << 12u) | (x))
+
+/*!
+ * @brief Name of the reserved NameServer used for listmp_sharedmemory.
+ */
+#define LISTMP_SHAREDMEMORY_NAMESERVER "ListMPSharedMemory"
+
+/*!
+ * @brief Cache size
+ */
+#define LISTMP_SHAREDMEMORY_CACHESIZE 128
+
+
+
+/* =============================================================================
+ * Structures and Enums
+ * =============================================================================
+ */
+/*! @brief structure for listmp_sharedmemory module state */
+struct listmp_sharedmemory_module_object {
+ atomic_t ref_count;
+ /*!< Reference count */
+ void *ns_handle;
+ /*!< Handle to the local NameServer used for storing GP objects */
+ struct list_head obj_list;
+ /*!< List holding created listmp_sharedmemory objects */
+ struct mutex *local_gate;
+ /*!< Handle to lock for protecting obj_list */
+ struct listmp_config cfg;
+ /*!< Current config values */
+ struct listmp_config default_cfg;
+ /*!< Default config values */
+ listmp_sharedmemory_params default_inst_params;
+ /*!< Default instance creation parameters */
+};
+
+/*!
+ * @var listmp_sharedmemory_nameServer
+ *
+ * @brief Name of the reserved NameServer used for listmp_sharedmemory.
+ */
+static
+struct listmp_sharedmemory_module_object listmp_sharedmemory_state = {
+ .default_cfg.max_name_len = 32,
+ .default_cfg.use_name_server = true,
+ .default_inst_params.shared_addr = 0,
+ .default_inst_params.shared_addr_size = 0,
+ .default_inst_params.name = NULL,
+ .default_inst_params.gate = NULL,
+ .default_inst_params.list_type = listmp_type_SHARED};
+
+/*!
+ * @brief Structure for the internal Handle for the listmp_sharedmemory.
+ */
+struct listmp_sharedmemory_obj{
+ struct list_head list_elem;
+ /*!< Used for creating a linked list */
+ VOLATILE struct listmp_elem *listmp_elem;
+ /*!< Used for storing listmp_sharedmemory element */
+ struct listmp_proc_attrs *owner;
+ /*!< Creator's attributes associated with an instance */
+ listmp_sharedmemory_params params;
+ /*!< the parameter structure */
+ void *ns_key;
+ u32 index;
+ /*!< the index for SrPtr */
+ VOLATILE struct listmp_attrs *attrs;
+ /*!< Shared memory attributes */
+ void *top;
+ /*!< Pointer to the top Object */
+};
+
+
+/* =============================================================================
+ * Function definitions
+ * =============================================================================
+ */
+/*
+ * ======== _listmp_sharedmemory_create ========
+ * Purpose:
+ * Creates a new instance of listmp_sharedmemory module. This is an internal
+ * function because both listmp_sharedmemory_create and
+ * listmp_sharedmemory_open call use the same functionality.
+ */
+static listmp_sharedmemory_handle
+_listmp_sharedmemory_create(listmp_sharedmemory_params *params,
+ u32 create_flag);
+
+
+/* =============================================================================
+ * Function API's
+ * =============================================================================
+ */
+/*
+ * ======== listmp_sharedmemory_get_config ========
+ * Purpose:
+ * Function to get configuration parameters to setup the
+ * the listmp_sharedmemory module.
+ */
+int listmp_sharedmemory_get_config(struct listmp_config *cfgParams)
+{
+ int status = 0;
+
+ if (WARN_ON(cfgParams == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true)
+ /* If setup has not yet been called) */
+ memcpy(cfgParams, &listmp_sharedmemory_state.default_cfg,
+ sizeof(struct listmp_config));
+ else
+ memcpy(cfgParams, &listmp_sharedmemory_state.cfg,
+ sizeof(struct listmp_config));
+ return 0;
+
+exit:
+ printk(KERN_ERR "listmp_sharedmemory_get_config failed: "
+ "status = 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_setup ========
+ * Purpose:
+ * Function to setup the listmp_sharedmemory module.
+ */
+int listmp_sharedmemory_setup(struct listmp_config *config)
+{
+ int status = 0;
+ int status1 = 0;
+ void *nshandle = NULL;
+ struct nameserver_params params;
+ struct listmp_config tmp_cfg;
+
+ /* This sets the refCount variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable.
+ */
+ atomic_cmpmask_and_set(&listmp_sharedmemory_state.ref_count,
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&listmp_sharedmemory_state.ref_count)
+ != LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (config == NULL) {
+ listmp_sharedmemory_get_config(&tmp_cfg);
+ config = &tmp_cfg;
+ }
+
+ if (WARN_ON(config->max_name_len == 0)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (likely((config->use_name_server == true))) {
+ /* Initialize the parameters */
+ nameserver_params_init(&params);
+ params.max_value_len = 4;
+ params.max_name_len = config->max_name_len;
+ /* Create the nameserver for modules */
+ nshandle = nameserver_create(
+ LISTMP_SHAREDMEMORY_NAMESERVER, &params);
+ if (unlikely(nshandle == NULL)) {
+ status = LISTMPSHAREDMEMORY_E_FAIL;
+ goto exit;
+ }
+ }
+
+ listmp_sharedmemory_state.ns_handle = nshandle;
+ /* Construct the list object */
+ INIT_LIST_HEAD(&listmp_sharedmemory_state.obj_list);
+ /* Create a lock for protecting list object */
+ listmp_sharedmemory_state.local_gate = \
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (listmp_sharedmemory_state.local_gate == NULL) {
+ status = -ENOMEM;
+ goto clean_nameserver;
+ }
+
+ mutex_init(listmp_sharedmemory_state.local_gate);
+ /* Copy the cfg */
+ memcpy(&listmp_sharedmemory_state.cfg, config,
+ sizeof(struct listmp_config));
+ return 0;
+
+clean_nameserver:
+ printk(KERN_ERR "listmp_sharedmemory_setup: Failed to create the local "
+ "gate! status = 0x%x\n", status);
+ atomic_set(&listmp_sharedmemory_state.ref_count,
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0));
+ status1 = nameserver_delete
+ (&(listmp_sharedmemory_state.ns_handle));
+ BUG_ON(status1 < 0);
+
+exit:
+ printk(KERN_ERR "listmp_sharedmemory_setup failed! status = 0x%x\n",
+ status);
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_destroy ========
+ * Purpose:
+ * Function to destroy the listmp_sharedmemory module.
+ */
+int listmp_sharedmemory_destroy(void)
+{
+ int status = 0;
+ int status1 = 0;
+ struct list_head *elem = NULL;
+ struct list_head *head = &listmp_sharedmemory_state.obj_list;
+ struct list_head *next;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (atomic_dec_return(&listmp_sharedmemory_state.ref_count)
+ == LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0)) {
+ /* Temporarily increment refCount here. */
+ atomic_set(&listmp_sharedmemory_state.ref_count,
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1));
+ /* Check if any listmp_sharedmemory instances have not been
+ * deleted so far. If not, delete them. */
+ for (elem = (head)->next; elem != (head); elem = next) {
+ /* Retain the next pointer so it doesn't
+ get overwritten */
+ next = elem->next;
+ if (((struct listmp_sharedmemory_obj *) elem)->owner
+ ->proc_id == multiproc_get_id(NULL)) {
+ status1 = listmp_sharedmemory_delete(
+ (listmp_sharedmemory_handle *)
+ &(((struct listmp_sharedmemory_obj *) \
+ elem)->top));
+ WARN_ON(status1 < 0);
+ } else {
+ status1 = listmp_sharedmemory_close(
+ (listmp_sharedmemory_handle)
+ (((struct listmp_sharedmemory_obj *) \
+ elem)->top));
+ WARN_ON(status1 < 0);
+ }
+ }
+
+ /* Again reset refCount. */
+ atomic_set(&listmp_sharedmemory_state.ref_count,
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0));
+ if (likely(listmp_sharedmemory_state.cfg.use_name_server
+ == true)) {
+ /* Delete the nameserver for modules */
+ status = nameserver_delete(
+ &(listmp_sharedmemory_state.ns_handle));
+ BUG_ON(status < 0);
+ }
+
+ /* Destruct the list object */
+ list_del(&listmp_sharedmemory_state.obj_list);
+ /* Delete the list lock */
+ kfree(listmp_sharedmemory_state.local_gate);
+ listmp_sharedmemory_state.local_gate = NULL;
+ memset(&listmp_sharedmemory_state.cfg, 0,
+ sizeof(struct listmp_config));
+ /* Decrease the refCount */
+ atomic_set(&listmp_sharedmemory_state.ref_count,
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0));
+ }
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_destroy failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_params_init ========
+ * Purpose:
+ * Function to initialize the config-params structure with supplier-specified
+ * defaults before instance creation.
+ */
+void listmp_sharedmemory_params_init(listmp_sharedmemory_handle handle,
+ listmp_sharedmemory_params *params)
+{
+ s32 status = 0;
+ struct listmp_sharedmemory_obj *obj = NULL;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (handle == NULL) {
+ memcpy(params,
+ &(listmp_sharedmemory_state.default_inst_params),
+ sizeof(listmp_sharedmemory_params));
+ } else {
+ obj = (struct listmp_sharedmemory_obj *)
+ (((listmp_sharedmemory_object *) handle)->obj);
+
+ memcpy((void *)&obj->params,
+ (void *)params,
+ sizeof(listmp_sharedmemory_params));
+ }
+ return;
+
+exit:
+ printk(KERN_ERR "listmp_sharedmemory_params_init failed! "
+ "status = 0x%x\n", status);
+ return;
+}
+
+/*
+ * ======== listmp_sharedmemory_create ========
+ * Purpose:
+ * Creates a new instance of listmp_sharedmemory module.
+ */
+listmp_sharedmemory_handle listmp_sharedmemory_create(
+ listmp_sharedmemory_params *params)
+{
+ s32 status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON((params->shared_addr == (u32)NULL)
+ && (params->list_type != listmp_type_FAST))) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(params->shared_addr_size
+ < listmp_sharedmemory_shared_memreq(params))) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)
+ _listmp_sharedmemory_create(params, true);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_create failed! "
+ "status = 0x%x\n", status);
+ }
+ return (listmp_sharedmemory_handle) handle;
+}
+
+/*
+ * ======== listmp_sharedmemory_delete ========
+ * Purpose:
+ * Deletes a instance of listmp_sharedmemory instance object.
+ */
+int listmp_sharedmemory_delete(listmp_sharedmemory_handle *listmp_handleptr)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ listmp_sharedmemory_params *params = NULL;
+ u32 key;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(listmp_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(*listmp_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *) (*listmp_handleptr);
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+ params = (listmp_sharedmemory_params *) &obj->params;
+
+ if (obj->owner->proc_id != multiproc_get_id(NULL)) {
+ status = -EPERM;
+ goto exit;
+ }
+
+ if (obj->owner->open_count > 1) {
+ status = -EBUSY;
+ goto exit;
+ }
+
+ if (obj->owner->open_count != 1) {
+ status = -EBUSY;
+ goto exit;
+ }
+
+ /* Remove from the local list */
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ list_del(&obj->list_elem);
+ mutex_unlock(listmp_sharedmemory_state.local_gate);
+
+ if (likely(params->name != NULL)) {
+ /* Free memory for the name */
+ kfree(params->name);
+ /* Remove from the name server */
+ if (likely(listmp_sharedmemory_state.cfg.use_name_server)) {
+ if (obj->ns_key != NULL) {
+ nameserver_remove_entry(
+ listmp_sharedmemory_state.ns_handle,
+ obj->ns_key);
+ obj->ns_key = NULL;
+ }
+ }
+ }
+
+ /* Free memory for the processor info's */
+ kfree(obj->owner);
+ /* Now free the handle */
+ kfree(obj);
+ obj = NULL;
+
+ /* Now free the handle */
+ kfree(handle);
+ handle = NULL;
+ *listmp_handleptr = NULL;
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_delete failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+
+}
+
+
+/*
+ * ======== listmp_sharedmemory_shared_memreq ========
+ * Purpose:
+ * Function to return the amount of shared memory required for creation of
+ * each instance.
+ */
+int listmp_sharedmemory_shared_memreq(listmp_sharedmemory_params *params)
+{
+ int retval = 0;
+
+ if (WARN_ON(params == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (params->list_type == listmp_type_SHARED)
+ retval = (LISTMP_SHAREDMEMORY_CACHESIZE * 2);
+
+exit:
+ if (retval < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_shared_memreq failed! "
+ "retval = 0x%x\n", retval);
+ }
+ /*! @retval ((1 * sizeof(struct listmp_elem))
+ *! + 1 * sizeof(struct listmp_attrs)) if params is null */
+ /*! @retval (2 * cacheSize) if params is provided */
+ /*! @retval (0) if hardware queue */
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_open ========
+ * Purpose:
+ * Function to open a listmp_sharedmemory instance
+ */
+int listmp_sharedmemory_open(listmp_sharedmemory_handle *listmp_handleptr,
+ listmp_sharedmemory_params *params)
+{
+ int status = 0;
+ bool done_flag = false;
+ struct list_head *elem;
+ u32 key;
+ u32 shared_shm_base;
+ struct listmp_attrs *attrs;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(listmp_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON((listmp_sharedmemory_state.cfg.use_name_server == false)
+ && (params->shared_addr == (u32)NULL))) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON((listmp_sharedmemory_state.cfg.use_name_server == true)
+ && (params->shared_addr == (u32)NULL))
+ && (params->name == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ /* First check in the local list */
+ list_for_each(elem, &listmp_sharedmemory_state.obj_list) {
+ if (((struct listmp_sharedmemory_obj *)elem)->params.shared_addr
+ == params->shared_addr) {
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ if (((struct listmp_sharedmemory_obj *)elem)
+ ->owner->proc_id
+ == multiproc_get_id(NULL))
+ ((struct listmp_sharedmemory_obj *)elem)
+ ->owner->open_count++;
+ mutex_unlock(
+ listmp_sharedmemory_state.local_gate);
+ *listmp_handleptr = \
+ (((struct listmp_sharedmemory_obj *)
+ elem)->top);
+ done_flag = true;
+ break;
+ } else if ((params->name != NULL)
+ && (((struct listmp_sharedmemory_obj *)elem) \
+ ->params.name != NULL)){
+ if (strcmp(((struct listmp_sharedmemory_obj *)elem)
+ ->params.name, params->name) == 0) {
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ if (((struct listmp_sharedmemory_obj *)elem)
+ ->owner->proc_id
+ == multiproc_get_id(NULL))
+ ((struct listmp_sharedmemory_obj *)elem)
+ ->owner->open_count++;
+ mutex_unlock(
+ listmp_sharedmemory_state.local_gate);
+ *listmp_handleptr = \
+ (((struct listmp_sharedmemory_obj *)
+ elem)->top);
+ done_flag = true;
+ break;
+ }
+ }
+ }
+
+ if (likely(done_flag == false)) {
+ if (unlikely(params->shared_addr == NULL)) {
+ if (likely(listmp_sharedmemory_state.cfg.use_name_server
+ == true)){
+ /* Find in name server */
+ status =
+ nameserver_get(
+ listmp_sharedmemory_state.ns_handle,
+ params->name,
+ &shared_shm_base,
+ sizeof(u32),
+ NULL);
+ if (status >= 0)
+ params->shared_addr =
+ sharedregion_get_ptr(
+ (u32 *)shared_shm_base);
+ }
+ }
+ }
+
+ if (status >= 0) {
+ attrs = (struct listmp_attrs *) (params->shared_addr);
+ if (unlikely(attrs->status != (LISTMP_SHAREDMEMORY_CREATED)))
+ status = LISTMPSHAREDMEMORY_E_NOTCREATED;
+ else if (unlikely(attrs->version !=
+ (LISTMP_SHAREDMEMORY_VERSION)))
+ status = LISTMPSHAREDMEMORY_E_VERSION;
+ }
+
+ if (likely(status >= 0))
+ *listmp_handleptr = (listmp_sharedmemory_handle)
+ _listmp_sharedmemory_create(params, false);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_open failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_close ========
+ * Purpose:
+ * Function to close a previously opened instance
+ */
+int listmp_sharedmemory_close(listmp_sharedmemory_handle listmp_handle)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ listmp_sharedmemory_params *params = NULL;
+ u32 key;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+ if (obj == NULL) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ if (obj->owner->proc_id == multiproc_get_id(NULL))
+ (obj)->owner->open_count--;
+
+ params = (listmp_sharedmemory_params *) &obj->params;
+ /* Check if ListMP is opened on same processor*/
+ if (((struct listmp_sharedmemory_obj *)obj)->owner->creator == false) {
+ list_del(&obj->list_elem);
+ /* remove from the name server */
+ if (params->name != NULL)
+ /* Free memory for the name */
+ kfree(params->name);
+
+ kfree(obj->owner);
+ kfree(obj);
+ obj = NULL;
+ kfree(handle);
+ handle = NULL;
+ }
+
+ mutex_unlock(listmp_sharedmemory_state.local_gate);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_close failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_empty ========
+ * Purpose:
+ * Function to check if the shared memory list is empty
+ */
+bool listmp_sharedmemory_empty(listmp_sharedmemory_handle listmp_handle)
+{
+
+ int status = 0;
+ bool is_empty = false;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ s32 retval = 0;
+ struct listmp_elem *sharedHead;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0) {
+ status = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /*! @retval true if list is empty */
+ sharedHead = (struct listmp_elem *)(sharedregion_get_srptr(
+ (void *)obj->listmp_elem, obj->index));
+
+ if (obj->listmp_elem->next == sharedHead)
+ is_empty = true;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ return is_empty;
+}
+
+/*
+ * ======== listmp_sharedmemory_get_head ========
+ * Purpose:
+ * Function to get head element from a shared memory list
+ */
+void *listmp_sharedmemory_get_head(listmp_sharedmemory_handle listmp_handle)
+{
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *elem = NULL;
+ struct listmp_elem *localHeadNext = NULL;
+ struct listmp_elem *localNext = NULL;
+ struct listmp_elem *sharedHead = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true)
+ goto exit;
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ /*! @retval NULL if listmp_handle passed is NULL */
+ elem = NULL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0)
+ goto exit;
+ }
+
+ localHeadNext = sharedregion_get_ptr((u32 *)obj->listmp_elem->next);
+ /* See if the listmp_sharedmemory_object was empty */
+ if (localHeadNext == (struct listmp_elem *)obj->listmp_elem) {
+ /*! @retval NULL if list is empty */
+ elem = NULL ;
+ } else {
+ /* Elem to return */
+ elem = localHeadNext;
+
+ localNext = sharedregion_get_ptr((u32 *)elem->next);
+ sharedHead = (struct listmp_elem *) sharedregion_get_srptr(
+ (void *)obj->listmp_elem, obj->index);
+
+ /* Fix the head of the list next pointer */
+ obj->listmp_elem->next = elem->next;
+
+ /* Fix the prev pointer of the new first elem on the
+ list */
+ localNext->prev = sharedHead;
+ }
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ return elem;
+}
+
+/*
+ * ======== listmp_sharedmemory_get_tail ========
+ * Purpose:
+ * Function to get tail element from a shared memory list
+ */
+void *listmp_sharedmemory_get_tail(listmp_sharedmemory_handle listmp_handle)
+{
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *elem = NULL;
+ struct listmp_elem *localHeadNext = NULL;
+ struct listmp_elem *localHeadPrev = NULL;
+ struct listmp_elem *localPrev = NULL;
+ struct listmp_elem *sharedHead = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true)
+ goto exit;
+
+ if (WARN_ON(listmp_sharedmemory_state.ns_handle == NULL)) {
+ /*! @retval NULL if Module was not initialized */
+ elem = NULL;
+ goto exit;
+ }
+ if (WARN_ON(listmp_handle == NULL)) {
+ /*! @retval NULL if listmp_handle passed is NULL */
+ elem = NULL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0)
+ goto exit;
+ }
+
+ localHeadNext = sharedregion_get_ptr((u32 *)obj->listmp_elem->next);
+ localHeadPrev = sharedregion_get_ptr((u32 *)obj->listmp_elem->prev);
+
+ /* See if the listmp_sharedmemory_object was empty */
+ if (localHeadNext == (struct listmp_elem *)obj->listmp_elem) {
+ /* Empty, return NULL */
+ elem = NULL ;
+ } else {
+ /* Elem to return */
+ elem = localHeadPrev;
+ localPrev = sharedregion_get_ptr((u32 *)elem->prev);
+ sharedHead = (struct listmp_elem *) sharedregion_get_srptr(
+ (void *)obj->listmp_elem, obj->index);
+ obj->listmp_elem->prev = elem->prev;
+ localPrev->next = sharedHead;
+ }
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ return elem;
+}
+
+/*
+ * ======== listmp_sharedmemory_put_head ========
+ * Purpose:
+ * Function to put head element into a shared memory list
+ */
+int listmp_sharedmemory_put_head(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *elem)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *localNextElem = NULL;
+ struct listmp_elem *sharedElem = NULL;
+ struct listmp_elem *sharedHead = NULL;
+ s32 retval = 0;
+ u32 index;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(listmp_handle == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ index = sharedregion_get_index(elem);
+ sharedElem = (struct listmp_elem *) sharedregion_get_srptr(elem, index);
+ sharedHead = (struct listmp_elem *)sharedregion_get_srptr(
+ (void *)obj->listmp_elem, obj->index);
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0) {
+ status = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /* Add the new elem into the list */
+ elem->next = obj->listmp_elem->next;
+ elem->prev = sharedHead;
+ localNextElem = sharedregion_get_ptr((u32 *)elem->next);
+ localNextElem->prev = sharedElem;
+ obj->listmp_elem->next = sharedElem;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_put_head failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_put_tail ========
+ * Purpose:
+ * Function to put tail element into a shared memory list
+ */
+int listmp_sharedmemory_put_tail(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *elem)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *localPrevElem = NULL;
+ struct listmp_elem *sharedElem = NULL;
+ struct listmp_elem *sharedHead = NULL;
+ s32 retval = 0;
+ u32 index;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ /* Safe to do outside the gate */
+ index = sharedregion_get_index(elem);
+ sharedElem = (struct listmp_elem *)
+ sharedregion_get_srptr(elem, index);
+ sharedHead = (struct listmp_elem *)sharedregion_get_srptr
+ ((void *)obj->listmp_elem,
+ obj->index);
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0) {
+ status = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /* Add the new elem into the list */
+ elem->next = sharedHead;
+ elem->prev = obj->listmp_elem->prev;
+ localPrevElem = sharedregion_get_ptr((u32 *)elem->prev);
+ localPrevElem->next = sharedElem;
+ obj->listmp_elem->prev = sharedElem;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_put_tail failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_insert ========
+ * Purpose:
+ * Function to insert an element into a shared memory list
+ */
+int listmp_sharedmemory_insert(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *new_elem,
+ struct listmp_elem *cur_elem)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *localPrevElem = NULL;
+ struct listmp_elem *sharedNewElem = NULL;
+ struct listmp_elem *sharedCurElem = NULL;
+ s32 retval = 0;
+ u32 index;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(new_elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0) {
+ status = -EINVAL;
+ goto exit;
+ }
+ }
+
+ /* If NULL change cur_elem to the obj */
+ if (cur_elem == NULL)
+ cur_elem = (struct listmp_elem *)obj->listmp_elem->next;
+
+ /* Get SRPtr for new_elem */
+ index = sharedregion_get_index(new_elem);
+ sharedNewElem = (struct listmp_elem *)
+ sharedregion_get_srptr(new_elem, index);
+
+ /* Get SRPtr for cur_elem */
+ index = sharedregion_get_index(cur_elem);
+ sharedCurElem = (struct listmp_elem *)
+ sharedregion_get_srptr(cur_elem, index);
+
+ /* Get SRPtr for cur_elem->prev */
+ localPrevElem = sharedregion_get_ptr((u32 *)cur_elem->prev);
+
+ new_elem->next = sharedCurElem;
+ new_elem->prev = cur_elem->prev;
+ localPrevElem->next = sharedNewElem;
+ cur_elem->prev = sharedNewElem;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_insert failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_remove ========
+ * Purpose:
+ * Function to remove a element from a shared memory list
+ */
+int listmp_sharedmemory_remove(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *elem)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *localPrevElem = NULL;
+ struct listmp_elem *localNextElem = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(elem == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0) {
+ status = -EINVAL;
+ goto exit;
+ }
+ }
+
+ localPrevElem = sharedregion_get_ptr((u32 *)elem->prev);
+ localNextElem = sharedregion_get_ptr((u32 *)elem->next);
+
+ localPrevElem->next = elem->next;
+ localNextElem->prev = elem->prev;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "listmp_sharedmemory_remove failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+/*
+ * ======== listmp_sharedmemory_next ========
+ * Purpose:
+ * Function to traverse to next element in shared memory list
+ */
+void *listmp_sharedmemory_next(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *elem)
+{
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *retElem = NULL;
+ struct listmp_elem *sharedNextElem = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true)
+ goto exit;
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0)
+ goto exit;
+ }
+
+ /* If element is NULL start at head */
+ if (elem == NULL)
+ sharedNextElem = (struct listmp_elem *) obj->listmp_elem->next;
+ else
+ sharedNextElem = (struct listmp_elem *)elem->next;
+
+ retElem = sharedregion_get_ptr((u32 *)sharedNextElem);
+
+ /*! @retval NULL if list is empty */
+ if (retElem == (struct listmp_elem *)obj->listmp_elem)
+ retElem = NULL;
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ return retElem;
+}
+
+/*
+ * ======== listmp_sharedmemory_prev ========
+ * Purpose:
+ * Function to traverse to prev element in shared memory list
+ */
+void *listmp_sharedmemory_prev(listmp_sharedmemory_handle listmp_handle,
+ struct listmp_elem *elem)
+{
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ struct listmp_elem *retElem = NULL;
+ struct listmp_elem *sharedPrevElem = NULL;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(listmp_sharedmemory_state.ref_count),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(0),
+ LISTMPSHAREDMEMORY_MAKE_MAGICSTAMP(1)) == true)
+ goto exit;
+
+ handle = (listmp_sharedmemory_object *)listmp_handle;
+ obj = (struct listmp_sharedmemory_obj *) handle->obj;
+
+ if (obj->params.gate != NULL) {
+ retval = gatepeterson_enter(obj->params.gate);
+ if (retval < 0)
+ goto exit;
+ }
+
+ /* If elem is NULL use head */
+ if (elem == NULL)
+ sharedPrevElem = (struct listmp_elem *)
+ obj->listmp_elem->prev;
+ else
+ sharedPrevElem = (struct listmp_elem *)elem->prev;
+
+ retElem = sharedregion_get_ptr((u32 *)sharedPrevElem);
+
+ /*! @retval NULL if list is empty */
+ if (retElem == (struct listmp_elem *)(obj->listmp_elem))
+ retElem = NULL;
+
+ if (obj->params.gate != NULL)
+ gatepeterson_leave(obj->params.gate, 0);
+
+exit:
+ return retElem;
+}
+
+/*
+ * ======== _listmp_sharedmemory_create ========
+ * Purpose:
+ * Creates a new instance of listmp_sharedmemory module. This is an internal
+ * function because both listmp_sharedmemory_create and
+ * listmp_sharedmemory_open call use the same functionality.
+ */
+listmp_sharedmemory_handle _listmp_sharedmemory_create(
+ listmp_sharedmemory_params *params, u32 create_flag)
+{
+ int status = 0;
+ listmp_sharedmemory_object *handle = NULL;
+ struct listmp_sharedmemory_obj *obj = NULL;
+ u32 key;
+ u32 shm_index;
+ u32 *shared_shm_base;
+
+ BUG_ON(params == NULL);
+
+ /* Allow local lock not being provided. Don't do protection if local
+ * lock is not provided.
+ */
+ /* Create the handle */
+ handle = kzalloc(sizeof(listmp_sharedmemory_object), GFP_KERNEL);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ obj = kzalloc(sizeof(struct listmp_sharedmemory_obj),
+ GFP_KERNEL);
+ if (obj == NULL) {
+ /*! @retval NULL if Memory allocation failed for
+ * internal object "Memory allocation failed for handle"
+ * "of type struct listmp_sharedmemory_obj"); */
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ handle->obj = (struct listmp_sharedmemory_obj *)obj ;
+ handle->empty = &listmp_sharedmemory_empty;
+ handle->get_head = &listmp_sharedmemory_get_head;
+ handle->get_tail = &listmp_sharedmemory_get_tail;
+ handle->put_head = &listmp_sharedmemory_put_head;
+ handle->put_tail = &listmp_sharedmemory_put_tail;
+ handle->insert = &listmp_sharedmemory_insert;
+ handle->remove = &listmp_sharedmemory_remove;
+ handle->next = &listmp_sharedmemory_next;
+ handle->prev = &listmp_sharedmemory_prev;
+
+ /* Update attrs */
+ obj->attrs = (struct listmp_attrs *) params->shared_addr;
+ /* Assign the memory with proper cache line padding */
+ obj->listmp_elem = (void *) ((u32)obj->attrs + \
+ LISTMP_SHAREDMEMORY_CACHESIZE);
+ obj->index = sharedregion_get_index(params->shared_addr);
+
+ if (create_flag == true) {
+ obj->attrs->shared_addr_size = params->shared_addr_size;
+ obj->attrs->version = LISTMP_SHAREDMEMORY_VERSION;
+ obj->listmp_elem->next = obj->listmp_elem->prev =
+ (struct listmp_elem *)
+ (sharedregion_get_srptr((void *)obj->listmp_elem,
+ obj->index));
+ }
+
+ /* Populate the params member */
+ memcpy((void *)&obj->params, (void *)params,
+ sizeof(listmp_sharedmemory_params));
+
+ if (likely(listmp_sharedmemory_state.cfg.use_name_server
+ == true)) {
+ if (obj->params.name != NULL) {
+ /* Copy the name */
+ obj->params.name = kmalloc(strlen(params->name) + 1,
+ GFP_KERNEL);
+
+ if (obj->params.name == NULL) {
+ /*! @retval NULL if Memory allocation failed for
+ name */
+ status = -ENOMEM;
+ } else {
+ strncpy(obj->params.name, params->name,
+ strlen(params->name) + 1);
+ }
+ }
+ }
+
+ /* Update processor information */
+ obj->owner = kmalloc(sizeof(struct listmp_proc_attrs),
+ GFP_KERNEL);
+ if (obj->owner == NULL) {
+ printk(KERN_ERR "_listmp_sharedmemory_create: Memory "
+ "allocation failed for processor information!\n");
+ status = -ENOMEM;
+ } else {
+ /* Update owner and opener details */
+ if (create_flag == true) {
+ obj->owner->creator = true;
+ obj->owner->open_count = 1;
+ obj->owner->proc_id = multiproc_get_id(NULL);
+ obj->top = handle;
+ obj->attrs->status = \
+ LISTMP_SHAREDMEMORY_CREATED;
+ } else {
+ obj->owner->creator = false;
+ obj->owner->open_count = 0;
+ obj->owner->proc_id = MULTIPROC_INVALIDID;
+ obj->top = handle;
+ }
+
+ /* Put in the local list */
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ INIT_LIST_HEAD(&obj->list_elem);
+ list_add_tail((&obj->list_elem),
+ &listmp_sharedmemory_state.obj_list);
+ mutex_unlock(listmp_sharedmemory_state.local_gate);
+
+ if (create_flag == true) {
+
+ /* We will store a shared pointer in the
+ * NameServer
+ */
+ shm_index = sharedregion_get_index(params->shared_addr);
+ shared_shm_base = sharedregion_get_srptr(
+ params->shared_addr, shm_index);
+ /* Add list instance to name server */
+ if (obj->params.name != NULL) {
+ obj->ns_key = nameserver_add_uint32(
+ listmp_sharedmemory_state.ns_handle,
+ params->name,
+ (u32) (shared_shm_base));
+ if (obj->ns_key == NULL)
+ status = -EFAULT;
+ }
+ }
+ }
+
+ if (status < 0) {
+ /* Remove from the local list */
+ key = mutex_lock_interruptible(
+ listmp_sharedmemory_state.local_gate);
+ list_del(&obj->list_elem);
+ mutex_unlock(listmp_sharedmemory_state.local_gate);
+
+ if (likely(listmp_sharedmemory_state.cfg.use_name_server
+ == true)) {
+ if ((obj->params.name != NULL) && (status != -EFAULT))
+ nameserver_remove_entry(
+ listmp_sharedmemory_state.ns_handle,
+ obj->ns_key);
+ }
+ if (obj->owner != NULL)
+ kfree(obj->owner);
+
+ if (obj->params.name != NULL)
+ kfree(obj->params.name);
+
+ if (obj != NULL) {
+ kfree(obj);
+ obj = NULL;
+ }
+ if (handle != NULL) {
+ kfree(handle);
+ handle = NULL;
+ }
+ }
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "_listmp_sharedmemory_create failed! "
+ "status = 0x%x\n", status);
+ }
+ return (listmp_sharedmemory_handle) handle;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c
new file mode 100644
index 000000000000..0328ee53d2fb
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c
@@ -0,0 +1,689 @@
+/*
+ * listmp_sharedmemory_ioctl.c
+ *
+ * This file implements all the ioctl operations required on the
+ * listmp_sharedmemory module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+/* Standard headers */
+#include <linux/types.h>
+
+/* Linux headers */
+#include <linux/uaccess.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+/* Module Headers */
+#include <listmp.h>
+#include <listmp_sharedmemory.h>
+#include <listmp_sharedmemory_ioctl.h>
+#include <sharedregion.h>
+
+/*
+ * ======== listmp_sharedmemory_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_get_config function
+ */
+static inline int listmp_sharedmemory_ioctl_get_config(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ struct listmp_config config;
+
+ status = listmp_sharedmemory_get_config(&config);
+ if (unlikely(status))
+ goto exit;
+
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct listmp_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_setup function
+ */
+static inline int listmp_sharedmemory_ioctl_setup(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ struct listmp_config config;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct listmp_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ status = listmp_sharedmemory_setup(&config);
+ cargs->api_status = status;
+ if (unlikely(status))
+ goto exit;
+exit:
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_destroy function
+ */
+static inline int listmp_sharedmemory_ioctl_destroy(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ cargs->api_status = listmp_sharedmemory_destroy();
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_params_init function
+ */
+static inline int listmp_sharedmemory_ioctl_params_init(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ listmp_sharedmemory_params params;
+
+ size = copy_from_user(&params,
+ cargs->args.params_init.params,
+ sizeof(listmp_sharedmemory_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ listmp_sharedmemory_params_init(
+ cargs->args.params_init.listmp_handle, &params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(listmp_sharedmemory_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ cargs->api_status = status;
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_create ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_create function
+ */
+static inline int listmp_sharedmemory_ioctl_create(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ listmp_sharedmemory_params params;
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(listmp_sharedmemory_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ /* Allocate memory for the name */
+ if (cargs->args.create.name_len > 0) {
+ params.name = kmalloc(cargs->args.create.name_len, GFP_KERNEL);
+ if (params.name == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ /* Copy the name */
+ size = copy_from_user(params.name,
+ cargs->args.create.params->name,
+ cargs->args.create.name_len);
+ if (size) {
+ retval = -EFAULT;
+ goto free_name;
+ }
+ }
+
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.create.shared_addr_srptr);
+ if (unlikely(params.shared_addr == NULL))
+ goto free_name;
+
+ /* Update gate in params. */
+ params.gate = cargs->args.create.knl_gate;
+ cargs->args.create.listmp_handle = listmp_sharedmemory_create(&params);
+
+ size = copy_to_user(cargs->args.create.params, &params,
+ sizeof(listmp_sharedmemory_params));
+ if (!size)
+ goto free_name;
+
+ /* Error copying, so delete the handle */
+ retval = -EFAULT;
+ if (cargs->args.create.listmp_handle)
+ listmp_sharedmemory_delete(&cargs->args.create.listmp_handle);
+
+free_name:
+ if (cargs->args.create.name_len > 0)
+ kfree(params.name);
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_delete function
+ */
+static inline int listmp_sharedmemory_ioctl_delete(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ cargs->api_status = listmp_sharedmemory_delete(
+ &(cargs->args.delete_listmp.listmp_handle));
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_open ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_open function
+ */
+static inline int listmp_sharedmemory_ioctl_open(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ listmp_sharedmemory_params params;
+ void *listmp_handle = NULL;
+
+ size = copy_from_user(&params, cargs->args.open.params,
+ sizeof(listmp_sharedmemory_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ if (cargs->args.open.name_len > 0) {
+ params.name = kmalloc(cargs->args.open.name_len, GFP_KERNEL);
+ if (params.name != NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ /* Copy the name */
+ size = copy_from_user(params.name,
+ cargs->args.open.params->name,
+ cargs->args.open.name_len);
+ if (size) {
+ retval = -EFAULT;
+ goto free_name;
+ }
+ }
+
+ /* For open by name, the shared_add_srptr may be invalid */
+ if (cargs->args.open.shared_addr_srptr != \
+ (u32)SHAREDREGION_INVALIDSRPTR) {
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.open.shared_addr_srptr);
+ }
+ if (unlikely(params.shared_addr == NULL))
+ goto free_name;
+
+ /* Update gate in params. */
+ params.gate = cargs->args.open.knl_gate;
+ status = listmp_sharedmemory_open(&listmp_handle, &params);
+ if (status < 0)
+ goto free_name;
+ cargs->args.open.listmp_handle = listmp_handle;
+
+ size = copy_to_user(cargs->args.open.params, &params,
+ sizeof(listmp_sharedmemory_params));
+ if (!size)
+ goto free_name;
+
+ /* Error copying, so close the handle */
+ retval = -EFAULT;
+ if (cargs->args.open.listmp_handle)
+ listmp_sharedmemory_close(cargs->args.open.listmp_handle);
+
+free_name:
+ if (cargs->args.open.name_len > 0)
+ kfree(params.name);
+
+ cargs->api_status = status;
+exit:
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_close ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_close function
+ */
+static inline int listmp_sharedmemory_ioctl_close(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ cargs->api_status = \
+ listmp_sharedmemory_close(cargs->args.close.listmp_handle);
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_is_empty ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_empty function
+ */
+static inline int listmp_sharedmemory_ioctl_empty(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ cargs->args.is_empty.is_empty = \
+ listmp_sharedmemory_empty(cargs->args.is_empty.listmp_handle);
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_get_head ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_get_head function
+ */
+static inline int listmp_sharedmemory_ioctl_get_head(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem;
+ u32 *elem_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL;
+
+ elem = listmp_sharedmemory_get_head(cargs->args.get_head.listmp_handle);
+ if (unlikely(elem == NULL))
+ goto exit;
+
+ index = sharedregion_get_index(elem);
+ if (unlikely(index < 0))
+ goto exit;
+
+ elem_srptr = sharedregion_get_srptr((void *)elem, index);
+
+ cargs->api_status = 0;
+exit:
+ cargs->args.get_head.elem_srptr = elem_srptr;
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_get_tail ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_get_tail function
+ */
+static inline int listmp_sharedmemory_ioctl_get_tail(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem;
+ u32 *elem_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL;
+
+ elem = listmp_sharedmemory_get_tail(cargs->args.get_tail.listmp_handle);
+ if (unlikely(elem == NULL))
+ goto exit;
+
+ index = sharedregion_get_index(elem);
+ if (unlikely(index < 0))
+ goto exit;
+
+ elem_srptr = sharedregion_get_srptr((void *)elem, index);
+
+ cargs->api_status = 0;
+exit:
+ cargs->args.get_tail.elem_srptr = elem_srptr;
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_put_head ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_put_head function
+ */
+static inline int listmp_sharedmemory_ioctl_put_head(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem;
+
+ cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL;
+
+ elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.put_head.elem_srptr);
+ if (unlikely(elem == NULL))
+ goto exit;
+
+ cargs->api_status = listmp_sharedmemory_put_head(
+ cargs->args.put_head.listmp_handle, elem);
+exit:
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_put_tail ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_put_tail function
+ */
+static inline int listmp_sharedmemory_ioctl_put_tail(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem;
+
+ cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL;
+
+ elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.put_tail.elem_srptr);
+ if (unlikely(elem == NULL))
+ goto exit;
+
+ cargs->api_status = listmp_sharedmemory_put_tail(
+ cargs->args.put_head.listmp_handle, elem);
+exit:
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_insert ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_insert function
+ */
+static inline int listmp_sharedmemory_ioctl_insert(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *new_elem;
+ struct listmp_elem *cur_elem;
+
+ new_elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.insert.new_elem_srptr);
+ if (unlikely(new_elem == NULL))
+ goto exit;
+
+ cur_elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.insert.cur_elem_srptr);
+ if (unlikely(cur_elem == NULL))
+ goto exit;
+
+ cargs->api_status = listmp_sharedmemory_insert(
+ cargs->args.insert.listmp_handle, new_elem, cur_elem);
+exit:
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_remove ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_remove function
+ */
+static inline int listmp_sharedmemory_ioctl_remove(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem;
+
+ elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.remove.elem_srptr);
+ if (unlikely(elem == NULL))
+ goto exit;
+
+ cargs->api_status = listmp_sharedmemory_remove(
+ cargs->args.get_head.listmp_handle, elem);
+
+exit:
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_next ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_next function
+ */
+static inline int listmp_sharedmemory_ioctl_next(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem = NULL;
+ struct listmp_elem *ret_elem = NULL;
+ u32 *next_elem_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ if (cargs->args.next.elem_srptr != NULL) {
+ elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.next.elem_srptr);
+ }
+ ret_elem = (struct listmp_elem *) listmp_sharedmemory_next(
+ cargs->args.next.listmp_handle, elem);
+ if (unlikely(ret_elem == NULL))
+ goto exit;
+
+ index = sharedregion_get_index(ret_elem);
+ if (unlikely(index < 0))
+ goto exit;
+
+ next_elem_srptr = sharedregion_get_srptr((void *)ret_elem, index);
+
+ cargs->api_status = 0;
+exit:
+ cargs->args.next.next_elem_srptr = next_elem_srptr;
+ return 0;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_prev ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_prev function
+ */
+static inline int listmp_sharedmemory_ioctl_prev(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ struct listmp_elem *elem = NULL;
+ struct listmp_elem *ret_elem = NULL;
+ u32 *prev_elem_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ if (cargs->args.next.elem_srptr != NULL) {
+ elem = (struct listmp_elem *) sharedregion_get_ptr(
+ cargs->args.prev.elem_srptr);
+ }
+ ret_elem = (struct listmp_elem *) listmp_sharedmemory_prev(
+ cargs->args.prev.listmp_handle, elem);
+ if (unlikely(ret_elem == NULL))
+ goto exit;
+
+ index = sharedregion_get_index(ret_elem);
+ if (unlikely(index < 0))
+ goto exit;
+
+ prev_elem_srptr = sharedregion_get_srptr((void *)ret_elem, index);
+
+ cargs->api_status = 0;
+exit:
+ cargs->args.prev.prev_elem_srptr = prev_elem_srptr;
+ return 0;
+
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl_shared_memreq ========
+ * Purpose:
+ * This ioctl interface to listmp_sharedmemory_shared_memreq function
+ */
+static inline int listmp_sharedmemory_ioctl_shared_memreq(
+ struct listmp_sharedmemory_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ listmp_sharedmemory_params params;
+
+ size = copy_from_user(&params, cargs->args.shared_memreq.params,
+ sizeof(listmp_sharedmemory_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->args.shared_memreq.bytes =
+ listmp_sharedmemory_shared_memreq(&params);
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== listmp_sharedmemory_ioctl ========
+ * Purpose:
+ * ioctl interface function for listmp_sharedmemory module
+ */
+int listmp_sharedmemory_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int os_status = 0;
+ struct listmp_sharedmemory_cmd_args __user *uarg =
+ (struct listmp_sharedmemory_cmd_args __user *)args;
+ struct listmp_sharedmemory_cmd_args cargs;
+ unsigned long size;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+ if (os_status) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct listmp_sharedmemory_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_LISTMP_SHAREDMEMORY_GETCONFIG:
+ os_status = listmp_sharedmemory_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_SETUP:
+ os_status = listmp_sharedmemory_ioctl_setup(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_DESTROY:
+ os_status = listmp_sharedmemory_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_PARAMS_INIT:
+ os_status = listmp_sharedmemory_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_CREATE:
+ os_status = listmp_sharedmemory_ioctl_create(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_DELETE:
+ os_status = listmp_sharedmemory_ioctl_delete(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_OPEN:
+ os_status = listmp_sharedmemory_ioctl_open(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_CLOSE:
+ os_status = listmp_sharedmemory_ioctl_close(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_ISEMPTY:
+ os_status = listmp_sharedmemory_ioctl_empty(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_GETHEAD:
+ os_status = listmp_sharedmemory_ioctl_get_head(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_GETTAIL:
+ os_status = listmp_sharedmemory_ioctl_get_tail(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_PUTHEAD:
+ os_status = listmp_sharedmemory_ioctl_put_head(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_PUTTAIL:
+ os_status = listmp_sharedmemory_ioctl_put_tail(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_INSERT:
+ os_status = listmp_sharedmemory_ioctl_insert(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_REMOVE:
+ os_status = listmp_sharedmemory_ioctl_remove(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_NEXT:
+ os_status = listmp_sharedmemory_ioctl_next(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_PREV:
+ os_status = listmp_sharedmemory_ioctl_prev(&cargs);
+ break;
+
+ case CMD_LISTMP_SHAREDMEMORY_SHAREDMEMREQ:
+ os_status = listmp_sharedmemory_ioctl_shared_memreq(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ os_status = -ENOTTY;
+ break;
+ }
+ if (os_status < 0)
+ goto exit;
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs,
+ sizeof(struct listmp_sharedmemory_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+ return os_status;
+
+exit:
+ printk(KERN_ERR "listmp_sharedmemory_ioctl failed: status = 0x%x\n",
+ os_status);
+ return os_status;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/messageq.c b/drivers/dsp/syslink/multicore_ipc/messageq.c
new file mode 100755
index 000000000000..718981f2fafa
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/messageq.c
@@ -0,0 +1,1575 @@
+/*
+ * messageq.c
+ *
+ * The messageQ module supports the structured sending and receiving of
+ * variable length messages. This module can be used for homogeneous or
+ * heterogeneous multi-processor messaging.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/*!
+ * MessageQ provides more sophisticated messaging than other modules. It is
+ * typically used for complex situations such as multi-processor messaging.
+ *
+ * The following are key features of the MessageQ module:
+ * -Writers and readers can be relocated to another processor with no
+ * runtime code changes.
+ * -Timeouts are allowed when receiving messages.
+ * -Readers can determine the writer and reply back.
+ * -Receiving a message is deterministic when the timeout is zero.
+ * -Messages can reside on any message queue.
+ * -Supports zero-copy transfers.
+ * -Can send and receive from any type of thread.
+ * -Notification mechanism is specified by application.
+ * -Allows QoS (quality of service) on message buffer pools. For example,
+ * using specific buffer pools for specific message queues.
+ *
+ * Messages are sent and received via a message queue. A reader is a thread
+ * that gets (reads) messages from a message queue. A writer is a thread that
+ * puts (writes) a message to a message queue. Each message queue has one
+ * reader and can have many writers. A thread may read from or write to
+ * multiple message queues.
+ *
+ * Conceptually, the reader thread owns a message queue. The reader thread
+ * creates a message queue. Writer threads a created message queues to
+ * get access to them.
+ *
+ * Message queues are identified by a system-wide unique name. Internally,
+ * MessageQ uses the NameServer module for managing
+ * these names. The names are used for opening a message queue. Using
+ * names is not required.
+ *
+ * Messages must be allocated from the MessageQ module. Once a message is
+ * allocated, it can be sent on any message queue. Once a message is sent, the
+ * writer loses ownership of the message and should not attempt to modify the
+ * message. Once the reader receives the message, it owns the message. It
+ * may either free the message or re-use the message.
+ *
+ * Messages in a message queue can be of variable length. The only
+ * requirement is that the first field in the definition of a message must be a
+ * MsgHeader structure. For example:
+ * typedef struct MyMsg {
+ * messageq_MsgHeader header;
+ * ...
+ * } MyMsg;
+ *
+ * The MessageQ API uses the messageq_MsgHeader internally. Your application
+ * should not modify or directly access the fields in the messageq_MsgHeader.
+ *
+ * All messages sent via the MessageQ module must be allocated from a
+ * Heap implementation. The heap can be used for
+ * other memory allocation not related to MessageQ.
+ *
+ * An application can use multiple heaps. The purpose of having multiple
+ * heaps is to allow an application to regulate its message usage. For
+ * example, an application can allocate critical messages from one heap of fast
+ * on-chip memory and non-critical messages from another heap of slower
+ * external memory
+ *
+ * MessageQ does support the usage of messages that allocated via the
+ * alloc function. Please refer to the static_msg_init
+ * function description for more details.
+ *
+ * In a multiple processor system, MessageQ communications to other
+ * processors via MessageQ_transport} instances. There must be one and
+ * only one IMessageQ_transport instance for each processor where communication
+ * is desired.
+ * So on a four processor system, each processor must have three
+ * IMessageQ_transport instance.
+ *
+ * The user only needs to create the IMessageQ_transport instances. The
+ * instances are responsible for registering themselves with MessageQ.
+ * This is accomplished via the register_transport function.
+ */
+
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Utilities headers */
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/semaphore.h>
+
+/* Syslink headers */
+#include <syslink/atomic_linux.h>
+
+/* Module level headers */
+#include <nameserver.h>
+#include <multiproc.h>
+#include <messageq_transportshm.h>
+#include <heap.h>
+#include <messageq.h>
+
+
+/* Macro to make a correct module magic number with refCount */
+#define MESSAGEQ_MAKE_MAGICSTAMP(x) ((MESSAGEQ_MODULEID << 12u) | (x))
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/*!
+ * @brief Name of the reserved NameServer used for MessageQ.
+ */
+#define MESSAGEQ_NAMESERVER "MessageQ"
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/* structure for MessageQ module state */
+struct messageq_module_object {
+ atomic_t ref_count;
+ /*!< Reference count */
+ void *ns_handle;
+ /*!< Handle to the local NameServer used for storing GP objects */
+ struct mutex *gate_handle;
+ /*!< Handle of gate to be used for local thread safety */
+ struct messageq_config cfg;
+ /*!< Current config values */
+ struct messageq_config default_cfg;
+ /*!< Default config values */
+ struct messageq_params default_inst_params;
+ /*!< Default instance creation parameters */
+ void *transports[MULTIPROC_MAXPROCESSORS][MESSAGEQ_NUM_PRIORITY_QUEUES];
+ /*!< Transport to be set in messageq_register_transport */
+ void **queues; /*messageq_handle *queues;*/
+ /*!< Grow option */
+ void **heaps; /*Heap_Handle *heaps; */
+ /*!< Heap to be set in messageq_registerHeap */
+ u16 num_queues;
+ /*!< Heap to be set in messageq_registerHeap */
+ u16 num_heaps;
+ /*!< Number of Heaps */
+ bool can_free_queues;
+ /*!< Grow option */
+};
+
+/*!
+ * @brief Structure for the Handle for the MessageQ.
+ */
+struct messageq_object {
+ struct messageq_params params;
+ /*! Instance specific creation parameters */
+ char *name;
+ /*! MessageQ name */
+ u32 queue;
+ /* Unique id */
+ struct list_head normal_list;
+ /* Embedded List objects */
+ struct list_head high_list;
+ /* Embedded List objects */
+ /*OsalSemaphore_Handle synchronizer;*/
+ struct semaphore *synchronizer;
+ /* Semaphore used for synchronizing message events */
+};
+
+
+static struct messageq_module_object messageq_state = {
+ .ns_handle = NULL,
+ .gate_handle = NULL,
+ .queues = NULL,
+ .heaps = NULL,
+ .num_queues = 1,
+ .num_heaps = 1,
+ .can_free_queues = false,
+ .default_cfg.num_heaps = 1,
+ .default_cfg.max_runtime_entries = 32,
+ .default_cfg.name_table_gate = NULL,
+ .default_cfg.max_name_len = 32,
+ .default_inst_params.reserved = 0
+};
+
+
+/* =============================================================================
+ * Constants
+ * =============================================================================
+ */
+/*
+ * Used to denote a message that was initialized
+ * with the messageq_static_msg_init function.
+ */
+#define MESSAGEQ_STATICMSG 0xFFFF
+
+
+/* =============================================================================
+ * Forward declarations of internal functions
+ * =============================================================================
+ */
+/*
+ * @brief Grow the MessageQ table
+ *
+ * @sa messageq_create
+ */
+static u16 _messageq_grow(struct messageq_object *obj);
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+/*
+ * ======== messageq_get_config ========
+ * Purpose:
+ * Function to get the default configuration for the MessageQ
+ * module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to MessageQ_setup filled in by the
+ * MessageQ module with the default parameters. If the user does
+ * not wish to make any change in the default parameters, this API
+ * is not required to be called.
+ * the listmp_sharedmemory module.
+ */
+void messageq_get_config(struct messageq_config *cfg)
+{
+ if (WARN_ON(cfg == NULL))
+ goto exit;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true) {
+ /* (If setup has not yet been called) */
+ memcpy(cfg, &messageq_state.default_cfg,
+ sizeof(struct messageq_config));
+ } else {
+ memcpy(cfg, &messageq_state.cfg,
+ sizeof(struct messageq_config));
+ }
+ return;
+
+exit:
+ printk(KERN_ERR "messageq_get_config: Argument of type "
+ "(struct messageq_config *) passed is null!\n");
+}
+EXPORT_SYMBOL(messageq_get_config);
+
+/*
+ * ======== messageq_setup ========
+ * Purpose:
+ * Function to setup the MessageQ module.
+ *
+ * This function sets up the MessageQ module. This function must
+ * be called before any other instance-level APIs can be invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then MessageQ_getConfig can be called to get the
+ * configuration filled with the default values. After this, only
+ * the required configuration values can be changed. If the user
+ * does not wish to make any change in the default parameters, the
+ * application can simply call MessageQ with NULL parameters.
+ * The default parameters would get automatically used.
+ */
+int messageq_setup(const struct messageq_config *cfg)
+{
+ int status = MESSAGEQ_SUCCESS;
+ struct nameserver_params params;
+ struct messageq_config tmpcfg;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable.
+ */
+ atomic_cmpmask_and_set(&messageq_state.ref_count,
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(0));
+ if (atomic_inc_return(&messageq_state.ref_count)
+ != MESSAGEQ_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (cfg == NULL) {
+ messageq_get_config(&tmpcfg);
+ cfg = &tmpcfg;
+ }
+
+ if (WARN_ON(cfg->max_name_len == 0)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(cfg->max_name_len == 0)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (cfg->name_table_gate != NULL) {
+ messageq_state.gate_handle = cfg->name_table_gate;
+ } else {
+ /* User has not provided any gate handle, so create a default
+ * handle for protecting list object */
+ messageq_state.gate_handle = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+ if (messageq_state.gate_handle == NULL) {
+ /*! @retval MESSAGEQ_E_FAIL Failed to create lock! */
+ status = MESSAGEQ_E_FAIL;
+ printk(KERN_ERR "messageq_setup: Failed to create a "
+ "mutex.\n");
+ status = -ENOMEM;
+ goto exit;
+ }
+ mutex_init(messageq_state.gate_handle);
+ }
+
+ /* Initialize the parameters */
+ nameserver_params_init(&params);
+ params.max_value_len = 4;
+ params.max_name_len = cfg->max_name_len;
+
+ /* Create the nameserver for modules */
+ messageq_state.ns_handle = nameserver_create(MESSAGEQ_NAMESERVER,
+ &params);
+ if (messageq_state.ns_handle == NULL) {
+ /*! @retval MESSAGEQ_E_FAIL Failed to create the
+ * MessageQ nameserver*/
+ status = MESSAGEQ_E_FAIL;
+ printk(KERN_ERR "messageq_setup: Failed to create the messageq"
+ "nameserver!\n");
+ goto nameserver_create_fail;
+ }
+
+ messageq_state.num_heaps = cfg->num_heaps;
+ messageq_state.heaps = kzalloc(sizeof(void *) * \
+ messageq_state.num_heaps, GFP_KERNEL);
+ if (messageq_state.heaps == NULL) {
+ status = -ENOMEM;
+ goto heaps_alloc_fail;
+ }
+
+ messageq_state.num_queues = cfg->max_runtime_entries;
+ messageq_state.queues = kzalloc(sizeof(struct messageq_object *) * \
+ messageq_state.num_queues, GFP_KERNEL);
+ if (messageq_state.queues == NULL) {
+ status = -ENOMEM;
+ goto queues_alloc_fail;
+ }
+
+ memset(&(messageq_state.transports), 0, (sizeof(void *) * \
+ MULTIPROC_MAXPROCESSORS * \
+ MESSAGEQ_NUM_PRIORITY_QUEUES));
+
+ BUG_ON(status < 0);
+ return status;
+
+queues_alloc_fail:
+ if (messageq_state.queues != NULL)
+ kfree(messageq_state.queues);
+heaps_alloc_fail:
+ if (messageq_state.heaps != NULL)
+ kfree(messageq_state.heaps);
+ if (messageq_state.ns_handle != NULL)
+ nameserver_delete(&messageq_state.ns_handle);
+nameserver_create_fail:
+ if (cfg->name_table_gate != NULL) {
+ if (messageq_state.gate_handle != NULL) {
+ kfree(messageq_state.gate_handle);
+ messageq_state.gate_handle = NULL;
+ }
+ }
+
+ memset(&messageq_state.cfg, 0, sizeof(struct messageq_config));
+ messageq_state.queues = NULL;
+ messageq_state.heaps = NULL;
+ messageq_state.num_queues = 0;
+ messageq_state.num_heaps = 1;
+ messageq_state.can_free_queues = true;
+
+exit:
+ if (status < 0) {
+ atomic_set(&messageq_state.ref_count,
+ MESSAGEQ_MAKE_MAGICSTAMP(0));
+ printk(KERN_ERR "messageq_setup failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_setup);
+
+/*
+ * ======== messageq_destroy ========
+ * Purpose:
+ * Function to destroy the MessageQ module.
+ */
+int messageq_destroy(void)
+{
+ int status = MESSAGEQ_SUCCESS;
+ u32 i;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (!(atomic_dec_return(&messageq_state.ref_count)
+ == MESSAGEQ_MAKE_MAGICSTAMP(0))) {
+ status = 1;
+ goto exit;
+ }
+
+ if (WARN_ON(messageq_state.ns_handle == NULL)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ /* Delete any Message Queues that have not been deleted so far. */
+ for (i = 0; i < messageq_state.num_queues; i++) {
+ if (messageq_state.queues[i] != NULL)
+ messageq_delete(&(messageq_state.queues[i]));
+ }
+
+ /* Delete the nameserver for modules */
+ status = nameserver_delete(&messageq_state.ns_handle);
+ BUG_ON(status < 0);
+
+ /* Delete the gate if created internally */
+ if (messageq_state.cfg.name_table_gate == NULL) {
+ kfree(messageq_state.gate_handle);
+ messageq_state.gate_handle = NULL;
+ BUG_ON(status < 0);
+ }
+
+ memset(&(messageq_state.transports), 0, (sizeof(void *) * \
+ MULTIPROC_MAXPROCESSORS * MESSAGEQ_NUM_PRIORITY_QUEUES));
+ if (messageq_state.heaps != NULL) {
+ kfree(messageq_state.heaps);
+ messageq_state.heaps = NULL;
+ }
+ if (messageq_state.queues != NULL) {
+ kfree(messageq_state.queues);
+ messageq_state.queues = NULL;
+ }
+
+ memset(&messageq_state.cfg, 0, sizeof(struct messageq_config));
+ messageq_state.num_queues = 0;
+ messageq_state.num_heaps = 1;
+ messageq_state.can_free_queues = true;
+ atomic_set(&messageq_state.ref_count,
+ MESSAGEQ_MAKE_MAGICSTAMP(0));
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_destroy failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_destroy);
+
+/*
+ * ======== messageq_params_init ========
+ * Purpose:
+ * Initialize this config-params structure with supplier-specified
+ * defaults before instance creation.
+ */
+void messageq_params_init(void *messageq_handle,
+ struct messageq_params *params)
+{
+ struct messageq_object *object = NULL;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)
+ goto exit;
+
+ if (WARN_ON(params == NULL)) {
+ printk(KERN_ERR "messageq_params_init failed:Argument of "
+ "type(messageq_params *) is NULL!\n");
+ goto exit;
+ }
+
+ if (messageq_handle == NULL) {
+ memcpy(params, &(messageq_state.default_inst_params),
+ sizeof(struct messageq_params));
+ } else {
+ object = (struct messageq_object *) messageq_handle;
+ memcpy((void *)params, (void *)&object->params,
+ sizeof(struct messageq_params));
+ }
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_params_init);
+
+/*
+ * ======== messageq_create ========
+ * Purpose:
+ * Creates a new instance of MessageQ module.
+ */
+void *messageq_create(char *name, const struct messageq_params *params)
+{
+ int status = 0;
+ struct messageq_object *handle = NULL;
+ bool found = false;
+ u16 count = 0;
+ int i;
+ u16 start;
+ int key;
+ u16 queueIndex = 0;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ /* Create the generic handle */
+ handle = kzalloc(sizeof(struct messageq_object), 0);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ start = 0; /* Statically allocated objects not supported */
+ count = messageq_state.num_queues;
+ /* Search the dynamic array for any holes */
+ for (i = start; i < count ; i++) {
+ if (messageq_state.queues[i] == NULL) {
+ messageq_state.queues[i] = (void *) handle;
+ queueIndex = i;
+ found = true;
+ break;
+ }
+ }
+ /*
+ * If no free slot was found:
+ * - if no growth allowed, raise an error
+ * - if growth is allowed, grow the array
+ */
+ if (found == false) {
+ if (messageq_state.cfg.max_runtime_entries
+ != MESSAGEQ_ALLOWGROWTH) {
+ mutex_unlock(messageq_state.gate_handle);
+ status = MESSAGEQ_E_MAXREACHED;
+ printk(KERN_ERR "messageq_create: All message queues "
+ "are full!\n");
+ goto free_slot_fail;
+ } else {
+ queueIndex = _messageq_grow(handle);
+ if (queueIndex == MESSAGEQ_INVALIDMESSAGEQ) {
+ mutex_unlock(messageq_state.gate_handle);
+ status = MESSAGEQ_E_MAXREACHED;
+ printk(KERN_ERR "messageq_create: All message "
+ "queues are full!\n");
+ goto free_slot_fail;
+ }
+ }
+ }
+
+ BUG_ON(status < 0);
+ mutex_unlock(messageq_state.gate_handle);
+
+ /* Construct the list object */
+ INIT_LIST_HEAD(&handle->normal_list);
+ INIT_LIST_HEAD(&handle->high_list);
+
+ /* Copy the name */
+ if (name != NULL) {
+ handle->name = kmalloc((strlen(name) + 1), GFP_KERNEL);
+ if (handle->name == NULL) {
+ status = -ENOMEM;
+ goto handle_name_alloc_fail;
+ }
+ strncpy(handle->name, name, strlen(name) + 1);
+ }
+
+ /* Update processor information */
+ handle->queue = ((u32)(multiproc_get_id(NULL)) << 16) | queueIndex;
+ /*handle->synchronizer = OsalSemaphore_create(OsalSemaphore_Type_Binary
+ | OsalSemaphore_IntType_Interruptible);*/
+ handle->synchronizer = kzalloc(sizeof(struct semaphore), GFP_KERNEL);
+ if (handle->synchronizer == NULL) {
+ status = MESSAGEQ_E_FAIL;
+ printk(KERN_ERR "messageq_create: Failed to create "
+ "synchronizer semaphore!\n");
+ goto semaphore_create_fail;
+ } else {
+ sema_init(handle->synchronizer, 0);
+ }
+
+ if (name != NULL) {
+ nameserver_add_uint32(messageq_state.ns_handle, name,
+ handle->queue);
+ }
+ goto exit;
+
+semaphore_create_fail:
+ if (handle->name != NULL)
+ kfree(handle->name);
+
+handle_name_alloc_fail:
+ list_del(&handle->high_list);
+ list_del(&handle->normal_list);
+
+free_slot_fail:
+ /* Now free the handle */
+ if (handle != NULL) {
+ kfree(handle);
+ handle = NULL;
+ }
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_create failed! status = 0x%x\n",
+ status);
+ }
+ return (void *) handle;
+}
+EXPORT_SYMBOL(messageq_create);
+
+/*
+ * ======== messageq_delete ========
+ * Purpose:
+ * Deletes a instance of MessageQ module.
+ */
+int messageq_delete(void **msg_handleptr)
+{
+ int status = 0;
+ struct messageq_object *handle = NULL;
+ int key;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(msg_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(*msg_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct messageq_object *) (*msg_handleptr);
+
+ /* Take the local lock */
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+
+ if (handle->name != NULL) {
+ /* remove from the name serve */
+ nameserver_remove(messageq_state.ns_handle, handle->name);
+ /* Free memory for the name */
+ kfree(handle->name);
+ }
+
+ /* Release the local lock */
+ mutex_unlock(messageq_state.gate_handle);
+
+ /* Free the list */
+ list_del(&handle->high_list);
+ list_del(&handle->normal_list);
+
+ /*if (handle->synchronizer != NULL)
+ status = OsalSemaphore_delete(&handle->synchronizer);*/
+ if (handle->synchronizer != NULL) {
+ kfree(handle->synchronizer);
+ handle->synchronizer = NULL;
+ }
+ /* Clear the MessageQ handle from array. */
+ messageq_state.queues[handle->queue] = NULL;
+
+ /* Now free the handle */
+ kfree(handle);
+ *msg_handleptr = NULL;
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_delete failed! status = 0x%x\n",
+ status);;
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_delete);
+
+/*
+ * ======== messageq_open ========
+ * Purpose:
+ * Opens a created instance of MessageQ module.
+ */
+int messageq_open(char *name, u32 *queue_id)
+{
+ int status = 0;
+ int len = 0;
+
+ if (atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(queue_id == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ /* Initialize return queue ID to invalid. */
+ *queue_id = MESSAGEQ_INVALIDMESSAGEQ;
+ len = nameserver_get(messageq_state.ns_handle, name, queue_id,
+ sizeof(u32), NULL);
+ if (len < 0) {
+ if (len == -ENOENT) {
+ /* Name not found */
+ status = -ENOENT;
+ } else {
+ /* Any other error from nameserver */
+ status = len;
+ }
+ }
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_open failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_open);
+
+/*
+ * ======== messageq_close ========
+ * Purpose:
+ * Closes previously opened/created instance of MessageQ module.
+ */
+void messageq_close(u32 *queue_id)
+{
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(queue_id == NULL)) {
+ printk(KERN_ERR "messageq_close: queue_id passed is NULL!\n");
+ goto exit;
+ }
+
+ *queue_id = MESSAGEQ_INVALIDMESSAGEQ;
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_close);
+
+/*
+ * ======== messageq_get ========
+ */
+int messageq_get(void *messageq_handle, messageq_msg *msg,
+ u32 timeout)
+{
+ int status = 0;
+ struct messageq_object *obj = (struct messageq_object *)messageq_handle;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(msg == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON(obj == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ /* Keep looping while there is no element in the list */
+ /* Take the local lock */
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (!list_empty(&obj->high_list)) {
+ *msg = (messageq_msg) (obj->high_list.next);
+ list_del_init(obj->high_list.next);
+ }
+ /* Leave the local lock */
+ mutex_unlock(messageq_state.gate_handle);
+ while (*msg == NULL) {
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (!list_empty(&obj->normal_list)) {
+ *msg = (messageq_msg) (obj->normal_list.next);
+ list_del_init(obj->normal_list.next);
+ }
+ mutex_unlock(messageq_state.gate_handle);
+
+ if (*msg == NULL) {
+ /*
+ * Block until notified. If pend times-out, no message
+ * should be returned to the caller
+ */
+ /*! @retval NULL timeout has occurred */
+ if (obj->synchronizer != NULL) {
+ /* TODO: cater to different timeout values */
+ /*status = OsalSemaphore_pend(
+ obj->synchronizer, timeout); */
+ status = down_timeout(obj->synchronizer,
+ msecs_to_jiffies(timeout));
+ if (status < 0) {
+ *msg = NULL;
+ break;
+ }
+ }
+ key = mutex_lock_interruptible(
+ messageq_state.gate_handle);
+ if (!list_empty(&obj->high_list)) {
+ *msg = (messageq_msg) (obj->high_list.next);
+ list_del_init(obj->high_list.next);
+ }
+ mutex_unlock(messageq_state.gate_handle);
+ }
+ }
+ return status;
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "messageq_get failed! status = 0x%x\n", status);
+ return status;
+}
+EXPORT_SYMBOL(messageq_get);
+
+/*
+ * ======== messageq_count ========
+ * Purpose:
+ * Count the number of messages in the queue
+ */
+int messageq_count(void *messageq_handle)
+{
+ struct messageq_object *obj = (struct messageq_object *)messageq_handle;
+ int count = 0;
+ struct list_head *elem;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(obj == NULL)) {
+ printk(KERN_ERR "messageq_count: obj passed is NULL!\n");
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle) ;
+ list_for_each(elem, &obj->high_list) {
+ count++;
+ }
+ list_for_each(elem, &obj->normal_list) {
+ count++;
+ }
+ mutex_unlock(messageq_state.gate_handle);
+
+exit:
+ return count;
+}
+EXPORT_SYMBOL(messageq_count);
+
+/*
+ * ======== messageq_static_msg_init ========
+ * Purpose:
+ * Initialize a static message
+ */
+void messageq_static_msg_init(messageq_msg msg, u32 size)
+{
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_static_msg_init: msg is invalid!\n");
+ goto exit;
+ }
+
+ /* Fill in the fields of the message */
+ msg->heap_id = MESSAGEQ_STATICMSG;
+ msg->msg_size = size;
+ msg->reply_id = (u16)MESSAGEQ_INVALIDMESSAGEQ;
+ msg->msg_id = MESSAGEQ_INVALIDMSGID;
+ msg->dst_id = (u16)MESSAGEQ_INVALIDMESSAGEQ;
+ msg->flags = MESSAGEQ_HEADERVERSION | MESSAGEQ_NORMALPRI;
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_static_msg_init);
+
+/*
+ * ======== messageq_alloc ========
+ * Purpose:
+ * Allocate a message and initial the needed fields (note some
+ * of the fields in the header at set via other APIs or in the
+ * messageq_put function.
+ */
+messageq_msg messageq_alloc(u16 heap_id, u32 size)
+{
+ messageq_msg msg = NULL;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(heap_id >= messageq_state.num_heaps)) {
+ printk(KERN_ERR "messageq_alloc: heap_id is invalid!\n");
+ goto exit;
+ }
+
+ if (messageq_state.heaps[heap_id] != NULL) {
+ /* Allocate the message. No alignment requested */
+ msg = heap_alloc(messageq_state.heaps[heap_id], size, 0);
+ if (msg == NULL) {
+ printk(KERN_ERR "messageq_alloc: message allocation "
+ "failed!\n");
+ goto exit;
+ }
+
+ /* Fill in the fields of the message */
+ msg->msg_size = size;
+ msg->heap_id = heap_id;
+ msg->reply_id = (u16)MESSAGEQ_INVALIDMESSAGEQ;
+ msg->dst_id = (u16)MESSAGEQ_INVALIDMESSAGEQ;
+ msg->msg_id = MESSAGEQ_INVALIDMSGID;
+ msg->flags = MESSAGEQ_HEADERVERSION | MESSAGEQ_NORMALPRI;
+ } else {
+ printk(KERN_ERR "messageq_alloc: heap_id was not "
+ "registered!\n");
+ }
+
+exit:
+ return msg;
+}
+EXPORT_SYMBOL(messageq_alloc);
+
+/*
+ * ======== messageq_free ========
+ * Purpose:
+ * Frees the message.
+ */
+int messageq_free(messageq_msg msg)
+{
+ u32 status = 0;
+ void *heap = NULL;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(msg == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (msg->heap_id >= messageq_state.num_heaps) {
+ status = MESSAGEQ_E_INVALIDHEAPID;
+ goto exit;
+ }
+ if (msg->heap_id == MESSAGEQ_STATICMSG) {
+ status = MESSAGEQ_E_CANNOTFREESTATICMSG;
+ goto exit;
+ }
+
+ heap = messageq_state.heaps[msg->heap_id];
+ heap_free(heap, msg, msg->msg_size);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_free failed! status = 0x%x\n",
+ status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_free);
+
+/*
+ * ======== messageq_put ========
+ * Purpose:
+ * Put a message in the queue
+ */
+int messageq_put(u32 queue_id, messageq_msg msg)
+{
+ int status = 0;
+ u16 dst_proc_id = (u16)(queue_id >> 16);
+ struct messageq_object *obj = NULL;
+ void *transport = NULL;
+ u32 priority;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+ if (WARN_ON(msg == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ msg->dst_id = (u16)(queue_id);
+ msg->dst_proc = (u16)(queue_id >> 16);
+ if (dst_proc_id != multiproc_get_id(NULL)) {
+ if (dst_proc_id >= multiproc_get_max_processors()) {
+ /* Invalid destination processor id */
+ status = MESSAGEQ_E_INVALIDPROCID;
+ goto exit;
+ }
+
+ priority = (u32)((msg->flags) & MESSAGEQ_TRANSPORTPRIORITYMASK);
+ /* Call the transport associated with this message queue */
+ transport = messageq_state.transports[dst_proc_id][priority];
+ if (transport == NULL) {
+ /* Try the other transport */
+ priority = !priority;
+ transport =
+ messageq_state.transports[dst_proc_id][priority];
+ }
+
+ if (transport != NULL)
+ status = messageq_transportshm_put(transport, msg);
+ else {
+ status = -ENODEV;
+ goto exit;
+ }
+ } else {
+ /* It is a local MessageQ */
+ obj = (struct messageq_object *)
+ (messageq_state.queues[(u16)(queue_id)]);
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if ((msg->flags & MESSAGEQ_PRIORITYMASK) == \
+ MESSAGEQ_URGENTPRI) {
+ list_add((struct list_head *) msg, &obj->high_list);
+ } else {
+ if ((msg->flags & MESSAGEQ_PRIORITYMASK) == \
+ MESSAGEQ_NORMALPRI) {
+ list_add_tail((struct list_head *) msg,
+ &obj->normal_list);
+ } else {
+ list_add_tail((struct list_head *) msg,
+ &obj->high_list);
+ }
+ }
+ mutex_unlock(messageq_state.gate_handle);
+
+ /* Notify the reader. */
+ if (obj->synchronizer != NULL) {
+ up(obj->synchronizer);
+ /*OsalSemaphore_post(obj->synchronizer);*/
+ }
+ }
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "messageq_put failed! status = 0x%x\n", status);
+ return status;
+}
+EXPORT_SYMBOL(messageq_put);
+
+/*
+ * ======== messageq_register_heap ========
+ * Purpose:
+ * register a heap
+ */
+int messageq_register_heap(void *heap_handle, u16 heap_id)
+{
+ int status = 0;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+ /* Make sure the heap_id is valid */
+ if (WARN_ON(heap_id >= messageq_state.num_heaps)) {
+ /*! @retval MESSAGEQ_E_HEAPIDINVALID Invalid heap_id */
+ status = MESSAGEQ_E_HEAPIDINVALID;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (messageq_state.heaps[heap_id] == NULL)
+ messageq_state.heaps[heap_id] = heap_handle;
+ else {
+ /*! @retval MESSAGEQ_E_ALREADYEXISTS Specified heap is
+ already registered. */
+ status = MESSAGEQ_E_ALREADYEXISTS;
+ }
+ mutex_unlock(messageq_state.gate_handle);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_register_heap failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_register_heap);
+
+/*
+ * ======== messageq_unregister_heap ========
+ * Purpose:
+ * Unregister a heap
+ */
+int messageq_unregister_heap(u16 heap_id)
+{
+ int status = 0;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ /* Make sure the heap_id is valid */
+ if (WARN_ON(heap_id > messageq_state.num_heaps)) {
+ /*! @retval MESSAGEQ_E_HEAPIDINVALID Invalid heap_id */
+ status = MESSAGEQ_E_HEAPIDINVALID;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (messageq_state.heaps != NULL)
+ messageq_state.heaps[heap_id] = NULL;
+ mutex_unlock(messageq_state.gate_handle);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_unregister_heap failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_unregister_heap);
+
+/*
+ * ======== messageq_register_transport ========
+ * Purpose:
+ * register a transport
+ */
+int messageq_register_transport(void *messageq_transportshm_handle,
+ u16 proc_id, u32 priority)
+{
+ int status = 0;
+ int key;
+
+ BUG_ON(messageq_transportshm_handle == NULL);
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ /* Make sure the proc_id is valid */
+ if (WARN_ON(proc_id >= multiproc_get_max_processors())) {
+ /*! @retval MESSAGEQ_E_PROCIDINVALID Invalid proc_id */
+ status = MESSAGEQ_E_PROCIDINVALID;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (messageq_state.transports[proc_id][priority] == NULL) {
+ messageq_state.transports[proc_id][priority] = \
+ messageq_transportshm_handle;
+ } else {
+ /*! @retval MESSAGEQ_E_ALREADYEXISTS Specified transport is
+ already registered. */
+ status = MESSAGEQ_E_ALREADYEXISTS;
+ }
+ mutex_unlock(messageq_state.gate_handle);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_register_transport failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_register_transport);
+
+/*
+ * ======== messageq_unregister_transport ========
+ * Purpose:
+ * Unregister a transport
+ */
+int messageq_unregister_transport(u16 proc_id, u32 priority)
+{
+ int status = 0;
+ int key;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ /* Make sure the proc_id is valid */
+ if (WARN_ON(proc_id >= multiproc_get_max_processors())) {
+ /*! @retval MESSAGEQ_E_PROCIDINVALID Invalid proc_id */
+ status = MESSAGEQ_E_PROCIDINVALID;
+ goto exit;
+ }
+
+ key = mutex_lock_interruptible(messageq_state.gate_handle);
+ if (messageq_state.transports[proc_id][priority] == NULL)
+ messageq_state.transports[proc_id][priority] = NULL;
+ mutex_unlock(messageq_state.gate_handle);
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_unregister_transport failed! "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(messageq_unregister_transport);
+
+/*
+ * ======== messageq_set_reply_queue ========
+ * Purpose:
+ * Set the destination queue of the message.
+ */
+void messageq_set_reply_queue(void *messageq_handle, messageq_msg msg)
+{
+ struct messageq_object *obj = \
+ (struct messageq_object *) messageq_handle;
+
+ BUG_ON(messageq_handle == NULL);
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_set_reply_queue: msg passed is "
+ "NULL!\n");
+ goto exit;
+ }
+
+ msg->reply_id = (u16)(obj->queue);
+ msg->reply_proc = (u16)(obj->queue >> 16);
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_set_reply_queue);
+
+/*
+ * ======== messageq_get_queue_id ========
+ * Purpose:
+ * Get the queue _id of the message.
+ */
+u32 messageq_get_queue_id(void *messageq_handle)
+{
+ struct messageq_object *obj = \
+ (struct messageq_object *) messageq_handle;
+ u32 queue_id = MESSAGEQ_INVALIDMESSAGEQ;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(obj == NULL)) {
+ printk(KERN_ERR "messageq_get_queue_id: obj passed is NULL!\n");
+ goto exit;
+ }
+
+ queue_id = (obj->queue);
+
+exit:
+ return queue_id;
+}
+EXPORT_SYMBOL(messageq_get_queue_id);
+
+/*
+ * ======== messageq_get_proc_id ========
+ * Purpose:
+ * Get the proc _id of the message.
+ */
+u16 messageq_get_proc_id(void *messageq_handle)
+{
+ struct messageq_object *obj = \
+ (struct messageq_object *) messageq_handle;
+ u16 proc_id = MULTIPROC_INVALIDID;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(obj == NULL)) {
+ printk(KERN_ERR "messageq_get_proc_id: obj passed is NULL!\n");
+ goto exit;
+ }
+
+ proc_id = (u16)(obj->queue >> 16);
+
+exit:
+ return proc_id;
+}
+EXPORT_SYMBOL(messageq_get_proc_id);
+
+/*
+ * ======== messageq_get_dst_queue ========
+ * Purpose:
+ * Get the destination queue of the message.
+ */
+u32 messageq_get_dst_queue(messageq_msg msg)
+{
+ u32 queue_id = MESSAGEQ_INVALIDMESSAGEQ;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_get_dst_queue: msg passed is "
+ "NULL!\n");
+ goto exit;
+ }
+
+ /*construct queue value */
+ if (msg->dst_id != (u32)MESSAGEQ_INVALIDMESSAGEQ)
+ queue_id = ((u32) multiproc_get_id(NULL) << 16) | msg->dst_id;
+
+exit:
+ return queue_id;
+}
+EXPORT_SYMBOL(messageq_get_dst_queue);
+
+/*
+ * ======== messageq_get_msg_id ========
+ * Purpose:
+ * Get the message id of the message.
+ */
+u16 messageq_get_msg_id(messageq_msg msg)
+{
+ u16 id = MESSAGEQ_INVALIDMSGID;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_get_msg_id: msg passed is NULL!\n");
+ goto exit;
+ }
+
+ id = msg->msg_id;
+
+exit:
+ return id;
+}
+EXPORT_SYMBOL(messageq_get_msg_id);
+
+/*
+ * ======== messageq_get_msg_size ========
+ * Purpose:
+ * Get the message size of the message.
+ */
+u32 messageq_get_msg_size(messageq_msg msg)
+{
+ u32 size = 0;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_get_msg_size: msg passed is NULL!\n");
+ goto exit;
+ }
+
+ size = msg->msg_size;
+
+exit:
+ return size;
+}
+EXPORT_SYMBOL(messageq_get_msg_size);
+
+/*
+ * ======== messageq_get_msg_pri ========
+ * Purpose:
+ * Get the message priority of the message.
+ */
+u32 messageq_get_msg_pri(messageq_msg msg)
+{
+ u32 priority = MESSAGEQ_NORMALPRI;
+
+ BUG_ON(msg == NULL);
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_get_msg_pri: msg passed is NULL!\n");
+ goto exit;
+ }
+
+ priority = ((u32)(msg->flags & MESSAGEQ_PRIORITYMASK));
+
+exit:
+ return priority;
+}
+EXPORT_SYMBOL(messageq_get_msg_pri);
+
+/*
+ * ======== messageq_get_reply_queue ========
+ * Purpose:
+ * Get the embedded source message queue out of the message.
+ */
+u32 messageq_get_reply_queue(messageq_msg msg)
+{
+ u32 queue = MESSAGEQ_INVALIDMESSAGEQ;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_get_reply_queue: msg passed is "
+ "NULL!\n");
+ goto exit;
+ }
+
+ if (msg->reply_id != (u16)MESSAGEQ_INVALIDMESSAGEQ)
+ queue = ((u32)(msg->reply_proc) << 16) | msg->reply_id;
+
+exit:
+ return queue;
+}
+EXPORT_SYMBOL(messageq_get_reply_queue);
+
+/*
+ * ======== messageq_set_msg_id ========
+ * Purpose:
+ * Set the message id of the message.
+ */
+void messageq_set_msg_id(messageq_msg msg, u16 msg_id)
+{
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_set_msg_id: msg passed is NULL!\n");
+ goto exit;
+ }
+
+ msg->msg_id = msg_id;
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_set_msg_id);
+
+/*
+ * ======== messageq_set_msg_pri ========
+ * Purpose:
+ * Set the priority of the message.
+ */
+void messageq_set_msg_pri(messageq_msg msg, u32 priority)
+{
+ if (WARN_ON(atomic_cmpmask_and_lt(&(messageq_state.ref_count),
+ MESSAGEQ_MAKE_MAGICSTAMP(0),
+ MESSAGEQ_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(msg == NULL)) {
+ printk(KERN_ERR "messageq_set_msg_pri: msg passed is NULL!\n");
+ goto exit;
+ }
+
+ msg->flags = priority & MESSAGEQ_PRIORITYMASK;
+
+exit:
+ return;
+}
+EXPORT_SYMBOL(messageq_set_msg_pri);
+
+/* =============================================================================
+ * Internal functions
+ * =============================================================================
+ */
+/*
+ * ======== _messageq_grow ========
+ * Purpose:
+ * Grow the MessageQ table
+ */
+u16 _messageq_grow(struct messageq_object *obj)
+{
+ u16 queue_index = messageq_state.num_queues;
+ int oldSize;
+ void **queues;
+ void **oldqueues;
+
+ if (WARN_ON(obj == NULL)) {
+ printk(KERN_ERR "_messageq_grow: obj passed is NULL!\n");
+ goto exit;
+ }
+
+ oldSize = (messageq_state.num_queues) * \
+ sizeof(struct messageq_object *);
+ queues = kmalloc(oldSize + sizeof(struct messageq_object *),
+ GFP_KERNEL);
+ if (queues == NULL) {
+ printk(KERN_ERR "_messageq_grow: Growing the messageq "
+ "failed!\n");
+ goto exit;
+ }
+
+ /* Copy contents into new table */
+ memcpy(queues, messageq_state.queues, oldSize);
+ /* Fill in the new entry */
+ queues[queue_index] = (void *)obj;
+ /* Hook-up new table */
+ oldqueues = messageq_state.queues;
+ messageq_state.queues = queues;
+ messageq_state.num_queues++;
+
+ /* Delete old table if not statically defined*/
+ if (messageq_state.can_free_queues == true)
+ kfree(oldqueues);
+ else
+ messageq_state.can_free_queues = true;
+
+exit:
+ return queue_index;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/messageq_ioctl.c b/drivers/dsp/syslink/multicore_ipc/messageq_ioctl.c
new file mode 100644
index 000000000000..a3efaac9b59b
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/messageq_ioctl.c
@@ -0,0 +1,484 @@
+/*
+ * messageq_ioctl.c
+ *
+ * This file implements all the ioctl operations required on the messageq
+ * module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Linux headers */
+#include <linux/uaccess.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+/* Module Headers */
+#include <messageq.h>
+#include <messageq_ioctl.h>
+#include <sharedregion.h>
+
+/*
+ * ======== messageq_ioctl_put ========
+ * Purpose:
+ * This ioctl interface to messageq_put function
+ */
+static inline int messageq_ioctl_put(struct messageq_cmd_args *cargs)
+{
+ int status = 0;
+ messageq_msg msg;
+
+ msg = (messageq_msg) sharedregion_get_ptr(cargs->args.put.msg_srptr);
+ if (unlikely(msg == NULL))
+ goto exit;
+
+ status = messageq_put(cargs->args.put.queue_id, msg);
+
+ cargs->api_status = status;
+exit:
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_get ========
+ * Purpose:
+ * This ioctl interface to messageq_get function
+ */
+static inline int messageq_ioctl_get(struct messageq_cmd_args *cargs)
+{
+ messageq_msg msg = NULL;
+ u32 *msg_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ cargs->api_status = messageq_get(cargs->args.get.messageq_handle,
+ &msg,
+ cargs->args.get.timeout);
+ if (unlikely(cargs->api_status < 0))
+ goto exit;
+
+ index = sharedregion_get_index(msg);
+ if (unlikely(index < 0)) {
+ cargs->api_status = index;
+ goto exit;
+ }
+
+ msg_srptr = sharedregion_get_srptr(msg, index);
+
+exit:
+ cargs->args.get.msg_srptr = msg_srptr;
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_count ========
+ * Purpose:
+ * This ioctl interface to messageq_count function
+ */
+static inline int messageq_ioctl_count(struct messageq_cmd_args *cargs)
+{
+ cargs->args.count.count = \
+ messageq_count(cargs->args.count.messageq_handle);
+
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_alloc ========
+ * Purpose:
+ * This ioctl interface to messageq_alloc function
+ */
+static inline int messageq_ioctl_alloc(struct messageq_cmd_args *cargs)
+{
+ messageq_msg msg;
+ u32 *msg_srptr = SHAREDREGION_INVALIDSRPTR;
+ int index;
+
+ msg = messageq_alloc(cargs->args.alloc.heap_id, cargs->args.alloc.size);
+ if (unlikely(msg == NULL))
+ goto exit;
+
+ index = sharedregion_get_index(msg);
+ if (unlikely(index < 0))
+ goto exit;
+
+ msg_srptr = sharedregion_get_srptr(msg, index);
+
+ cargs->api_status = 0;
+exit:
+ cargs->args.alloc.msg_srptr = msg_srptr;
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_free ========
+ * Purpose:
+ * This ioctl interface to messageq_free function
+ */
+static inline int messageq_ioctl_free(struct messageq_cmd_args *cargs)
+{
+ int status = 0;
+ messageq_msg msg;
+
+ msg = sharedregion_get_ptr(cargs->args.free.msg_srptr);
+ if (unlikely(msg == NULL))
+ goto exit;
+ status = messageq_free(msg);
+
+ cargs->api_status = status;
+exit:
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to messageq_params_init function
+ */
+static inline int messageq_ioctl_params_init(struct messageq_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ struct messageq_params params;
+
+ messageq_params_init(cargs->args.params_init.messageq_handle,
+ &params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct messageq_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = status;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_ioctl_create ========
+ * Purpose:
+ * This ioctl interface to messageq_create function
+ */
+static inline int messageq_ioctl_create(struct messageq_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ struct messageq_params params;
+ char *name = NULL;
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct messageq_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ /* Allocate memory for the name */
+ if (cargs->args.create.name_len > 0) {
+ name = kmalloc(cargs->args.create.name_len, GFP_KERNEL);
+ if (name == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ size = copy_from_user(name, cargs->args.create.name,
+ cargs->args.create.name_len);
+ if (size) {
+ retval = -EFAULT;
+ goto free_name;
+ }
+ }
+
+ cargs->args.create.messageq_handle = messageq_create(name, &params);
+ if (cargs->args.create.messageq_handle != NULL) {
+ cargs->args.create.queue_id = messageq_get_queue_id(
+ cargs->args.create.messageq_handle);
+ }
+
+free_name:
+ if (cargs->args.create.name_len > 0)
+ kfree(name);
+
+ cargs->api_status = status;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to messageq_delete function
+ */
+static inline int messageq_ioctl_delete(struct messageq_cmd_args *cargs)
+{
+ cargs->api_status =
+ messageq_delete(&(cargs->args.delete_messageq.messageq_handle));
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_open ========
+ * Purpose:
+ * This ioctl interface to messageq_open function
+ */
+static inline int messageq_ioctl_open(struct messageq_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ char *name = NULL;
+ u32 queue_id = MESSAGEQ_INVALIDMESSAGEQ;
+
+ /* Allocate memory for the name */
+ if (cargs->args.open.name_len > 0) {
+ name = kmalloc(cargs->args.open.name_len, GFP_KERNEL);
+ if (name == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ size = copy_from_user(name, cargs->args.open.name,
+ cargs->args.open.name_len);
+ if (size) {
+ retval = -EFAULT;
+ goto free_name;
+ }
+ }
+
+ status = messageq_open(name, &queue_id);
+ cargs->args.open.queue_id = queue_id;
+
+free_name:
+ if (cargs->args.open.name_len > 0)
+ kfree(name);
+
+ cargs->api_status = status;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_ioctl_close ========
+ * Purpose:
+ * This ioctl interface to messageq_close function
+ */
+static inline int messageq_ioctl_close(struct messageq_cmd_args *cargs)
+{
+ u32 queue_id = cargs->args.close.queue_id;
+ messageq_close(&queue_id);
+ cargs->args.close.queue_id = queue_id;
+
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to messageq_get_config function
+ */
+static inline int messageq_ioctl_get_config(struct messageq_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_config config;
+
+ messageq_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct messageq_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to messageq_setup function
+ */
+static inline int messageq_ioctl_setup(struct messageq_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_config config;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct messageq_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = messageq_setup(&config);
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to messageq_destroy function
+ */
+static inline int messageq_ioctl_destroy(struct messageq_cmd_args *cargs)
+{
+ cargs->api_status = messageq_destroy();
+ return 0;
+}
+
+
+/*
+ * ======== messageq_ioctl_register_heap ========
+ * Purpose:
+ * This ioctl interface to messageq_register_heap function
+ */
+static inline int messageq_ioctl_register_heap(struct messageq_cmd_args *cargs)
+{
+ cargs->api_status = \
+ messageq_register_heap(cargs->args.register_heap.heap_handle,
+ cargs->args.register_heap.heap_id);
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl_unregister_heap ========
+ * Purpose:
+ * This ioctl interface to messageq_unregister_heap function
+ */
+static inline int messageq_ioctl_unregister_heap(
+ struct messageq_cmd_args *cargs)
+{
+ cargs->api_status = messageq_unregister_heap(
+ cargs->args.unregister_heap.heap_id);
+ return 0;
+}
+
+/*
+ * ======== messageq_ioctl ========
+ * Purpose:
+ * ioctl interface function for messageq module
+ */
+int messageq_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int os_status = 0;
+ struct messageq_cmd_args __user *uarg =
+ (struct messageq_cmd_args __user *)args;
+ struct messageq_cmd_args cargs;
+ unsigned long size;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+ if (os_status) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg, sizeof(struct messageq_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_MESSAGEQ_PUT:
+ os_status = messageq_ioctl_put(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_GET:
+ os_status = messageq_ioctl_get(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_COUNT:
+ os_status = messageq_ioctl_count(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_ALLOC:
+ os_status = messageq_ioctl_alloc(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_FREE:
+ os_status = messageq_ioctl_free(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_PARAMS_INIT:
+ os_status = messageq_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_CREATE:
+ os_status = messageq_ioctl_create(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_DELETE:
+ os_status = messageq_ioctl_delete(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_OPEN:
+ os_status = messageq_ioctl_open(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_CLOSE:
+ os_status = messageq_ioctl_close(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_GETCONFIG:
+ os_status = messageq_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_SETUP:
+ os_status = messageq_ioctl_setup(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_DESTROY:
+ os_status = messageq_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_REGISTERHEAP:
+ os_status = messageq_ioctl_register_heap(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_UNREGISTERHEAP:
+ os_status = messageq_ioctl_unregister_heap(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ os_status = -ENOTTY;
+ break;
+ }
+ if (os_status < 0)
+ goto exit;
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct messageq_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+ return os_status;
+
+exit:
+ printk(KERN_ERR "messageq_ioctl failed: status = 0x%x\n", os_status);
+ return os_status;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/messageq_transportshm.c b/drivers/dsp/syslink/multicore_ipc/messageq_transportshm.c
new file mode 100644
index 000000000000..344e7435770e
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/messageq_transportshm.c
@@ -0,0 +1,778 @@
+/*
+ * messageq_transportshm.c
+ *
+ * MessageQ Transport module
+ *
+ * Copyright (C) 2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* Syslink headers */
+#include <syslink/atomic_linux.h>
+/* Module level headers */
+#include <multiproc.h>
+#include <nameserver.h>
+#include <gatepeterson.h>
+#include <notify.h>
+#include <messageq.h>
+#include <listmp_sharedmemory.h>
+#include <messageq_transportshm.h>
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/* Cache line size */
+#define MESSAGEQ_TRANSPORTSHM_CACHESIZE 128
+
+/* Indicates that the transport is up. */
+#define MESSAGEQ_TRANSPORTSHM_UP 0xBADC0FFE
+
+/* messageq_transportshm Version. */
+#define MESSAGEQ_TRANSPORTSHM_VERSION 1
+
+/*!
+ * @brief Macro to make a correct module magic number with refCount
+ */
+#define MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(x) \
+ ((MESSAGEQ_TRANSPORTSHM_MODULEID << 12u) | (x))
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/*
+ * Defines the messageq_transportshm state object, which contains all the
+ * module specific information.
+ */
+struct messageq_transportshm_moduleobject {
+ atomic_t ref_count;
+ struct messageq_transportshm_config cfg;
+ /*< messageq_transportshm configuration structure */
+ struct messageq_transportshm_config def_cfg;
+ /*< Default module configuration */
+ struct messageq_transportshm_params def_inst_params;
+ /*< Default instance parameters */
+ void *gate_handle;
+ /*< Handle to the gate for local thread safety */
+ void *transports[MULTIPROC_MAXPROCESSORS][MESSAGEQ_NUM_PRIORITY_QUEUES];
+ /*!< Transport to be set in messageq_register_transport */
+
+};
+
+/*
+ * Structure of attributes in shared memory
+ */
+struct messageq_transportshm_attrs {
+ VOLATILE u32 version;
+ VOLATILE u32 flag;
+};
+
+/*
+ * Structure defining config parameters for the MessageQ transport
+ * instances.
+ */
+struct messageq_transportshm_object {
+ VOLATILE struct messageq_transportshm_attrs *attrs[2];
+ /* Attributes for both processors */
+ void *my_listmp_handle;
+ /* List for this processor */
+ void *remote_listmp_handle;
+ /* List for remote processor */
+ VOLATILE int status;
+ /* Current status */
+ int my_index;
+ /* 0 | 1 */
+ int remote_index;
+ /* 1 | 0 */
+ int notify_event_no;
+ /* Notify event to be used */
+ void *notify_driver;
+ /* Notify driver to be used */
+ u16 proc_id;
+ /* Dest proc id */
+ void *gate;
+ /* Gate for critical regions */
+ struct messageq_transportshm_params params;
+ /* Instance specific parameters */
+ u32 priority;
+ /*!< Priority of messages supported by this transport */
+};
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/*
+ * @var messageq_transportshm_state
+ *
+ * messageq_transportshm state object variable
+ */
+static struct messageq_transportshm_moduleobject messageq_transportshm_state = {
+ .gate_handle = NULL,
+ .def_cfg.err_fxn = 0,
+ .def_inst_params.gate = NULL,
+ .def_inst_params.shared_addr = 0x0,
+ .def_inst_params.shared_addr_size = 0x0,
+ .def_inst_params.notify_event_no = (u32)(-1),
+ .def_inst_params.notify_driver = NULL,
+ .def_inst_params.priority = MESSAGEQ_NORMALPRI
+};
+
+
+/* =============================================================================
+ * Forward declarations of internal functions
+ * =============================================================================
+ */
+/* Callback function registered with the Notify module. */
+static void _messageq_transportshm_notify_fxn(u16 proc_id,
+ u32 event_no, void *arg, u32 payload);
+
+/* =============================================================================
+ * APIs called directly by applications
+ * =============================================================================
+ */
+/*
+ * ======== messageq_transportshm_get_config ========
+ * Purpose:
+ * Get the default configuration for the messageq_transportshm
+ * module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to messageq_transportshm_setup filled in
+ * by the messageq_transportshm module with the default parameters.
+ * If the user does not wish to make any change in the default
+ * parameters, this API is not required to be called.
+ */
+void messageq_transportshm_get_config(
+ struct messageq_transportshm_config *cfg)
+{
+ if (WARN_ON(cfg == NULL))
+ goto exit;
+
+ if (atomic_cmpmask_and_lt(&(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true) {
+ memcpy(cfg, &(messageq_transportshm_state.def_cfg),
+ sizeof(struct messageq_transportshm_config));
+ } else {
+ memcpy(cfg, &(messageq_transportshm_state.cfg),
+ sizeof(struct messageq_transportshm_config));
+ }
+ return;
+
+exit:
+ printk(KERN_ERR "messageq_transportshm_get_config: Argument of type"
+ "(struct messageq_transportshm_config *) passed is null!\n");
+}
+
+
+/*
+ * ======== messageq_transportshm_setup ========
+ * Purpose:
+ * Setup the messageq_transportshm module.
+ *
+ * This function sets up the messageq_transportshm module. This
+ * function must be called before any other instance-level APIs can
+ * be invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then messageq_transportshm_getConfig can be called
+ * to get the configuration filled with the default values. After
+ * this, only the required configuration values can be changed. If
+ * the user does not wish to make any change in the default
+ * parameters, the application can simply call
+ * messageq_transportshm_setup with NULL parameters. The default
+ * parameters would get automatically used.
+ */
+int messageq_transportshm_setup(const struct messageq_transportshm_config *cfg)
+{
+ int status = MESSAGEQ_TRANSPORTSHM_SUCCESS;
+ struct messageq_transportshm_config tmpCfg;
+
+ /* This sets the refCount variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable.
+ */
+ atomic_cmpmask_and_set(&messageq_transportshm_state.ref_count,
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&messageq_transportshm_state.ref_count)
+ != MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1u)) {
+ return 1;
+ }
+
+ if (cfg == NULL) {
+ messageq_transportshm_get_config(&tmpCfg);
+ cfg = &tmpCfg;
+ }
+
+ messageq_transportshm_state.gate_handle = \
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (messageq_transportshm_state.gate_handle == NULL) {
+ /* @retval MESSAGEQTRANSPORTSHM_E_FAIL Failed to create
+ GateMutex! */
+ status = MESSAGEQ_TRANSPORTSHM_E_FAIL;
+ printk(KERN_ERR "messageq_transportshm_setup: Failed to create "
+ "mutex!\n");
+ atomic_set(&messageq_transportshm_state.ref_count,
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0));
+ goto exit;
+ }
+ mutex_init(messageq_transportshm_state.gate_handle);
+
+ /* Copy the user provided values into the state object. */
+ memcpy(&messageq_transportshm_state.cfg, cfg,
+ sizeof(struct messageq_transportshm_config));
+ memset(&(messageq_transportshm_state.transports), 0, (sizeof(void *) * \
+ MULTIPROC_MAXPROCESSORS * MESSAGEQ_NUM_PRIORITY_QUEUES));
+ return status;
+
+exit:
+ printk(KERN_ERR "messageq_transportshm_setup failed: status = 0x%x",
+ status);
+ return status;
+}
+
+
+/*
+ * ======== messageq_transportshm_destroy ========
+ * Purpose:
+ * Destroy the messageq_transportshm module.
+ *
+ * Once this function is called, other messageq_transportshm module
+ * APIs, except for the messageq_transportshm_getConfig API cannot
+ * be called anymore.
+ */
+int messageq_transportshm_destroy(void)
+{
+ int status = 0;
+ u16 i;
+ u16 j;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (!(atomic_dec_return(&messageq_transportshm_state.ref_count)
+ == MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0))) {
+ status = 1;
+ goto exit;
+ }
+
+ /* Temporarily increment ref_count here. */
+ atomic_set(&messageq_transportshm_state.ref_count,
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1));
+
+ /* Delete any Transports that have not been deleted so far. */
+ for (i = 0; i < MULTIPROC_MAXPROCESSORS; i++) {
+ for (j = 0 ; j < MESSAGEQ_NUM_PRIORITY_QUEUES; j++) {
+ if (messageq_transportshm_state.transports[i][j] != \
+ NULL) {
+ messageq_transportshm_delete(&
+ (messageq_transportshm_state.transports[i][j]));
+ }
+ }
+ }
+ if (messageq_transportshm_state.gate_handle != NULL) {
+ kfree(messageq_transportshm_state.gate_handle);
+ messageq_transportshm_state.gate_handle = NULL;
+ }
+
+ /* Decrease the ref_count */
+ atomic_set(&messageq_transportshm_state.ref_count,
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0));
+ return 0;
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "messageq_transportshm_destroy failed: "
+ "status = 0x%x\n", status);
+ }
+ return status;
+}
+
+
+/*
+ * ======== messageq_transportshm_params_init ========
+ * Purpose:
+ * Get Instance parameters
+ */
+void messageq_transportshm_params_init(void *mqtshm_handle,
+ struct messageq_transportshm_params *params)
+{
+ struct messageq_transportshm_object *object = NULL;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true)) {
+ printk(KERN_ERR "messageq_transportshm_params_init: Module was "
+ " not initialized\n");
+ goto exit;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ printk(KERN_ERR "messageq_transportshm_params_init: Argument of"
+ " type (struct messageq_transportshm_params *) "
+ "is NULL!");
+ goto exit;
+ }
+
+ if (mqtshm_handle == NULL) {
+ memcpy(params, &(messageq_transportshm_state.def_inst_params),
+ sizeof(struct messageq_transportshm_params));
+ } else {
+ /* Return updated messageq_transportshm instance
+ specific parameters. */
+ object = (struct messageq_transportshm_object *) mqtshm_handle;
+ memcpy(params, &(object->params),
+ sizeof(struct messageq_transportshm_params));
+ }
+
+exit:
+ return;
+}
+
+/*
+ * ======== messageq_transportshm_create ========
+ * Purpose:
+ * Create a transport instance. This function waits for the remote
+ * processor to complete its transport creation. Hence it must be
+ * called only after the remote processor is running.
+ */
+void *messageq_transportshm_create(u16 proc_id,
+ const struct messageq_transportshm_params *params)
+{
+ struct messageq_transportshm_object *handle = NULL;
+ int status = 0;
+ int my_index;
+ int remote_index;
+ listmp_sharedmemory_params listmp_params[2];
+ VOLATILE u32 *otherflag;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(params->shared_addr_size < \
+ messageq_transportshm_shared_mem_req(params))) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (messageq_transportshm_state.transports[proc_id][params->priority] \
+ != NULL) {
+ /* Specified transport is already registered. */
+ status = MESSAGEQ_E_ALREADYEXISTS;
+ goto exit;
+ }
+
+ /*
+ * Determine who gets the '0' slot and who gets the '1' slot
+ * The '0' slot is given to the lower multiproc id.
+ */
+ if (multiproc_get_id(NULL) < proc_id) {
+ my_index = 0;
+ remote_index = 1;
+ } else {
+ my_index = 1;
+ remote_index = 0;
+ }
+
+ handle = kzalloc(sizeof(struct messageq_transportshm_object),
+ GFP_KERNEL);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ handle->attrs[0] = (struct messageq_transportshm_attrs *)
+ params->shared_addr;
+ handle->attrs[1] = (struct messageq_transportshm_attrs *)
+ ((u32)(handle->attrs[0]) + \
+ MESSAGEQ_TRANSPORTSHM_CACHESIZE);
+ handle->status = messageq_transportshm_status_INIT;
+ handle->gate = params->gate;
+ memcpy(&(handle->params), (void *)params,
+ sizeof(struct messageq_transportshm_params));
+
+ status = notify_register_event(params->notify_driver, proc_id,
+ params->notify_event_no,
+ _messageq_transportshm_notify_fxn,
+ (void *)handle);
+ if (status < 0) {
+ /* @retval NULL Notify register failed */
+ printk(KERN_ERR "messageq_transportshm_create: "
+ "notify_register_event failed!\n");
+ goto notify_register_fail;
+ }
+
+ handle->notify_driver = params->notify_driver;
+ handle->notify_event_no = params->notify_event_no;
+ handle->priority = params->priority;
+ handle->proc_id = proc_id;
+ handle->my_index = my_index;
+ handle->remote_index = remote_index;
+
+ /* Create the shared lists for the transport. */
+ listmp_sharedmemory_params_init(NULL, &(listmp_params[0]));
+ listmp_params[0].shared_addr = (u32 *)((u32)(params->shared_addr) + \
+ (2 * MESSAGEQ_TRANSPORTSHM_CACHESIZE));
+ listmp_params[0].shared_addr_size = \
+ listmp_sharedmemory_shared_memreq(&(listmp_params[0]));
+ listmp_params[0].gate = params->gate;
+ listmp_params[0].name = NULL;
+ listmp_params[0].list_type = listmp_type_SHARED;
+
+ listmp_sharedmemory_params_init(NULL, &(listmp_params[1]));
+ listmp_params[1].shared_addr = \
+ (u32 *)((u32)(listmp_params[0].shared_addr) + \
+ listmp_params[0].shared_addr_size);
+ listmp_params[1].shared_addr_size = \
+ listmp_sharedmemory_shared_memreq(&(listmp_params[1]));
+ listmp_params[1].name = NULL;
+ listmp_params[1].list_type = listmp_type_SHARED;
+ listmp_params[1].gate = params->gate;
+
+ handle->my_listmp_handle = listmp_sharedmemory_create
+ (&(listmp_params[my_index]));
+ handle->attrs[my_index]->version = MESSAGEQ_TRANSPORTSHM_VERSION;
+ handle->attrs[my_index]->flag = MESSAGEQ_TRANSPORTSHM_UP;
+
+ /* Store in VOLATILE to make sure it is not compiled out... */
+ otherflag = &(handle->attrs[remote_index]->flag);
+
+ /* Loop until the other side is up */
+ while (*otherflag != MESSAGEQ_TRANSPORTSHM_UP)
+ ;
+
+ if (handle->attrs[remote_index]->version
+ != MESSAGEQ_TRANSPORTSHM_VERSION) {
+ /* @retval NULL Versions do not match */
+ printk(KERN_ERR "messageq_transportshm_create: "
+ "Incorrect version of remote transport!\n");
+ goto exit;
+ }
+
+ status = listmp_sharedmemory_open
+ ((listmp_sharedmemory_handle *) &(handle->remote_listmp_handle),
+ &listmp_params[remote_index]);
+ if (status < 0) {
+ /* @retval NULL List creation failed */
+ goto listmp_open_fail;
+ }
+
+ /* Register the transport with MessageQ */
+ status = messageq_register_transport((void *)handle, proc_id,
+ (u32)params->priority);
+ if (status >= 0) {
+ messageq_transportshm_state.transports
+ [proc_id][params->priority] = (void *)handle;
+ handle->status = messageq_transportshm_status_UP;
+ }
+ return handle;
+
+listmp_open_fail:
+ printk(KERN_ERR "messageq_transportshm_create: "
+ "listmp_sharedmemory_open failed!\n");
+notify_register_fail:
+ if (status < 0) {
+ if (handle != NULL)
+ messageq_transportshm_delete((void **)(&handle));
+ }
+
+exit:
+ printk(KERN_ERR "messageq_transportshm_create failed: status = 0x%x\n",
+ status);
+ return handle;
+}
+
+/*
+ * ======== messageq_transportshm_delete ========
+ * Purpose:
+ * Delete instance
+ */
+int messageq_transportshm_delete(void **mqtshm_handleptr)
+{
+ int status = 0;
+ int tmpstatus = 0;
+ struct messageq_transportshm_object *obj;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(mqtshm_handleptr == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(*mqtshm_handleptr == NULL)) {
+ /* @retval MESSAGEQTRANSPORTSHM_E_HANDLE Invalid NULL handle
+ specified */
+ status = MESSAGEQ_TRANSPORTSHM_E_HANDLE;
+ printk(KERN_WARNING "messageq_transportshm_delete: Invalid NULL"
+ " mqtshm_handle specified! status = 0x%x\n", status);
+ goto exit;
+ }
+
+ obj = (struct messageq_transportshm_object *) (*mqtshm_handleptr);
+ /* Clear handle in the local array */
+ messageq_transportshm_state.transports[obj->proc_id][obj->priority] = \
+ NULL;
+ obj->attrs[obj->my_index]->flag = 0;
+ status = listmp_sharedmemory_delete(
+ (listmp_sharedmemory_handle *)&obj->my_listmp_handle);
+ if (status < 0) {
+ printk(KERN_WARNING "messageq_transportshm_delete: Failed to "
+ "delete listmp_sharedmemory instance!\n");
+ }
+
+ tmpstatus = listmp_sharedmemory_close(
+ (listmp_sharedmemory_handle) obj->remote_listmp_handle);
+ if ((tmpstatus < 0) && (status >= 0)) {
+ status = tmpstatus;
+ printk(KERN_WARNING "messageq_transportshm_delete: Failed to "
+ "close listmp_sharedmemory instance!\n");
+ }
+
+ tmpstatus = messageq_unregister_transport(obj->proc_id,
+ obj->params.priority);
+ if ((tmpstatus < 0) && (status >= 0)) {
+ status = tmpstatus;
+ printk(KERN_WARNING "messageq_transportshm_delete: Failed to "
+ "unregister transport!\n");
+ }
+
+ tmpstatus = notify_unregister_event(obj->notify_driver, obj->proc_id,
+ obj->notify_event_no,
+ _messageq_transportshm_notify_fxn,
+ (void *)obj);
+ if ((tmpstatus < 0) && (status >= 0)) {
+ status = tmpstatus;
+ printk(KERN_WARNING "messageq_transportshm_delete: Failed to "
+ "unregister notify event!\n");
+ }
+
+ kfree(obj);
+ *mqtshm_handleptr = NULL;
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "messageq_transportshm_delete failed: "
+ "status = 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== messageq_transportshm_put ========
+ * Purpose:
+ * Put msg to remote list
+*/
+int messageq_transportshm_put(void *mqtshm_handle,
+ void *msg)
+{
+ int status = 0;
+ struct messageq_transportshm_object *obj = \
+ (struct messageq_transportshm_object *) mqtshm_handle;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(messageq_transportshm_state.ref_count),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(0),
+ MESSAGEQTRANSPORTSHM_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ BUG_ON(mqtshm_handle == NULL);
+ if (WARN_ON(msg == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+ if (WARN_ON(obj == NULL)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ status = listmp_put_tail(obj->remote_listmp_handle,
+ (struct listmp_elem *) msg);
+ if (status < 0) {
+ /* @retval MESSAGEQ_TRANSPORTSHM_E_FAIL
+ * Notification to remote processor failed!
+ */
+ status = MESSAGEQ_TRANSPORTSHM_E_FAIL;
+ printk(KERN_ERR "messageq_transportshm_put: Failed to put "
+ "message in the shared list! status = 0x%x\n", status);
+ goto exit;
+ }
+
+ status = notify_sendevent(obj->notify_driver, obj->proc_id,
+ obj->notify_event_no, 0, false);
+ if (status < 0)
+ goto notify_send_fail;
+ else
+ goto exit;
+
+notify_send_fail:
+ printk(KERN_ERR "messageq_transportshm_put: Notification to remote "
+ "processor failed, status = 0x%x\n", status);
+ /* If sending the event failed, then remove the element from the list.*/
+ /* Ignore the status of remove. */
+ listmp_remove(obj->remote_listmp_handle, (struct listmp_elem *) msg);
+
+exit:
+ if (status < 0)
+ printk(KERN_ERR "messageq_transportshm_put failed: "
+ "status = 0x%x\n", status);
+ return status;
+}
+
+/*
+ * ======== messageq_transportshm_control ========
+ * Purpose:
+ * Control Function
+*/
+int messageq_transportshm_control(void *mqtshm_handle, u32 cmd, u32 *cmdArg)
+{
+ BUG_ON(mqtshm_handle == NULL);
+
+ printk(KERN_ALERT "messageq_transportshm_control not supported!\n");
+ return MESSAGEQTRANSPORTSHM_E_NOTSUPPORTED;
+}
+
+/*
+ * ======== messageq_transportshm_get_status ========
+ * Purpose:
+ * Get status
+ */
+enum messageq_transportshm_status messageq_transportshm_get_status(
+ void *mqtshm_handle)
+{
+ struct messageq_transportshm_object *obj = \
+ (struct messageq_transportshm_object *) mqtshm_handle;
+
+ BUG_ON(obj == NULL);
+
+ return obj->status;
+}
+
+/*
+ * ======== messageq_transportshm_put ========
+ * Purpose:
+ * Get shared memory requirements.
+ */
+u32 messageq_transportshm_shared_mem_req(const
+ struct messageq_transportshm_params *params)
+{
+ u32 totalSize;
+ listmp_sharedmemory_params listmp_params;
+ u32 listmp_size;
+
+ /* There are two transport flags in shared memory */
+ totalSize = 2 * MESSAGEQ_TRANSPORTSHM_CACHESIZE;
+
+ listmp_sharedmemory_params_init(NULL, &listmp_params);
+ listmp_size = listmp_sharedmemory_shared_memreq(&listmp_params);
+
+ /* MyList */
+ totalSize += listmp_size;
+
+ /* RemoteList */
+ totalSize += listmp_size;
+
+ return totalSize;
+}
+
+
+/* =============================================================================
+ * internal functions
+ * =============================================================================
+ */
+/*
+ * ======== _messageq_transportshm_notify_fxn ========
+ * Purpose:
+ * Callback function registered with the Notify module.
+ */
+void _messageq_transportshm_notify_fxn(u16 proc_id, u32 event_no,
+ void *arg, u32 payload)
+{
+ struct messageq_transportshm_object *obj = NULL;
+ messageq_msg msg = NULL;
+ u32 queue_id;
+
+ if (WARN_ON(arg == NULL))
+ goto exit;
+
+ obj = (struct messageq_transportshm_object *)arg;
+ /* While there is are messages, get them out and send them to
+ * their final destination. */
+ while ((msg = (messageq_msg) listmp_get_head(obj->my_listmp_handle))
+ != NULL) {
+ /* Get the destination message queue Id */
+ queue_id = messageq_get_dst_queue(msg);
+ messageq_put(queue_id, msg);
+ }
+ return;
+
+exit:
+ printk(KERN_ERR "messageq_transportshm_notify_fxn: argument passed is "
+ "NULL!\n");
+}
+
+
+/*
+ * ======== messageq_transportshm_delete ========
+ * Purpose:
+ * This will set the asynchronous error function for the transport module
+ */
+void messageq_transportshm_set_err_fxn(
+ void (*err_fxn)(
+ enum MessageQTransportShm_Reason reason,
+ void *handle,
+ void *msg,
+ u32 info))
+{
+ u32 key;
+
+ key = mutex_lock_interruptible(messageq_transportshm_state.gate_handle);
+ if (key < 0)
+ goto exit;
+
+ messageq_transportshm_state.cfg.err_fxn = err_fxn;
+ mutex_unlock(messageq_transportshm_state.gate_handle);
+
+exit:
+ return;
+}
+
+
diff --git a/drivers/dsp/syslink/multicore_ipc/messageq_transportshm_ioctl.c b/drivers/dsp/syslink/multicore_ipc/messageq_transportshm_ioctl.c
new file mode 100644
index 000000000000..700b8c76516f
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/messageq_transportshm_ioctl.c
@@ -0,0 +1,330 @@
+/*
+ * messageq_transportshm_ioctl.c
+ *
+ * This file implements all the ioctl operations required on the
+ * messageq_transportshm module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Linux headers */
+#include <linux/uaccess.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+
+/* Module Headers */
+#include <messageq.h>
+#include <messageq_transportshm.h>
+#include <messageq_transportshm_ioctl.h>
+#include <sharedregion.h>
+
+/*
+ * ======== messageq_transportshm_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_get_config function
+ */
+static inline int messageq_transportshm_ioctl_get_config(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_transportshm_config config;
+
+ messageq_transportshm_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct messageq_transportshm_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_setup function
+ */
+static inline int messageq_transportshm_ioctl_setup(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_transportshm_config config;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct messageq_transportshm_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = messageq_transportshm_setup(&config);
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_destroy function
+ */
+static inline int messageq_transportshm_ioctl_destroy(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ cargs->api_status = messageq_transportshm_destroy();
+ return 0;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_params_init function
+ */
+static inline int messageq_transportshm_ioctl_params_init(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ s32 retval = 0;
+ int status = 0;
+ unsigned long size;
+ struct messageq_transportshm_params params;
+
+ messageq_transportshm_params_init(
+ cargs->args.params_init.messageq_transportshm_handle, &params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct messageq_transportshm_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = status;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_create ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_create function
+ */
+static inline int messageq_transportshm_ioctl_create(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_transportshm_params params;
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct messageq_transportshm_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ params.shared_addr = sharedregion_get_ptr(
+ (u32 *)cargs->args.create.shared_addr_srptr);
+ if (unlikely(params.shared_addr == NULL))
+ goto exit;
+
+ params.gate = cargs->args.create.knl_lock_handle;
+ params.notify_driver = cargs->args.create.knl_notify_driver;
+ cargs->args.create.messageq_transportshm_handle = \
+ messageq_transportshm_create(cargs->args.create.proc_id,
+ &params);
+
+ /*
+ * Here we are not validating the return from the module.
+ * Even it is NULL, we pass it to user and user has to pass
+ * proper return to application
+ */
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_ioctl_delete function
+ */
+static inline int messageq_transportshm_ioctl_delete(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ cargs->api_status = messageq_transportshm_delete(
+ &(cargs->args.delete_transport.messageq_transportshm_handle));
+ return 0;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_put ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_put function
+ */
+static inline int messageq_transportshm_ioctl_put(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ int status = 0;
+ messageq_msg msg;
+
+ msg = (messageq_msg) sharedregion_get_ptr(cargs->args.put.msg_srptr);
+ if (unlikely(msg == NULL))
+ goto exit;
+
+ status = messageq_transportshm_put(
+ cargs->args.put.messageq_transportshm_handle, msg);
+
+ cargs->api_status = status;
+exit:
+ return 0;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_leave ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_leave function
+ */
+static inline int messageq_transportshm_ioctl_get_status(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ cargs->args.get_status.status = \
+ messageq_transportshm_get_status(
+ cargs->args.get_status.messageq_transportshm_handle);
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl_shared_memreq ========
+ * Purpose:
+ * This ioctl interface to messageq_transportshm_shared_memreq function
+ */
+static inline int messageq_transportshm_ioctl_shared_memreq(
+ struct messageq_transportshm_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct messageq_transportshm_params params;
+
+ size = copy_from_user(&params, cargs->args.shared_memreq.params,
+ sizeof(struct messageq_transportshm_params));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->args.shared_memreq.bytes =
+ messageq_transportshm_shared_mem_req(&params);
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== messageq_transportshm_ioctl ========
+ * Purpose:
+ * ioctl interface function for messageq_transportshm
+ */
+int messageq_transportshm_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int os_status = 0;
+ struct messageq_transportshm_cmd_args __user *uarg =
+ (struct messageq_transportshm_cmd_args __user *)args;
+ s32 retval = 0;
+ struct messageq_transportshm_cmd_args cargs;
+ unsigned long size;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+ if (os_status) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct messageq_transportshm_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_MESSAGEQ_TRANSPORTSHM_GETCONFIG:
+ os_status = messageq_transportshm_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_SETUP:
+ os_status = messageq_transportshm_ioctl_setup(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_DESTROY:
+ os_status = messageq_transportshm_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_PARAMS_INIT:
+ retval = messageq_transportshm_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_CREATE:
+ os_status = messageq_transportshm_ioctl_create(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_DELETE:
+ os_status = messageq_transportshm_ioctl_delete(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_PUT:
+ os_status = messageq_transportshm_ioctl_put(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_GETSTATUS:
+ os_status = messageq_transportshm_ioctl_get_status(&cargs);
+ break;
+
+ case CMD_MESSAGEQ_TRANSPORTSHM_SHAREDMEMREQ:
+ os_status = messageq_transportshm_ioctl_shared_memreq(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ os_status = -ENOTTY;
+ break;
+ }
+ if (os_status < 0)
+ goto exit;
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs,
+ sizeof(struct messageq_transportshm_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+ return os_status;
+
+exit:
+ printk(KERN_ERR "messageq_transportshm_ioctl failed: status = 0x%x\n",
+ os_status);
+ return os_status;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/multiproc.c b/drivers/dsp/syslink/multicore_ipc/multiproc.c
new file mode 100755
index 000000000000..17a3bce19113
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/multiproc.c
@@ -0,0 +1,242 @@
+/*
+* multiproc.c
+*
+* Many multi-processor modules have the concept of processor id. MultiProc
+* centeralizes the processor id management.
+*
+* Copyright (C) 2008-2009 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.
+*/
+
+/*
+ * ======== multiproc.c ========
+ * Notes:
+ * The processor id start at 0 and ascend without skipping values till maximum_
+ * no_of_processors - 1
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <syslink/atomic_linux.h>
+/* Utilities headers */
+#include <linux/string.h>
+
+/* Module level headers */
+#include <multiproc.h>
+
+/* Macro to make a correct module magic number with ref_count */
+#define MULTIPROC_MAKE_MAGICSTAMP(x) ((MULTIPROC_MODULEID << 12u) | (x))
+
+/*
+ * multiproc module state object
+ */
+struct multiproc_module_object {
+ struct multiproc_config cfg; /* Module configuration structure */
+ struct multiproc_config def_cfg; /* Default module configuration */
+ atomic_t ref_count; /* Reference count */
+};
+
+static struct multiproc_module_object multiproc_state = {
+ .def_cfg.max_processors = 4,
+ .def_cfg.name_list[0][0] = "MPU",
+ .def_cfg.name_list[1][0] = "Tesla",
+ .def_cfg.name_list[2][0] = "SysM3",
+ .def_cfg.name_list[3][0] = "AppM3",
+ .def_cfg.id = 0
+};
+
+/*
+ * ======== multiproc_get_config ========
+ * Purpose:
+ * This will get the default configuration for the multiproc module
+ */
+void multiproc_get_config(struct multiproc_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+ if (atomic_cmpmask_and_lt(
+ &(multiproc_state.ref_count),
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(1)) == true) {
+ /* (If setup has not yet been called) */
+ memcpy(cfg, &multiproc_state.def_cfg,
+ sizeof(struct multiproc_config));
+ } else {
+ memcpy(cfg, &multiproc_state.cfg,
+ sizeof(struct multiproc_config));
+ }
+}
+EXPORT_SYMBOL(multiproc_get_config);
+
+/*
+ * ======== multiproc_setup ========
+ * Purpose:
+ * This function sets up the multiproc module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked
+ */
+s32 multiproc_setup(struct multiproc_config *cfg)
+{
+ s32 status = 0;
+ struct multiproc_config tmp_cfg;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable.
+ */
+ atomic_cmpmask_and_set(&multiproc_state.ref_count,
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&multiproc_state.ref_count)
+ != MULTIPROC_MAKE_MAGICSTAMP(1u)) {
+ status = 1;
+ } else {
+ if (cfg == NULL) {
+ multiproc_get_config(&tmp_cfg);
+ cfg = &tmp_cfg;
+ }
+
+ memcpy(&multiproc_state.cfg, cfg,
+ sizeof(struct multiproc_config));
+ }
+
+ return status;
+}
+EXPORT_SYMBOL(multiproc_setup);
+
+/*
+ * ======== multiproc_setup ========
+ * Purpose:
+ * This function destroy the multiproc module.
+ * Once this function is called, other multiproc module APIs,
+ * except for the multiproc_get_config API cannot be called
+ * anymore.
+ */
+s32 multiproc_destroy(void)
+{
+ int status = 0;
+
+ if (atomic_cmpmask_and_lt(
+ &(multiproc_state.ref_count),
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(1)) == true) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ atomic_dec_return(&multiproc_state.ref_count);
+
+exit:
+ return status;
+}
+EXPORT_SYMBOL(multiproc_destroy);
+
+/*
+ * ======== multiProc_set_local_id ========
+ * Purpose:
+ * This will set the processor id of local processor on run time
+ */
+int multiproc_set_local_id(u16 proc_id)
+{
+ int status = 0;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(multiproc_state.ref_count),
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(1)) == true)) {
+ status = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ status = -EINVAL;
+ goto exit;
+ }
+
+ multiproc_state.cfg.id = proc_id;
+
+exit:
+ return status;
+}
+EXPORT_SYMBOL(multiproc_set_local_id);
+
+/*
+ * ======== multiProc_get_local_id ========
+ * Purpose:
+ * This will get the processor id from proccessor name
+ */
+u16 multiproc_get_id(const char *proc_name)
+{
+ s32 i;
+ u16 proc_id = MULTIPROC_INVALIDID;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(multiproc_state.ref_count),
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ /* If the name is NULL, just return the local id */
+ if (proc_name == NULL)
+ proc_id = multiproc_state.cfg.id;
+ else {
+ for (i = 0; i < multiproc_state.cfg.max_processors ; i++) {
+ if (strcmp(proc_name,
+ &multiproc_state.cfg.name_list[i][0]) == 0) {
+ proc_id = i;
+ break;
+ }
+ }
+ }
+
+exit:
+ return proc_id;
+}
+EXPORT_SYMBOL(multiproc_get_id);
+
+/*
+ * ======== multiProc_set_local_id ========
+ * Purpose:
+ * This will get the processor name from proccessor id
+ */
+char *multiproc_get_name(u16 proc_id)
+{
+ char *proc_name = NULL;
+
+ /* On error condition return NULL pointer, else entry from name list */
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(multiproc_state.ref_count),
+ MULTIPROC_MAKE_MAGICSTAMP(0),
+ MULTIPROC_MAKE_MAGICSTAMP(1)) == true))
+ goto exit;
+
+ if (WARN_ON(proc_id >= MULTIPROC_MAXPROCESSORS))
+ goto exit;
+
+ proc_name = multiproc_state.cfg.name_list[proc_id];
+
+exit:
+ return proc_name;
+}
+EXPORT_SYMBOL(multiproc_get_name);
+
+/*
+ * ======== multiProc_set_local_id ========
+ * Purpose:
+ * This will get the maximum proccessor id in the system
+ */
+u16 multiproc_get_max_processors(void)
+{
+ return multiproc_state.cfg.max_processors;
+
+}
+EXPORT_SYMBOL(multiproc_get_max_processors);
+
diff --git a/drivers/dsp/syslink/multicore_ipc/multiproc_ioctl.c b/drivers/dsp/syslink/multicore_ipc/multiproc_ioctl.c
new file mode 100755
index 000000000000..e457b5f5a3d8
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/multiproc_ioctl.c
@@ -0,0 +1,164 @@
+/*
+* multiproc_ioctl.c
+*
+* This provides the ioctl interface for multiproc module
+*
+* Copyright (C) 2008-2009 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.
+*/
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <multiproc.h>
+#include <multiproc_ioctl.h>
+
+/*
+ * ======== mproc_ioctl_setup ========
+ * Purpose:
+ * This wrapper function will call the multproc function
+ * to setup the module
+ */
+static int mproc_ioctl_setup(struct multiproc_cmd_args *cargs)
+{
+ struct multiproc_config config;
+ s32 status = 0;
+ ulong size;
+
+ size = copy_from_user(&config,
+ cargs->args.setup.config,
+ sizeof(struct multiproc_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = multiproc_setup(&config);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== mproc_ioctl_destroy ========
+ * Purpose:
+ * This wrapper function will call the multproc function
+ * to destroy the module
+ */
+static int mproc_ioctl_destroy(struct multiproc_cmd_args *cargs)
+{
+ cargs->api_status = multiproc_destroy();
+ return 0;
+}
+
+/*
+ * ======== mproc_ioctl_get_config ========
+ * Purpose:
+ * This wrapper function will call the multproc function
+ * to get the default configuration the module
+ */
+static int mproc_ioctl_get_config(struct multiproc_cmd_args *cargs)
+{
+ struct multiproc_config config;
+ u32 size;
+
+ multiproc_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct multiproc_config));
+ if (size) {
+ cargs->api_status = -EFAULT;
+ return 0;
+ }
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== mproc_ioctl_setup ========
+ * Purpose:
+ * This wrapper function will call the multproc function
+ * to setup the module
+ */
+static int multiproc_ioctl_set_local_id(struct multiproc_cmd_args *cargs)
+{
+ cargs->api_status = multiproc_set_local_id(cargs->args.set_local_id.id);
+ return 0;
+}
+
+/*
+ * ======== multiproc_ioctl ========
+ * Purpose:
+ * This ioctl interface for multiproc module
+ */
+int multiproc_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct multiproc_cmd_args __user *uarg =
+ (struct multiproc_cmd_args __user *)args;
+ struct multiproc_cmd_args cargs;
+
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct multiproc_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_MULTIPROC_SETUP:
+ status = mproc_ioctl_setup(&cargs);
+ break;
+
+ case CMD_MULTIPROC_DESTROY:
+ status = mproc_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_MULTIPROC_GETCONFIG:
+ status = mproc_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_MULTIPROC_SETLOCALID:
+ status = multiproc_ioctl_set_local_id(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct multiproc_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/nameserver.c b/drivers/dsp/syslink/multicore_ipc/nameserver.c
new file mode 100644
index 000000000000..dbcf37111208
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/nameserver.c
@@ -0,0 +1,1003 @@
+/*
+ * nameserver.c
+ *
+ * The nameserver module manages local name/value pairs that
+ * enables an application and other modules to store and retrieve
+ * values based on a name.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <syslink/atomic_linux.h>
+
+#include <nameserver.h>
+#include <multiproc.h>
+#include <nameserver_remote.h>
+
+#define NS_MAX_NAME_LEN 32
+#define NS_MAX_RUNTIME_ENTRY (~0)
+#define NS_MAX_VALUE_LEN 4
+
+/*
+ * The dynamic name/value table looks like the following. This approach allows
+ * each instance table to have different value and different name lengths.
+ * The names block is allocated on the create. The size of that block is
+ * (max_runtime_entries * max_name_en). That block is sliced and diced up and
+ * given to each table entry.
+ * The same thing is done for the values block.
+ *
+ * names table values
+ * ------------- ------------- -------------
+ * | |<-\ | elem | /----->| |
+ * | | \-------| name | / | |
+ * | | | value |-/ | |
+ * | | | len | | |
+ * | |<-\ |-----------| | |
+ * | | \ | elem | | |
+ * | | \------| name | /------>| |
+ * | | | value |-/ | |
+ * ------------- | len | | |
+ * ------------- | |
+ * | |
+ * | |
+ * -------------
+ *
+ * There is an optimization for small values (e.g. <= sizeof(UInt32).
+ * In this case, there is no values block allocated. Instead the value
+ * field is used directly. This optimization occurs and is managed when
+ * obj->max_value_len <= sizeof(Us3232).
+ *
+ * The static create is a little different. The static entries point directly
+ * to a name string (and value). Since it points directly to static items,
+ * this entries cannot be removed.
+ * If max_runtime_entries is non-zero, a names and values block is created.
+ * Here is an example of a table with 1 static entry and 2 dynamic entries
+ *
+ * ------------
+ * this entries cannot be removed.
+ * If max_runtime_entries is non-zero, a names and values block is created.
+ * Here is an example of a table with 1 static entry and 2 dynamic entries
+ *
+ * ------------
+ * | elem |
+ * "myName" <-----------| name |----------> someValue
+ * | value |
+ * names | len | values
+ * ------------- ------------- -------------
+ * | |<-\ | elem | /----->| |
+ * | | \-------| name | / | |
+ * | | | value |-/ | |
+ * | | | len | | |
+ * | |<-\ |-----------| | |
+ * | | \ | elem | | |
+ * | | \------| name | /------>| |
+ * | | | value |-/ | |
+ * ------------- | len | | |
+ * ------------- | |
+ * | |
+ * | |
+ * -------------
+ *
+ * NameServerD uses a freeList and namelist to maintain the empty
+ * and filled-in entries. So when a name/value pair is added, an entry
+ * is pulled off the freeList, filled-in and placed on the namelist.
+ * The reverse happens on a remove.
+ *
+ * For static adds, the entries are placed on the namelist statically.
+ *
+ * For dynamic creates, the freeList is populated in postInt and there are no
+ * entries placed on the namelist (this happens when the add is called).
+ *
+ */
+
+/* Macro to make a correct module magic number with refCount */
+#define NAMESERVER_MAKE_MAGICSTAMP(x) ((NAMESERVER_MODULEID << 12u) | (x))
+
+/*
+ * A name/value table entry
+ */
+struct nameserver_entry {
+ struct list_head elem; /* List element */
+ u32 hash; /* Hash value */
+ char *name; /* Name portion of name/value pair */
+ u32 len; /* Length of the value field. */
+ void *buf; /* Value portion of name/value entry */
+ bool collide; /* Does the hash collides? */
+ struct nameserver_entry *next; /* Pointer to the next entry,
+ used incase of collision only */
+};
+
+/*
+ * A nameserver instance object
+ */
+struct nameserver_object {
+ struct list_head elem;
+ char *name; /* Name of the instance */
+ u32 count; /* Counter for entries */
+ struct mutex *gate_handle; /* Gate for critical regions */
+ struct list_head name_list; /* Filled entries list */
+ struct nameserver_params params; /* The parameter structure */
+};
+
+
+/* nameserver module state object */
+struct nameserver_module_object {
+ struct list_head obj_list;
+ struct mutex *list_lock;
+ struct nameserver_remote_object **remote_handle_list;
+ atomic_t ref_count;
+};
+
+/*
+ * Variable for holding state of the nameserver module.
+ */
+struct nameserver_module_object nameserver_state = {
+ .obj_list = LIST_HEAD_INIT(nameserver_state.obj_list),
+ .list_lock = NULL,
+ .remote_handle_list = NULL,
+};
+
+/*
+ * Lookup table for CRC calculation.
+ */
+static const u32 string_crc_table[256u] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+/*
+ * ======== nameserver_setup ========
+ * Purpose:
+ * This will calculate hash for a string
+ */
+static u32 nameserver_string_hash(const char *string)
+{
+ u32 i;
+ u32 hash ;
+ u32 len = strlen(string);
+
+ for (i = 0, hash = len; i < len; i++)
+ hash = (hash >> 8) ^
+ string_crc_table[(hash & 0xff)] ^ string[i];
+
+ return hash;
+}
+
+/*
+ * ======== nameserver_setup ========
+ * Purpose:
+ * This will setup the nameserver module
+ */
+int nameserver_setup(void)
+{
+ struct nameserver_remote_object **list = NULL;
+ s32 retval = 0;
+ u16 nr_procs = 0;
+
+ /* This sets the ref_count variable if not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable
+ */
+ atomic_cmpmask_and_set(&nameserver_state.ref_count,
+ NAMESERVER_MAKE_MAGICSTAMP(0),
+ NAMESERVER_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&nameserver_state.ref_count)
+ != NAMESERVER_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ nr_procs = multiproc_get_max_processors();
+ list = kmalloc(nr_procs * sizeof(struct nameserver_remote_object *),
+ GFP_KERNEL);
+ if (list == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ memset(list , 0, nr_procs * sizeof(struct nameserver_remote_object *));
+ nameserver_state.remote_handle_list = list;
+ nameserver_state.list_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (nameserver_state.list_lock == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ /* mutex is initialized with state = UNLOCKED */
+ mutex_init(nameserver_state.list_lock);
+ return 0;
+
+error:
+ kfree(list);
+ printk(KERN_ERR "nameserver_setup failed, retval: %x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_setup);
+
+/*
+ * ======== nameserver_destroy ========
+ * Purpose:
+ * This will destroy the nameserver module
+ */
+int nameserver_destroy(void)
+{
+ s32 retval = 0;
+ struct mutex *lock = NULL;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(nameserver_state.ref_count),
+ NAMESERVER_MAKE_MAGICSTAMP(0),
+ NAMESERVER_MAKE_MAGICSTAMP(1)) == true)) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!(atomic_dec_return(&nameserver_state.ref_count)
+ == NAMESERVER_MAKE_MAGICSTAMP(0))) {
+ retval = 1;
+ goto exit;
+ }
+
+ if (WARN_ON(nameserver_state.list_lock == NULL)) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* If a nameserver instance exist, do not proceed */
+ if (!list_empty(&nameserver_state.obj_list)) {
+ retval = -EBUSY;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(nameserver_state.list_lock);
+ if (retval)
+ goto exit;
+
+ lock = nameserver_state.list_lock;
+ nameserver_state.list_lock = NULL;
+ mutex_unlock(lock);
+ kfree(lock);
+ kfree(nameserver_state.remote_handle_list);
+ nameserver_state.remote_handle_list = NULL;
+ return 0;
+
+exit:
+ if (retval < 0) {
+ printk(KERN_ERR "nameserver_destroy failed, retval: %x\n",
+ retval);
+ }
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_destroy);
+
+/*!
+ * Purpose:
+ * Initialize this config-params structure with supplier-specified
+ * defaults before instance creation.
+ */
+int nameserver_params_init(struct nameserver_params *params)
+{
+ BUG_ON(params == NULL);
+ params->check_existing = true;
+ params->gate_handle = NULL;
+ params->max_name_len = NS_MAX_NAME_LEN;
+ params->max_runtime_entries = NS_MAX_RUNTIME_ENTRY;
+ params->max_value_len = NS_MAX_VALUE_LEN;
+ params->table_heap = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(nameserver_params_init);
+
+/*
+ * ======== nameserver_get_params ========
+ * Purpose:
+ * This will initialize config-params structure with
+ * supplier-specified defaults before instance creation
+ */
+int nameserver_get_params(void *handle,
+ struct nameserver_params *params)
+{
+ struct nameserver_object *nshandle = NULL;
+
+ BUG_ON(params == NULL);
+ if (handle == NULL) {
+ params->check_existing = true;
+ params->max_name_len = NS_MAX_NAME_LEN;
+ params->max_runtime_entries = NS_MAX_RUNTIME_ENTRY;
+ params->max_value_len = NS_MAX_VALUE_LEN;
+ params->gate_handle = NULL;
+ params->table_heap = NULL;
+ } else {
+ nshandle = (struct nameserver_object *)handle;
+ params->check_existing = nshandle->params.check_existing;
+ params->max_name_len = nshandle->params.max_name_len;
+ params->max_runtime_entries =
+ nshandle->params.max_runtime_entries;
+ params->max_value_len = nshandle->params.max_value_len;
+ params->gate_handle = nshandle->params.gate_handle;
+ params->table_heap = nshandle->params.table_heap;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(nameserver_get_params);
+
+/*
+ * ======== nameserver_get_params ========
+ * Purpose:
+ * This will get the handle of a nameserver instance
+ * from name
+ */
+void *nameserver_get_handle(const char *name)
+{
+ struct nameserver_object *obj = NULL;
+
+ BUG_ON(name == NULL);
+ list_for_each_entry(obj, &nameserver_state.obj_list, elem) {
+ if (strcmp(obj->name, name) == 0)
+ goto succes;
+ }
+ return NULL;
+
+succes:
+ return (void *)obj;
+}
+EXPORT_SYMBOL(nameserver_get_handle);
+
+/*
+ * ======== nameserver_create ========
+ * Purpose:
+ * This will create a name server instance
+ */
+void *nameserver_create(const char *name,
+ const struct nameserver_params *params)
+{
+ struct nameserver_object *new_obj = NULL;
+ u32 name_len;
+ s32 retval = 0;
+
+ BUG_ON(name == NULL);
+ BUG_ON(params == NULL);
+
+ name_len = strlen(name) + 1;
+ if (name_len > params->max_name_len) {
+ retval = E2BIG;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(nameserver_state.list_lock);
+ if (retval)
+ goto exit;
+
+ /* check if the name is already registered or not */
+ new_obj = nameserver_get_handle(name);
+ if (new_obj != NULL) {
+ retval = EEXIST;
+ goto error;
+ }
+
+ new_obj = kmalloc(sizeof(struct nameserver_object), GFP_KERNEL);
+ if (new_obj == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ new_obj->name = kmalloc(name_len, GFP_ATOMIC);
+ if (new_obj->name == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ strncpy(new_obj->name, name, name_len);
+ memcpy(&new_obj->params, params,
+ sizeof(struct nameserver_params));
+ if (params->max_value_len < sizeof(u32))
+ new_obj->params.max_value_len = sizeof(u32);
+ else
+ new_obj->params.max_value_len = params->max_value_len;
+
+ new_obj->gate_handle =
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (new_obj->gate_handle == NULL) {
+ retval = -ENOMEM;
+ goto error_mutex;
+ }
+
+ mutex_init(new_obj->gate_handle);
+ new_obj->count = 0;
+ /* Put in the nameserver instance to local list */
+ INIT_LIST_HEAD(&new_obj->name_list);
+ list_add_tail(&new_obj->elem, &nameserver_state.obj_list);
+ mutex_unlock(nameserver_state.list_lock);
+ return (void *)new_obj;
+
+error_mutex:
+ kfree(new_obj->name);
+
+error:
+ mutex_unlock(nameserver_state.list_lock);
+ kfree(new_obj);
+
+exit:
+ printk(KERN_ERR "nameserver_create failed retval:%x \n", retval);
+ return NULL;
+}
+EXPORT_SYMBOL(nameserver_create);
+
+
+/*
+ * ======== nameserver_delete ========
+ * Purpose:
+ * This will delete a name server instance
+ */
+int nameserver_delete(void **handle)
+{
+ struct nameserver_object *temp_obj = NULL;
+ struct mutex *gate_handle = NULL;
+ bool localgate = false;
+ s32 retval = 0;
+
+ BUG_ON(handle == NULL);
+ temp_obj = (struct nameserver_object *) (*handle);
+ retval = mutex_lock_interruptible(temp_obj->gate_handle);
+ if (retval)
+ goto exit;
+
+ /* Do not proceed if an entry in the in the table */
+ if (temp_obj->count != 0) {
+ retval = -EBUSY;
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(nameserver_state.list_lock);
+ if (retval)
+ goto error;
+
+ list_del(&temp_obj->elem);
+ mutex_unlock(nameserver_state.list_lock);
+ gate_handle = temp_obj->gate_handle;
+ /* free the memory allocated for instance name */
+ kfree(temp_obj->name);
+ /* Delete the lock handle if created internally */
+ if (temp_obj->params.gate_handle == NULL)
+ localgate = true;
+
+ /* Free the memory used for handle */
+ kfree(temp_obj);
+ *handle = NULL;
+ mutex_unlock(gate_handle);
+ if (localgate == true)
+ kfree(gate_handle);
+ return 0;
+
+error:
+ mutex_unlock(temp_obj->gate_handle);
+exit:
+ printk(KERN_ERR "nameserver_delete failed retval:%x \n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_delete);
+
+/*
+ * ======== nameserver_is_entry_found ========
+ * Purpose:
+ * This will return true if the entry fond in the table
+ */
+static bool nameserver_is_entry_found(const char *name, u32 hash,
+ struct list_head *list,
+ struct nameserver_entry **entry)
+{
+ struct nameserver_entry *node = NULL;
+ bool hash_match = false;
+ bool name_match = false;
+
+
+ list_for_each_entry(node, list, elem) {
+ /* Hash not matchs, take next node */
+ if (node->hash == hash)
+ hash_match = true;
+ else
+ continue;
+ /* If the name matchs, incase hash is duplicate */
+ if (strcmp(node->name, name) == 0)
+ name_match = true;
+
+ if (hash_match && name_match) {
+ if (entry != NULL)
+ *entry = node;
+ return true;
+ }
+
+ hash_match = false;
+ name_match = false;
+ }
+ return false;
+}
+
+/*
+ * ======== nameserver_add ========
+ * Purpose:
+ * This will add an entry into a nameserver instance
+ */
+void *nameserver_add(void *handle, const char *name,
+ void *buffer, u32 length)
+{
+ struct nameserver_entry *new_node = NULL;
+ struct nameserver_object *temp_obj = NULL;
+ bool found = false;
+ u32 hash;
+ u32 name_len;
+ s32 retval = 0;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+ BUG_ON(buffer == NULL);
+ if (WARN_ON(length == 0)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ temp_obj = (struct nameserver_object *)handle;
+ retval = mutex_lock_interruptible(temp_obj->gate_handle);
+ if (retval)
+ goto exit;
+
+ if (temp_obj->count >= temp_obj->params.max_runtime_entries) {
+ retval = -ENOSPC;
+ goto error;
+ }
+
+ /* make the null char in to account */
+ name_len = strlen(name) + 1;
+ if (name_len > temp_obj->params.max_name_len) {
+ retval = -E2BIG;
+ goto error;
+ }
+
+ /* TODO : hash and collide ?? */
+ hash = nameserver_string_hash(name);
+ found = nameserver_is_entry_found(name, hash,
+ &temp_obj->name_list, &new_node);
+ if (found == true) {
+ retval = -EEXIST;
+ goto error;
+ }
+
+ new_node = kmalloc(sizeof(struct nameserver_entry), GFP_KERNEL);
+ if (new_node == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ new_node->hash = hash;
+ new_node->collide = true;
+ new_node->len = length;
+ new_node->next = NULL;
+ new_node->name = kmalloc(name_len, GFP_KERNEL);
+ if (new_node->name == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ new_node->buf = kmalloc(length, GFP_KERNEL);
+ if (new_node->buf == NULL) {
+ retval = -ENOMEM;
+ goto error1;
+ }
+
+ strncpy(new_node->name, name, name_len);
+ memcpy(new_node->buf, buffer, length);
+ list_add_tail(&new_node->elem, &temp_obj->name_list);
+ temp_obj->count++;
+ mutex_unlock(temp_obj->gate_handle);
+ return new_node;
+
+error1:
+ kfree(new_node->name);
+
+error:
+ mutex_unlock(temp_obj->gate_handle);
+ kfree(new_node);
+exit:
+ printk(KERN_ERR "nameserver_add failed status: %x \n", retval);
+ return NULL;
+
+}
+EXPORT_SYMBOL(nameserver_add);
+
+/*
+ * ======== nameserver_add_uint32 ========
+ * Purpose:
+ * This will a Uint32 value into a nameserver instance
+ */
+void *nameserver_add_uint32(void *handle, const char *name,
+ u32 value)
+{
+ struct nameserver_entry *new_node = NULL;
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+
+ new_node = nameserver_add(handle, name, &value, sizeof(u32));
+ return new_node;
+}
+EXPORT_SYMBOL(nameserver_add_uint32);
+
+/*
+ * ======== nameserver_remove ========
+ * Purpose:
+ * This will remove a name/value pair from a name server
+ */
+int nameserver_remove(void *handle, const char *name)
+{
+ struct nameserver_object *temp_obj = NULL;
+ struct nameserver_entry *entry = NULL;
+ bool found = false;
+ u32 hash;
+ u32 name_len;
+ s32 retval = 0;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+
+ temp_obj = (struct nameserver_object *)handle;
+ name_len = strlen(name) + 1;
+ if (name_len > temp_obj->params.max_name_len) {
+ retval = -E2BIG;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(temp_obj->gate_handle);
+ if (retval)
+ goto exit;
+
+ /* TODO :check collide & hash usage */
+ hash = nameserver_string_hash(name);
+ found = nameserver_is_entry_found(name, hash,
+ &temp_obj->name_list, &entry);
+ if (found == false) {
+ retval = -ENOENT;
+ goto error;
+ }
+
+ kfree(entry->buf);
+ kfree(entry->name);
+ list_del(&entry->elem);
+ kfree(entry);
+ temp_obj->count--;
+ mutex_unlock(temp_obj->gate_handle);
+ return 0;
+
+error:
+ mutex_unlock(temp_obj->gate_handle);
+
+exit:
+ printk(KERN_ERR "nameserver_remove failed status:%x \n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_remove);
+
+/*
+ * ======== nameserver_remove_entry ========
+ * Purpose:
+ * This will remove a name/value pair from a name server
+ */
+int nameserver_remove_entry(void *nshandle, void *nsentry)
+{
+ struct nameserver_entry *node = NULL;
+ struct nameserver_object *handle = NULL;
+ s32 retval = 0;
+
+ BUG_ON(nshandle == NULL);
+ BUG_ON(nsentry == NULL);
+
+ handle = (struct nameserver_object *)nshandle;
+ node = (struct nameserver_entry *)nsentry;
+ retval = mutex_lock_interruptible(handle->gate_handle);
+ if (retval)
+ goto exit;
+
+ kfree(node->buf);
+ kfree(node->name);
+ list_del(&node->elem);
+ kfree(node);
+ handle->count--;
+ mutex_unlock(handle->gate_handle);
+ return 0;
+
+exit:
+ printk(KERN_ERR "nameserver_remove_entry failed status:%x \n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_remove_entry);
+
+
+/*
+ * ======== nameserver_get_local ========
+ * Purpose:
+ * This will retrieve the value portion of a name/value
+ * pair from local table
+ */
+int nameserver_get_local(void *handle, const char *name,
+ void *buffer, u32 length)
+{
+ struct nameserver_object *temp_obj = NULL;
+ struct nameserver_entry *entry = NULL;
+ bool found = false;
+ u32 hash;
+ s32 retval = 0;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+ BUG_ON(buffer == NULL);
+ if (WARN_ON(length == 0)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ temp_obj = (struct nameserver_object *)handle;
+ retval = mutex_lock_interruptible(temp_obj->gate_handle);
+ if (retval)
+ goto exit;
+
+ /* TODO :check collide & hash usage */
+ hash = nameserver_string_hash(name);
+ found = nameserver_is_entry_found(name, hash,
+ &temp_obj->name_list, &entry);
+ if (found == false) {
+ retval = -ENOENT;
+ goto error;
+ }
+
+ if (entry->len >= length) {
+ memcpy(buffer, entry->buf, length);
+ retval = length;
+ } else {
+ memcpy(buffer, entry->buf, entry->len);
+ retval = entry->len;
+ }
+
+ mutex_unlock(temp_obj->gate_handle);
+ return retval;
+
+error:
+ mutex_unlock(temp_obj->gate_handle);
+
+exit:
+ printk(KERN_ERR "nameserver_get_local entry not found!\n");
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_get_local);
+
+/*
+ * ======== nameserver_get ========
+ * Purpose:
+ * This will etrieve the value portion of a name/value
+ * pair from local table
+ */
+int nameserver_get(void *handle, const char *name,
+ void *buffer, u32 length, u16 proc_id[])
+{
+ struct nameserver_object *temp_obj = NULL;
+ u16 max_proc_id;
+ u16 local_proc_id;
+ s32 retval = -ENOENT;
+ u32 i;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+ BUG_ON(buffer == NULL);
+ if (WARN_ON(length == 0)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ temp_obj = (struct nameserver_object *)handle;
+ max_proc_id = multiproc_get_max_processors();
+ local_proc_id = multiproc_get_id(NULL);
+ if (proc_id == NULL) {
+ retval = nameserver_get_local(temp_obj, name,
+ buffer, length);
+ if (retval > 0) /* Got the value */
+ goto exit;
+
+ for (i = 0; i < max_proc_id; i++) {
+ /* Skip current processor */
+ if (i == local_proc_id)
+ continue;
+
+ if (nameserver_state.remote_handle_list[i] == NULL)
+ continue;
+
+ retval = nameserver_remote_get(
+ nameserver_state.remote_handle_list[i],
+ temp_obj->name, name, buffer, length);
+ if (retval > 0 || ((retval < 0) &&
+ (retval != -ENOENT))) /* Got the value */
+ break;
+ }
+ goto exit;
+ }
+
+ for (i = 0; i < max_proc_id; i++) {
+ /* Skip processor with invalid id */
+ if (proc_id[i] == MULTIPROC_INVALIDID)
+ continue;
+
+ if (i == local_proc_id) {
+ retval = nameserver_get_local(temp_obj,
+ name, buffer, length);
+ if (retval > 0)
+ break;
+
+ } else {
+ retval = nameserver_remote_get(
+ nameserver_state.remote_handle_list[proc_id[i]],
+ temp_obj->name, name, buffer, length);
+ if (retval > 0 || ((retval < 0) &&
+ (retval != -ENOENT))) /* Got the value */
+ break;
+ }
+ }
+
+exit:
+ if (retval < 0)
+ printk(KERN_ERR "nameserver_get failed: status=%x \n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_get);
+
+/*
+ * ======== nameserver_get ========
+ * Purpose:
+ * This will etrieve the value portion of a name/value
+ * pair from local table
+ *
+ * Returns the number of characters that matched with an entry
+ * So if "abc" was an entry and you called match with "abcd", this
+ * function will have the "abc" entry. The return would be 3 since
+ * three characters matched
+ *
+ */
+int nameserver_match(void *handle, const char *name, u32 *value)
+{
+ struct nameserver_object *temp_obj = NULL;
+ struct nameserver_entry *node = NULL;
+ s32 retval = 0;
+ u32 hash;
+ bool found = false;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(name == NULL);
+ BUG_ON(value == NULL);
+
+ temp_obj = (struct nameserver_object *)handle;
+ retval = mutex_lock_interruptible(temp_obj->gate_handle);
+ if (retval)
+ goto exit;
+
+ hash = nameserver_string_hash(name);
+ list_for_each_entry(node, &temp_obj->name_list, elem) {
+ if (node->hash == hash) {
+ *value = *(u32 *)node->buf;
+ found = true;
+ }
+ }
+
+ if (found == false)
+ retval = -ENOENT;
+
+exit:
+ printk(KERN_ERR "nameserver_match failed status:%x \n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_match);
+
+/*
+ * ======== nameserver_register_remote_driver ========
+ * Purpose:
+ * This will register a remote driver for a processor
+ */
+int nameserver_register_remote_driver(void *handle, u16 proc_id)
+{
+ struct nameserver_remote_object *temp = NULL;
+ s32 retval = 0;
+ u16 proc_count;
+
+ BUG_ON(handle == NULL);
+ proc_count = multiproc_get_max_processors();
+ if (WARN_ON(proc_id >= proc_count)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ temp = (struct nameserver_remote_object *)handle;
+ nameserver_state.remote_handle_list[proc_id] = temp;
+ return 0;
+
+exit:
+ printk(KERN_ERR
+ "nameserver_register_remote_driver failed status:%x \n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_register_remote_driver);
+
+/*
+ * ======== nameserver_unregister_remote_driver ========
+ * Purpose:
+ * This will unregister a remote driver for a processor
+ */
+int nameserver_unregister_remote_driver(u16 proc_id)
+{
+ s32 retval = 0;
+ u16 proc_count;
+
+ proc_count = multiproc_get_max_processors();
+ if (WARN_ON(proc_id >= proc_count)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ nameserver_state.remote_handle_list[proc_id] = NULL;
+ return 0;
+
+exit:
+ printk(KERN_ERR
+ "nameserver_unregister_remote_driver failed status:%x \n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(nameserver_unregister_remote_driver);
+
diff --git a/drivers/dsp/syslink/multicore_ipc/nameserver_ioctl.c b/drivers/dsp/syslink/multicore_ipc/nameserver_ioctl.c
new file mode 100755
index 000000000000..1192697bc867
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/nameserver_ioctl.c
@@ -0,0 +1,592 @@
+/*
+* nameserver_ioctl.c
+*
+* This provides the ioctl interface for nameserver module
+*
+* Copyright (C) 2008-2009 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.
+*/
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <nameserver.h>
+#include <nameserver_ioctl.h>
+
+/*
+ * FUNCTIONS NEED TO BE REVIEWED OPTIMIZED!
+ */
+
+/*
+ * ======== nameserver_ioctl_setup ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * setup nameserver module
+ */
+static int nameserver_ioctl_setup(
+ struct nameserver_cmd_args *cargs)
+{
+ cargs->api_status = nameserver_setup();
+ return 0;
+}
+
+/*
+ * ======== nameserver_ioctl_destroy ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * destroy nameserver module
+ */
+static int nameserver_ioctl_destroy(
+ struct nameserver_cmd_args *cargs)
+{
+ cargs->api_status = nameserver_destroy();
+ return 0;
+}
+
+/*
+ * ======== nameserver_ioctl_params_init ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * get the default configuration of a nameserver instance
+ */
+static int nameserver_ioctl_params_init(struct nameserver_cmd_args *cargs)
+{
+ struct nameserver_params params;
+ s32 status = 0;
+ ulong size;
+
+ cargs->api_status = nameserver_params_init(&params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct nameserver_params));
+ if (size)
+ status = -EFAULT;
+
+ return status;
+}
+
+/*
+ * ======== nameserver_ioctl_get_handle ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * get the handle of a nameserver instance from name
+ */
+static int nameserver_ioctl_get_handle(struct nameserver_cmd_args *cargs)
+{
+ void *handle = NULL;
+ char *name = NULL;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.get_handle.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.get_handle.name,
+ cargs->args.get_handle.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ handle = nameserver_get_handle(name);
+ cargs->args.get_handle.handle = handle;
+ cargs->api_status = 0;
+
+name_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== nameserver_ioctl_create ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * create a name server instance
+ */
+static int nameserver_ioctl_create(struct nameserver_cmd_args *cargs)
+{
+ struct nameserver_params params;
+ void *handle = NULL;
+ char *name = NULL;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.create.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.create.name,
+ cargs->args.create.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto copy_from_usr_error;
+ }
+
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct nameserver_params));
+ if (size) {
+ status = -EFAULT;
+ goto copy_from_usr_error;
+ }
+
+ handle = nameserver_create(name, &params);
+ cargs->args.create.handle = handle;
+ cargs->api_status = 0;
+
+copy_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_ioctl_delete ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * delete a name server instance
+ */
+static int nameserver_ioctl_delete(struct nameserver_cmd_args *cargs)
+{
+ cargs->api_status =
+ nameserver_delete(&cargs->args.delete_instance.handle);
+ return 0;
+}
+
+/*
+ * ======== nameserver_ioctl_add ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * add an entry into a nameserver instance
+ */
+static int nameserver_ioctl_add(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ char *buf = NULL;
+ void *entry;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.add.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.add.name,
+ cargs->args.add.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ buf = kmalloc(cargs->args.add.len, GFP_KERNEL);
+ if (buf == NULL) {
+ status = -ENOMEM;
+ goto buf_alloc_error;
+ }
+
+ size = copy_from_user(buf, cargs->args.add.buf,
+ cargs->args.add.len);
+ if (size) {
+ status = -EFAULT;
+ goto buf_from_usr_error;
+ }
+
+ entry = nameserver_add(cargs->args.add.handle, name, buf,
+ cargs->args.add.len);
+ cargs->args.add.entry = entry;
+ cargs->args.add.node = entry;
+ cargs->api_status = 0;
+
+buf_from_usr_error:
+ kfree(buf);
+
+buf_alloc_error: /* Fall through */
+name_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_ioctl_add_uint32 ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * add a Uint32 entry into a nameserver instance
+ */
+static int nameserver_ioctl_add_uint32(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ void *entry;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.addu32.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.addu32.name,
+ cargs->args.addu32.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ entry = nameserver_add_uint32(cargs->args.addu32.handle, name,
+ cargs->args.addu32.value);
+ cargs->args.addu32.entry = entry;
+ cargs->api_status = 0;
+
+name_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_ioctl_match ========
+ * Purpose:
+ * This wrapper function will call the nameserver function
+ * to retrieve the value portion of a name/value
+ * pair from local table
+ */
+static int nameserver_ioctl_match(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ u32 buf;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.match.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.match.name,
+ cargs->args.match.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ cargs->api_status =
+ nameserver_match(cargs->args.match.handle, name, &buf);
+ size = copy_to_user(cargs->args.match.value, &buf, sizeof(u32 *));
+ if (size) {
+ status = -EFAULT;
+ goto buf_to_usr_error;
+ }
+
+buf_to_usr_error: /* Fall through */
+name_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== nameserver_ioctl_remove ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * remove a name/value pair from a name server
+ */
+static int nameserver_ioctl_remove(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.remove.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ size = copy_from_user(name, cargs->args.remove.name,
+ cargs->args.remove.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ cargs->api_status =
+ nameserver_remove(cargs->args.remove.handle, name);
+
+name_from_usr_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_ioctl_remove_entry ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * remove an entry from a name server
+ */
+static int nameserver_ioctl_remove_entry(struct nameserver_cmd_args *cargs)
+{
+ cargs->api_status = nameserver_remove_entry(
+ cargs->args.remove_entry.handle,
+ cargs->args.remove_entry.entry);
+ return 0;
+}
+
+/*
+ * ======== nameserver_ioctl_get_local ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * retrieve the value portion of a name/value pair from local table
+ */
+static int nameserver_ioctl_get_local(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ char *buf = NULL;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.get_local.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ buf = kmalloc(cargs->args.get_local.len, GFP_KERNEL);
+ if (buf == NULL) {
+ status = -ENOMEM;
+ goto buf_alloc_error;
+ }
+
+ size = copy_from_user(name, cargs->args.get_local.name,
+ cargs->args.get_local.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ cargs->api_status = nameserver_get_local(
+ cargs->args.get_local.handle, name,
+ buf, cargs->args.get_local.len);
+ size = copy_to_user(cargs->args.get_local.buf, buf,
+ cargs->args.get_local.len);
+ if (size)
+ status = -EFAULT;
+
+name_from_usr_error:
+ kfree(buf);
+
+buf_alloc_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_ioctl_get ========
+ * Purpose:
+ * This wrapper function will call the nameserver function to
+ * retrieve the value portion of a name/value pair from table
+ */
+static int nameserver_ioctl_get(struct nameserver_cmd_args *cargs)
+{
+ char *name = NULL;
+ char *buf = NULL;
+ u16 *proc_id = NULL;
+ s32 status = 0;
+ ulong size;
+
+ name = kmalloc(cargs->args.get.name_len + 1, GFP_KERNEL);
+ if (name == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ name[cargs->args.get_handle.name_len] = '\0';
+ buf = kmalloc(cargs->args.get.len, GFP_KERNEL);
+ if (buf == NULL) {
+ status = -ENOMEM;
+ goto buf_alloc_error;
+ }
+
+ proc_id = kmalloc(cargs->args.get.proc_len, GFP_KERNEL);
+ if (proc_id == NULL) {
+ status = -ENOMEM;
+ goto proc_alloc_error;
+ }
+
+ size = copy_from_user(name, cargs->args.get.name,
+ cargs->args.get.name_len);
+ if (size) {
+ status = -EFAULT;
+ goto name_from_usr_error;
+ }
+
+ status = copy_from_user(proc_id, cargs->args.get.proc_id,
+ cargs->args.get.proc_len);
+ if (size) {
+ status = -EFAULT;
+ goto proc_from_usr_error;
+ }
+
+ cargs->api_status = nameserver_get(cargs->args.get.handle, name, buf,
+ cargs->args.get.len, proc_id);
+ size = copy_to_user(cargs->args.get.buf, buf,
+ cargs->args.get.len);
+ if (size)
+ status = -EFAULT;
+
+
+proc_from_usr_error: /* Fall through */
+name_from_usr_error:
+ kfree(proc_id);
+
+proc_alloc_error:
+ kfree(buf);
+
+buf_alloc_error:
+ kfree(name);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== nameserver_ioctl ========
+ * Purpose:
+ * This ioctl interface for nameserver module
+ */
+int nameserver_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct nameserver_cmd_args __user *uarg =
+ (struct nameserver_cmd_args __user *)args;
+ struct nameserver_cmd_args cargs;
+
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct nameserver_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_NAMESERVER_ADD:
+ status = nameserver_ioctl_add(&cargs);
+ break;
+
+ case CMD_NAMESERVER_ADDUINT32:
+ status = nameserver_ioctl_add_uint32(&cargs);
+ break;
+
+ case CMD_NAMESERVER_GET:
+ status = nameserver_ioctl_get(&cargs);
+ break;
+
+ case CMD_NAMESERVER_GETLOCAL:
+ status = nameserver_ioctl_get_local(&cargs);
+ break;
+
+ case CMD_NAMESERVER_MATCH:
+ status = nameserver_ioctl_match(&cargs);
+ break;
+
+ case CMD_NAMESERVER_REMOVE:
+ status = nameserver_ioctl_remove(&cargs);
+ break;
+
+ case CMD_NAMESERVER_REMOVEENTRY:
+ status = nameserver_ioctl_remove_entry(&cargs);
+ break;
+
+ case CMD_NAMESERVER_PARAMS_INIT:
+ status = nameserver_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_NAMESERVER_CREATE:
+ status = nameserver_ioctl_create(&cargs);
+ break;
+
+ case CMD_NAMESERVER_DELETE:
+ status = nameserver_ioctl_delete(&cargs);
+ break;
+
+ case CMD_NAMESERVER_GETHANDLE:
+ status = nameserver_ioctl_get_handle(&cargs);
+ break;
+
+ case CMD_NAMESERVER_SETUP:
+ status = nameserver_ioctl_setup(&cargs);
+ break;
+
+ case CMD_NAMESERVER_DESTROY:
+ status = nameserver_ioctl_destroy(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct nameserver_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/nameserver_remote.c b/drivers/dsp/syslink/multicore_ipc/nameserver_remote.c
new file mode 100644
index 000000000000..43227996266a
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/nameserver_remote.c
@@ -0,0 +1,49 @@
+/*
+ * nameserver_remote.c
+ *
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+
+#include <nameserver_remote.h>
+
+/*
+ * ======== nameserver_remote_get ========
+ * Purpose:
+ * This will get data from remote name server
+ */
+int nameserver_remote_get(const struct nameserver_remote_object *handle,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len)
+{
+ s32 retval = 0;
+
+ if (handle == NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON((instance_name == NULL) || (name == NULL)
+ || (value == NULL))) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = handle->get(handle, instance_name,
+ name, value, value_len, NULL);
+
+exit:
+ return retval;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify.c b/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify.c
new file mode 100755
index 000000000000..925533cfb20c
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify.c
@@ -0,0 +1,713 @@
+/*
+ * nameserver_remotenotify.c
+ *
+ * The nameserver_remotenotify module provides functionality to get name
+ * value pair from a remote nameserver.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Utilities headers */
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/semaphore.h>
+
+/* Syslink headers */
+#include <syslink/atomic_linux.h>
+
+/* Module level headers */
+#include <gate_remote.h>
+#include <gatepeterson.h>
+#include <nameserver.h>
+#include <multiproc.h>
+#include <nameserver_remotenotify.h>
+#include <notify.h>
+
+
+/*
+ * Macro to make a correct module magic number with refCount
+ */
+#define NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(x) \
+ ((NAMESERVERREMOTENOTIFY_MODULEID << 12u) | (x))
+
+/*
+ * Cache line length
+ * TODO: Short-term hack. Make parameter or figure out some other way!
+ */
+#define NAMESERVERREMOTENOTIFY_CACHESIZE 128
+
+/*
+ * Maximum length of value buffer that can be stored in the NameServer
+ * managed by this NameServerRemoteNotify instance.
+ */
+#define NAMESERVERREMOTENOTIFY_MAXVALUEBUFLEN 300
+
+/* Defines the nameserver_remotenotify state object, which contains all the
+ * module specific information
+ */
+struct nameserver_remotenotify_module_object {
+ struct nameserver_remotenotify_config cfg;
+ struct nameserver_remotenotify_config def_cfg;
+ struct nameserver_remotenotify_params def_inst_params;
+ bool is_setup;
+ void *gate_handle;
+ atomic_t ref_count;
+};
+
+/*
+ * NameServer remote transport state attributes
+ */
+struct nameserver_remotenotify_attrs {
+ u32 version;
+ u32 status;
+ u32 shared_addr_size;
+};
+
+/*
+ * NameServer remote transport packet definition
+ */
+struct nameserver_remotenotify_message {
+ u32 request;
+ u32 response;
+ u32 request_status;
+ u32 value;
+ u32 value_len;
+ char instance_name[32];
+ char name[32];
+ char value_buf[NAMESERVERREMOTENOTIFY_MAXVALUEBUFLEN];
+};
+
+/*
+ * NameServer remote transport state object definition
+ */
+struct nameserver_remotenotify_obj {
+ struct nameserver_remotenotify_attrs *attrs;
+ struct nameserver_remotenotify_message *msg[2];
+ struct nameserver_remotenotify_params params;
+ u16 remote_proc_id;
+ struct mutex *local_gate;
+ struct semaphore *sem_handle; /* Binary semaphore */
+};
+
+/*
+ * NameServer remote transport state object definition
+ */
+struct nameserver_remotenotify_object {
+ int (*get)(void *,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len, void *reserved);
+ void *obj; /* Implementation specific object */
+};
+
+/*
+ * nameserver_remotenotify state object variable
+ */
+static struct nameserver_remotenotify_module_object
+ nameserver_remotenotify_state = {
+ .is_setup = false,
+ .gate_handle = NULL,
+ .def_cfg.reserved = 0,
+ .def_inst_params.gate = NULL,
+ .def_inst_params.shared_addr = 0x0,
+ .def_inst_params.shared_addr_size = 0x0,
+ .def_inst_params.notify_event_no = (u32) -1,
+ .def_inst_params.notify_driver = NULL,
+};
+
+/*
+ * ======== nameserver_remotenotify_get_config ========
+ * Purpose:
+ * This will get the default configuration for the nameserver remote
+ * module
+ * This function can be called by the application to get their
+ * configuration parameter to nameserver_remotenotify_setup filled
+ * in by the nameserver_remotenotify module with the default
+ * parameters. If the user does not wish to make any change in the
+ * default parameters, this API is not required to be called
+ */
+void nameserver_remotenotify_get_config(
+ struct nameserver_remotenotify_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+ if (nameserver_remotenotify_state.is_setup == false)
+ memcpy(cfg, &(nameserver_remotenotify_state.def_cfg),
+ sizeof(struct nameserver_remotenotify_config));
+ else
+ memcpy(cfg, &(nameserver_remotenotify_state.cfg),
+ sizeof(struct nameserver_remotenotify_config));
+}
+
+
+/*
+ * ======== nameserver_remotenotify_setup ========
+ * Purpose:
+ * This will setup the nameserver_remotenotify module
+ * This function sets up the nameserver_remotenotify module. This
+ * function must be called before any other instance-level APIs can
+ * be invoked
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then nameserver_remotenotify_get_config can be called
+ * to get the configuration filled with the default values. After
+ * this, only the required configuration values can be changed. If
+ * the user does not wish to make any change in the default
+ * parameters, the application can simply call
+ * nameserver_remotenotify_setup with NULL parameters. The default
+ * parameters would get automatically used
+ */
+int nameserver_remotenotify_setup(
+ struct nameserver_remotenotify_config *cfg)
+{
+ struct nameserver_remotenotify_config tmp_cfg;
+ s32 retval = 0;
+ struct mutex *lock = NULL;
+ bool user_cfg = true;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable.
+ */
+ atomic_cmpmask_and_set(&nameserver_remotenotify_state.ref_count,
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0));
+ if (atomic_inc_return(&nameserver_remotenotify_state.ref_count)
+ != NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (cfg == NULL) {
+ nameserver_remotenotify_get_config(&tmp_cfg);
+ cfg = &tmp_cfg;
+ user_cfg = false;
+ }
+
+ /* Create a default gate handle for local module protection */
+ lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (lock == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ mutex_init(lock);
+ nameserver_remotenotify_state.gate_handle = lock;
+ if (user_cfg)
+ memcpy(&nameserver_remotenotify_state.cfg, cfg,
+ sizeof(struct nameserver_remotenotify_config));
+
+ nameserver_remotenotify_state.is_setup = true;
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== nameserver_remotenotify_destroy ========
+ * Purpose:
+ * This will destroy the nameserver_remotenotify module.
+ * Once this function is called, other nameserver_remotenotify
+ * module APIs, except for the nameserver_remotenotify_get_config
+ * API cannot be called anymore.
+ */
+int nameserver_remotenotify_destroy(void)
+{
+ s32 retval = 0;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(
+ &(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true)) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!(atomic_dec_return(&nameserver_remotenotify_state.ref_count)
+ == NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0))) {
+ retval = 1;
+ goto exit;
+ }
+
+ if (nameserver_remotenotify_state.gate_handle != NULL)
+ kfree(nameserver_remotenotify_state.gate_handle);
+
+ nameserver_remotenotify_state.is_setup = false;
+ return 0;
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== ameserver_remotenotify_params_init ========
+ * Purpose:
+ * This will get the current configuration values
+ */
+void nameserver_remotenotify_params_init(void *handle,
+ struct nameserver_remotenotify_params *params)
+{
+ struct nameserver_remotenotify_object *object = NULL;
+ struct nameserver_remotenotify_obj *obj = NULL;
+
+ if (atomic_cmpmask_and_lt(&(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ printk(KERN_ERR "nameserver_remotenotify_params_init failed: "
+ "Module is not initialized!\n");
+ return;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ printk(KERN_ERR "nameserver_remotenotify_params_init failed: "
+ "Argument of type(nameserver_remotenotify_params *) "
+ "is NULL!\n");
+ return;
+ }
+
+ object = (struct nameserver_remotenotify_object *)handle;
+ if (handle == NULL)
+ memcpy(params,
+ &(nameserver_remotenotify_state.def_inst_params),
+ sizeof(struct nameserver_remotenotify_params));
+ else {
+ obj = (struct nameserver_remotenotify_obj *)object->obj;
+ /* Return updated nameserver_remotenotify instance specific
+ * parameters.
+ */
+ memcpy(params, &(obj->params),
+ sizeof(struct nameserver_remotenotify_params));
+ }
+}
+
+
+/*
+ * ======== nameserver_remotenotify_callback ========
+ * Purpose:
+ * This will be called when a notify event is received
+ */
+void nameserver_remotenotify_callback(u16 proc_id, u32 event_no,
+ void *arg, u32 payload)
+{
+ struct nameserver_remotenotify_obj *handle = NULL;
+ u32 proc_count;
+ u16 offset = 0;
+ void *nshandle = NULL;
+ u32 value_len;
+ u32 key;
+ s32 retval = 0;
+ s32 count = -ENOENT;
+
+ if (atomic_cmpmask_and_lt(&(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(arg == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ proc_count = multiproc_get_max_processors();
+ if (WARN_ON(proc_id >= proc_count)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct nameserver_remotenotify_obj *)arg;
+ if ((multiproc_get_id(NULL) > proc_id))
+ offset = 1;
+
+ if (handle->msg[1 - offset]->request != true)
+ goto signal_response;
+
+ /* This is a request */
+ value_len = handle->msg[1 - offset]->value_len;
+ nshandle = nameserver_get_handle(
+ handle->msg[1 - offset]->instance_name);
+ if (nshandle != NULL) {
+ /* Search for the NameServer entry */
+ if (value_len == sizeof(u32)) {
+ count = nameserver_get_local(nshandle,
+ handle->msg[1 - offset]->name,
+ &handle->msg[1 - offset]->value,
+ value_len);
+ } else {
+ count = nameserver_get_local(nshandle,
+ handle->msg[1 - offset]->name,
+ &handle->msg[1 - offset]->value_buf,
+ value_len);
+ }
+ }
+
+ key = gatepeterson_enter(handle->params.gate);
+ /* If retval > 0 then an entry found */
+ if (count != -ENOENT)
+ handle->msg[1 - offset]->request_status = true;
+
+ /* Send a response back */
+ handle->msg[1 - offset]->response = true;
+ handle->msg[1 - offset]->request = false;
+ /* now we can leave the gate */
+ gatepeterson_leave(handle->params.gate, key);
+
+ /*
+ * The NotifyDriver handle must exists at this point,
+ * otherwise the notify_sendEvent should have failed
+ */
+ retval = notify_sendevent(handle->params.notify_driver,
+ proc_id, event_no, 0, true);
+
+signal_response:
+ if (handle->msg[offset]->response == true)
+ up(handle->sem_handle);
+exit:
+ if (retval < 0) {
+ printk(KERN_ERR "nameserver_remotenotify_callback failed! "
+ "status = 0x%x\n", retval);
+ }
+ return;
+}
+
+/*
+ * ======== nameserver_remotenotify_get ========
+ * Purpose:
+ * This will get a remote name value pair
+ */
+int nameserver_remotenotify_get(void *rhandle,
+ const char *instance_name, const char *name,
+ void *value, u32 value_len, void *reserved)
+{
+ struct nameserver_remotenotify_object *handle = NULL;
+ struct nameserver_remotenotify_obj *obj = NULL;
+ s32 offset = 0;
+ s32 len;
+ u32 key;
+ s32 retval = 0;
+
+ BUG_ON(instance_name == NULL);
+ BUG_ON(name == NULL);
+ BUG_ON(value == NULL);
+ BUG_ON((value_len <= 0) || \
+ (value_len > NAMESERVERREMOTENOTIFY_MAXVALUEBUFLEN));
+
+ if (atomic_cmpmask_and_lt(&(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(rhandle == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if ((value_len == 0) || \
+ (value_len > NAMESERVERREMOTENOTIFY_MAXVALUEBUFLEN)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct nameserver_remotenotify_object *)rhandle;
+ obj = (struct nameserver_remotenotify_obj *)handle->obj;
+ if (multiproc_get_id(NULL) > obj->remote_proc_id)
+ offset = 1;
+
+ key = gatepeterson_enter(obj->params.gate);
+ /* This is a request message */
+ obj->msg[offset]->request = 1;
+ obj->msg[offset]->response = 0;
+ obj->msg[offset]->request_status = 0;
+ obj->msg[offset]->value_len = value_len;
+ len = strlen(instance_name) + 1; /* Take termination null char */
+ strncpy(obj->msg[offset]->instance_name, instance_name, len);
+ len = strlen(name);
+ strncpy(obj->msg[offset]->name, name, len);
+
+ /* Send the notification to remote processor */
+ retval = notify_sendevent(obj->params.notify_driver,
+ obj->remote_proc_id,
+ obj->params.notify_event_no,
+ 0, /* Payload */
+ false); /* Not sending a payload */
+ if (retval < 0) {
+ /* Undo previous operations */
+ obj->msg[offset]->request = 0;
+ obj->msg[offset]->value_len = 0;
+ goto notify_error;
+ }
+
+ gatepeterson_leave(obj->params.gate, key);
+
+ /* Pend on the semaphore */
+ retval = down_interruptible(obj->sem_handle);
+ if (retval) {
+ retval = -EINTR ;
+ goto exit;
+ }
+
+ key = gatepeterson_enter(obj->params.gate);
+ if (obj->msg[offset]->request_status != true) {
+ retval = -ENOENT;
+ goto request_error;
+ }
+
+ if (!value_len) {
+ retval = -ENOENT;
+ goto request_error;
+ }
+
+ if (value_len == sizeof(u32))
+ memcpy((void *)value, (void *) &(obj->msg[offset]->value),
+ sizeof(u32));
+ else
+ memcpy((void *)value, (void *)&(obj->msg[offset]->value_buf),
+ value_len);
+
+ obj->msg[offset]->request_status = false;
+ obj->msg[offset]->request = 0;
+ obj->msg[offset]->response = 0;
+ retval = value_len;
+
+notify_error:
+request_error:
+ gatepeterson_leave(obj->params.gate, key);
+exit:
+ return retval;
+}
+
+/*
+ * ======== nameServer_remote_notify_params_init ========
+ * Purpose:
+ * This will get the current configuration values
+ */
+int nameServer_remote_notify_params_init(
+ struct nameserver_remotenotify_params *params)
+{
+ BUG_ON(params == NULL);
+
+ params->notify_event_no = 0;
+ params->notify_driver = NULL;
+ params->shared_addr = NULL;
+ params->shared_addr_size = 0;
+ params->gate = NULL;
+ return 0;
+}
+
+/*
+ * ======== nameserver_remotenotify_create ========
+ * Purpose:
+ * This will setup the nameserver remote module
+ */
+void *nameserver_remotenotify_create(u16 proc_id,
+ const struct nameserver_remotenotify_params *params)
+{
+ struct nameserver_remotenotify_object *handle = NULL;
+ struct nameserver_remotenotify_obj *obj = NULL;
+ u16 proc_count;
+ s32 retval = 0;
+ s32 retval1 = 0;
+ u32 offset = 0;
+
+ if (atomic_cmpmask_and_lt(&(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (WARN_ON(params->notify_driver == NULL ||
+ params->shared_addr == NULL ||
+ params->shared_addr_size == 0)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ proc_count = multiproc_get_max_processors();
+ if (proc_id >= proc_count) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ obj = kmalloc(sizeof(struct nameserver_remotenotify_obj), GFP_KERNEL);
+ handle = kmalloc(sizeof(struct nameserver_remotenotify_object),
+ GFP_KERNEL);
+ if (obj == NULL || handle == NULL) {
+ retval = -ENOMEM;
+ goto mem_error;
+ }
+
+ handle->get = nameserver_remotenotify_get;
+ handle->obj = (void *)obj;
+ obj->local_gate = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (obj->local_gate == NULL) {
+ retval = -ENOMEM;
+ goto mem_error;
+ }
+
+ obj->remote_proc_id = proc_id;
+ if (multiproc_get_id(NULL) > proc_id)
+ offset = 1;
+
+ obj->attrs = (struct nameserver_remotenotify_attrs *)
+ params->shared_addr;
+ obj->msg[0] = (struct nameserver_remotenotify_message *)
+ ((u32)obj->attrs +
+ NAMESERVERREMOTENOTIFY_CACHESIZE);
+ obj->msg[1] = (struct nameserver_remotenotify_message *)
+ ((u32)obj->msg[0] +
+ sizeof(struct
+ nameserver_remotenotify_message));
+ /* Clear out self shared structures */
+ memset(obj->msg[offset], 0,
+ sizeof(struct nameserver_remotenotify_message));
+ memcpy(&obj->params, params,
+ sizeof(struct nameserver_remotenotify_params));
+ retval = notify_register_event(params->notify_driver, proc_id,
+ params->notify_event_no,
+ nameserver_remotenotify_callback,
+ (void *)obj);
+ if (retval < 0)
+ goto notify_error;
+
+ retval = nameserver_register_remote_driver((void *)handle, proc_id);
+ obj->sem_handle = kmalloc(sizeof(struct semaphore), GFP_KERNEL);
+ if (obj->sem_handle == NULL) {
+ retval = -ENOMEM;
+ goto sem_alloc_error;
+ }
+
+ sema_init(obj->sem_handle, 0);
+ /* its is at the end since its init state = unlocked? */
+ mutex_init(obj->local_gate);
+ return (void *)handle;
+
+sem_alloc_error:
+ nameserver_unregister_remote_driver(proc_id);
+ /* Do we want to check the staus ? */
+ retval1 = notify_unregister_event(obj->params.notify_driver,
+ obj->remote_proc_id,
+ obj->params.notify_event_no,
+ nameserver_remotenotify_callback,
+ (void *)obj);
+
+notify_error:
+ kfree(obj->local_gate);
+
+mem_error:
+ kfree(obj);
+ kfree(handle);
+
+exit:
+ printk(KERN_ERR "nameserver_remotenotify_create failed! "
+ "status = 0x%x\n", retval);
+ return NULL;
+}
+
+
+/*
+ * ======== nameserver_remotenotify_create ========
+ * Purpose:
+ * This will delete the nameserver remote transport instance
+ */
+int nameserver_remotenotify_delete(void **rhandle)
+{
+ struct nameserver_remotenotify_object *handle = NULL;
+ struct nameserver_remotenotify_obj *obj = NULL;
+ s32 retval = 0;
+ struct mutex *gate = NULL;
+
+ if (atomic_cmpmask_and_lt(&(nameserver_remotenotify_state.ref_count),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(0),
+ NAMESERVERREMOTENOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON((rhandle == NULL) || (*rhandle == NULL))) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ handle = (struct nameserver_remotenotify_object *)(*rhandle);
+ obj = (struct nameserver_remotenotify_obj *)handle->obj;
+ if (obj == NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(obj->local_gate);
+ if (retval)
+ goto exit;
+
+ retval = nameserver_unregister_remote_driver(obj->remote_proc_id);
+ /* Do we have to bug_on/warn_on oops here intead of exit ?*/
+ if (retval < 0)
+ goto exit;
+
+ kfree(obj->sem_handle);
+ obj->sem_handle = NULL;
+ /* Unregister the event from Notify */
+ retval = notify_unregister_event(obj->params.notify_driver,
+ obj->remote_proc_id,
+ obj->params.notify_event_no,
+ nameserver_remotenotify_callback,
+ (void *)obj);
+ if (retval == NOTIFY_SUCCESS)
+ retval = 0;
+ gate = obj->local_gate;
+ kfree(obj);
+ kfree(handle);
+ *rhandle = NULL;
+ mutex_unlock(gate);
+ kfree(gate);
+
+exit:
+ if (retval < 0) {
+ printk(KERN_ERR "nameserver_remotenotify_delete failed! "
+ "status = 0x%x\n", retval);
+ }
+ return retval;
+}
+
+
+/*
+ * ======== nameserver_remotenotify_create ========
+ * Purpose:
+ * This will give shared memory requirements for the
+ * nameserver remote transport instance
+ */
+u32 nameserver_remotenotify_shared_memreq(const
+ struct nameserver_remotenotify_params *params)
+{
+ u32 total_size;
+ /* params is not used- to remove warning. */
+ (void)params;
+
+ BUG_ON(params == NULL);
+ /*
+ * The attrs takes a Ipc_cacheSize plus 2 Message structs are required.
+ * One for sending request and one for sending response.
+ */
+ total_size = NAMESERVERREMOTENOTIFY_CACHESIZE +
+ (2 * sizeof(struct nameserver_remotenotify_message));
+ return total_size;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify_ioctl.c b/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify_ioctl.c
new file mode 100755
index 000000000000..038c84528b26
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/nameserver_remotenotify_ioctl.c
@@ -0,0 +1,339 @@
+/*
+ * nameserver_remotenotify_ioctl.h
+ *
+ * The nameserver_remotenotify module provides functionality to get name
+ * value pair from a remote nameserver.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <sharedregion.h>
+#include <nameserver_remotenotify_ioctl.h>
+
+/*
+ * ======== nameserver_remotenotify_ioctl_get ======
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_get function
+ */
+static int nameserver_remotenotify_ioctl_get(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ s32 status = 0;
+ ulong size;
+ char *instance_name = NULL;
+ char *name = NULL;
+ u8 *value = NULL;
+
+ if (cargs->args.get.instance_name_len) {
+ instance_name = kmalloc(cargs->args.get.instance_name_len + 1,
+ GFP_KERNEL);
+ if (instance_name == NULL) {
+ status = ENOMEM;
+ goto exit;
+ }
+
+ instance_name[cargs->args.get.instance_name_len] = '\0';
+ size = copy_from_user(instance_name,
+ cargs->args.get.instance_name,
+ cargs->args.get.instance_name_len);
+ if (size) {
+ status = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ if (cargs->args.get.name_len) {
+ name = kmalloc(cargs->args.get.name_len + 1,
+ GFP_KERNEL);
+ if (name == NULL) {
+ status = ENOMEM;
+ goto exit;
+ }
+
+ instance_name[cargs->args.get.instance_name_len] = '\0';
+ size = copy_from_user(name, cargs->args.get.name,
+ cargs->args.get.name_len);
+ if (size) {
+ status = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ /* Allocate memory for the value */
+ if (cargs->args.get.value_len >= 0) {
+ value = kmalloc(cargs->args.get.value_len, GFP_KERNEL);
+ size = copy_from_user(value, cargs->args.get.value,
+ cargs->args.get.value_len);
+ if (size) {
+ status = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ cargs->args.get.len = nameserver_remotenotify_get(
+ cargs->args.get.handle,
+ instance_name,
+ name,
+ value,
+ cargs->args.get.value_len,
+ cargs->args.get.reserved);
+ cargs->api_status = 0;
+
+exit:
+ kfree(value);
+ kfree(name);
+ kfree(instance_name);
+ return status;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_shared_memreq ======
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_shared_memreq function
+ */
+static int nameserver_remotenotify_ioctl_shared_memreq(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ struct nameserver_remotenotify_params params;
+ s32 status = 0;
+ ulong size;
+
+ /* params may be NULL. */
+ if (cargs->args.shared_memreq.params != NULL) {
+ size = copy_from_user(&params,
+ cargs->args.shared_memreq.params,
+ sizeof(struct nameserver_remotenotify_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+ }
+
+ cargs->args.shared_memreq.shared_mem_size =
+ nameserver_remotenotify_shared_memreq(&params);
+ cargs->api_status = 0;
+
+exit:
+ return status;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_params_init ========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_params_init function
+ */
+static int nameserver_remotenotify_ioctl_params_init(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ struct nameserver_remotenotify_params params;
+ s32 status = 0;
+ ulong size;
+
+ nameserver_remotenotify_params_init(cargs->args.params_init.handle,
+ &params);
+ size = copy_to_user(cargs->args.params_init.params, &params,
+ sizeof(struct nameserver_remotenotify_params));
+ if (size)
+ status = -EFAULT;
+
+ cargs->api_status = 0;
+ return status;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_create========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_create function
+ */
+static int nameserver_remotenotify_ioctl_create(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ struct nameserver_remotenotify_params params;
+ s32 status = 0;
+ ulong size;
+ size = copy_from_user(&params, cargs->args.create.params,
+ sizeof(struct nameserver_remotenotify_params));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ params.shared_addr = sharedregion_get_ptr((u32 *)
+ cargs->args.create.params->shared_addr);
+ cargs->args.create.handle = nameserver_remotenotify_create(
+ cargs->args.create.proc_id,
+ &params);
+ cargs->api_status = 0;
+exit:
+ return status;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_delete ========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_delete function
+ */
+static int nameserver_remotenotify_ioctl_delete(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ cargs->api_status = nameserver_remotenotify_delete(
+ &cargs->args.delete_instance.handle);
+ return 0;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_get_config function
+ */
+static int nameserver_remotenotify_ioctl_get_config(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ s32 status = 0;
+ ulong size;
+ struct nameserver_remotenotify_config config;
+
+ nameserver_remotenotify_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct nameserver_remotenotify_config));
+ if (size)
+ status = -EFAULT;
+
+ cargs->api_status = 0;
+ return status;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_setup function
+ */
+static int nameserver_remotenotify_ioctl_setup(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ struct nameserver_remotenotify_config config;
+ s32 status = 0;
+ ulong size;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct nameserver_remotenotify_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = nameserver_remotenotify_setup(&config);
+exit:
+ return status;
+}
+
+
+/*
+ * ======== nameserver_remotenotify_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to nameserver_remotenotify_destroy function
+ */
+static int nameserver_remotenotify_ioctl_destroy(
+ struct nameserver_remotenotify_cmd_args *cargs)
+{
+ cargs->api_status = nameserver_remotenotify_destroy();
+ return 0;
+}
+
+/*
+ * ======== nameserver_remotenotify_ioctl ========
+ * Purpose:
+ * This ioctl interface for nameserver_remotenotify module
+ */
+int nameserver_remotenotify_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct nameserver_remotenotify_cmd_args __user *uarg =
+ (struct nameserver_remotenotify_cmd_args __user *)args;
+ struct nameserver_remotenotify_cmd_args cargs;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct nameserver_remotenotify_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_NAMESERVERREMOTENOTIFY_GET:
+ status = nameserver_remotenotify_ioctl_get(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_SHAREDMEMREQ:
+ status = nameserver_remotenotify_ioctl_shared_memreq(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_PARAMS_INIT:
+ status = nameserver_remotenotify_ioctl_params_init(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_CREATE:
+ status = nameserver_remotenotify_ioctl_create(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_DELETE:
+ status = nameserver_remotenotify_ioctl_delete(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_GETCONFIG:
+ status = nameserver_remotenotify_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_SETUP:
+ status = nameserver_remotenotify_ioctl_setup(&cargs);
+ break;
+
+ case CMD_NAMESERVERREMOTENOTIFY_DESTROY:
+ status = nameserver_remotenotify_ioctl_destroy(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs,
+ sizeof(struct nameserver_remotenotify_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/platform.c b/drivers/dsp/syslink/multicore_ipc/platform.c
new file mode 100644
index 000000000000..3e410779d16d
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/platform.c
@@ -0,0 +1,1420 @@
+/*
+ * platform.c
+ *
+ * Implementation of platform initialization logic for Syslink IPC.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+/* Standard header files */
+#include <linux/types.h>
+#include <linux/module.h>
+
+
+/* Utilities & Osal headers */
+/*#include <Gate.h>
+#include <GateMutex.h>
+#include <Memory.h>*/
+
+/* SysLink device specific headers */
+#include "../procmgr/proc4430/proc4430.h"
+
+/* Module level headers */
+#include <multiproc.h>
+#include <sysmgr.h>
+#include <_sysmgr.h>
+#include <sysmemmgr.h>
+#include <platform.h>
+#include <gatepeterson.h>
+#include <sharedregion.h>
+#include <listmp.h>
+#include <messageq.h>
+#include <messageq_transportshm.h>
+#include <notify.h>
+/*#include <NotifyDriver.h>*/
+#include <notify_ducatidriver.h>
+#include <nameserver.h>
+#include <nameserver_remote.h>
+#include <nameserver_remotenotify.h>
+#include <procmgr.h>
+#include <heap.h>
+#include <heapbuf.h>
+
+#include <platform_mem.h>
+
+
+/** ============================================================================
+ * Application specific configuration, please change these value according to
+ * your application's need.
+ * ============================================================================
+ */
+/* App defines */
+
+/* SYSM3 Heap */
+#define SYSM3HEAPID 0
+#define SYSM3HEAPNAME "SysMgrHeap0"
+
+/* APPM3 Heap */
+#define APPM3HEAPID 1
+#define APPM3HEAPNAME "SysMgrHeap1"
+
+
+/*!
+ * @brief Interrupt ID of physical interrupt handled by the Notify driver to
+ * receive events.
+ */
+#define BASE_DUCATI2ARM_INTID 26
+
+/*!
+ * @brief Interrupt ID of physical interrupt handled by the Notify driver to
+ * send events.
+ */
+#define BASE_ARM2DUCATI_INTID 50
+
+/*!
+ * @brief Maximum events supported by Notify component
+ */
+#define NOTIFY_MAX_EVENTS 32
+
+/*!
+ * @brief Number of event reserved i.e. can not be used by application
+ */
+#define NOTIFY_NUMRESERVEDEVENTS 0
+
+/*!
+ * @brief Wait for this much poll count when sending event
+ */
+#define NOTIFY_SENDEVENTPOLLCOUNT ((u32) -1)
+
+/*!
+ * @brief Align buffer in Heap
+ */
+#define HEAPBUF_ALIGN 128
+
+/*!
+ * @brief Number of blocks in the heap
+ */
+#define HEAPBUF_NUMBLOCKS 16
+
+/*!
+ * @brief Size of each blocks in heap
+ */
+#define HEAPBUF_BLOCKSIZE 256
+
+
+/*! @brief Start of shared memory */
+#define SHAREDMEMORY_PHY_BASEADDR 0x8B000000
+#define SHAREDMEMORY_PHY_BASESIZE 0x00100000
+
+/*! @brief Start of shared memory for SysM3 */
+#define SHAREDMEMORY_PHY_BASEADDR_SYSM3 0x8B000000
+#define SHAREDMEMORY_PHY_BASESIZE_SYSM3 0x00054000
+
+/*! @brief Start of shared memory AppM3 */
+#define SHAREDMEMORY_PHY_BASEADDR_APPM3 0x8B055000
+#define SHAREDMEMORY_PHY_BASESIZE_APPM3 0x00054000
+
+/*! @brief Start of SHM for SysM3 */
+#define SHAREDMEMORY_SLV_VRT_BASEADDR_SYSM3 0xA0000000
+#define SHAREDMEMORY_SLV_VRT_BASESIZE_SYSM3 0x00055000
+
+/*! @brief Start of SHM for AppM3 */
+#define SHAREDMEMORY_SLV_VRT_BASEADDR_APPM3 0xA0055000
+#define SHAREDMEMORY_SLV_VRT_BASESIZE_APPM3 0x00055000
+
+/*! @brief Start of Boot load page for SysM3 */
+#define BOOTLOADPAGE_SLV_VRT_BASEADDR_SYSM3 0xA0054000
+#define BOOTLOADPAGE_SLV_VRT_BASESIZE_SYSM3 0x00001000
+
+/*! @brief Start of Boot load page for AppM3 */
+#define BOOTLOADPAGE_SLV_VRT_BASEADDR_APPM3 0xA00A9000
+#define BOOTLOADPAGE_SLV_VRT_BASESIZE_APPM3 0x00001000
+
+/*! @brief Start of shared memory */
+#define SHAREDMEMORY_SWDMM_PHY_BASEADDR 0x8A300000
+#define SHAREDMEMORY_SWDMM_PHY_BASESIZE 0x00C00000
+
+/*! @brief Start of SHM SW DMMfor Ducati */
+#define SHAREDMEMORY_SWDMM_SLV_VRT_BASEADDR 0x81300000
+#define SHAREDMEMORY_SWDMM_SLV_VRT_BASESIZE 0x00C00000
+
+/*!
+ * @brief Size of the shared memory heap, this heap is used for providing
+ * shared memory to drivers/instances. Should not be used for any other purpose.
+ */
+#define SMHEAP_SIZE SHAREDMEMORY_PHY_BASESIZE
+
+/*!
+ * @brief Shared region index for Shared memory heap.
+ */
+#define SMHEAP_SRINDEX 0
+
+/*!
+ * @brief Shared region index for Shared memory heap for SysM3.
+ */
+#define SMHEAP_SRINDEX_SYSM3 0
+
+/*!
+ * @brief Shared region index for Shared memory heap for AppM3.
+ */
+#define SMHEAP_SRINDEX_APPM3 1
+
+/*!
+ * @brief Shared region index for Shared memory SW DMM section.
+ */
+#define SMHEAP_SRINDEX_SWDMM 2
+
+/*!
+ * @brief Shared region index for SysM3 boot load page
+ */
+#define BOOTLOADPAGE_SRINDEX 1
+
+
+/*!
+ * @brief Event no used by sysmemmgr
+ */
+#define PLATFORM_SYSMEMMGR_EVENTNO 31
+
+
+/** ============================================================================
+ * Command Id used by bootloadpage logic to transfer info
+ * ============================================================================
+ */
+/*!
+ * @brief Command ID for notify driver.
+ */
+#define PLATFORM_CMD_NOTIFYDRIVER SYSMGR_CMD_SHAREDREGION_ENTRY_END
+
+/*!
+ * @brief Command ID for GatePeterson used by nameserverremotenotify.
+ */
+#define PLATFORM_CMD_GPNSRN (PLATFORM_CMD_NOTIFYDRIVER + 1)
+
+/*!
+ * @brief Command ID for nameserverremotenotify.
+ */
+#define PLATFORM_CMD_NSRN (PLATFORM_CMD_NOTIFYDRIVER + 2)
+
+/*!
+ * @brief Command ID for GatePeterson used by HeapBuf.
+ */
+#define PLATFORM_CMD_GPHEAPBUF (PLATFORM_CMD_NOTIFYDRIVER + 3)
+
+/*!
+ * @brief Command ID for HeapBuf.
+ */
+#define PLATFORM_CMD_HEAPBUF (PLATFORM_CMD_NOTIFYDRIVER + 4)
+
+/*!
+ * @brief Command ID for GatePeterson used by MessageQTransportShm.
+ */
+#define PLATFORM_CMD_GPMQT (PLATFORM_CMD_NOTIFYDRIVER + 5)
+
+/*!
+ * @brief Command ID for MessageQTransportShm.
+ */
+#define PLATFORM_CMD_MQT (PLATFORM_CMD_NOTIFYDRIVER + 6)
+
+
+/** ============================================================================
+ * Handles used by platform logic
+ * ============================================================================
+ */
+void *platform_notifydrv_handle;
+
+/* Handles for SysM3 */
+void *platform_nsrn_gate_handle_sysm3;
+void *platform_nsrn_handle_sysm3;
+void *platform_notifydrv_handle_sysm3;
+void *platform_heap_gate_handle_sysm3;
+void *platform_heap_handle_sysm3;
+void *platform_mqt_gate_handle_sysm3;
+void *platform_transport_shm_handle_sysm3;
+void *platform_messageq_sysm3;
+
+/* Handles for AppM3 */
+void *platform_nsrn_gate_handle_appm3;
+void *platform_nsrn_handle_appm3;
+void *platform_notifydrv_handle_appm3;
+void *platform_heap_gate_handle_appm3;
+void *platform_heap_handle_appm3;
+void *platform_mqt_gate_handle_appm3;
+void *platform_transport_shm_handle_appm3;
+void *platform_messageq_appm3;
+
+
+/** ============================================================================
+ * Struct & Enums.
+ * ============================================================================
+ */
+/* Struct for reading platform specific gate peterson configuration values */
+struct platform_gaterpeterson_params {
+ u32 shared_mem_addr; /* Shared memory address */
+ u32 shared_mem_size; /* Shared memory size */
+ u32 remote_proc_id; /* Remote processor identifier */
+};
+
+struct platform_notify_ducatidrv_params {
+ u32 shared_mem_addr; /* Shared memory address */
+ u32 shared_mem_size; /* Shared memory size */
+ u16 remote_proc_id; /* Remote processor identifier */
+};
+
+struct platform_nameserver_remotenotify_params {
+ u32 shared_mem_addr; /* Shared memory address */
+ u32 shared_mem_size; /* Shared memory size */
+ u32 notify_event_no; /* Notify Event number to used */
+};
+
+struct platform_heapbuf_params {
+ u32 shared_mem_addr; /* Shared memory address */
+ u32 shared_mem_size; /* Shared memory size */
+ u32 shared_buf_addr; /* Shared memory address */
+ u32 shared_buf_size; /* Shared memory size */
+ u32 num_blocks;
+ u32 block_size;
+};
+
+struct platform_messageq_transportshm_params {
+ u32 shared_mem_addr; /* Shared memory address */
+ u32 shared_mem_size; /* Shared memory size */
+ u32 notify_event_no; /* Notify Event number */
+};
+
+struct platform_proc_config_params {
+ u32 use_notify;
+ u32 use_messageq;
+ u32 use_heapbuf;
+ u32 use_frameq;
+ u32 use_ring_io;
+ u32 use_listmp;
+ u32 use_nameserver;
+};
+
+/** ============================================================================
+ * Macros and types
+ * ============================================================================
+ */
+/*!
+ * @brief Number of slave memory entries for OMAP4430.
+ */
+#define NUM_MEM_ENTRIES 3
+
+/*!
+ * @brief Number of slave memory entries for OMAP4430 SYSM3.
+ */
+#define NUM_MEM_ENTRIES_SYSM3 1
+
+/*!
+ * @brief Number of slave memory entries for OMAP4430 APPM3.
+ */
+#define NUM_MEM_ENTRIES_APPM3 1
+
+/*!
+ * @brief Position of reset vector memory region in the memEntries array.
+ */
+#define RESET_VECTOR_ENTRY_ID 0
+
+
+/** ============================================================================
+ * Globals
+ * ============================================================================
+ */
+/*!
+ * @brief Array of memory entries for OMAP4430
+ */
+static struct proc4430_mem_entry mem_entries[NUM_MEM_ENTRIES] = {
+ {
+ "DUCATI_SHM_SYSM3", /* NAME : Name of the memory region */
+ SHAREDMEMORY_PHY_BASEADDR_SYSM3,
+ /* PHYSADDR : Physical address */
+ SHAREDMEMORY_SLV_VRT_BASEADDR_SYSM3,
+ /* SLAVEVIRTADDR : Slave virtual address */
+ (u32) -1u,
+ /* MASTERVIRTADDR : Master virtual address (if known) */
+ SHAREDMEMORY_SLV_VRT_BASESIZE_SYSM3,
+ /* SIZE : Size of the memory region */
+ true, /* SHARE : Shared access memory? */
+ },
+ {
+ "DUCATI_SHM_APPM3", /* NAME : Name of the memory region */
+ SHAREDMEMORY_PHY_BASEADDR_APPM3,
+ /* PHYSADDR : Physical address */
+ SHAREDMEMORY_SLV_VRT_BASEADDR_APPM3,
+ /* SLAVEVIRTADDR : Slave virtual address */
+ (u32) -1u,
+ /* MASTERVIRTADDR : Master virtual address (if known) */
+ SHAREDMEMORY_SLV_VRT_BASESIZE_APPM3,
+ /* SIZE : Size of the memory region */
+ true, /* SHARE : Shared access memory? */
+ },
+ {
+ "DUCATI_SHM_SWDMM", /* NAME : Name of the memory region */
+ SHAREDMEMORY_SWDMM_PHY_BASEADDR,
+ /* PHYSADDR : Physical address */
+ SHAREDMEMORY_SWDMM_SLV_VRT_BASEADDR,
+ /* SLAVEVIRTADDR : Slave virtual address */
+ (u32) -1u,
+ /* MASTERVIRTADDR : Master virtual address (if known) */
+ SHAREDMEMORY_SWDMM_SLV_VRT_BASESIZE,
+ /* SIZE : Size of the memory region */
+ true, /* SHARE : Shared access memory? */
+ }
+};
+
+void *procmgr_handle;
+void *procmgr_proc_handle;
+void *platform_sm_heap_virt_addr_sysm3;
+void *platform_sm_heap_virt_addr_appm3;
+
+/*!
+ * @brief Handle to the ProcMgr instance used.
+ */
+void *procmgr_handle;
+
+/*!
+ * @brief Handle to the Processor instance used.
+ */
+void *procmgr_proc_handle;
+
+/*!
+ * @brief Handle to the SysM3 ProcMgr instance used.
+ */
+void *procmgr_handle_sysm3;
+
+/*!
+ * @brief Handle to the AppM3 ProcMgr instance used.
+ */
+void *procmgr_handle_appm3;
+
+
+/*!
+ * @brief Handle to the SysM3 Processor instance used.
+ */
+void *procmgr_proc_handle_sysm3;
+
+/*!
+ * @brief Handle to the AppM3 Processor instance used.
+ */
+void *procmgr_proc_handle_appm3;
+
+/*!
+ * @brief File ID of the file loaded.
+ */
+u32 procmgr_file_id;
+
+/*!
+ * @brief Shared memory heap virtual address.
+ */
+void *platform_sm_heap_virt_addr;
+
+/*!
+ * @brief Shared memory heap physical address.
+ */
+void *platform_sm_heap_phys_addr;
+
+/*!
+ * @brief Scalability info
+ */
+struct sysmgr_proc_config pc_params;
+
+/*!
+ * @brief SW DMM virtual address.
+ */
+void *platform_sw_dmm_virt_addr;
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+
+/*
+ * ======== platform_setup ========
+ * Purpose:
+ * TBD: logic would change completely in the final system.
+ */
+s32 platform_setup(struct sysmgr_config *config)
+{
+
+ s32 status = 0;
+ struct proc4430_config proc_config;
+ struct proc_mgr_params params;
+ struct proc4430_params proc_params;
+ struct proc_mgr_attach_params attach_params;
+ u16 proc_id;
+ struct sysmemmgr_config sysmemmgr_cfg;
+ struct platform_mem_map_info info;
+
+ if (WARN_ON(config == NULL)) {
+ /*! @retval SYSMGR_E_INVALIDARG Argument of type
+ * (GatePeterson_Config *) passed is null*/
+ status = -EINVAL;
+ goto invalid_config_fail;
+ }
+
+ /* Map the static region */
+ info.src = SHAREDMEMORY_PHY_BASEADDR;
+ info.size = SHAREDMEMORY_PHY_BASESIZE;
+ info.is_cached = false;
+ status = platform_mem_map(&info);
+ if (status < 0)
+ goto mem_map_fail;
+
+ /* Get default config for System memory manager */
+ sysmemmgr_get_config(&sysmemmgr_cfg);
+ /* Initialize the System memory manager */
+ sysmemmgr_cfg.static_mem_size = SHAREDMEMORY_PHY_BASESIZE;
+ sysmemmgr_cfg.static_phys_base_addr = SHAREDMEMORY_PHY_BASEADDR;
+ sysmemmgr_cfg.static_virt_base_addr = info.dst;
+ sysmemmgr_cfg.event_no = PLATFORM_SYSMEMMGR_EVENTNO;
+ status = sysmemmgr_setup(&sysmemmgr_cfg);
+ if (status < 0)
+ goto sysmemmgr_setup_fail;
+
+ /* The heap for SysM3 and AppM3 are allocated at once */
+ platform_sm_heap_virt_addr = sysmemmgr_alloc(SMHEAP_SIZE,
+ sysmemmgr_allocflag_physical);
+ if (platform_sm_heap_virt_addr == NULL)
+ goto sysmemmgr_alloc_fail;
+
+ platform_sm_heap_virt_addr_sysm3 = platform_sm_heap_virt_addr;
+ /* The AppM3 shared area is after SysM3 heap + boot load page */
+ platform_sm_heap_virt_addr_appm3 = (platform_sm_heap_virt_addr_sysm3 +
+ SHAREDMEMORY_PHY_BASESIZE_SYSM3 +
+ BOOTLOADPAGE_SLV_VRT_BASESIZE_SYSM3);
+
+
+ /* Create the shared region entry for the SysM3 heap */
+ sharedregion_add(SMHEAP_SRINDEX_SYSM3,
+ platform_sm_heap_virt_addr_sysm3,
+ SHAREDMEMORY_PHY_BASESIZE_SYSM3);
+ /* Zero out the shared memory for SysM3 */
+ memset((void *) platform_sm_heap_virt_addr_sysm3,
+ 0,
+ SHAREDMEMORY_PHY_BASESIZE_SYSM3);
+
+ /* Create the shared region entry for the AppM3 heap */
+ sharedregion_add(SMHEAP_SRINDEX_APPM3,
+ platform_sm_heap_virt_addr_appm3,
+ SHAREDMEMORY_PHY_BASESIZE_APPM3);
+ /* Zero out the shared memory for AppM3 */
+ memset((void *) platform_sm_heap_virt_addr_appm3,
+ 0,
+ SHAREDMEMORY_PHY_BASESIZE_APPM3);
+
+ /* Map the static region */
+ info.src = SHAREDMEMORY_SWDMM_PHY_BASEADDR;
+ info.size = SHAREDMEMORY_SWDMM_PHY_BASESIZE;
+ info.is_cached = false;
+ status = platform_mem_map(&info);
+ if (status < 0)
+ goto mem_map_fail;
+ platform_sw_dmm_virt_addr = (void *) info.dst;
+ /* Create the shared region entry for the SW DMM heap */
+ sharedregion_add(SMHEAP_SRINDEX_SWDMM,
+ platform_sw_dmm_virt_addr,
+ info.size);
+
+ proc4430_get_config(&proc_config);
+ status = proc4430_setup(&proc_config);
+ if (status < 0)
+ goto proc_setup_fail;
+
+
+ /* Get MultiProc ID by name. */
+ proc_id = multiproc_get_id("SysM3");
+
+ /* Create an instance of the Processor object for OMAP4430 */
+ proc4430_params_init(NULL, &proc_params);
+ proc_params.num_mem_entries = NUM_MEM_ENTRIES;
+ proc_params.mem_entries = mem_entries;
+ proc_params.reset_vector_mem_entry = RESET_VECTOR_ENTRY_ID;
+ procmgr_proc_handle = proc4430_create(proc_id, &proc_params);
+ if (procmgr_proc_handle == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto proc_create_fail;
+ }
+
+ /* Initialize parameters */
+ proc_mgr_params_init(NULL, &params);
+ params.proc_handle = procmgr_proc_handle;
+ procmgr_handle = proc_mgr_create(proc_id, &params);
+ if (procmgr_handle == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto proc_mgr_create_fail;
+ }
+
+ proc_mgr_get_attach_params(NULL, &attach_params);
+ /* Default params will be used if NULL is passed. */
+ status = proc_mgr_attach(procmgr_handle, &attach_params);
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto proc_mgr_attach_fail;
+ }
+
+
+ /* SysM3 and AppM3 use the same handle */
+ procmgr_handle_sysm3 = procmgr_handle;
+ procmgr_proc_handle_sysm3 = procmgr_proc_handle;
+
+ procmgr_handle = NULL;
+ procmgr_proc_handle = NULL;
+
+
+
+ /* Get MultiProc ID by name. */
+ proc_id = multiproc_get_id("AppM3");
+
+ /* Create an instance of the Processor object for OMAP4430 */
+ proc4430_params_init(NULL, &proc_params);
+ proc_params.num_mem_entries = NUM_MEM_ENTRIES;
+ proc_params.mem_entries = mem_entries;
+ proc_params.reset_vector_mem_entry = RESET_VECTOR_ENTRY_ID;
+ procmgr_proc_handle = proc4430_create(proc_id, &proc_params);
+ if (procmgr_proc_handle == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto proc_create_fail;
+ }
+
+ /* Initialize parameters */
+ proc_mgr_params_init(NULL, &params);
+ params.proc_handle = procmgr_proc_handle;
+ procmgr_handle = proc_mgr_create(proc_id, &params);
+ if (procmgr_handle == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto proc_mgr_create_fail;
+ }
+
+ proc_mgr_get_attach_params(NULL, &attach_params);
+ /* Default params will be used if NULL is passed. */
+ status = proc_mgr_attach(procmgr_handle, &attach_params);
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto proc_mgr_attach_fail;
+ }
+
+ procmgr_handle_appm3 = procmgr_handle;
+ procmgr_proc_handle_appm3 = procmgr_proc_handle;
+ goto exit;
+
+proc_mgr_attach_fail:
+ printk(KERN_ERR "platform_setup: proc_mgr_attach failed [0x%x]"
+ " for processor [0x%x]\n", status, proc_id);
+ goto exit;
+
+proc_mgr_create_fail:
+ printk(KERN_ERR "platform_setup: proc_mgr_create failed [0x%x]",
+ status);
+ goto exit;
+proc_create_fail:
+ printk(KERN_ERR "platform_setup: proc4430_create failed [0x%x]",
+ status);
+ goto exit;
+proc_setup_fail:
+ printk(KERN_ERR "platform_setup: proc4430_setup failed [0x%x]",
+ status);
+ goto exit;
+sysmemmgr_alloc_fail:
+ printk(KERN_ERR "platform_setup: sysmemmgr_alloc failed [0x%x]",
+ status);
+ goto exit;
+sysmemmgr_setup_fail:
+ printk(KERN_ERR "platform_setup: sysmemmgr_setup failed [0x%x]",
+ status);
+ goto exit;
+mem_map_fail:
+ printk(KERN_ERR "platform_setup: platform_mem_map failed [0x%x]",
+ status);
+ goto exit;
+invalid_config_fail:
+ printk(KERN_ERR "platform_setup: Argument of type (sysmgr_get_config *)"
+ " passed is null [0x%x]", status);
+exit:
+ return status;
+}
+
+
+/*
+ * ======== platform_destroy ========
+ * Purpose:
+ * Function to finalize the platform.
+ */
+s32 platform_destroy(void)
+{
+ s32 status = 0;
+ struct platform_mem_unmap_info u_info;
+ /* Delete the Processor instances */
+
+ if (procmgr_handle_appm3 != NULL) {
+ status = proc_mgr_detach(procmgr_handle_appm3);
+ WARN_ON(status < 0);
+ }
+
+ if (procmgr_proc_handle_appm3 != NULL) {
+ status = proc4430_delete(&procmgr_proc_handle_appm3);
+ WARN_ON(status < 0);
+ }
+
+ if (procmgr_handle_appm3 != NULL) {
+ status = proc_mgr_delete(&procmgr_handle_appm3);
+ WARN_ON(status < 0);
+ }
+
+ if (procmgr_handle_sysm3 != NULL) {
+ status = proc_mgr_detach(procmgr_handle_sysm3);
+ WARN_ON(status < 0);
+ }
+
+ if (procmgr_proc_handle_sysm3 != NULL) {
+ status = proc4430_delete(&procmgr_proc_handle_sysm3);
+ WARN_ON(status < 0);
+ }
+
+ if (procmgr_handle_sysm3 != NULL) {
+ status = proc_mgr_delete(&procmgr_handle_sysm3);
+ WARN_ON(status < 0);
+ }
+
+ status = proc4430_destroy();
+ WARN_ON(status < 0);
+
+
+ sharedregion_remove(SMHEAP_SRINDEX_APPM3);
+ sharedregion_remove(SMHEAP_SRINDEX_SYSM3);
+
+ sysmemmgr_free(platform_sm_heap_virt_addr, SMHEAP_SIZE,
+ sysmemmgr_allocflag_physical);
+
+ status = sysmemmgr_destroy();
+ WARN_ON(status < 0);
+
+ if (platform_sm_heap_virt_addr != NULL) {
+ u_info.addr = (u32) platform_sm_heap_virt_addr;
+ platform_mem_unmap(&u_info);
+ }
+
+ if (platform_sw_dmm_virt_addr != NULL) {
+ u_info.addr = (u32) platform_sw_dmm_virt_addr;
+ platform_mem_unmap(&u_info);
+ }
+
+ return status;
+}
+
+
+/*
+ * ======== platform_load_callback ========
+ * Purpose:
+ * Function called by proc_mgr when slave is in loaded state.
+ */
+void platform_load_callback(void *arg)
+{
+ s32 status = 0;
+ u16 proc_id = (u32) arg;
+ u16 local_id = MULTIPROC_INVALIDID;
+ struct sharedregion_info info;
+ u32 boot_load_page;
+ u32 sh_addr_base;
+ u32 nwrite;
+ int index;
+
+ printk(KERN_ERR "platform_load_callback\n");
+
+ /* Get the written entry */
+ local_id = multiproc_get_id(NULL);
+
+ if (proc_id == multiproc_get_id("SysM3"))
+ index = SMHEAP_SRINDEX_SYSM3;
+ else if (proc_id == multiproc_get_id("AppM3"))
+ index = SMHEAP_SRINDEX_APPM3;
+ else {
+ status = SYSMGR_E_FAIL;
+ goto proc_invalid_id;
+ }
+ /* Add the to sharedregion */
+ switch (index) {
+ case SMHEAP_SRINDEX_SYSM3: /* For SysM3 */
+ /* Get the boot load page address */
+ boot_load_page = BOOTLOADPAGE_SLV_VRT_BASEADDR_SYSM3;
+ status = proc_mgr_translate_addr(procmgr_handle_sysm3,
+ (void *) &sh_addr_base,
+ PROC_MGR_ADDRTYPE_MASTERKNLVIRT,
+ (void *) boot_load_page,
+ PROC_MGR_ADDRTYPE_SLAVEVIRT);
+ if (status < 0)
+ break;
+ /* Zero out the boot load page */
+ memset((void *) sh_addr_base,
+ 0,
+ BOOTLOADPAGE_SLV_VRT_BASESIZE_SYSM3);
+ break;
+
+ case SMHEAP_SRINDEX_APPM3: /* For AppM3 */
+ /* Get the boot load page address */
+ boot_load_page = BOOTLOADPAGE_SLV_VRT_BASEADDR_APPM3;
+ status = proc_mgr_translate_addr(procmgr_handle_appm3,
+ (void *) &sh_addr_base,
+ PROC_MGR_ADDRTYPE_MASTERKNLVIRT,
+ (void *) boot_load_page,
+ PROC_MGR_ADDRTYPE_SLAVEVIRT);
+ if (status < 0)
+ break;
+
+ /* Zero out the boot load page */
+ memset((void *) sh_addr_base,
+ 0,
+ BOOTLOADPAGE_SLV_VRT_BASESIZE_APPM3);
+ break;
+ }
+
+ if (status < 0)
+ goto proc_mgr_translate_addr_fail;
+
+ /* Set the boot load page address */
+ sysmgr_set_boot_load_page(proc_id, sh_addr_base);
+
+ /* Write the boot table (containing both regions) to */
+ /* the current processor */
+
+ /* For SysM3 */
+ sharedregion_get_table_info(SMHEAP_SRINDEX_SYSM3,
+ local_id,
+ &info);
+ platform_sm_heap_virt_addr_sysm3 = sysmemmgr_translate(
+ platform_sm_heap_virt_addr_sysm3,
+ sysmemmgr_xltflag_kvirt2phys);
+ info.base = (void *) SHAREDMEMORY_SLV_VRT_BASEADDR_SYSM3;
+ nwrite = sysmgr_put_object_config(proc_id,
+ (void *) &info,
+ SYSMGR_CMD_SHAREDREGION_ENTRY_START +
+ SMHEAP_SRINDEX_SYSM3,
+ sizeof(struct sharedregion_info));
+ WARN_ON(nwrite != sizeof(struct sharedregion_info));
+
+ /* For AppM3 */
+ sharedregion_get_table_info(SMHEAP_SRINDEX_APPM3,
+ local_id,
+ &info);
+ platform_sm_heap_virt_addr_appm3 = sysmemmgr_translate(
+ platform_sm_heap_virt_addr_appm3,
+ sysmemmgr_xltflag_kvirt2phys);
+ info.base = (void *) SHAREDMEMORY_SLV_VRT_BASEADDR_APPM3;
+
+ /* Write info into the boot load page */
+ nwrite = sysmgr_put_object_config(proc_id,
+ (void *) &info,
+ SYSMGR_CMD_SHAREDREGION_ENTRY_START +
+ SMHEAP_SRINDEX_APPM3,
+ sizeof(struct sharedregion_info));
+ WARN_ON(nwrite != sizeof(struct sharedregion_info));
+
+ /* For SW DMM region */
+ sharedregion_get_table_info(SMHEAP_SRINDEX_SWDMM,
+ local_id,
+ &info);
+ info.base = (void *) SHAREDMEMORY_SWDMM_SLV_VRT_BASEADDR;
+
+ /* Write info into the boot load page */
+ nwrite = sysmgr_put_object_config(proc_id,
+ (void *) &info,
+ SYSMGR_CMD_SHAREDREGION_ENTRY_START +
+ SMHEAP_SRINDEX_SWDMM,
+ sizeof(struct sharedregion_info));
+ WARN_ON(nwrite != sizeof(struct sharedregion_info));
+ goto exit;
+
+proc_mgr_translate_addr_fail:
+ printk(KERN_ERR "platform_load_callback: proc_mgr_translate_addr failed"
+ " [0x%x] for proc_id [0x%x]\n",
+ status, proc_id);
+ goto exit;
+proc_invalid_id:
+ printk(KERN_ERR "platform_load_callback failed invalid proc_id [0x%x]\n",
+ proc_id);
+exit:
+ return;
+}
+EXPORT_SYMBOL(platform_load_callback);
+
+
+/*
+ * ======== platform_start_callback ========
+ * Purpose:
+ * Function called by proc_mgr when slave is in started state.
+ * FIXME: logic would change completely in the final system.
+ */
+void platform_start_callback(void *arg)
+{
+ s32 status = 0;
+ u16 local_id = MULTIPROC_INVALIDID;
+ u16 proc_id = (u32) arg;
+ u32 nread = 0;
+ u32 i = 0;
+ u32 cmd_id;
+ u32 sh_addr;
+ int index;
+
+ struct notify_ducatidrv_params notify_shm_params;
+ struct gatepeterson_params gate_params;
+ struct nameserver_remotenotify_params nsr_params;
+ struct heapbuf_params heap_params;
+ struct messageq_transportshm_params msgqt_params;
+ struct sharedregion_config sr_config;
+ struct sharedregion_info info;
+
+ struct platform_notify_ducatidrv_params pnds_params;
+ struct platform_heapbuf_params phb_params;
+ struct platform_gaterpeterson_params pgp_params;
+ struct platform_nameserver_remotenotify_params pnsrn_params;
+ struct platform_messageq_transportshm_params pmqt_params;
+ /*u32 proc_ids[2];*/
+
+ printk(KERN_ERR "platform_start_callback\n");
+ if (proc_id == multiproc_get_id("SysM3"))
+ index = SMHEAP_SRINDEX_SYSM3;
+ else if (proc_id == multiproc_get_id("AppM3"))
+ index = SMHEAP_SRINDEX_APPM3;
+ else {
+ status = SYSMGR_E_FAIL;
+ goto proc_invalid_id;
+ }
+ /* Wait for slave to write the scalability info */
+ sysmgr_wait_for_scalability_info(proc_id);
+ /* Read the scalability info */
+ do {
+ nread = sysmgr_get_object_config(proc_id, (void *) &pc_params,
+ SYSMGR_CMD_SCALABILITY,
+ sizeof(struct sysmgr_proc_config));
+ } while (nread != sizeof(struct sysmgr_proc_config));
+
+ if (status >= 0) {
+ local_id = multiproc_get_id(NULL);
+ status = multiproc_set_local_id(local_id);
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto multiproc_fail;
+ }
+ }
+
+ /* TODO: add condition: proc_id == multiproc_get_id("SysM3") */
+ if (pc_params.use_notify) {
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &pnds_params,
+ PLATFORM_CMD_NOTIFYDRIVER,
+ sizeof(struct \
+ platform_notify_ducatidrv_params));
+ } while (nread != \
+ sizeof(struct platform_notify_ducatidrv_params));
+
+ sh_addr = (u32)sharedregion_get_ptr((u32 *)
+ pnds_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ notify_ducatidrv_params_init(NULL, &notify_shm_params);
+ notify_shm_params.shared_addr = sh_addr;
+ notify_shm_params.shared_addr_size = \
+ pnds_params.shared_mem_size;
+ notify_shm_params.num_events = NOTIFY_MAX_EVENTS;
+ notify_shm_params.num_reserved_events = \
+ NOTIFY_NUMRESERVEDEVENTS;
+ notify_shm_params.send_event_poll_count = \
+ NOTIFY_SENDEVENTPOLLCOUNT;
+ notify_shm_params.recv_int_id = BASE_DUCATI2ARM_INTID;
+ notify_shm_params.send_int_id = BASE_ARM2DUCATI_INTID;
+ notify_shm_params.remote_proc_id = proc_id;
+ if (platform_notifydrv_handle == NULL) {
+ /* Create instance of Notify Ducati Driver */
+ platform_notifydrv_handle = notify_ducatidrv_create(
+ "NOTIFYDRIVER_DUCATI",
+ &notify_shm_params);
+ if (platform_notifydrv_handle == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto notify_ducatidrv_create_fail;
+ }
+ }
+
+ /* The notify is created only once and used for Sys and App */
+ if (index == SMHEAP_SRINDEX_APPM3)
+ platform_notifydrv_handle_appm3 =
+ platform_notifydrv_handle;
+ else
+ platform_notifydrv_handle_sysm3 =
+ platform_notifydrv_handle;
+ }
+ if (pc_params.use_nameserver) {
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &pgp_params,
+ PLATFORM_CMD_GPNSRN,
+ sizeof(struct \
+ platform_gaterpeterson_params));
+ } while (nread != sizeof(struct platform_gaterpeterson_params));
+ sh_addr = (u32)sharedregion_get_ptr((u32 *)
+ pgp_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ gatepeterson_params_init(NULL, &gate_params);
+ gate_params.shared_addr = (void *) sh_addr;
+ gate_params.shared_addr_size = pgp_params.shared_mem_size;
+ do {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_open(
+ &platform_nsrn_gate_handle_appm3,
+ &gate_params);
+ else
+ status = gatepeterson_open(
+ &platform_nsrn_gate_handle_sysm3,
+ &gate_params);
+ } while (status == -ENXIO);
+
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto gatepeterson_open_fail;
+ }
+
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &pnsrn_params,
+ PLATFORM_CMD_NSRN,
+ sizeof(struct \
+ platform_nameserver_remotenotify_params));
+ } while (nread != \
+ sizeof(struct
+ platform_nameserver_remotenotify_params));
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ pnsrn_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ /*
+ * Create the NameServerRemote implementation that is used to
+ * communicate with the remote processor. It uses some shared
+ * memory and the Notify module.
+ *
+ * Note that this implementation uses Notify to communicate, so
+ * interrupts need to be enabled.
+ */
+ nameserver_remotenotify_params_init(NULL, &nsr_params);
+ nsr_params.notify_driver = platform_notifydrv_handle;
+ /* Both are using same notify */
+ nsr_params.notify_event_no = pnsrn_params.notify_event_no;
+ nsr_params.shared_addr = (void *) sh_addr;
+ nsr_params.shared_addr_size = pnsrn_params.shared_mem_size;
+ if (index == SMHEAP_SRINDEX_APPM3) {
+ nsr_params.gate =
+ (void *) platform_nsrn_gate_handle_appm3;
+ platform_nsrn_handle_appm3 =
+ nameserver_remotenotify_create(
+ proc_id,
+ &nsr_params);
+ if (platform_nsrn_handle_appm3 == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto nameserver_remotenotify_create_fail;
+ }
+ } else {
+ nsr_params.gate =
+ (void *) platform_nsrn_gate_handle_sysm3;
+ platform_nsrn_handle_sysm3 =
+ nameserver_remotenotify_create(
+ proc_id,
+ &nsr_params);
+ if (platform_nsrn_handle_sysm3 == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto nameserver_remotenotify_create_fail;
+ }
+ }
+ }
+ if (pc_params.use_heapbuf) {
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &pgp_params,
+ PLATFORM_CMD_GPHEAPBUF,
+ sizeof(struct \
+ platform_gaterpeterson_params));
+ } while (nread != sizeof(struct
+ platform_gaterpeterson_params));
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ pgp_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ gatepeterson_params_init(NULL, &gate_params);
+ gate_params.shared_addr = (void *) sh_addr;
+ gate_params.shared_addr_size = pgp_params.shared_mem_size;
+ do {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_open(
+ &platform_heap_gate_handle_appm3,
+ &gate_params);
+ else
+ status = gatepeterson_open(
+ &platform_heap_gate_handle_sysm3,
+ &gate_params);
+ } while (status == -ENXIO);
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto gatepeterson_open_fail;
+ }
+
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &phb_params,
+ PLATFORM_CMD_HEAPBUF,
+ sizeof(struct platform_heapbuf_params));
+ } while (nread != sizeof(struct platform_heapbuf_params));
+ /* Create the heap. */
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ phb_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ heapbuf_params_init(NULL, &heap_params);
+ heap_params.shared_addr = (void *) sh_addr;
+ heap_params.align = HEAPBUF_ALIGN;
+ heap_params.num_blocks = phb_params.num_blocks;
+ heap_params.block_size = phb_params.block_size;
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ phb_params.shared_buf_size);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ heap_params.shared_buf_size = phb_params.shared_buf_size;
+ heap_params.shared_buf = (void *) sh_addr;
+ if (index == SMHEAP_SRINDEX_APPM3) {
+ heap_params.name = APPM3HEAPNAME;
+ heap_params.gate = platform_heap_gate_handle_appm3;
+ } else {
+ heap_params.name = SYSM3HEAPNAME;
+ heap_params.gate = platform_heap_gate_handle_sysm3;
+ }
+ heap_params.shared_addr_size = phb_params.shared_mem_size;
+ do {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = heapbuf_open(
+ &platform_heap_handle_appm3,
+ &heap_params);
+ else
+ status = heapbuf_open(
+ &platform_heap_handle_sysm3,
+ &heap_params);
+ } while (status == -ENXIO);
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto heapbuf_open_fail;
+ }
+ }
+ if (pc_params.use_messageq) {
+ do {
+ nread = sysmgr_get_object_config(proc_id, &pgp_params,
+ PLATFORM_CMD_GPMQT,
+ sizeof(struct \
+ platform_gaterpeterson_params));
+ } while (nread != sizeof(struct platform_gaterpeterson_params));
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ pgp_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ gatepeterson_params_init(NULL, &gate_params);
+ gate_params.shared_addr = (void *) sh_addr;
+ gate_params.shared_addr_size = pgp_params.shared_mem_size;
+ do {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_open(
+ &platform_mqt_gate_handle_appm3,
+ &gate_params);
+ else
+ status = gatepeterson_open(
+ &platform_mqt_gate_handle_sysm3,
+ &gate_params);
+ } while (status == -ENXIO);
+
+ if (status < 0) {
+ status = SYSMGR_E_FAIL;
+ goto gatepeterson_open_fail;
+ }
+
+ do {
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &pmqt_params,
+ PLATFORM_CMD_MQT,
+ sizeof(struct \
+ platform_messageq_transportshm_params));
+ } while (nread != sizeof(
+ struct platform_messageq_transportshm_params));
+ /* Register this heap with platform_messageq */
+ if (index == SMHEAP_SRINDEX_APPM3)
+ messageq_register_heap(platform_heap_handle_appm3,
+ APPM3HEAPID);
+ else
+ messageq_register_heap(platform_heap_handle_sysm3,
+ SYSM3HEAPID);
+ sh_addr = (u32) sharedregion_get_ptr((u32 *)
+ pmqt_params.shared_mem_addr);
+ if (sh_addr == (u32)NULL) {
+ status = SYSMGR_E_FAIL;
+ goto sharedregion_getptr_fail;
+ }
+ messageq_transportshm_params_init(NULL, &msgqt_params);
+ msgqt_params.shared_addr = (void *) sh_addr;
+ msgqt_params.notify_event_no = pmqt_params.notify_event_no;
+ msgqt_params.notify_driver = platform_notifydrv_handle;
+ msgqt_params.shared_addr_size = pmqt_params.shared_mem_size;
+ if (index == SMHEAP_SRINDEX_APPM3) {
+ msgqt_params.gate = platform_mqt_gate_handle_appm3;
+ platform_transport_shm_handle_appm3 =
+ messageq_transportshm_create(
+ proc_id,
+ &msgqt_params);
+ if (platform_transport_shm_handle_appm3 == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto messageq_transportshm_create_fail;
+ }
+ } else {
+ msgqt_params.gate = platform_mqt_gate_handle_sysm3;
+ platform_transport_shm_handle_sysm3 =
+ messageq_transportshm_create(
+ proc_id,
+ &msgqt_params);
+ if (platform_transport_shm_handle_sysm3 == NULL) {
+ status = SYSMGR_E_FAIL;
+ goto messageq_transportshm_create_fail;
+ }
+
+ }
+ }
+
+ if (status >= 0) {
+ /* Wait for slave to complete the setup */
+ sysmgr_wait_for_slave_setup(proc_id);
+
+ /* Now get the Shared region entries that may have been created
+ * by Slave, but actual physical memory is not assigned to
+ * those entries, only virtual DSP memory exists.
+ */
+ sharedregion_get_config(&sr_config);
+ for (i = 0; i < sr_config.max_regions; i++) {
+ cmd_id = SYSMGR_CMD_SHAREDREGION_ENTRY_START + i;
+ nread = sysmgr_get_object_config(proc_id,
+ (void *) &info, cmd_id,
+ sizeof(struct sharedregion_info));
+ if (nread == sizeof(struct sharedregion_info)) {
+ /* FIXME: Do the DMM and convert the entry into
+ * kernel virtual address and put it in the
+ * shared region for host */
+ }
+ }
+ }
+ goto exit;
+
+messageq_transportshm_create_fail:
+ printk(KERN_ERR "platform_start_callback: "
+ "messageq_transportshm_create failed status[0x%x]", status);
+ goto exit;
+heapbuf_open_fail:
+ printk(KERN_ERR "platform_start_callback: gatepeterson_open "
+ "failed status[0x%x]", status);
+ goto exit;
+nameserver_remotenotify_create_fail:
+ printk(KERN_ERR "platform_start_callback: "
+ "nameserver_remotenotify_create failed status[0x%x]", status);
+ goto exit;
+gatepeterson_open_fail:
+ printk(KERN_ERR "platform_start_callback: gatepeterson_open "
+ "failed status[0x%x]", status);
+ goto exit;
+notify_ducatidrv_create_fail:
+ printk(KERN_ERR "platform_start_callback: notify_ducatidrv_create "
+ "failed status[0x%x]", status);
+ goto exit;
+sharedregion_getptr_fail:
+ printk(KERN_ERR "platform_start_callback: sharedregion_get_ptr failed"
+ " status[0x%x]", status);
+ goto exit;
+multiproc_fail:
+ printk(KERN_ERR "platform_start_callback: multiproc_set_local_id failed"
+ " status[0x%x]", status);
+proc_invalid_id:
+ printk(KERN_ERR "platform_load_callback failed invalid"
+ " proc_id [0x%x]\n", proc_id);
+exit:
+ return;
+}
+EXPORT_SYMBOL(platform_start_callback);
+/* FIXME: since application has to call this API for now */
+
+
+/*
+ * ======== platform_stop_callback ========
+ * Purpose:
+ * Function called by proc_mgr when slave is in stopped state.
+ * FIXME: logic would change completely in the final system.
+ */
+void platform_stop_callback(void *arg)
+{
+ s32 status = 0;
+ u16 proc_id = (u32) arg;
+ int index = 0;
+ u32 nread = 0;
+
+ if (proc_id == multiproc_get_id("SysM3"))
+ index = SMHEAP_SRINDEX_SYSM3;
+ else if (proc_id == multiproc_get_id("AppM3"))
+ index = SMHEAP_SRINDEX_APPM3;
+ else {
+ status = SYSMGR_E_FAIL;
+ goto proc_invalid_id;
+ }
+
+ /* Read the scalability info */
+ do {
+ nread = sysmgr_get_object_config(proc_id, (void *) &pc_params,
+ SYSMGR_CMD_SCALABILITY,
+ sizeof(struct sysmgr_proc_config));
+ } while (nread != sizeof(struct sysmgr_proc_config));
+
+ if (pc_params.use_messageq) {
+ /* Finalize drivers */
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_close(
+ &platform_mqt_gate_handle_appm3);
+ else
+ status = gatepeterson_close(
+ &platform_mqt_gate_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : mqt "
+ "gatepeterson_close failed [0x%x]", status);
+ }
+
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = messageq_transportshm_delete(
+ &platform_transport_shm_handle_appm3);
+ else
+ status = messageq_transportshm_delete(
+ &platform_transport_shm_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "messageq_transportshm_delete failed [0x%x]",
+ status);
+ }
+ }
+
+ if (pc_params.use_nameserver) {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_close(
+ &platform_nsrn_gate_handle_appm3);
+ else
+ status = gatepeterson_close(
+ &platform_nsrn_gate_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : nsrn"
+ "gatepeterson_close failed [0x%x]", status);
+ }
+
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = nameserver_remotenotify_delete(
+ &platform_nsrn_handle_appm3);
+ else
+ status = nameserver_remotenotify_delete(
+ &platform_nsrn_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "nameserver_remotenotify_delete failed [0x%x]",
+ status);
+ }
+ }
+
+ if (pc_params.use_heapbuf) {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = messageq_unregister_heap(APPM3HEAPID);
+ else
+ status = messageq_unregister_heap(SYSM3HEAPID);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "messageq_unregister_heap failed [0x%x]",
+ status);
+ }
+
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = heapbuf_close(platform_heap_handle_appm3);
+ else
+ status = heapbuf_close(platform_heap_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "heapbuf_close failed [0x%x]", status);
+ }
+ if (index == SMHEAP_SRINDEX_APPM3)
+ status = gatepeterson_close(
+ &platform_heap_gate_handle_appm3);
+ else
+ status = gatepeterson_close(
+ &platform_heap_gate_handle_sysm3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : heap"
+ "gatepeterson_close failed [0x%x]", status);
+ }
+
+ }
+
+ if (pc_params.use_notify) {
+ if (index == SMHEAP_SRINDEX_APPM3)
+ platform_notifydrv_handle_appm3 = NULL;
+ else
+ platform_notifydrv_handle_sysm3 = NULL;
+
+ if (platform_notifydrv_handle_sysm3 == NULL &&
+ platform_notifydrv_handle_appm3 == NULL) {
+ status = notify_ducatidrv_delete(
+ (struct notify_driver_object **)
+ &platform_notifydrv_handle);
+ platform_notifydrv_handle = NULL;
+ }
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "notify_ducatidrv_delete failed [0x%x]",
+ status);
+ }
+ }
+
+ status = sharedregion_remove(SMHEAP_SRINDEX_APPM3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "sharedregion_remove failed [0x%x]", status);
+ }
+
+ status = sharedregion_remove(SMHEAP_SRINDEX_SYSM3);
+ if (status < 0) {
+ printk(KERN_ERR "platform_stop_callback : "
+ "sharedregion_remove failed [0x%x]", status);
+ }
+
+ goto exit;
+
+proc_invalid_id:
+ printk(KERN_ERR "platform_load_callback failed invalid"
+ " proc_id [0x%x]\n", proc_id);
+exit:
+ return;
+}
+EXPORT_SYMBOL(platform_stop_callback);
+/* FIXME: since application has to call this API for now */
diff --git a/drivers/dsp/syslink/multicore_ipc/platform_mem.c b/drivers/dsp/syslink/multicore_ipc/platform_mem.c
new file mode 100644
index 000000000000..025605b8295c
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/platform_mem.c
@@ -0,0 +1,288 @@
+/*
+ * platform_mem.c
+ *
+ * Target memory management interface implementation.
+ *
+ * This abstracts the Memory management interface in the kernel
+ * code. Allocation, Freeing-up, copy and address translate are
+ * supported for the kernel memory management.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Linux specific header files */
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <platform_mem.h>
+#include <atomic_linux.h>
+
+/* Macro to make a correct module magic number with ref_count */
+#define PLATFORM_MEM_MAKE_MAGICSTAMP(x) ((PLATFORM_MEM_MODULEID << 12u) | (x))
+
+/*
+ * Structure for containing
+ */
+struct platform_mem_map_table_info {
+ struct list_head mem_entry; /* Pointer to mem_entry entry */
+ u32 physical_address; /* Actual address */
+ u32 knl_virtual_address; /* Mapped address */
+ u32 size; /* Size of the region mapped */
+};
+
+/*
+ * Structure defining state object of system memory manager
+ */
+struct platform_mem_module_object {
+ atomic_t ref_count; /* Reference count */
+ struct list_head map_table; /* Head of map table */
+ struct mutex *gate; /* Pointer to lock */
+};
+
+
+/*
+ * Object containing state of the platform mem module
+ */
+static struct platform_mem_module_object platform_mem_state;
+
+/*
+ * ======== platform_mem_setup ========
+ * Purpose:
+ * This will initialize the platform mem module.
+ */
+int platform_mem_setup(void)
+{
+ s32 retval = 0;
+
+ atomic_cmpmask_and_set(&platform_mem_state.ref_count,
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0));
+ if (atomic_inc_return(&platform_mem_state.ref_count)
+ != PLATFORM_MEM_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ /* Create the Gate handle */
+ platform_mem_state.gate =
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (platform_mem_state.gate == NULL) {
+ retval = -ENOMEM;
+ goto gate_create_fail;
+ }
+
+ /* Construct the map table */
+ INIT_LIST_HEAD(&platform_mem_state.map_table);
+ mutex_init(platform_mem_state.gate);
+ goto exit;
+
+gate_create_fail:
+ atomic_set(&platform_mem_state.ref_count,
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0));
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(platform_mem_setup);
+
+/*
+ * ======== platform_mem_destroy ========
+ * Purpose:
+ * This will finalize the platform mem module.
+ */
+int platform_mem_destroy(void)
+{
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (atomic_dec_return(&platform_mem_state.ref_count)
+ == PLATFORM_MEM_MAKE_MAGICSTAMP(0)) {
+ list_del(&platform_mem_state.map_table);
+ /* Delete the gate handle */
+ kfree(platform_mem_state.gate);
+ }
+
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(platform_mem_destroy);
+
+/*
+ * ======== platform_mem_map ========
+ * Purpose:
+ * This will maps a memory area into virtual space.
+ */
+int platform_mem_map(memory_map_info *map_info)
+{
+ int retval = 0;
+ struct platform_mem_map_table_info *info = NULL;
+
+ if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (WARN_ON(map_info == NULL)) {
+ retval = -EINVAL;
+ goto exit;
+
+ }
+
+ if (map_info->src == (u32) NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ info = kmalloc(sizeof(struct platform_mem_map_table_info),
+ GFP_KERNEL);
+ if (info == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(platform_mem_state.gate);
+ if (retval)
+ goto lock_fail;
+
+ map_info->dst = 0;
+ if (map_info->is_cached == true)
+ map_info->dst = (u32) ioremap((dma_addr_t)
+ (map_info->src), map_info->size);
+ else
+ map_info->dst = (u32) ioremap_nocache((dma_addr_t)
+ (map_info->src), map_info->size);
+
+ if (map_info->dst == 0) {
+ retval = -EFAULT;
+ goto ioremap_fail;
+ }
+
+ /* Populate the info */
+ info->physical_address = map_info->src;
+ info->knl_virtual_address = map_info->dst;
+ info->size = map_info->size;
+ /* Put the info into the list */
+ list_add(&info->mem_entry, &platform_mem_state.map_table);
+ mutex_unlock(platform_mem_state.gate);
+ goto exit;
+
+ioremap_fail:
+ mutex_unlock(platform_mem_state.gate);
+lock_fail:
+ kfree(info);
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(platform_mem_map);
+
+/*
+ * ======== platform_mem_unmap ========
+ * Purpose:
+ * This will unmaps a memory area into virtual space.
+ */
+int platform_mem_unmap(memory_unmap_info *unmap_info)
+{
+ s32 retval = 0;
+ struct platform_mem_map_table_info *info = NULL;
+
+
+ if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (unmap_info == NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (unmap_info->addr == (u32) NULL) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(platform_mem_state.gate);
+ if (retval)
+ goto exit;
+
+ iounmap((unsigned int *) unmap_info->addr);
+ /* Delete the node in the map table */
+ list_for_each_entry(info, &platform_mem_state.map_table, mem_entry) {
+ if (info->knl_virtual_address == unmap_info->addr) {
+ list_del(&info->mem_entry);
+ kfree(info);
+ break;
+ }
+ }
+ mutex_unlock(platform_mem_state.gate);
+
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(platform_mem_unmap);
+
+/*
+ * ======== platform_mem_map ========
+ * Purpose:
+ * This will translate an address.
+ */
+void *platform_mem_translate(void *src_addr, enum memory_xlt_flags flags)
+{
+ void *buf = NULL;
+ struct platform_mem_map_table_info *tinfo = NULL;
+ u32 frm_addr;
+ u32 to_addr;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(0),
+ PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ retval = mutex_lock_interruptible(platform_mem_state.gate);
+ if (retval)
+ goto exit;
+
+ /* Traverse to the node in the map table */
+ list_for_each_entry(tinfo, &platform_mem_state.map_table, mem_entry) {
+ frm_addr = (flags == PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS) ?
+ tinfo->knl_virtual_address : tinfo->physical_address;
+ to_addr = (flags == PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS) ?
+ tinfo->physical_address : tinfo->knl_virtual_address;
+ if ((((u32) src_addr) >= frm_addr)
+ && (((u32) src_addr) < (frm_addr + tinfo->size))) {
+ buf = (void *) (to_addr + ((u32)src_addr - frm_addr));
+ break;
+ }
+ }
+ mutex_unlock(platform_mem_state.gate);
+
+exit:
+ return buf;
+}
+EXPORT_SYMBOL(platform_mem_translate);
+
diff --git a/drivers/dsp/syslink/multicore_ipc/platformcfg.c b/drivers/dsp/syslink/multicore_ipc/platformcfg.c
new file mode 100755
index 000000000000..360b275f0f43
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/platformcfg.c
@@ -0,0 +1,91 @@
+/*
+ * platformcfg.c
+ *
+ * Implementation of platform specific configuration for Syslink.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Utilities headers */
+#include <linux/string.h>
+
+
+/* Module headers */
+#include <sysmgr.h>
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+/*
+ * ======== platform_override_config ========
+ * Purpose:
+ * Function to override the default confiuration values.
+ */
+int platform_override_config(struct sysmgr_config *config)
+{
+ int status = 0;
+
+ if (WARN_ON(config == NULL)) {
+ status = -EINVAL;
+ goto failure;
+ }
+
+ /* Override the multiproc default config */
+ config->multiproc_cfg.max_processors = 4;
+ config->multiproc_cfg.id = 0;
+ strcpy(config->multiproc_cfg.name_list[0], "MPU");
+ strcpy(config->multiproc_cfg.name_list[1], "Tesla");
+ strcpy(config->multiproc_cfg.name_list[2], "SysM3");
+ strcpy(config->multiproc_cfg.name_list[3], "AppM3");
+
+ /* Override the gatepeterson default config */
+
+ /* Override the sharedregion default config */
+ config->sharedregion_cfg.gate_handle = NULL;
+ config->sharedregion_cfg.heap_handle = NULL;
+ config->sharedregion_cfg.max_regions = 4;
+
+ /* Override the listmp default config */
+
+ /* Override the messageq default config */
+ /* We use 2 heaps, 1 for APPM3 and 1 for SYSM3 */
+ /* FIXME: Temporary Fix - Add one more for the SW DMM heap */
+ if (config->messageq_cfg.num_heaps < 3)
+ config->messageq_cfg.num_heaps = 3;
+
+ /* Override the notify default config */
+ config->notify_cfg.maxDrivers = 2;
+
+ /* Override the procmgr default config */
+
+ /* Override the heapbuf default config */
+
+ /* Override the listmp_sharedmemory default config */
+
+ /* Override the messageq_transportshm default config */
+
+ /* Override the notify ducati driver default config */
+
+ /* Override the nameserver remotenotify default config */
+ goto success;
+
+failure:
+ printk(KERN_ERR "platform_override_config failed [0x%x]", status);
+success:
+ return status;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/sharedregion.c b/drivers/dsp/syslink/multicore_ipc/sharedregion.c
new file mode 100755
index 000000000000..c5ad146d4da7
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sharedregion.c
@@ -0,0 +1,775 @@
+/*
+ * sharedregion.c
+ *
+ * The SharedRegion module is designed to be used in a
+ * multi-processor environment where there are memory regions
+ * that are shared and accessed across different processors
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <syslink/atomic_linux.h>
+
+#include <multiproc.h>
+#include <nameserver.h>
+#include <sharedregion.h>
+
+/* Macro to make a correct module magic number with refCount */
+#define SHAREDREGION_MAKE_MAGICSTAMP(x) ((SHAREDREGION_MODULEID << 16u) | (x))
+
+#define SHAREDREGION_MAX_REGIONS_DEFAULT 4
+
+/*
+ * Module state object
+ */
+struct sharedregion_module_object {
+ atomic_t ref_count; /* Reference count */
+ struct mutex *gate_handle;
+ struct sharedregion_info *table; /* Ptr to the table */
+ u32 bitOffset; /* Index bit offset */
+ u32 region_size; /* Max size of each region */
+ struct sharedregion_config cfg; /* Current config values */
+};
+
+/*
+ * Shared region state object variable with default settings
+ */
+static struct sharedregion_module_object sharedregion_state = {
+ .cfg.heap_handle = NULL,
+ .cfg.gate_handle = NULL,
+ .cfg.max_regions = SHAREDREGION_MAX_REGIONS_DEFAULT
+};
+
+/*
+ * ======== sharedregion_get_config ========
+ * Purpose:
+ * This will get sharedregion module configiguration
+ */
+int sharedregion_get_config(struct sharedregion_config *config)
+{
+ BUG_ON((config == NULL));
+ memcpy(config, &sharedregion_state.cfg,
+ sizeof(struct sharedregion_config));
+ return 0;
+}
+EXPORT_SYMBOL(sharedregion_get_config);
+
+
+/*
+ * ======== sharedregion_get_bitoffset ========
+ * Purpose:
+ * This will get get the bit offset
+ */
+static u32 sharedregion_get_bitoffset(u32 max_regions)
+{
+ u32 i;
+ u32 bitoffset = 0;
+ for (i = ((sizeof(void *) * 8) - 1); i >= 0; i--) {
+ if (max_regions > (1 << i))
+ break;
+ }
+
+ bitoffset = (((sizeof(void *) * 8) - 1) - i);
+ return bitoffset;
+}
+
+/*
+ * ======== sharedregion_setup ========
+ * Purpose:
+ * This will get setup the sharedregion module
+ */
+int sharedregion_setup(const struct sharedregion_config *config)
+{
+ struct sharedregion_config *tmpcfg = &sharedregion_state.cfg;
+ struct sharedregion_info *table = NULL;
+ u32 i;
+ u32 j;
+ s32 retval = 0;
+ u16 proc_count;
+
+ /* This sets the refCount variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable
+ */
+ atomic_cmpmask_and_set(&sharedregion_state.ref_count,
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&sharedregion_state.ref_count)
+ != SHAREDREGION_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (config != NULL) {
+ if (WARN_ON(config->max_regions == 0)) {
+ retval = -EINVAL;
+ goto error;
+ }
+ memcpy(&sharedregion_state.cfg, config,
+ sizeof(struct sharedregion_config));
+ }
+
+ sharedregion_state.gate_handle = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+ if (sharedregion_state.gate_handle == NULL)
+ goto gate_create_fail;
+
+ sharedregion_state.bitOffset =
+ sharedregion_get_bitoffset(tmpcfg->max_regions);
+ sharedregion_state.region_size = (1 << sharedregion_state.bitOffset);
+ proc_count = multiproc_get_max_processors();
+ /* TODO check heap usage & + 1 ? */
+ sharedregion_state.table = kmalloc(sizeof(struct sharedregion_info) *
+ tmpcfg->max_regions * (proc_count + 1),
+ GFP_KERNEL);
+ if (sharedregion_state.table == NULL) {
+ retval = -ENOMEM;
+ goto table_alloc_fail;
+ }
+
+ table = sharedregion_state.table;
+ for (i = 0; i < tmpcfg->max_regions; i++) {
+ for (j = 0; j < (proc_count + 1); j++) {
+ (table + (j * tmpcfg->max_regions) + i)->is_valid =
+ false;
+ (table + (j * tmpcfg->max_regions) + i)->base = 0;
+ (table + (j * tmpcfg->max_regions) + i)->len = 0;
+ }
+ }
+
+ mutex_init(sharedregion_state.gate_handle);
+ return 0;
+
+table_alloc_fail:
+ kfree(sharedregion_state.gate_handle);
+
+gate_create_fail:
+ memset(&sharedregion_state, 0,
+ sizeof(struct sharedregion_module_object));
+ sharedregion_state.cfg.max_regions = SHAREDREGION_MAX_REGIONS_DEFAULT;
+
+error:
+ printk(KERN_ERR "sharedregion_setup failed status:%x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_setup);
+
+/*
+ * ======== sharedregion_destroy ========
+ * Purpose:
+ * This will get destroy the sharedregion module
+ */
+int sharedregion_destroy(void)
+{
+ s32 retval = 0;
+ void *gate_handle = NULL;
+
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (!(atomic_dec_return(&sharedregion_state.ref_count)
+ == SHAREDREGION_MAKE_MAGICSTAMP(0))) {
+ retval = 1; /* Syslink is not handling this on 2.0.0.06 */
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval)
+ goto error;
+
+ kfree(sharedregion_state.table);
+ gate_handle = sharedregion_state.gate_handle; /* backup gate handle */
+ memset(&sharedregion_state, 0,
+ sizeof(struct sharedregion_module_object));
+ sharedregion_state.cfg.max_regions = SHAREDREGION_MAX_REGIONS_DEFAULT;
+ mutex_unlock(gate_handle);
+ kfree(gate_handle);
+ return 0;
+
+error:
+ if (retval < 0) {
+ printk(KERN_ERR "sharedregion_destroy failed status:%x\n",
+ retval);
+ }
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_destroy);
+
+/*
+ * ======== sharedregion_add ========
+ * Purpose:
+ * This will add a memory segment to the lookup table
+ * during runtime by base and length
+ */
+int sharedregion_add(u32 index, void *base, u32 len)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ s32 retval = 0;
+ u32 i;
+ u16 myproc_id;
+ bool overlap = false;
+ bool same = false;
+
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (index >= sharedregion_state.cfg.max_regions ||
+ sharedregion_state.region_size < len) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ myproc_id = multiproc_get_id(NULL);
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval)
+ goto error;
+
+
+ table = sharedregion_state.table;
+ /* Check for overlap */
+ for (i = 0; i < sharedregion_state.cfg.max_regions; i++) {
+ entry = (table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + i);
+ if (entry->is_valid) {
+ /* Handle duplicate entry */
+ if ((base == entry->base) && (len == entry->len)) {
+ same = true;
+ break;
+ }
+
+ if ((base >= entry->base) &&
+ (base < (void *)((u32)entry->base + entry->len))) {
+ overlap = true;
+ break;
+ }
+
+ if ((base < entry->base) &&
+ (void *)((u32)base + len) >= entry->base) {
+ overlap = true;
+ break;
+ }
+ }
+ }
+
+ if (same) {
+ retval = 1;
+ goto success;
+ }
+
+ if (overlap) {
+ /* FHACK: FIX ME */
+ retval = 1;
+ goto mem_overlap_error;
+ }
+
+ entry = (table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + index);
+ if (entry->is_valid == false) {
+ entry->base = base;
+ entry->len = len;
+ entry->is_valid = true;
+
+ } else {
+ /* FHACK: FIX ME */
+ retval = 1;
+ goto dup_entry_error;
+ }
+
+success:
+ mutex_unlock(sharedregion_state.gate_handle);
+ return 0;
+
+dup_entry_error: /* Fall through */
+mem_overlap_error:
+ printk(KERN_WARNING "sharedregion_add entry exists status: %x\n",
+ retval);
+ mutex_unlock(sharedregion_state.gate_handle);
+
+error:
+ if (retval < 0)
+ printk(KERN_ERR "sharedregion_add failed status:%x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_add);
+
+/*
+ * ======== sharedregion_remove ========
+ * Purpose:
+ * This will removes a memory segment to the lookup table
+ * during runtime by base and length
+ */
+int sharedregion_remove(u32 index)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ u16 myproc_id;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (index >= sharedregion_state.cfg.max_regions) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval)
+ goto error;
+
+ myproc_id = multiproc_get_id(NULL);
+ table = sharedregion_state.table;
+ entry = (table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + index);
+ entry->is_valid = false;
+ entry->base = NULL;
+ entry->len = 0;
+ mutex_unlock(sharedregion_state.gate_handle);
+ return 0;
+
+error:
+ printk(KERN_ERR "sharedregion_remove failed status:%x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_remove);
+
+/*
+ * ======== sharedregion_get_index ========
+ * Purpose:
+ * This will return the index for the specified address pointer.
+ */
+int sharedregion_get_index(void *addr)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ bool found = false;
+ u32 i;
+ u16 myproc_id;
+ s32 retval = 0;
+
+ if (WARN_ON(atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true)) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ myproc_id = multiproc_get_id(NULL);
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ table = sharedregion_state.table;
+ for (i = 0; i < sharedregion_state.cfg.max_regions; i++) {
+ entry = (table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + i);
+ if ((addr >= entry->base) &&
+ (addr < (void *)((u32)entry->base + (entry->len)))) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ retval = i;
+ else
+ retval = -ENOENT; /* No entry found in the table */
+
+ mutex_unlock(sharedregion_state.gate_handle);
+ return retval;
+
+exit:
+ printk(KERN_ERR "sharedregion_get_index failed index:%x\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_get_index);
+
+/*
+ * ======== sharedregion_get_ptr ========
+ * Purpose:
+ * This will return the address pointer associated with the
+ * shared region pointer
+ */
+void *sharedregion_get_ptr(u32 *srptr)
+{
+ struct sharedregion_info *entry = NULL;
+ void *ptr = NULL;
+ u16 myproc_id;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (srptr == SHAREDREGION_INVALIDSRPTR)
+ goto error;
+
+ myproc_id = multiproc_get_id(NULL);
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (WARN_ON(retval != 0))
+ goto error;
+
+ entry = (sharedregion_state.table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + ((u32)srptr >> sharedregion_state.bitOffset));
+ /* TO DO check:: is this correct ? */
+ ptr = ((void *)(((u32)srptr &
+ ((1 << sharedregion_state.bitOffset) - 1)) + (u32)entry->base));
+ mutex_unlock(sharedregion_state.gate_handle);
+ return ptr;
+
+error:
+ printk(KERN_ERR "sharedregion_get_ptr failed \n");
+ return (void *)NULL;
+
+}
+EXPORT_SYMBOL(sharedregion_get_ptr);
+
+/*
+ * ======== sharedregion_get_srptr ========
+ * Purpose:
+ * This will return sharedregion pointer associated with the
+ * an address in a shared region area registered with the
+ * sharedregion module
+ */
+u32 *sharedregion_get_srptr(void *addr, s32 index)
+{
+ struct sharedregion_info *entry = NULL;
+ u32 *ptr = SHAREDREGION_INVALIDSRPTR ;
+ u32 myproc_id;
+ s32 retval = 0;
+
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ if (WARN_ON(addr == NULL))
+ goto error;
+
+ if (WARN_ON(index >= sharedregion_state.cfg.max_regions))
+ goto error;
+
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (WARN_ON(retval != 0))
+ goto error;
+
+ myproc_id = multiproc_get_id(NULL);
+ entry = (sharedregion_state.table
+ + (myproc_id * sharedregion_state.cfg.max_regions)
+ + index);
+ ptr = (u32 *) ((index << sharedregion_state.bitOffset)
+ | ((u32)addr - (u32)entry->base));
+ mutex_unlock(sharedregion_state.gate_handle);
+ return ptr;
+
+error:
+ printk(KERN_ERR "sharedregion_get_srptr failed\n");
+ return (u32 *)NULL;
+}
+EXPORT_SYMBOL(sharedregion_get_srptr);
+
+/*
+ * ======== sharedregion_get_table_info ========
+ * Purpose:
+ * This will get the table entry information for the
+ * specified index and id
+ */
+int sharedregion_get_table_info(u32 index, u16 proc_id,
+ struct sharedregion_info *info)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ u16 proc_count;
+ s32 retval = 0;
+
+ BUG_ON(info == NULL);
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ proc_count = multiproc_get_max_processors();
+ if (index >= sharedregion_state.cfg.max_regions ||
+ proc_id >= proc_count) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval)
+ goto error;
+
+ table = sharedregion_state.table;
+ entry = (table
+ + (proc_id * sharedregion_state.cfg.max_regions)
+ + index);
+ memcpy((void *) info, (void *) entry, sizeof(struct sharedregion_info));
+ mutex_unlock(sharedregion_state.gate_handle);
+ return 0;
+
+error:
+ printk(KERN_ERR "sharedregion_get_table_info failed status:%x\n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_get_table_info);
+
+/*
+ * ======== sharedregion_set_table_info ========
+ * Purpose:
+ * This will set the table entry information for the
+ * specified index and id
+ */
+int sharedregion_set_table_info(u32 index, u16 proc_id,
+ struct sharedregion_info *info)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ u16 proc_count;
+ s32 retval = 0;
+
+ BUG_ON(info != NULL);
+ if (atomic_cmpmask_and_lt(&(sharedregion_state.ref_count),
+ SHAREDREGION_MAKE_MAGICSTAMP(0),
+ SHAREDREGION_MAKE_MAGICSTAMP(1)) == true) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ proc_count = multiproc_get_max_processors();
+ if (index >= sharedregion_state.cfg.max_regions ||
+ proc_id >= proc_count) {
+ retval = -EINVAL;
+ goto error;
+ }
+
+ retval = mutex_lock_interruptible(sharedregion_state.gate_handle);
+ if (retval)
+ goto error;
+
+ table = sharedregion_state.table;
+ entry = (table
+ + (proc_id * sharedregion_state.cfg.max_regions)
+ + index);
+ memcpy((void *) entry, (void *) info, sizeof(struct sharedregion_info));
+ mutex_unlock(sharedregion_state.gate_handle);
+ return 0;
+
+error:
+ printk(KERN_ERR "sharedregion_set_table_info failed status:%x\n",
+ retval);
+ return retval;
+}
+EXPORT_SYMBOL(sharedregion_set_table_info);
+
+/*
+ * ======== Sharedregion_attach ========
+ * Purpose:
+ * This will attachs the shared region with an proc_id
+ *
+ * Application should call this function from the callback
+ * function registered for device attach to the processor
+ * manager. All modules which requires some logic setup
+ * to be done when a device gets attach to the system,
+ * should export API like this. Please see the below psuedo
+ * code for example:
+ * Example
+ * code
+ * void function (proc_id, config) {
+ * NotifyDriver_attach (proc_id, config->ndParams);
+ * SysMemMgr_attach (proc_id);
+ * SMM_attach (proc_id);
+ * NameServerRemoteTransport_attach(proc_id, config->nsrtParams);
+ * SharedRegion_attach (proc_id);
+ * SharedMemory_getConfig (&cfg);
+ * for (i = 0u; i < cfg->maxRegions; i++) {
+ * SharedRegion_getTableInfo(i, &myinfo, myProcId);
+ * SharedRegion_getTableInfo(i, &peerinfo, proc_id);
+ * DMM_map (proc_id,
+ * PA(myinfo->vaddr),
+ * peerinfo->vaddr,
+ * myinfo->len);
+ * }
+ * ...
+ * }
+ *
+ * main () {
+ * # attach callback for device attach only
+ * ProcMgr_register (function, proc_id, DEV_ATTACH);
+ * }
+ *
+ */
+void sharedregion_attach(u16 proc_id)
+{
+ struct sharedregion_info *entry = NULL;
+ struct sharedregion_info *table = NULL;
+ char *hexstr = "0123456789ABCDEF";
+ char tname[80];
+ u16 proc_id_list[2];
+ u32 addr = 0;
+ u32 len;
+ u16 proc_count;
+ void *nshandle;
+ s32 retval = 0;
+ s32 i;
+
+ if (WARN_ON(sharedregion_state.table == NULL))
+ goto error;
+
+ proc_count = multiproc_get_max_processors();
+ if (WARN_ON(proc_id >= proc_count))
+ goto error;
+
+ proc_id_list[0] = proc_id;
+ proc_id_list[1] = MULTIPROC_INVALIDID;
+ nshandle = nameserver_get_handle(SHAREDREGION_NAMESERVER);
+ if (nshandle == NULL)
+ goto error;
+
+ /* Get Shared region entries from the remote shared region nameserver */
+ for (i = 0u; i < sharedregion_state.cfg.max_regions; i++) {
+ memset(tname, 0, 80);
+ strcpy(tname, "SHAREDREGION:SRENTRY_ADDR_");
+ tname[strlen(tname)] = hexstr[(proc_id >> 4u) & 0xF];
+ tname[strlen(tname)] = hexstr[proc_id & 0xF];
+ tname[strlen(tname)] = '_';
+ tname[strlen(tname)] = hexstr[(i >> 28u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 24u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 20u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 16u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 12u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 8u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 4u) & 0xF];
+ tname[strlen(tname)] = hexstr[i & 0xF];
+ retval = nameserver_get(nshandle, tname,
+ &len, sizeof(u32), &proc_id_list[0]);
+ if (WARN_ON(retval))
+ ;
+
+ memset(tname, 0, 80u);
+ strcpy(tname, "SHAREDREGION:SRENTRY_LEN_");
+ tname[strlen(tname)] = hexstr[(proc_id >> 4u) & 0xF];
+ tname[strlen(tname)] = hexstr[proc_id & 0xF];
+ tname[strlen(tname)] = '_';
+ tname[strlen(tname)] = hexstr[(i >> 28u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 24u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 20u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 16u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 12u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 8u) & 0xF];
+ tname[strlen(tname)] = hexstr[(i >> 4u) & 0xF];
+ tname[strlen(tname)] = hexstr[i & 0xF];
+
+ /* TO DO : check this */
+ retval = nameserver_get(nshandle, tname,
+ &len, sizeof(u32), &proc_id_list[0]);
+ if (WARN_ON(retval))
+ ;
+
+ /* Found an entry in the remote nameserver */
+ /* Add it into the shared region table */
+ if (retval == 0) {
+ retval = mutex_lock_interruptible(
+ sharedregion_state.gate_handle);
+ if (WARN_ON(retval))
+ break;
+
+ table = sharedregion_state.table;
+ /* mark entry invalid */
+ entry = (table
+ + (proc_id * sharedregion_state.cfg.max_regions)
+ + i);
+ entry->base = (void *)addr;
+ entry->len = len;
+ entry->is_valid = false;
+ mutex_unlock(sharedregion_state.gate_handle);
+ }
+
+ }
+
+error:
+ return;
+}
+EXPORT_SYMBOL(sharedregion_attach);
+
+/*
+ * ======== Sharedregion_detach ========
+ * Purpose:
+ * This will detachs the shared region for an proc_id
+ *
+ * Application should call this function from the callback
+ * function registered for device detach to the processorl
+ * manager. All modules which requires some logic setup
+ * to be done when a device gets detach from the system,
+ * should export API like this.
+ * Please see the below psuedo code for example:
+ * @Example
+ * @code
+ * void function (proc_id) {
+ * SharedRegion_detach (proc_id);
+ * SysMemMgr_detach (proc_id);
+ * ...
+ * # Name server must be detached last
+ * nameserver_detach (proc_id);
+ * }
+ *
+ * main () {
+ * # attach callback for device detach only
+ * Processor_register (function, proc_id, DEV_DETACH);
+ * }
+ *
+ */
+void sharedregion_detach(u16 proc_id)
+{
+ u16 proc_count;
+
+ if (WARN_ON(sharedregion_state.table == NULL))
+ goto error;
+
+ proc_count = multiproc_get_max_processors();
+ if (WARN_ON(proc_id >= proc_count))
+ goto error;
+
+error:
+ return;
+}
+EXPORT_SYMBOL(sharedregion_detach);
+
diff --git a/drivers/dsp/syslink/multicore_ipc/sharedregion_ioctl.c b/drivers/dsp/syslink/multicore_ipc/sharedregion_ioctl.c
new file mode 100755
index 000000000000..aee1aaea4c8e
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sharedregion_ioctl.c
@@ -0,0 +1,349 @@
+/*
+ * sharedregion_ioctl.c
+ *
+ * The sharedregion module is designed to be used in a
+ * multi-processor environment where there are memory regions
+ * that are shared and accessed across different processors
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+
+#include <multiproc.h>
+#include <sharedregion.h>
+#include <sharedregion_ioctl.h>
+#include <platform_mem.h>
+
+/*
+ * ======== sharedregion_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to sharedregion_get_config function
+ */
+static int sharedregion_ioctl_get_config(struct sharedregion_cmd_args *cargs)
+{
+
+ struct sharedregion_config config;
+ s32 status = 0;
+ s32 size;
+
+ cargs->api_status = sharedregion_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct sharedregion_config));
+ if (size)
+ status = -EFAULT;
+
+ return status;
+}
+
+
+/*
+ * ======== sharedregion_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to sharedregion_setup function
+ */
+static int sharedregion_ioctl_setup(struct sharedregion_cmd_args *cargs)
+{
+ struct sharedregion_config config;
+ struct sharedregion_config defaultcfg;
+ struct sharedregion_info info;
+ struct sharedregion_info *table;
+ u32 proc_count = 0;
+ u32 i;
+ u32 j;
+ s32 status = 0;
+ s32 size;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct sharedregion_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = sharedregion_setup(&config);
+ if (cargs->api_status != 0)
+ goto exit;
+
+ cargs->api_status = sharedregion_get_config(&defaultcfg);
+ size = copy_to_user(cargs->args.setup.default_cfg,
+ &defaultcfg,
+ sizeof(struct sharedregion_config));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ proc_count = multiproc_get_max_processors();
+ table = cargs->args.setup.table;
+ for (i = 0; i < config.max_regions; i++) {
+ for (j = 0; j < (proc_count); j++) {
+ sharedregion_get_table_info(i, j, &info);
+ if (info.is_valid == true) {
+ /* Convert kernel virtual address to physical
+ * addresses */
+ info.base = platform_mem_translate(info.base,
+ PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS);
+ size = copy_to_user((void *) (table
+ + (j * config.max_regions)
+ + i),
+ (void *) &info,
+ sizeof(
+ struct sharedregion_info));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ } /* End of inner if */
+ } /* End of outer if */
+ } /* End of inner for loop */
+ }
+
+exit:
+ return status;
+}
+
+/*
+ * ======== sharedregion_ioctl_destroy========
+ * Purpose:
+ * This ioctl interface to sharedregion_destroy function
+ */
+static int sharedregion_ioctl_destroy(
+ struct sharedregion_cmd_args *cargs)
+{
+ cargs->api_status = sharedregion_destroy();
+ return 0;
+}
+
+/*
+ * ======== sharedregion_ioctl_add ========
+ * Purpose:
+ * This ioctl interface to sharedregion_add function
+ */
+static int sharedregion_ioctl_add(struct sharedregion_cmd_args *cargs)
+{
+ u32 base = (u32)platform_mem_translate(cargs->args.add.base,
+ PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT);
+ cargs->api_status = sharedregion_add(cargs->args.add.index,
+ (void *)base, cargs->args.add.len);
+ return 0;
+}
+
+
+
+/*
+ * ======== sharedregion_ioctl_get_index ========
+ * Purpose:
+ * This ioctl interface to sharedregion_get_index function
+ */
+static int sharedregion_ioctl_get_index(struct sharedregion_cmd_args *cargs)
+{
+ s32 index = 0;
+
+ index = sharedregion_get_index(cargs->args.get_index.addr);
+ cargs->args.get_index.index = index;
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== sharedregion_ioctl_get_ptr ========
+ * Purpose:
+ * This ioctl interface to sharedregion_get_ptr function
+ */
+static int sharedregion_ioctl_get_ptr(struct sharedregion_cmd_args *cargs)
+{
+ void *addr = NULL;
+
+ addr = sharedregion_get_ptr(cargs->args.get_ptr.srptr);
+ /* We are not checking the return from the module, its user
+ responsibilty to pass proper value to application
+ */
+ cargs->args.get_ptr.addr = addr;
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== sharedregion_ioctl_get_srptr ========
+ * Purpose:
+ * This ioctl interface to sharedregion_get_srptr function
+ */
+static int sharedregion_ioctl_get_srptr(struct sharedregion_cmd_args *cargs)
+{
+ u32 *srptr = NULL;
+
+ srptr = sharedregion_get_srptr(cargs->args.get_srptr.addr,
+ cargs->args.get_srptr.index);
+ /* We are not checking the return from the module, its user
+ responsibilty to pass proper value to application
+ */
+ cargs->args.get_srptr.srptr = srptr;
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== sharedregion_ioctl_get_table_info ========
+ * Purpose:
+ * This ioctl interface to sharedregion_get_table_info function
+ */
+static int sharedregion_ioctl_get_table_info(
+ struct sharedregion_cmd_args *cargs)
+{
+ struct sharedregion_info info;
+ s32 status = 0;
+ s32 size;
+
+ cargs->api_status = sharedregion_get_table_info(
+ cargs->args.get_table_info.index,
+ cargs->args.get_table_info.proc_id, &info);
+ size = copy_to_user(cargs->args.get_table_info.info, &info,
+ sizeof(struct sharedregion_info));
+ if (size)
+ status = -EFAULT;
+
+ return status;
+}
+
+
+/*
+ * ======== sharedregion_ioctl_remove ========
+ * Purpose:
+ * This ioctl interface to sharedregion_remove function
+ */
+static int sharedregion_ioctl_remove(struct sharedregion_cmd_args *cargs)
+{
+ cargs->api_status = sharedregion_remove(cargs->args.remove.index);
+ return 0;
+}
+
+/*
+ * ======== sharedregion_ioctl_set_table_info ========
+ * Purpose:
+ * This ioctl interface to sharedregion_set_table_info function
+ */
+static int sharedregion_ioctl_set_table_info(
+ struct sharedregion_cmd_args *cargs)
+{
+ struct sharedregion_info info;
+ s32 status = 0;
+ s32 size;
+
+ size = copy_from_user(&info, cargs->args.set_table_info.info,
+ sizeof(struct sharedregion_info));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = sharedregion_set_table_info(
+ cargs->args.set_table_info.index,
+ cargs->args.set_table_info.proc_id, &info);
+
+exit:
+ return status;
+}
+
+/*
+ * ======== sharedregion_ioctl ========
+ * Purpose:
+ * This ioctl interface for sharedregion module
+ */
+int sharedregion_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ s32 status = 0;
+ s32 size = 0;
+ struct sharedregion_cmd_args __user *uarg =
+ (struct sharedregion_cmd_args __user *)args;
+ struct sharedregion_cmd_args cargs;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+
+ if (status) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg,
+ sizeof(struct sharedregion_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_SHAREDREGION_GETCONFIG:
+ status = sharedregion_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_SETUP:
+ status = sharedregion_ioctl_setup(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_DESTROY:
+ status = sharedregion_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_ADD:
+ status = sharedregion_ioctl_add(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_GETINDEX:
+ status = sharedregion_ioctl_get_index(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_GETPTR:
+ status = sharedregion_ioctl_get_ptr(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_GETSRPTR:
+ status = sharedregion_ioctl_get_srptr(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_GETTABLEINFO:
+ status = sharedregion_ioctl_get_table_info(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_REMOVE:
+ status = sharedregion_ioctl_remove(&cargs);
+ break;
+
+ case CMD_SHAREDREGION_SETTABLEINFO:
+ status = sharedregion_ioctl_set_table_info(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ status = -ENOTTY;
+ break;
+ }
+
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct sharedregion_cmd_args));
+ if (size) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return status;
+}
+
diff --git a/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c b/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c
new file mode 100644
index 000000000000..60bdad0c188f
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c
@@ -0,0 +1,459 @@
+/*
+ * sysmemmgr.c
+ *
+ * Manager for the Slave system memory. Slave system level memory is allocated
+ * through this modules.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Utils headers */
+#include <linux/vmalloc.h>
+#include <syslink/atomic_linux.h>
+#include <syslink/platform_mem.h>
+/*#include <GateMutex.h>
+#include <Memory.h>
+#include <Trace.h>*/
+
+
+/* Module level headers */
+#include <sysmemmgr.h>
+/*#include <BuddyPageAllocator.h>*/
+
+
+/* =============================================================================
+ * Macros
+ * =============================================================================
+ */
+/*! @brief Event reserved for System memory manager */
+#define SYSMEMMGR_EVENTNO 12
+
+/* Macro to make a correct module magic number with ref_count */
+#define SYSMEMMGR_MAKE_MAGICSTAMP(x) ((SYSMEMMGR_MODULEID << 12) | (x))
+
+/* =============================================================================
+ * Structs & Enums
+ * =============================================================================
+ */
+/*! @brief Structure containing list of buffers. The list is kept sorted by
+ * address. */
+struct sysmemmgr_static_mem_struct {
+ struct sysmemmgr_static_mem_struct *next;
+ /*!< Pointer to next entry */
+ u32 address;
+ /*!< Address of this entry */
+ u32 size;
+ /*!< Size of this entry */
+};
+
+
+/*! @brief Static memory manager object. */
+struct sysmemmgr_static_mem_mgr_obj {
+ struct sysmemmgr_static_mem_struct head;
+ /*!< Pointer to head entry */
+ struct sysmemmgr_static_mem_struct tail;
+ /*!< Pointer to tail entry */
+};
+
+/*!
+ * @brief Structure defining state object of system memory manager.
+ */
+struct sysmemmgr_module_object {
+ atomic_t ref_count;
+ /*!< Reference count */
+ struct sysmemmgr_static_mem_mgr_obj static_mem_obj;
+ /*!< Static memory manager object */
+ struct mutex *gate_handle;
+ /*!< Pointer to lock */
+ struct sysmemmgr_config cfg;
+ /*!< Current configuration values */
+ struct sysmemmgr_config default_cfg;
+ /*!< Default configuration values */
+};
+
+
+/*!
+ * @brief Object containing state of the system memory manager.
+ */
+static struct sysmemmgr_module_object sysmemmgr_state = {
+ .default_cfg.sizeof_valloc = 0x100000,
+ .default_cfg.sizeof_palloc = 0x100000,
+ .default_cfg.page_size = 0x1000,
+ .default_cfg.event_no = SYSMEMMGR_EVENTNO,
+};
+
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+/*
+ * ======== sysmemmgr_get_config ========
+ * Purpose:
+ * Function to get the default values for configuration.
+ */
+void sysmemmgr_get_config(struct sysmemmgr_config *config)
+{
+ if (WARN_ON(config == NULL))
+ goto err_exit;
+
+ if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
+ SYSMEMMGR_MAKE_MAGICSTAMP(0),
+ SYSMEMMGR_MAKE_MAGICSTAMP(1)) == true)
+ memcpy((void *) config, (void *)(&sysmemmgr_state.default_cfg),
+ sizeof(struct sysmemmgr_config));
+ else
+ memcpy((void *) config, (void *)(&sysmemmgr_state.cfg),
+ sizeof(struct sysmemmgr_config));
+
+ return;
+
+err_exit:
+ printk(KERN_ERR "sysmemmgr_get_config: Argument of type "
+ "(struct sysmemmgr_config *) passed is NULL\n");
+ return;
+}
+
+
+/*
+ * ======== sysmemmgr_setup ========
+ * Purpose:
+ * Function to get the default values for configuration.
+ */
+int sysmemmgr_setup(struct sysmemmgr_config *config)
+{
+ int status = 0;
+ struct sysmemmgr_static_mem_mgr_obj *smmObj = NULL;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable.
+ */
+ atomic_cmpmask_and_set(&sysmemmgr_state.ref_count,
+ SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&sysmemmgr_state.ref_count) != \
+ SYSMEMMGR_MAKE_MAGICSTAMP(1)) {
+ status = SYSMEMMGR_S_ALREADYSETUP;
+ goto exit;
+ }
+
+ if (WARN_ON(config == NULL)) {
+ /* Config parameters are not provided */
+ status = -EINVAL;
+ goto err_config;
+ }
+ if (WARN_ON((config->static_virt_base_addr == (u32) NULL)
+ && (config->static_mem_size != 0))) {
+ /* Virtual Base address of static memory region is NULL */
+ status = -EINVAL;
+ goto err_virt_addr;
+ }
+ if (WARN_ON((config->static_phys_base_addr == (u32) NULL)
+ && (config->static_mem_size != 0))) {
+ /*Physical Base address of static memory region is NULL */
+ status = -EINVAL;
+ goto err_phys_addr;
+ }
+
+ /* Copy the config parameters to the module state */
+ memcpy((void *)(&sysmemmgr_state.cfg), (void *) config,
+ sizeof(struct sysmemmgr_config));
+
+ /* Create the static memory allocator */
+ if (config->static_mem_size != 0) {
+ smmObj = &sysmemmgr_state.static_mem_obj;
+ smmObj->head.address = config->static_virt_base_addr;
+ smmObj->head.size = 0;
+ smmObj->tail.address = (config->static_virt_base_addr + \
+ config->static_mem_size);
+ smmObj->tail.size = 0;
+ smmObj->head.next = &smmObj->tail;
+ smmObj->tail.next = NULL;
+ }
+
+ /* Create the lock */
+ sysmemmgr_state.gate_handle = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (sysmemmgr_state.gate_handle == NULL) {
+ /* Failed to create gate handle */
+ status = -ENOMEM;
+ goto err_mem_gate;
+ }
+ return 0;
+
+err_mem_gate:
+ printk(KERN_ERR "sysmemmgr_setup: Failed to create gate handle\n");
+ goto exit;
+
+err_phys_addr:
+ printk(KERN_ERR "sysmemmgr_setup: Physical Base address of static "
+ "memory region is NULL\n");
+ goto exit;
+
+err_virt_addr:
+ printk(KERN_ERR "sysmemmgr_setup: Virtual Base address of static "
+ "memory region is NULL\n");
+ goto exit;
+
+err_config:
+ printk(KERN_ERR "sysmemmgr_setup: Argument of type "
+ "(struct sysmemmgr_config *) passed is NULL\n");
+ goto exit;
+
+exit:
+ if (status < 0) {
+ atomic_set(&sysmemmgr_state.ref_count,
+ SYSMEMMGR_MAKE_MAGICSTAMP(0));
+ }
+ return status;
+}
+
+
+/*
+ * ======== sysmemmgr_destroy ========
+ * Purpose:
+ * Function to finalize the system memory manager module.
+ */
+int sysmemmgr_destroy(void)
+{
+ int status = 0;
+
+ if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
+ SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
+ true) {
+ /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
+ * initialized */
+ status = SYSMEMMGR_E_INVALIDSTATE;
+ goto err_exit;
+ }
+
+ if (atomic_dec_return(&sysmemmgr_state.ref_count) == \
+ SYSMEMMGR_MAKE_MAGICSTAMP(0)) {
+ /* Delete the lock */
+ kfree(sysmemmgr_state.gate_handle);
+ }
+ return 0;
+
+err_exit:
+ printk(KERN_ERR "sysmemgr_destroy: Module was not initialized\n");
+ return status;
+}
+
+
+/*
+ * ======== sysmemmgr_alloc ========
+ * Purpose:
+ * Function to allocate a memory block.
+ */
+void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag)
+{
+ int status = 0;
+ struct sysmemmgr_static_mem_mgr_obj *smObj = NULL;
+ struct sysmemmgr_static_mem_struct *ptr = NULL;
+ struct sysmemmgr_static_mem_struct *newptr = NULL;
+ void *ret_ptr = NULL;
+
+ if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
+ SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
+ true) {
+ /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
+ * initialized */
+ status = SYSMEMMGR_E_INVALIDSTATE;
+ goto err_exit;
+ }
+
+ if ((flag & sysmemmgr_allocflag_physical) && \
+ !(flag & sysmemmgr_allocflag_dma)) {
+ /* TBD: works with DMM
+ ret_ptr = platform_mem_alloc (size, 0,
+ MemoryOS_MemTypeFlags_Physical); */
+ if (ret_ptr == NULL) {
+ if (sysmemmgr_state.cfg.static_mem_size == 0) {
+ /* Memory pool is not configured. */
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ smObj = &sysmemmgr_state.static_mem_obj;
+ ptr = &smObj->head;
+ while (ptr && ptr->next) {
+ if (((ptr->next->address - \
+ (ptr->address + ptr->size)) >= size))
+ break;
+ ptr = ptr->next;
+ }
+
+ if (ptr->next == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ newptr = vmalloc(
+ sizeof(struct sysmemmgr_static_mem_struct));
+ if (newptr != NULL) {
+ newptr->address = ptr->address + ptr->size;
+ newptr->size = size;
+ newptr->next = ptr->next;
+ ptr->next = newptr;
+ ret_ptr = (void *) newptr->address;
+ } else {
+ status = -ENOMEM;
+ }
+ }
+ goto exit;
+ }
+
+ if (flag & sysmemmgr_allocflag_physical) {
+ ret_ptr = kmalloc(size, GFP_KERNEL);
+ if (ret_ptr == NULL)
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ if (flag & sysmemmgr_allocflag_dma) {
+ ret_ptr = kmalloc(size, GFP_KERNEL | GFP_DMA);
+ if (ret_ptr == NULL)
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ ret_ptr = vmalloc(size);
+ if (ret_ptr == NULL) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+err_exit:
+ printk(KERN_ERR "sysmemgr_alloc: Module was not initialized\n");
+exit:
+ if (WARN_ON(ret_ptr == NULL))
+ printk(KERN_ERR "sysmemmgr_alloc: Allocation failed\n");
+ return ret_ptr;
+}
+
+
+/*
+ * ======== sysmemmgr_free ========
+ * Purpose:
+ * Function to de-allocate a previous allocated memory block.
+ */
+int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag)
+{
+ int status = 0;
+ struct sysmemmgr_static_mem_mgr_obj *smObj = NULL;
+ struct sysmemmgr_static_mem_struct *ptr = NULL;
+ struct sysmemmgr_static_mem_struct *prev = NULL;
+
+ if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
+ SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
+ true) {
+ /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
+ * initialized */
+ status = SYSMEMMGR_E_INVALIDSTATE;
+ goto err_exit;
+ }
+
+ if ((flag & sysmemmgr_allocflag_physical) && \
+ !(flag & sysmemmgr_allocflag_dma)) {
+ if (((u32) blk >= sysmemmgr_state.cfg.static_virt_base_addr)
+ && ((u32) blk < \
+ (sysmemmgr_state.cfg.static_virt_base_addr + \
+ sysmemmgr_state.cfg.static_mem_size))) {
+ smObj = &sysmemmgr_state.static_mem_obj;
+ ptr = &smObj->head;
+ while (ptr && ptr->next) {
+ if (ptr->next->address == (u32) blk)
+ break;
+ ptr = ptr->next;
+ }
+ prev = ptr;
+ ptr = ptr->next;
+ prev->next = ptr->next;
+
+ /* Free the node */
+ vfree(ptr);
+ } else {
+ kfree(blk);
+ }
+ } else if (flag & sysmemmgr_allocflag_physical) {
+ kfree(blk);
+ } else if (flag & sysmemmgr_allocflag_dma) {
+ kfree(blk);
+ } else {
+ vfree(blk);
+ }
+ return 0;
+
+err_exit:
+ printk(KERN_ERR "sysmemgr_free: Module was not initialized\n");
+ return status;
+}
+
+
+/*
+ * ======== sysmemmgr_setup ========
+ * Purpose:
+ * Function to translate an address among different address spaces.
+ */
+void *sysmemmgr_translate(void *src_addr, enum sysmemmgr_xltflag flags)
+{
+ void *ret_ptr = NULL;
+
+ switch (flags) {
+ case sysmemmgr_xltflag_kvirt2phys:
+ {
+ if (((u32) src_addr >= \
+ sysmemmgr_state.cfg.static_virt_base_addr) && \
+ ((u32) src_addr < \
+ (sysmemmgr_state.cfg.static_virt_base_addr + \
+ sysmemmgr_state.cfg.static_mem_size))) {
+ ret_ptr = (void *)(((u32) src_addr - \
+ sysmemmgr_state.cfg.static_virt_base_addr) + \
+ (sysmemmgr_state.cfg.static_phys_base_addr));
+ } else {
+ ret_ptr = platform_mem_translate(src_addr,
+ PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS);
+ }
+ }
+ break;
+
+ case sysmemmgr_xltflag_phys2kvirt:
+ {
+ if (((u32) src_addr >= \
+ sysmemmgr_state.cfg.static_phys_base_addr) && \
+ ((u32) src_addr < \
+ (sysmemmgr_state.cfg.static_phys_base_addr + \
+ sysmemmgr_state.cfg.static_mem_size))) {
+ ret_ptr = (void *)(((u32) src_addr - \
+ sysmemmgr_state.cfg.static_phys_base_addr) + \
+ (sysmemmgr_state.cfg.static_virt_base_addr));
+ } else {
+ ret_ptr = platform_mem_translate(src_addr,
+ PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT);
+ }
+ }
+ break;
+
+ default:
+ {
+ printk(KERN_ALERT "sysmemmgr_translate: Unhandled translation "
+ "flag\n");
+ }
+ break;
+ }
+
+ return ret_ptr;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c b/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c
new file mode 100644
index 000000000000..725779045caf
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c
@@ -0,0 +1,223 @@
+/*
+ * sysmemmgr_ioctl.c
+ *
+ * This file implements all the ioctl operations required on the sysmemmgr
+ * module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Linux headers */
+#include <linux/uaccess.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+/* Module Headers */
+#include <sysmemmgr.h>
+#include <sysmemmgr_ioctl.h>
+
+
+/*
+ * ======== sysmemmgr_ioctl_get_config ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_get_config function
+ */
+static inline int sysmemmgr_ioctl_get_config(struct sysmemmgr_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct sysmemmgr_config config;
+
+ sysmemmgr_get_config(&config);
+ size = copy_to_user(cargs->args.get_config.config, &config,
+ sizeof(struct sysmemmgr_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = 0;
+exit:
+ return retval;
+}
+
+/*
+ * ======== sysmemmgr_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_setup function
+ */
+static inline int sysmemmgr_ioctl_setup(struct sysmemmgr_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct sysmemmgr_config config;
+
+ if (cargs->args.setup.config == NULL) {
+ cargs->api_status = sysmemmgr_setup(NULL);
+ goto exit;
+ }
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct sysmemmgr_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = sysmemmgr_setup(&config);
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== sysmemmgr_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_destroy function
+ */
+static inline int sysmemmgr_ioctl_destroy(struct sysmemmgr_cmd_args *cargs)
+{
+ cargs->api_status = sysmemmgr_destroy();
+ return 0;
+}
+
+/*
+ * ======== sysmemmgr_ioctl_alloc ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_alloc function
+ */
+static inline int sysmemmgr_ioctl_alloc(struct sysmemmgr_cmd_args *cargs)
+{
+ void *kbuf = NULL;
+ void *phys = NULL;
+
+ kbuf = sysmemmgr_alloc(cargs->args.alloc.size,
+ cargs->args.alloc.flags);
+ if (unlikely(kbuf == NULL))
+ goto exit;
+
+ /* If the flag is not virtually contiguous */
+ if (cargs->args.alloc.flags != sysmemmgr_allocflag_virtual)
+ phys = sysmemmgr_translate(kbuf, sysmemmgr_xltflag_kvirt2phys);
+ cargs->api_status = 0;
+
+exit:
+ cargs->args.alloc.kbuf = kbuf;
+ cargs->args.alloc.kbuf = phys;
+ return 0;
+}
+
+/*
+ * ======== sysmemmgr_ioctl_free ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_free function
+ */
+static inline int sysmemmgr_ioctl_free(struct sysmemmgr_cmd_args *cargs)
+{
+ cargs->api_status = sysmemmgr_free(cargs->args.free.kbuf,
+ cargs->args.free.size,
+ cargs->args.alloc.flags);
+ return 0;
+}
+
+/*
+ * ======== sysmemmgr_ioctl_translate ========
+ * Purpose:
+ * This ioctl interface to sysmemmgr_translate function
+ */
+static inline int sysmemmgr_ioctl_translate(struct sysmemmgr_cmd_args *cargs)
+{
+ cargs->args.translate.ret_ptr = sysmemmgr_translate(
+ cargs->args.translate.buf,
+ cargs->args.translate.flags);
+ WARN_ON(cargs->args.translate.ret_ptr == NULL);
+ cargs->api_status = 0;
+ return 0;
+}
+
+/*
+ * ======== sysmemmgr_ioctl ========
+ * Purpose:
+ * ioctl interface function for sysmemmgr module
+ */
+int sysmemmgr_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int os_status = 0;
+ struct sysmemmgr_cmd_args __user *uarg =
+ (struct sysmemmgr_cmd_args __user *)args;
+ struct sysmemmgr_cmd_args cargs;
+ unsigned long size;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+ if (os_status) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg, sizeof(struct sysmemmgr_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_SYSMEMMGR_GETCONFIG:
+ os_status = sysmemmgr_ioctl_get_config(&cargs);
+ break;
+
+ case CMD_SYSMEMMGR_SETUP:
+ os_status = sysmemmgr_ioctl_setup(&cargs);
+ break;
+
+ case CMD_SYSMEMMGR_DESTROY:
+ os_status = sysmemmgr_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_SYSMEMMGR_ALLOC:
+ os_status = sysmemmgr_ioctl_alloc(&cargs);
+ break;
+
+ case CMD_SYSMEMMGR_FREE:
+ os_status = sysmemmgr_ioctl_free(&cargs);
+ break;
+
+ case CMD_SYSMEMMGR_TRANSLATE:
+ os_status = sysmemmgr_ioctl_translate(&cargs);
+ break;
+
+ default:
+ WARN_ON(cmd);
+ os_status = -ENOTTY;
+ break;
+ }
+ if (os_status < 0)
+ goto exit;
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct sysmemmgr_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return os_status;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/sysmgr.c b/drivers/dsp/syslink/multicore_ipc/sysmgr.c
new file mode 100644
index 000000000000..46cebf492485
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sysmgr.c
@@ -0,0 +1,815 @@
+/*
+ * sysmgr.c
+ *
+ * Implementation of System manager.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+#include <syslink/atomic_linux.h>
+
+/* Module headers */
+#include <multiproc.h>
+#include <sysmemmgr.h>
+#include <sysmgr.h>
+#include <_sysmgr.h>
+#include <platform.h>
+#include <platform_mem.h>
+
+#include <gatepeterson.h>
+#include <sharedregion.h>
+#include <listmp.h>
+#include <messageq.h>
+#include <messageq_transportshm.h>
+#include <notify.h>
+/*#include <notify_driver.h>*/
+#include <notify_ducatidriver.h>
+
+#include <nameserver.h>
+#include <nameserver_remote.h>
+#include <nameserver_remotenotify.h>
+#include <procmgr.h>
+#include <heap.h>
+#include <heapbuf.h>
+
+/* =============================================================================
+ * Macros
+ * =============================================================================
+ */
+/*!
+ * @def BOOTLOADPAGESIZE
+ * @brief Error code base for System manager.
+ */
+#define BOOTLOADPAGESIZE (0x1000) /* 4K page size */
+
+/*!
+ * @def SYSMGR_ENTRYVALIDITYSTAMP
+ * @brief Validity stamp for boot load page entries.
+ */
+#define SYSMGR_ENTRYVALIDITYSTAMP (0xBABAC0C0)
+
+/*!
+ * @def SYSMGR_ENTRYVALIDSTAMP
+ * @brief Validity stamp for boot load page entries.
+ */
+#define SYSMGR_ENTRYVALIDSTAMP (0xBABAC0C0)
+
+/*!
+ * @def SYSMGR_SCALABILITYHANDSHAKESTAMP
+ * @brief scalability configuration handshake value.
+ */
+#define SYSMGR_SCALABILITYHANDSHAKESTAMP (0xBEEF0000)
+
+/*!
+ * @def SYSMGR_SETUPHANDSHAKESTAMP
+ * @brief Platform configured handshake value.
+ */
+#define SYSMGR_SETUPHANDSHAKESTAMP (0xBEEF0001)
+
+/*!
+ * @def SYSMGR_DESTROYHANDSHAKESTAMP
+ * @brief Destroy handshake value.
+ */
+#define SYSMGR_DESTROYHANDSHAKESTAMP (0xBEEF0002)
+
+/*!
+ * @def SYSMGR_BOOTLOADPAGESIZE
+ * @brief Boot load page size.
+ */
+#define SYSMGR_BOOTLOADPAGESIZE (0x00001000)
+
+/* Macro to make a correct module magic number with ref_count */
+#define SYSMGR_MAKE_MAGICSTAMP(x) ((SYSMGR_MODULEID << 12) | (x))
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/*! @brief structure for System manager boot load page entry */
+struct sysmgr_bootload_page_entry {
+ VOLATILE u32 offset;
+ /* Offset of next entry (-1 if not present) */
+ VOLATILE u32 valid;
+ /* Validity of the entry */
+ VOLATILE u32 size;
+ /* Size of the entry data */
+ VOLATILE u32 cmd_id;
+ /* Command ID */
+};
+
+/*! @brief structure containg system manager state object */
+struct sysmgr_boot_load_page {
+ VOLATILE struct sysmgr_bootload_page_entry host_config;
+ /* First entry, host specific configuration in the boot load page */
+ u8 padding1[(BOOTLOADPAGESIZE/2) - \
+ sizeof(struct sysmgr_bootload_page_entry)];
+ /* Padding1 */
+ VOLATILE u32 handshake;
+ /* Handshake variable, wrote by slave to indicate configuration done. */
+ VOLATILE struct sysmgr_bootload_page_entry slave_config;
+ /* First entry, slave specific configuration in the boot load page */
+ u8 padding2[(BOOTLOADPAGESIZE/2) - \
+ sizeof(struct sysmgr_bootload_page_entry) - \
+ sizeof(u32)];
+ /* Padding2 */
+};
+
+/*! @brief structure for System manager module state */
+struct sysmgr_module_object {
+ atomic_t ref_count;
+ /* Reference count */
+ struct sysmgr_config config;
+ /* Overall system configuration */
+ struct sysmgr_boot_load_page *boot_load_page[MULTIPROC_MAXPROCESSORS];
+ /* Boot load page of the slaves */
+ bool platform_mem_init_flag;
+ /* Platform memory manager initialize flag */
+ bool multiproc_init_flag;
+ /* Multiproc Initialize flag */
+ bool gatepeterson_init_flag;
+ /* Gatepeterson Initialize flag */
+ bool sharedregion_init_flag;
+ /* Sharedregion Initialize flag */
+ bool listmp_init_flag;
+ /* Listmp Initialize flag */
+ bool messageq_init_flag;
+ /* Messageq Initialize flag */
+ bool notify_init_flag;
+ /* Notify Initialize flag */
+ bool proc_mgr_init_flag;
+ /* Processor manager Initialize flag */
+ bool heapbuf_init_flag;
+ /* Heapbuf Initialize flag */
+ bool nameserver_init_flag;
+ /* Nameserver_remotenotify Initialize flag */
+ bool listmp_sharedmemory_init_flag;
+ /* Listmp_sharedmemory Initialize flag */
+ bool messageq_transportshm_init_flag;
+ /* Messageq_transportshm Initialize flag */
+ bool notify_ducatidrv_init_flag;
+ /* notify_ducatidrv Initialize flag */
+ bool nameserver_remotenotify_init_flag;
+ /* nameserver_remotenotify Initialize flag */
+ bool platform_init_flag;
+ /* Flag to indicate platform initialization status */
+};
+
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/*!
+ * @var sysmgr_state
+ *
+ * @brief Variable holding state of system manager.
+ */
+static struct sysmgr_module_object sysmgr_state;
+
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+/*
+ * ======== sysmgr_get_config ========
+ * Purpose:
+ * Function to get the default values for configuration.
+ */
+void sysmgr_get_config(struct sysmgr_config *config)
+{
+ s32 status = 0;
+
+ if (WARN_ON(config == NULL)) {
+ status = -EINVAL;
+ printk(KERN_ALERT "sysmgr_get_config [0x%x] : Argument of type"
+ " (sysmgr_get_config *) passed is null!",
+ status);
+ return;
+ }
+
+ /* Get the gatepeterson default config */
+ multiproc_get_config(&config->multiproc_cfg);
+
+ /* Get the gatepeterson default config */
+ gatepeterson_get_config(&config->gatepeterson_cfg);
+
+ /* Get the sharedregion default config */
+ sharedregion_get_config(&config->sharedregion_cfg);
+
+ /* Get the messageq default config */
+ messageq_get_config(&config->messageq_cfg);
+
+ /* Get the notify default config */
+ notify_get_config(&config->notify_cfg);
+
+ /* Get the proc_mgr default config */
+ proc_mgr_get_config(&config->proc_mgr_cfg);
+
+ /* Get the heapbuf default config */
+ heapbuf_get_config(&config->heapbuf_cfg);
+
+ /* Get the listmp_sharedmemory default config */
+ listmp_sharedmemory_get_config(&config->listmp_sharedmemory_cfg);
+
+ /* Get the messageq_transportshm default config */
+ messageq_transportshm_get_config(&config->messageq_transportshm_cfg);
+
+ /* Get the notify_ducati driver default config */
+ notify_ducatidrv_getconfig(&config->notify_ducatidrv_cfg);
+
+ /* Get the nameserver_remotenotify default config */
+ nameserver_remotenotify_get_config(
+ &config->nameserver_remotenotify_cfg);
+}
+EXPORT_SYMBOL(sysmgr_get_config);
+
+/*
+ * ======== sysmgr_get_object_config ========
+ * Purpose:
+ * Function to get the SysMgr Object configuration from Slave.
+ */
+u32 sysmgr_get_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size)
+{
+ struct sysmgr_bootload_page_entry *entry = NULL;
+ u32 offset = 0;
+ u32 ret = 0;
+ struct sysmgr_boot_load_page *blp = NULL;
+
+ blp = (struct sysmgr_boot_load_page *)
+ sysmgr_state.boot_load_page[proc_id];
+
+ entry = (struct sysmgr_bootload_page_entry *) &blp->slave_config;
+ while (entry->valid == SYSMGR_ENTRYVALIDSTAMP) {
+ if (entry->cmd_id == cmd_id) {
+ if (size == entry->size) {
+ memcpy(config, (void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ size);
+ ret = size;
+ break;
+ }
+ }
+ if (entry->offset != -1) {
+ offset += entry->offset;
+ entry = (struct sysmgr_bootload_page_entry *)
+ ((u32) &blp->slave_config + entry->offset);
+ } else {
+ break;
+ }
+ }
+
+ /* return number of bytes wrote to the boot load page */
+ return ret;
+}
+
+
+/*
+ * ======== sysmgr_put_object_config ========
+ * Purpose:
+ * Function to put the SysMgr Object configuration to Slave.
+ */
+u32 sysmgr_put_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size)
+{
+ struct sysmgr_bootload_page_entry *entry = NULL;
+ struct sysmgr_bootload_page_entry *prev = NULL;
+ u32 offset = 0;
+ struct sysmgr_boot_load_page *blp = NULL;
+
+ /* Get the boot load page pointer */
+ blp = sysmgr_state.boot_load_page[proc_id];
+
+ /* Put the entry at the end of list */
+ entry = (struct sysmgr_bootload_page_entry *) &blp->host_config;
+ while (entry->valid == SYSMGR_ENTRYVALIDSTAMP) {
+ prev = entry;
+ if (entry->offset != -1) {
+ offset += entry->offset;
+ entry = (struct sysmgr_bootload_page_entry *)
+ ((u32) &blp->host_config + entry->offset);
+ } else {
+ break;
+ }
+ }
+
+ /* First entry has prev set to NULL */
+ if (prev == NULL) {
+ entry->offset = -1;
+ entry->cmd_id = cmd_id;
+ entry->size = size;
+ memcpy((void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ config, size);
+ entry->valid = SYSMGR_ENTRYVALIDSTAMP;
+ } else {
+ entry = (struct sysmgr_bootload_page_entry *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry) + \
+ entry->size);
+ entry->offset = -1;
+ entry->cmd_id = cmd_id;
+ entry->size = size;
+ memcpy((void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ config, size);
+ entry->valid = SYSMGR_ENTRYVALIDSTAMP;
+
+ /* Attach the new created entry */
+ prev->offset = ((u32) entry - (u32) &blp->host_config);
+ }
+
+ /* return number of bytes wrote to the boot load page */
+ return size;
+}
+
+
+/*
+ * ======== sysmgr_setup ========
+ * Purpose:
+ * Function to setup the System.
+ */
+s32 sysmgr_setup(const struct sysmgr_config *cfg)
+{
+ s32 status = 0;
+ struct sysmgr_config *config = NULL;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable.
+ */
+ atomic_cmpmask_and_set(&sysmgr_state.ref_count,
+ SYSMGR_MAKE_MAGICSTAMP(0),
+ SYSMGR_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&sysmgr_state.ref_count)
+ != SYSMGR_MAKE_MAGICSTAMP(1)) {
+ status = 1;
+ goto exit;
+ }
+
+ if (cfg == NULL) {
+ sysmgr_get_config(&sysmgr_state.config);
+ config = &sysmgr_state.config;
+ } else {
+ memcpy((void *) (&sysmgr_state.config), (void *) cfg,
+ sizeof(struct sysmgr_config));
+ config = (struct sysmgr_config *) cfg;
+ }
+
+ /* Initialize PlatformMem */
+ status = platform_mem_setup();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : platform_mem_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "platform_mem_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.platform_mem_init_flag = true;
+ }
+
+ /* Override the platform specific configuration */
+ platform_override_config(config);
+
+ status = multiproc_setup(&(config->multiproc_cfg));
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : multiproc_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "sysmgr_setup : status [0x%x]\n" , status);
+ sysmgr_state.multiproc_init_flag = true;
+ }
+
+ /* Initialize ProcMgr */
+ if (status >= 0) {
+ status = proc_mgr_setup(&(config->proc_mgr_cfg));
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : proc_mgr_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "proc_mgr_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.proc_mgr_init_flag = true;
+ }
+ }
+
+ /* Initialize SharedRegion */
+ if (status >= 0) {
+ status = sharedregion_setup(&config->sharedregion_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : sharedregion_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "sharedregion_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.sharedregion_init_flag = true;
+ }
+ }
+
+ /* Initialize Notify */
+ if (status >= 0) {
+ status = notify_setup(&config->notify_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : notify_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "notify_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.notify_init_flag = true;
+ }
+ }
+
+ /* Initialize NameServer */
+ if (status >= 0) {
+ status = nameserver_setup();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : nameserver_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "nameserver_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.nameserver_init_flag = true;
+ }
+ }
+
+ /* Initialize GatePeterson */
+ if (status >= 0) {
+ status = gatepeterson_setup(&config->gatepeterson_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : gatepeterson_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "gatepeterson_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.gatepeterson_init_flag = true;
+ }
+ }
+
+ /* Intialize MessageQ */
+ if (status >= 0) {
+ status = messageq_setup(&config->messageq_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : messageq_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "messageq_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.messageq_init_flag = true;
+ }
+ }
+
+ /* Intialize HeapBuf */
+ if (status >= 0) {
+ status = heapbuf_setup(&config->heapbuf_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : heapbuf_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "heapbuf_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.heapbuf_init_flag = true;
+ }
+ }
+
+ /* Initialize ListMPSharedMemory */
+ if (status >= 0) {
+ status = listmp_sharedmemory_setup(
+ &config->listmp_sharedmemory_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : "
+ "listmp_sharedmemory_setup failed [0x%x]\n",
+ status);
+ } else {
+ printk(KERN_ERR "listmp_sharedmemory_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.listmp_sharedmemory_init_flag = true;
+ }
+ }
+
+ /* Initialize MessageQTransportShm */
+ if (status >= 0) {
+ status = messageq_transportshm_setup(
+ &config->messageq_transportshm_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : "
+ "messageq_transportshm_setup failed [0x%x]\n",
+ status);
+ } else {
+ printk(KERN_ERR "messageq_transportshm_setup : "
+ "status [0x%x]\n", status);
+ sysmgr_state.messageq_transportshm_init_flag = true;
+ }
+ }
+
+ /* Initialize Notify DucatiDriver */
+ if (status >= 0) {
+ status = notify_ducatidrv_setup(&config->notify_ducatidrv_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : "
+ "notify_ducatidrv_setup failed [0x%x]\n",
+ status);
+ } else {
+ printk(KERN_ERR "notify_ducatidrv_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.notify_ducatidrv_init_flag = true;
+ }
+ }
+
+ /* Initialize NameServerRemoteNotify */
+ if (status >= 0) {
+ status = nameserver_remotenotify_setup(
+ &config->nameserver_remotenotify_cfg);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : "
+ "nameserver_remotenotify_setup failed [0x%x]\n",
+ status);
+ } else {
+ printk(KERN_ERR "nameserver_remotenotify_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.nameserver_remotenotify_init_flag = true;
+ }
+ }
+
+ if (status >= 0) {
+ /* Call platform setup function */
+ status = platform_setup(config);
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_setup : platform_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ printk(KERN_ERR "platform_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.platform_init_flag = true;
+ }
+ }
+
+exit:
+ if (status < 0)
+ atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0));
+
+ return status;
+}
+EXPORT_SYMBOL(sysmgr_setup);
+
+/*
+ * ======== sysmgr_setup ========
+ * Purpose:
+ * Function to finalize the System.
+ */
+s32 sysmgr_destroy(void)
+{
+ s32 status = 0;
+
+ if (atomic_cmpmask_and_lt(&(sysmgr_state.ref_count),
+ SYSMGR_MAKE_MAGICSTAMP(0),
+ SYSMGR_MAKE_MAGICSTAMP(1)) != false) {
+ /*! @retval SYSMGR_E_INVALIDSTATE Module was not initialized */
+ status = SYSMGR_E_INVALIDSTATE;
+ goto exit;
+ }
+
+ if (atomic_dec_return(&sysmgr_state.ref_count)
+ != SYSMGR_MAKE_MAGICSTAMP(0)) {
+ status = 1;
+ goto exit;
+ }
+
+ /* Finalize Platform module*/
+ if (sysmgr_state.platform_init_flag == true) {
+ status = platform_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : platform_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.platform_init_flag = false;
+ }
+ }
+
+ /* Finalize NameServerRemoteNotify module */
+ if (sysmgr_state.nameserver_remotenotify_init_flag == true) {
+ status = nameserver_remotenotify_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "nameserver_remotenotify_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.nameserver_remotenotify_init_flag \
+ = false;
+ }
+ }
+
+ /* Finalize Notify Ducati Driver module */
+ if (sysmgr_state.notify_ducatidrv_init_flag == true) {
+ status = notify_ducatidrv_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "notify_ducatidrv_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.notify_ducatidrv_init_flag = false;
+ }
+ }
+
+ /* Finalize MessageQTransportShm module */
+ if (sysmgr_state.messageq_transportshm_init_flag == true) {
+ status = messageq_transportshm_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "messageq_transportshm_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.messageq_transportshm_init_flag = \
+ false;
+ }
+ }
+
+ /* Finalize ListMPSharedMemory module */
+ if (sysmgr_state.listmp_sharedmemory_init_flag == true) {
+ status = listmp_sharedmemory_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "listmp_sharedmemory_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.listmp_sharedmemory_init_flag = \
+ false;
+ }
+ }
+
+ /* Finalize HeapBuf module */
+ if (sysmgr_state.heapbuf_init_flag == true) {
+ status = heapbuf_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : heapbuf_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.heapbuf_init_flag = false;
+ }
+ }
+
+ /* Finalize MessageQ module */
+ if (sysmgr_state.messageq_init_flag == true) {
+ status = messageq_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : messageq_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.messageq_init_flag = false;
+ }
+ }
+
+ /* Finalize GatePeterson module */
+ if (sysmgr_state.gatepeterson_init_flag == true) {
+ status = gatepeterson_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "gatepeterson_destroy failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.gatepeterson_init_flag = false;
+ }
+ }
+
+ /* Finalize NameServer module */
+ if (sysmgr_state.nameserver_init_flag == true) {
+ status = nameserver_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : nameserver_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.nameserver_init_flag = false;
+ }
+ }
+
+ /* Finalize Notify module */
+ if (sysmgr_state.notify_init_flag == true) {
+ status = notify_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : sysmgr_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.notify_init_flag = false;
+ }
+ }
+
+ /* Finalize SharedRegion module */
+ if (sysmgr_state.sharedregion_init_flag == true) {
+ status = sharedregion_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : "
+ "sharedregion_destroy failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.sharedregion_init_flag = false;
+ }
+ }
+
+ /* Finalize ProcMgr module */
+ if (sysmgr_state.proc_mgr_init_flag == true) {
+ status = proc_mgr_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : proc_mgr_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.proc_mgr_init_flag = false;
+ }
+ }
+
+ /* Finalize MultiProc module */
+ if (sysmgr_state.multiproc_init_flag == true) {
+ status = multiproc_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : multiproc_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.proc_mgr_init_flag = false;
+ }
+ }
+
+ /* Finalize PlatformMem module */
+ if (sysmgr_state.platform_mem_init_flag == true) {
+ status = platform_mem_destroy();
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : platform_mem_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.platform_mem_init_flag = false;
+ }
+ }
+
+ atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0));
+
+exit:
+ if (status < 0) {
+ printk(KERN_ERR "sysmgr_destroy : failed with "
+ "status = [0x%x]\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(sysmgr_destroy);
+
+/*
+ * ======== sysmgr_set_boot_load_page ========
+ * Purpose:
+ * Function to set the boot load page address for a slave.
+ */
+void sysmgr_set_boot_load_page(u16 proc_id, u32 boot_load_page)
+{
+ struct sysmgr_boot_load_page *temp = \
+ (struct sysmgr_boot_load_page *) boot_load_page;
+
+ /* Initialize the host config area */
+ sysmgr_state.boot_load_page[proc_id] = temp;
+ temp->host_config.offset = -1;
+ temp->host_config.valid = 0;
+ temp->handshake = 0;
+}
+
+
+/*
+ * ======== sysmgr_wait_for_scalability_info ========
+ * Purpose:
+ * Function to wait for scalability handshake value.
+ */
+void sysmgr_wait_for_scalability_info(u16 proc_id)
+{
+ VOLATILE struct sysmgr_boot_load_page *temp = \
+ sysmgr_state.boot_load_page[proc_id];
+
+ printk(KERN_ERR "sysmgr_wait_for_scalability_info: BF while temp->handshake:%x\n",
+ temp->handshake);
+
+ printk(KERN_ERR "Please break the platform and load Ducati image.\n");
+
+ while (temp->handshake != SYSMGR_SCALABILITYHANDSHAKESTAMP)
+ ;
+
+ printk(KERN_ERR "sysmgr_wait_for_scalability_info:AF while temp->handshake:%x\n",
+ temp->handshake);
+
+}
+
+
+/*
+ * ======== sysmgr_wait_for_slave_setup ========
+ * Purpose:
+ * Function to wait for slave to complete setup.
+ */
+void sysmgr_wait_for_slave_setup(u16 proc_id)
+{
+ VOLATILE struct sysmgr_boot_load_page *temp = \
+ sysmgr_state.boot_load_page[proc_id];
+
+ while (temp->handshake != SYSMGR_SETUPHANDSHAKESTAMP)
+ ;
+}
diff --git a/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c b/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c
new file mode 100644
index 000000000000..2a9b4c31563e
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c
@@ -0,0 +1,143 @@
+/*
+ * sysmgr_ioctl.c
+ *
+ * This file implements all the ioctl operations required on the sysmgr
+ * module.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+/* Standard headers */
+#include <linux/types.h>
+
+/* Linux headers */
+#include <linux/uaccess.h>
+#include <linux/bug.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+/* Module Headers */
+#include <sysmgr.h>
+#include <sysmgr_ioctl.h>
+#include <platform.h>
+/*
+ * ======== sysmgr_ioctl_setup ========
+ * Purpose:
+ * This ioctl interface to sysmgr_setup function
+ */
+static inline int sysmgr_ioctl_setup(struct sysmgr_cmd_args *cargs)
+{
+ s32 retval = 0;
+ unsigned long size;
+ struct sysmgr_config config;
+
+ size = copy_from_user(&config, cargs->args.setup.config,
+ sizeof(struct sysmgr_config));
+ if (size) {
+ retval = -EFAULT;
+ goto exit;
+ }
+
+ cargs->api_status = sysmgr_setup(&config);
+
+exit:
+ return retval;
+}
+
+/*
+ * ======== sysmgr_ioctl_destroy ========
+ * Purpose:
+ * This ioctl interface to sysmgr_destroy function
+ */
+static inline int sysmgr_ioctl_destroy(struct sysmgr_cmd_args *cargs)
+{
+ cargs->api_status = sysmgr_destroy();
+ return 0;
+}
+
+/*
+ * ======== sysmgr_ioctl ========
+ * Purpose:
+ * ioctl interface function for sysmgr module
+ */
+int sysmgr_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int os_status = 0;
+ struct sysmgr_cmd_args __user *uarg =
+ (struct sysmgr_cmd_args __user *)args;
+ struct sysmgr_cmd_args cargs;
+ unsigned long size;
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
+ if (os_status) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ /* Copy the full args from user-side */
+ size = copy_from_user(&cargs, uarg, sizeof(struct sysmgr_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+ switch (cmd) {
+ case CMD_SYSMGR_SETUP:
+ os_status = sysmgr_ioctl_setup(&cargs);
+ break;
+
+ case CMD_SYSMGR_DESTROY:
+ os_status = sysmgr_ioctl_destroy(&cargs);
+ break;
+
+ case CMD_SYSMGR_LOADCALLBACK:
+#if defined CONFIG_SYSLINK_USE_SYSMGR
+ platform_load_callback((void *)(cargs.args.proc_id));
+ cargs.api_status = 0;
+#endif
+ break;
+
+ case CMD_SYSMGR_STARTCALLBACK:
+#if defined CONFIG_SYSLINK_USE_SYSMGR
+ platform_start_callback((void *)(cargs.args.proc_id));
+ cargs.api_status = 0;
+#endif
+ break;
+
+ case CMD_SYSMGR_STOPCALLBACK:
+#if defined CONFIG_SYSLINK_USE_SYSMGR
+ platform_stop_callback((void *)(cargs.args.proc_id));
+ cargs.api_status = 0;
+#endif
+ break;
+ default:
+ WARN_ON(cmd);
+ os_status = -ENOTTY;
+ break;
+ }
+ if (os_status < 0)
+ goto exit;
+
+ /* Copy the full args to the user-side. */
+ size = copy_to_user(uarg, &cargs, sizeof(struct sysmgr_cmd_args));
+ if (size) {
+ os_status = -EFAULT;
+ goto exit;
+ }
+
+exit:
+ return os_status;
+}
diff --git a/drivers/dsp/syslink/notify_dispatcher/Kbuild b/drivers/dsp/syslink/notify_dispatcher/Kbuild
new file mode 100644
index 000000000000..c729bb2bc844
--- /dev/null
+++ b/drivers/dsp/syslink/notify_dispatcher/Kbuild
@@ -0,0 +1,19 @@
+
+
+omap_ntfydisp = hw_mbox.o notify_dispatcher.o hw_ocp.o
+
+
+obj-$(CONFIG_NOTIFY_DISPATCHER) += notify_disp.o
+notify_disp-objs = $(omap_ntfydisp)
+
+
+ccflags-y += -Wno-strict-prototypes
+
+#Machine dependent
+ccflags-y += -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS \
+ -DCONFIG_DISABLE_BRIDGE_PM -DDSP_TRACEBUF_DISABLED \
+ -DVPOM4430_1_06
+
+#Header files
+ccflags-y += -Idrivers/dsp/syslink/inc
+
diff --git a/drivers/dsp/syslink/notify_dispatcher/hw_mbox.c b/drivers/dsp/syslink/notify_dispatcher/hw_mbox.c
new file mode 100644
index 000000000000..1edb6cb8bca8
--- /dev/null
+++ b/drivers/dsp/syslink/notify_dispatcher/hw_mbox.c
@@ -0,0 +1,374 @@
+/*
+ * hw_mbox.c
+ *
+ * Syslink dispatcher driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/MBXRegAcM.h>
+#include <syslink/MBXAccInt.h>
+#include <syslink/hw_defs.h>
+#include <syslink/hw_mbox.h>
+#include<linux/module.h>
+
+#if defined(OMAP3430)
+struct mailbox_context mboxsetting = {0, 0, 0};
+/*
+ * func: HAL_MBOX_saveSettings
+ * purpose:
+ * Saves the mailbox context
+ */
+long hw_mbox_save_settings(unsigned long base_address)
+{
+ long status = RET_OK;
+
+ mboxsetting.sysconfig =
+ MLBMAILBOX_SYSCONFIGReadRegister32(base_address);
+
+ /* Get current enable status */
+ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (base_address, HW_MBOX_U0_ARM11);
+ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (base_address, HW_MBOX_U1_UMA);
+
+ return status;
+}
+
+/*
+ * func:HAL_MBOX_restoreSettings
+ * purpose:
+ * Restores the mailbox context
+ */
+long hw_mbox_restore_settings(unsigned long base_address)
+{
+ long status = RET_OK;
+
+ /* Restore IRQ enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32
+ (base_address, HW_MBOX_U0_ARM11, mboxsetting.irqEnable0);
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(base_address, HW_MBOX_U1_UMA,
+ mboxsetting.irqEnable1);
+
+ /* Restore Sysconfig register */
+ MLBMAILBOX_SYSCONFIGWriteRegister32(base_address,
+ mboxsetting.sysconfig);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_restore_settings);
+#endif
+
+long hw_mbox_msg_read(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_read_value
+ )
+{
+ long status = RET_OK;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_PARAM(p_read_value, NULL, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Read 32-bit message in mail box */
+ *p_read_value = MLBMAILBOX_MESSAGE___0_15ReadRegister32
+ (base_address, (unsigned long)mail_box_id);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_msg_read);
+
+long hw_mbox_msg_write(const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const unsigned long write_value)
+{
+
+ long status = RET_OK;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Write 32-bit value to mailbox */
+ MLBMAILBOX_MESSAGE___0_15WriteRegister32(base_address,
+ (unsigned long)mail_box_id, (unsigned long)write_value);
+
+ return status;
+}
+
+long hw_mbox_is_full(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_is_full
+ )
+{
+ long status = RET_OK;
+ unsigned long fullStatus;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_PARAM(p_is_full, NULL, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* read the is full status parameter for Mailbox */
+ fullStatus = MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32
+ (base_address, (unsigned long)mail_box_id);
+
+ /* fill in return parameter */
+ *p_is_full = (fullStatus & 0xFF);
+
+ return status;
+}
+
+long hw_mbox_nomsg_get(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ unsigned long *const p_num_msg
+ )
+{
+ long status = RET_OK;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_PARAM(p_num_msg, NULL, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* Get number of messages available for MailBox */
+ *p_num_msg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32
+ (base_address, (unsigned long)mail_box_id);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_nomsg_get);
+
+long hw_mbox_event_enable(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long events
+ )
+{
+ long status = RET_OK;
+ unsigned long irqEnableReg;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(
+ mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ enableIrq,
+ HAL_MBOX_INT_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ user_id,
+ HAL_MBOX_USER_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+ /* update enable value */
+ irqEnableReg = (((unsigned long)(events)) <<
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH));
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE_SET___0_3WriteRegister32(base_address,
+ (unsigned long)user_id, (unsigned long)irqEnableReg);
+
+
+#else
+ /* Get current enable status */
+ irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (base_address, (unsigned long)user_id);
+
+ /* update enable value */
+ irqEnableReg |= ((unsigned long)(events)) <<
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH);
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32
+(base_address, (unsigned long)user_id, (unsigned long)irqEnableReg);
+#endif
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_event_enable);
+
+long hw_mbox_event_disable(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long events
+ )
+{
+ long status = RET_OK;
+ unsigned long irqDisableReg;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(
+ mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ disableIrq,
+ HAL_MBOX_INT_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ user_id,
+ HAL_MBOX_USER_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+ irqDisableReg = (((unsigned long)(events)) <<
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH));
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE_CLR___0_3WriteRegister32(base_address,
+ (unsigned long)user_id, (unsigned long)irqDisableReg);
+
+#else
+ /* Get current enable status */
+ irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
+ (base_address, (unsigned long)user_id);
+
+ /* update enable value */
+ irqDisableReg &= ~(((unsigned long)(events)) <<
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH));
+
+ /* write new enable status */
+ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(base_address,
+ (unsigned long)user_id, (unsigned long)irqDisableReg);
+#endif
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_event_disable);
+
+long hw_mbox_event_status(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ unsigned long *const p_eventStatus)
+{
+ long status = RET_OK;
+ unsigned long irq_status_reg;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_PARAM(pIrqStatus, NULL, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+ CHECK_INPUT_RANGE_MIN0(
+ mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ user_id,
+ HAL_MBOX_USER_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+ irq_status_reg = MLBMAILBOX_IRQSTATUS_CLR___0_3ReadRegister32(
+ base_address, (unsigned long)user_id);
+#else
+ /* Get Irq Status for specified mailbox/User Id */
+ irq_status_reg = MLBMAILBOX_IRQSTATUS___0_3ReadRegister32
+ (base_address, (unsigned long)user_id);
+#endif
+
+ /* update status value */
+ *p_eventStatus = (unsigned long)((((unsigned long)(irq_status_reg)) >>
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH)) &
+ ((unsigned long)(HW_MBOX_INT_ALL)));
+
+ return status;
+}
+
+long hw_mbox_event_ack(
+ const unsigned long base_address,
+ const enum hw_mbox_id_t mail_box_id,
+ const enum hw_mbox_userid_t user_id,
+ const unsigned long event
+ )
+{
+ long status = RET_OK;
+ unsigned long irq_status_reg;
+ /* Check input parameters */
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ irqStatus,
+ HAL_MBOX_INT_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ mail_box_id,
+ HAL_MBOX_ID_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(
+ user_id,
+ HAL_MBOX_USER_MAX,
+ RET_INVALID_ID,
+ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
+ /* calculate status to write */
+ irq_status_reg = ((unsigned long)event) <<
+ (((unsigned long)(mail_box_id))*HW_MBOX_ID_WIDTH);
+
+#if defined(OMAP44XX) || defined(VPOM4430_1_06)
+ /* clear Irq Status for specified mailbox/User Id */
+ MLBMAILBOX_IRQSTATUS_CLR___0_3WriteRegister32(base_address,
+ (unsigned long)user_id, (unsigned long)irq_status_reg);
+
+#else
+ /* clear Irq Status for specified mailbox/User Id */
+ MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(base_address,
+ (unsigned long)user_id, (unsigned long)irq_status_reg);
+#endif
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mbox_event_ack);
diff --git a/drivers/dsp/syslink/notify_dispatcher/hw_ocp.c b/drivers/dsp/syslink/notify_dispatcher/hw_ocp.c
new file mode 100644
index 000000000000..350fdf04cf2c
--- /dev/null
+++ b/drivers/dsp/syslink/notify_dispatcher/hw_ocp.c
@@ -0,0 +1,85 @@
+/*
+ * hw_ocp.c
+ *
+ * Syslink dispatcher driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/hw_ocp.h>
+#include <syslink/hw_defs.h>
+#include <syslink/MBXRegAcM.h>
+#include <syslink/MBXAccInt.h>
+#include <linux/module.h>
+
+
+long hw_ocp_soft_reset(const unsigned long base_address)
+{
+ long status = RET_OK;
+ MLBMAILBOX_SYSCONFIGSoftResetWrite32(base_address, HW_SET);
+ return status;
+}
+
+long hw_ocp_soft_reset_isdone(const unsigned long base_address,
+ unsigned long *reset_is_done)
+{
+ long status = RET_OK;
+
+ *reset_is_done = MLBMAILBOX_SYSSTATUSResetDoneRead32(base_address);
+
+ return status;
+}
+
+long hw_ocp_idle_modeset(const unsigned long base_address,
+ enum hal_ocp_idlemode_t idle_mode)
+{
+ long status = RET_OK;
+
+ MLBMAILBOX_SYSCONFIGSIdleModeWrite32(base_address, idle_mode);
+
+ return status;
+}
+
+
+long hw_ocp_idlemode_get(const unsigned long base_address,
+ enum hal_ocp_idlemode_t *idle_mode)
+{
+ long status = RET_OK;
+
+ *idle_mode = (enum hal_ocp_idlemode_t)
+ MLBMAILBOX_SYSCONFIGSIdleModeRead32(base_address);
+
+ return status;
+}
+
+long hw_ocp_autoidle_set(const unsigned long base_address,
+ enum hw_set_clear_t auto_idle)
+{
+ long status = RET_OK;
+
+ MLBMAILBOX_SYSCONFIGAutoIdleWrite32(base_address, auto_idle);
+
+ return status;
+}
+
+long hw_ocp_autoidle_get(const unsigned long base_address,
+ enum hw_set_clear_t *auto_idle)
+{
+ long status = RET_OK;
+
+ *auto_idle = (enum hw_set_clear_t)
+ MLBMAILBOX_SYSCONFIGAutoIdleRead32(base_address);
+
+ return status;
+}
+
diff --git a/drivers/dsp/syslink/notify_dispatcher/notify_dispatcher.c b/drivers/dsp/syslink/notify_dispatcher/notify_dispatcher.c
new file mode 100644
index 000000000000..d7de0460ced7
--- /dev/null
+++ b/drivers/dsp/syslink/notify_dispatcher/notify_dispatcher.c
@@ -0,0 +1,448 @@
+/*
+ * notify_dispatcher.c
+ *
+ * Syslnk IPC support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <syslink/GlobalTypes.h>
+#include <syslink/notify_dispatcher.h>
+#include <syslink/hw_mbox.h>
+#include <syslink/hw_ocp.h>
+#include <linux/delay.h>
+#include <mach/irqs.h>
+#include <linux/io.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Suman Anna");
+MODULE_AUTHOR("Hari Kanigeri");
+MODULE_DESCRIPTION("Dispatchers mailbox events");
+
+#define OMAP_MBOX_BASE 0x4A0F4000
+#define OMAP_MBOX_SIZE 0x2000
+
+struct mbox_isrs mailbx_swisrs;
+EXPORT_SYMBOL(mailbx_swisrs);
+
+struct mbox_config mailbx_hw_config;
+EXPORT_SYMBOL(mailbx_hw_config);
+
+
+unsigned long int i_mbox_module_no;
+unsigned long int i_a_irq_bit;
+const unsigned long int kmpu_mailboxes = 4;
+
+
+/* notify dispatcher module initialization function. */
+static int __init ntfy_disp_init_module(void) ;
+
+/* notify dispatcher module cleanup function. */
+static void __exit ntfy_disp_finalize_module(void) ;
+
+/*
+* Bind an ISR to the HW interrupt line coming into the processor
+*/
+irqreturn_t notify_mailbx0_user0_isr(int temp, void *anArg, struct pt_regs *p)
+{
+
+ REG int p_eventStatus = 0;
+ int mbox_index = mailbx_hw_config.mbox_modules - 1;
+ int i;
+
+ for (i = 0; i < mailbx_hw_config.mailboxes[mbox_index]; i++) {
+ /*Read the Event Status */
+ hw_mbox_event_status(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)(i), HW_MBOX_U0_ARM11,
+ (unsigned long *) &p_eventStatus);
+ if (p_eventStatus & HW_MBOX_INT_ALL) {
+ if ((mailbx_swisrs.isrs
+ [mbox_index][i*HW_MBOX_ID_WIDTH]) > 0) {
+ (*mailbx_swisrs.isrs[mbox_index][i
+ *HW_MBOX_ID_WIDTH])
+ (mailbx_swisrs.isr_params[mbox_index]
+ [i*HW_MBOX_ID_WIDTH]);
+
+ hw_mbox_event_ack(mailbx_hw_config.
+ mbox_linear_addr,
+ (enum hw_mbox_id_t)i,
+ HW_MBOX_U0_ARM11, HW_MBOX_INT_NEW_MSG);
+ }
+ }
+ }
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(notify_mailbx0_user0_isr);
+
+/*
+*
+* Bind an ISR to the HW interrupt line coming into the processor
+*/
+int ntfy_disp_bind_interrupt(int interrupt_no,
+ isr_call_back hw_isr, void *isr_arg)
+{
+ int status = 0;
+ bool valid_interrupt = false;
+ int i;
+
+ /*Validate the arguments*/
+ for (i = 0; i < mailbx_hw_config.mbox_modules; i++) {
+ if (interrupt_no == mailbx_hw_config.
+ interrupt_lines[i]) {
+ valid_interrupt = true;
+ break;
+ }
+ }
+ if (valid_interrupt != true)
+ status = -EINVAL;
+ if ((status == 0) && (hw_isr == NULL))
+ status = -EINVAL;
+ status =
+ request_irq(interrupt_no, (void *)hw_isr,
+ IRQF_SHARED, "mbox", notify_mailbx0_user0_isr);
+ if (status != 0)
+ printk(KERN_ALERT "REQUEST_IRQ FAILED\n");
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_bind_interrupt);
+/*
+*
+* Print the mailbox registers and other useful debug information
+*/
+void ntfy_disp_Debug(void)
+{
+ unsigned long p_eventStatus;
+ hw_mbox_event_status(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)1, HW_MBOX_U0_ARM11, &p_eventStatus);
+}
+
+/*
+*
+* Uninitialize the Notify disptacher Manager module
+*/
+int ntfy_disp_deinit(void)
+{
+ unsigned long int temp;
+ int i;
+
+ /*Reset the Mailbox module */
+ hw_ocp_soft_reset(mailbx_hw_config.mbox_linear_addr);
+ do {
+ hw_ocp_soft_reset_isdone(mailbx_hw_config.mbox_linear_addr,
+ &temp);
+ } while (temp == 0);
+
+ /*Reset the Configuration for the Mailbox modules on MPU */
+ for (i = 0; i < MAX_MBOX_MODULES; i++) {
+ if ((i < mailbx_hw_config.mbox_modules) &&
+ (mailbx_hw_config.interrupt_lines[i] != (-1)))
+ disable_irq((int)(mailbx_hw_config.interrupt_lines[i]));
+
+ mailbx_hw_config.interrupt_lines[i] = (-1);
+ mailbx_hw_config.mailboxes[i] = (-1);
+ }
+
+ if (mailbx_hw_config.mbox_linear_addr != NULL)
+ iounmap((unsigned int *) mailbx_hw_config.mbox_linear_addr);
+ mailbx_hw_config.mbox_modules = 0;
+ mailbx_hw_config.mbox_linear_addr = (unsigned long int) (-1);
+ return 0;
+}
+EXPORT_SYMBOL(ntfy_disp_deinit);
+/*
+*
+* Return the pointer to the Mailbox Manager's configuration object
+*/
+struct mbox_config *ntfy_disp_get_config(void)
+{
+ return &(mailbx_hw_config);
+}
+EXPORT_SYMBOL(ntfy_disp_get_config);
+/*
+*
+* Initialize the Mailbox Manager module and the mailbox hardware
+*/
+int ntfy_disp_init(void)
+{
+ int status = 0;
+ int i, j;
+
+ /*Initialize the configuration parameters for the Mailbox modules on
+ * MPU */
+ for (i = 0; i < MAX_MBOX_MODULES; i++) {
+ mailbx_hw_config.interrupt_lines[i] = (-1);
+ mailbx_hw_config.mailboxes[i] = (-1);
+ }
+ for (i = 0; i < MAX_MBOX_MODULES; i++) {
+ mailbx_swisrs.isrNo[i] = (-1);
+ for (j = 0; j < MAX_MBOX_ISRS; j++) {
+ mailbx_swisrs.isrs[i][j] = NULL;
+ mailbx_swisrs.isr_params[i][j] = NULL;
+ }
+ }
+ /*Setup the configuration parameters for the Mailbox modules on MPU */
+ mailbx_hw_config.mbox_linear_addr =
+ (u32)ioremap(OMAP_MBOX_BASE, OMAP_MBOX_SIZE);
+ mailbx_hw_config.mbox_modules = 1;
+ mailbx_hw_config.interrupt_lines[(mailbx_hw_config.mbox_modules-1)]
+ = INT_44XX_MAIL_U0_MPU;
+ mailbx_hw_config.mailboxes[(mailbx_hw_config.mbox_modules-1)]
+ = kmpu_mailboxes;
+
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_init);
+/*
+*
+* Disable a particular IRQ bit on a Mailbox IRQ Enable Register
+*/
+int ntfy_disp_interrupt_disable(unsigned long int mbox_module_no,
+ int a_irq_bit)
+{
+ int status = 0;
+
+ /*Validate the parameters */
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_irq_bit > (HW_MBOX_ID_WIDTH *
+ mailbx_hw_config.mailboxes[mbox_module_no-1])) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ /*Interrupts on transmission not supported currently */
+ if ((a_irq_bit % HW_MBOX_ID_WIDTH)) {
+ status = -EACCES;
+ goto func_end;
+ }
+ hw_mbox_event_disable(mailbx_hw_config.mbox_linear_addr ,
+ (enum hw_mbox_id_t)(a_irq_bit / HW_MBOX_ID_WIDTH),
+ HW_MBOX_U0_ARM11, HW_MBOX_INT_NEW_MSG);
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_interrupt_disable);
+/*
+*
+* Enable a particular IRQ bit on a Mailbox IRQ Enable Register
+*/
+int ntfy_disp_interrupt_enable(unsigned long int mbox_module_no,
+ int a_irq_bit)
+{
+ int status = 0;
+ /*Validate the parameters */
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_irq_bit > (HW_MBOX_ID_WIDTH *
+ mailbx_hw_config.mailboxes[mbox_module_no-1])) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (mailbx_swisrs.isrs[mbox_module_no-1][a_irq_bit] == NULL) {
+ status = -EFAULT;
+ goto func_end;
+ }
+ /*Interrupts on transmission not supported currently */
+ if (a_irq_bit % HW_MBOX_ID_WIDTH) {
+ status = -EACCES;
+ goto func_end;
+ }
+ hw_mbox_event_enable(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)(a_irq_bit / HW_MBOX_ID_WIDTH),
+ HW_MBOX_U0_ARM11, HW_MBOX_INT_NEW_MSG);
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_interrupt_enable);
+/*
+*
+* Read a message on a Mailbox FIFO queue
+*/
+int ntfy_disp_read(unsigned long int mbox_module_no,
+ int a_mbox_no, int *messages,
+ int *num_messages, short int read_all)
+{
+ int status = 0;
+
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_mbox_no >= mailbx_hw_config.mailboxes[mbox_module_no-1]) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (messages == NULL || num_messages == NULL) {
+ status = -EFAULT;
+ goto func_end;
+ }
+ /*Read a single message */
+ hw_mbox_nomsg_get(mailbx_hw_config.mbox_linear_addr ,
+ (enum hw_mbox_id_t)a_mbox_no, (unsigned long *const)num_messages);
+ if (*num_messages > 0) {
+ hw_mbox_msg_read(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)a_mbox_no, (unsigned long *const)messages);
+ } else
+ status = -EBUSY;
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_read);
+/*
+*
+* Register a ISR callback associated with a particular IRQ bit on a
+* Mailbox IRQ Enable Register and Also Reigisters a Interrupt Handler
+*/
+int ntfy_disp_register(unsigned long int mbox_module_no,
+ int a_irq_bit, isr_call_back isr_cbck_fn,
+ void *isrCallbackArgs)
+
+{
+ int status = 0;
+
+ i_mbox_module_no = mbox_module_no;
+ i_a_irq_bit = a_irq_bit;
+
+/*Validate the parameters */
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_irq_bit > (HW_MBOX_ID_WIDTH *
+ mailbx_hw_config.mailboxes[mbox_module_no-1])) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if ((isr_cbck_fn == NULL)) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_irq_bit % HW_MBOX_ID_WIDTH) {
+ status = -EINVAL;
+ goto func_end;
+ }
+
+ hw_mbox_event_disable(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)(a_irq_bit / HW_MBOX_ID_WIDTH),
+ HW_MBOX_U0_ARM11, HW_MBOX_INT_NEW_MSG);
+
+ mailbx_swisrs.isrs[mbox_module_no-1][a_irq_bit] = isr_cbck_fn;
+ mailbx_swisrs.isr_params[mbox_module_no-1][a_irq_bit] = isrCallbackArgs;
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_register);
+/*
+*
+* Send a message on a Mailbox FIFO queue
+*/
+int ntfy_disp_send(unsigned long int mbox_module_no,
+ int a_mbox_no, int message)
+{
+ int status = 0;
+
+ /*Validate the arguments */
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ if (a_mbox_no > mailbx_hw_config.mailboxes[mbox_module_no-1]) {
+ status = -EINVAL;
+ goto func_end;
+ }
+
+ /*Send the message */
+ hw_mbox_msg_write(mailbx_hw_config.mbox_linear_addr,
+ (enum hw_mbox_id_t)a_mbox_no, message);
+
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_send);
+/*
+*
+* Remove the ISR to the HW interrupt line coming into the processor
+*/
+int ntfy_disp_unbind_interrupt(int interrupt_no)
+{
+ int i;
+ short int valid_interrupt = false;
+
+ /*Validate the arguments*/
+ for (i = 0; i < mailbx_hw_config.mbox_modules; i++) {
+ if (interrupt_no == mailbx_hw_config.
+ interrupt_lines[i]) {
+ valid_interrupt = true;
+ break;
+ }
+ }
+ if (valid_interrupt != true)
+ return -EFAULT;
+ /*Unbind the HW Interrupt */
+ disable_irq(interrupt_no);
+ return 0;
+}
+EXPORT_SYMBOL(ntfy_disp_unbind_interrupt);
+/*
+*
+* Unregister a ISR callback associated with a particular IRQ bit on a
+* Mailbox IRQ Enable Register
+*/
+int ntfy_disp_unregister(unsigned long int mbox_module_no,
+ int a_irq_bit)
+{
+ int status = 0;
+
+ /*Validate the arguments */
+ if (mbox_module_no > mailbx_hw_config.mbox_modules) {
+ status = -EINVAL;
+ goto func_end;
+ }
+
+ if (a_irq_bit > (HW_MBOX_ID_WIDTH *
+ mailbx_hw_config.mailboxes[mbox_module_no-1])) {
+ status = -EINVAL;
+ goto func_end;
+ }
+
+ /*Interrupts on transmission not supported currently */
+ if (a_irq_bit % HW_MBOX_ID_WIDTH) {
+ status = -EINVAL;
+ goto func_end;
+ }
+ /*Remove the ISR plugin */
+ mailbx_swisrs.isrs[mbox_module_no-1][a_irq_bit] = NULL;
+ mailbx_swisrs.isr_params[mbox_module_no-1][a_irq_bit] = NULL;
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(ntfy_disp_unregister);
+
+/* Initialization function */
+static int __init ntfy_disp_init_module(void)
+{
+ ntfy_disp_init();
+ return 0;
+}
+
+/* Finalization function */
+static void __exit ntfy_disp_finalize_module(void)
+{
+ ntfy_disp_deinit();
+}
+
+module_init(ntfy_disp_init_module);
+module_exit(ntfy_disp_finalize_module);
diff --git a/drivers/dsp/syslink/notify_ducatidriver/Kbuild b/drivers/dsp/syslink/notify_ducatidriver/Kbuild
new file mode 100644
index 000000000000..fd82baca9f04
--- /dev/null
+++ b/drivers/dsp/syslink/notify_ducatidriver/Kbuild
@@ -0,0 +1,19 @@
+
+
+omap_ducatidriver = notify_ducati.o drv_ducati.o
+
+
+obj-$(CONFIG_NOTIFY_DUCATI) += notify_ducatidriver.o
+notify_ducatidriver-objs = $(omap_ducatidriver)
+
+
+ccflags-y += -Wno-strict-prototypes
+
+#Machine dependent
+ccflags-y += -DCONFIG_DISABLE_BRIDGE_PM -DDSP_TRACEBUF_DISABLED \
+ -DVPOM4430_1_06
+
+#Header files
+ccflags-y += -Idrivers/dsp/syslink/inc
+ccflags-y += -Iarch/arm/plat-omap/include/
+
diff --git a/drivers/dsp/syslink/notify_ducatidriver/drv_ducati.c b/drivers/dsp/syslink/notify_ducatidriver/drv_ducati.c
new file mode 100644
index 000000000000..20a848804459
--- /dev/null
+++ b/drivers/dsp/syslink/notify_ducatidriver/drv_ducati.c
@@ -0,0 +1,348 @@
+/*
+ * drv_ducatidrv.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+/* ----------------------------------- OS Specific Headers */
+#include <linux/autoconf.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/cdev.h>
+
+#include <linux/io.h>
+#include <asm/pgtable.h>
+#include <syslink/notifydefs.h>
+#include <syslink/notify_ducatidriver.h>
+#include <syslink/notify_ducatidriver_defs.h>
+#include <syslink/GlobalTypes.h>
+
+
+/** ============================================================================
+ * Macros and types
+ * ============================================================================
+ */
+#define NOTIFYDUCATI_NAME "notifyducatidrv"
+
+static char *driver_name = NOTIFYDUCATI_NAME;
+
+static s32 driver_major;
+
+static s32 driver_minor;
+
+struct notifyducati_dev {
+ struct cdev cdev;
+};
+
+static struct notifyducati_dev *notifyducati_device;
+
+static struct class *notifyducati_class;
+
+
+
+
+
+/* driver function to open the notify mailbox driver object. */
+static int drvducati_open(struct inode *inode, struct file *filp);
+static int drvducati_release(struct inode *inode, struct file *filp);
+static int drvducati_ioctl(struct inode *inode,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args);
+
+
+/* notify mailbox driver initialization function. */
+static int __init drvducati_initialize_module(void) ;
+
+/* notify mailbox driver cleanup function. */
+static void __exit drvducati_finalize_module(void) ;
+
+
+/* Function to invoke the APIs through ioctl. */
+static const struct file_operations driver_ops = {
+ .open = drvducati_open,
+ .release = drvducati_release,
+ .ioctl = drvducati_ioctl,
+
+};
+
+/* Initialization function */
+static int __init drvducati_initialize_module(void)
+{
+ int result = 0 ;
+ dev_t dev;
+
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ result = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ result = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ notifyducati_device = kmalloc(sizeof(struct notifyducati_dev),
+ GFP_KERNEL);
+ if (!notifyducati_device) {
+ result = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ goto func_end;
+ }
+ memset(notifyducati_device, 0, sizeof(struct notifyducati_dev));
+ cdev_init(&notifyducati_device->cdev, &driver_ops);
+ notifyducati_device->cdev.owner = THIS_MODULE;
+ notifyducati_device->cdev.ops = &driver_ops;
+
+ result = cdev_add(&notifyducati_device->cdev, dev, 1);
+
+ if (result) {
+ printk(KERN_ERR "Failed to add the syslink notify ducati device \n");
+ goto func_end;
+ }
+
+ /* udev support */
+ notifyducati_class = class_create(THIS_MODULE, "syslink-notifyducati");
+
+ if (IS_ERR(notifyducati_class)) {
+ printk(KERN_ERR "Error creating notifyducati class \n");
+ goto func_end;
+ }
+ device_create(notifyducati_class, NULL,
+ MKDEV(driver_major, driver_minor), NULL,
+ NOTIFYDUCATI_NAME);
+
+func_end:
+ return result ;
+}
+
+/* Finalization function */
+static void __exit drvducati_finalize_module(void)
+{
+ dev_t dev_no;
+
+ dev_no = MKDEV(driver_major, driver_minor);
+ if (notifyducati_device) {
+ cdev_del(&notifyducati_device->cdev);
+ kfree(notifyducati_device);
+ }
+ unregister_chrdev_region(dev_no, 1);
+ if (notifyducati_class) {
+ /* remove the device from sysfs */
+ device_destroy(notifyducati_class, MKDEV(driver_major,
+ driver_minor));
+ class_destroy(notifyducati_class);
+ }
+
+}
+/* driver open*/
+static int drvducati_open(struct inode *inode, struct file *filp)
+{
+ return 0 ;
+}
+
+/*drivr close*/
+static int drvducati_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+
+/*
+ * brief linux driver function to invoke the APIs through ioctl.
+ *
+ */
+static int drvducati_ioctl(struct inode *inode,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args)
+{
+ int status = 0;
+ int retval = 0;
+ struct notify_ducatidrv_cmdargs *cmd_args =
+ (struct notify_ducatidrv_cmdargs *) args;
+ struct notify_ducatidrv_cmdargs common_args;
+
+ switch (cmd) {
+ case CMD_NOTIFYDRIVERSHM_GETCONFIG: {
+ struct notify_ducatidrv_cmdargs_getconfig *src_args =
+ (struct notify_ducatidrv_cmdargs_getconfig *) args;
+ struct notify_ducatidrv_config cfg;
+ notify_ducatidrv_getconfig(&cfg);
+
+ retval = copy_to_user((void *)(src_args->cfg),
+ (const void *) &cfg,
+ sizeof(struct notify_ducatidrv_config));
+
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_SETUP: {
+ struct notify_ducatidrv_cmdargs_setup *src_args =
+ (struct notify_ducatidrv_cmdargs_setup *) args;
+ struct notify_ducatidrv_config cfg;
+ retval = copy_from_user((void *) &cfg,
+ (const void *)(src_args->cfg),
+ sizeof(struct notify_ducatidrv_config));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ status = notify_ducatidrv_setup(&cfg);
+ if (status < 0)
+ printk(KERN_ERR "FAIL: notify_ducatidrv_setup\n");
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_DESTROY: {
+ status = notify_ducatidrv_destroy();
+
+ if (status < 0)
+ printk(KERN_ERR "FAIL: notify_ducatidrv_destroy\n");
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_PARAMS_INIT: {
+ struct notify_ducatidrv_cmdargs_paramsinit src_args;
+ struct notify_ducatidrv_params params;
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(
+ struct notify_ducatidrv_cmdargs_paramsinit));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ notify_ducatidrv_params_init(src_args.handle, &params);
+
+ retval = copy_to_user((void *)(src_args.params),
+ (const void *) &params,
+ sizeof(struct notify_ducatidrv_params));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_CREATE: {
+ struct notify_ducatidrv_cmdargs_create src_args;
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_ducatidrv_cmdargs_create));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ src_args.handle = notify_ducatidrv_create(
+ src_args.driverName,
+ &(src_args.params));
+ if (src_args.handle == NULL) {
+ status = -EFAULT;
+ printk(KERN_ERR "drvducati_ioctl:status 0x%x,"
+ "NotifyDriverShm_create failed",
+ status);
+ }
+ retval = copy_to_user((void *)(args),
+ (const void *) &src_args,
+ sizeof(struct notify_ducatidrv_cmdargs_create));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_DELETE: {
+ struct notify_ducatidrv_cmdargs_delete src_args;
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_ducatidrv_cmdargs_delete));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ status = notify_ducatidrv_delete(&(src_args.handle));
+ if (status < 0)
+ printk(KERN_ERR "drvducati_ioctl:"
+ " notify_ducatidrv_delete failed"
+ " status = %d\n", status);
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_OPEN: {
+ struct notify_ducatidrv_cmdargs_open src_args;
+
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_ducatidrv_cmdargs_open));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ status = notify_ducatidrv_open(src_args.driverName,
+ &(src_args.handle));
+ if (status < 0)
+ printk(KERN_ERR "drvducati_ioctl:"
+ " notify_ducatidrv_open failed"
+ " status = %d\n", status);
+ retval = copy_to_user((void *)(args),
+ (const void *) &src_args,
+ sizeof(struct notify_ducatidrv_cmdargs_open));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ }
+ break;
+
+ case CMD_NOTIFYDRIVERSHM_CLOSE: {
+ struct notify_ducatidrv_cmdargs_close src_args;
+
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_ducatidrv_cmdargs_close));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ status = notify_ducatidrv_close(&(src_args.handle));
+ if (status < 0)
+ printk(KERN_ERR "drvducati_ioctl:"
+ " notify_ducatidrv_close"
+ " failed status = %d\n", status);
+ }
+ break;
+
+ default: {
+ status = -EINVAL;
+ printk(KERN_ERR "drivducati_ioctl:Unsupported"
+ " ioctl command specified");
+ }
+ break;
+ }
+
+func_end:
+ /* Set the status and copy the common args to user-side. */
+ common_args.api_status = status;
+ status = copy_to_user((void *) cmd_args,
+ (const void *) &common_args,
+ sizeof(struct notify_ducatidrv_cmdargs));
+
+ if (status < 0)
+ retval = -EFAULT;
+
+ return retval;
+}
+
+
+
+
+MODULE_LICENSE("GPL");
+module_init(drvducati_initialize_module);
+module_exit(drvducati_finalize_module);
diff --git a/drivers/dsp/syslink/notify_ducatidriver/notify_ducati.c b/drivers/dsp/syslink/notify_ducatidriver/notify_ducati.c
new file mode 100644
index 000000000000..4d14a9302703
--- /dev/null
+++ b/drivers/dsp/syslink/notify_ducatidriver/notify_ducati.c
@@ -0,0 +1,1249 @@
+/*
+ * notify_ducati.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <mach/mailbox.h>
+
+#include <syslink/notify_driver.h>
+#include <syslink/notifydefs.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/notify_ducatidriver.h>
+#include <syslink/multiproc.h>
+#include <syslink/atomic_linux.h>
+
+
+
+#define NOTIFYSHMDRV_MEM_ALIGN 0
+
+#define NOTIFYSHMDRV_MAX_EVENTS 32
+
+#define NOTIFYSHMDRV_INIT_STAMP 0xA9C8B7D6
+
+#define NOTIFYNONSHMDRV_MAX_EVENTS 1
+
+#define NOTIFYNONSHMDRV_RESERVED_EVENTS 1
+
+#define NOTIFYDRV_DUCATI_RECV_MBX 2
+
+#define NOTIFYDRV_DUCATI_SEND_MBX 3
+
+/*FIX ME: Make use of Multi Proc module */
+#define SELF_ID 0
+
+#define OTHER_ID 1
+
+#define UP 1
+
+#define DOWN 0
+
+#define PROC_TESLA 0
+#define PROC_DUCATI 1
+#define PROC_GPP 2
+#define PROCSYSM3 2
+#define PROCAPPM3 3
+#define MAX_SUBPROC_EVENTS 15
+
+/*FIXME MOVE THIS TO A SUITABLE HEADER */
+#define NOTIFYDRIVERSHM_MODULEID (u32) 0xb9d4
+
+/* Macro to make a correct module magic number with refCount */
+#define NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(x) \
+ ((NOTIFYDRIVERSHM_MODULEID << 12u) | (x))
+
+static struct omap_mbox *ducati_mbox;
+static void notify_ducatidrv_isr(void *ntfy_msg);
+static void notify_ducatidrv_isr_callback(void *ref_data, void* ntfy_msg);
+
+struct notify_driver_object_list {
+ struct list_head elem;
+ struct notify_driver_object *drv_handle;
+};
+
+
+/*
+ * brief Notify ducati driver instance object.
+ */
+struct notify_ducatidrv_object {
+ struct notify_ducatidrv_params params;
+ short int proc_id;
+ struct notify_drv_eventlist *event_list;
+ VOLATILE struct notify_shmdrv_ctrl *ctrl_ptr;
+ struct notify_shmdrv_eventreg *reg_chart;
+ struct notify_driver_object *drv_handle;
+ short int self_id;
+ short int other_id;
+};
+
+
+/*
+ * brief Defines the notify_ducatidrv state object, which contains all
+ * the module specific information.
+ */
+struct notify_ducatidrv_module {
+ atomic_t ref_count;
+ struct notify_ducatidrv_config cfg;
+ struct notify_ducatidrv_config def_cfg;
+ struct notify_ducatidrv_params def_inst_params;
+ struct mutex *gate_handle;
+ struct list_head drv_handle_list;
+} ;
+
+
+static struct notify_ducatidrv_module notify_ducatidriver_state = {
+ .gate_handle = NULL,
+ .def_inst_params.shared_addr = 0x0,
+ .def_inst_params.shared_addr_size = 0x0,
+ .def_inst_params.num_events = NOTIFYSHMDRV_MAX_EVENTS,
+ .def_inst_params.num_reserved_events = 3,
+ .def_inst_params.send_event_poll_count = (int) -1,
+ .def_inst_params.remote_proc_id = -1,
+ .def_inst_params.recv_int_id = (int) -1,
+ .def_inst_params.send_int_id = (int) -1
+};
+
+/*
+ * This function searchs for a element the List.
+ */
+static void notify_ducatidrv_qsearch_elem(struct list_head *list,
+ struct notify_drv_eventlistner *check_obj,
+ struct notify_drv_eventlistner **listener);
+
+
+/*
+ * brief Get the default configuration for the notify_ducatidrv module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to notify_ducatidrv_setup filled in by
+ * the notify_ducatidrv module with the default parameters. If the
+ * user does not wish to make any change in the default parameters,
+ * this API is not required to be called.
+ *
+ */
+void notify_ducatidrv_getconfig(struct notify_ducatidrv_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true)
+ memcpy(cfg,
+ &(notify_ducatidriver_state.def_cfg),
+ sizeof(struct notify_ducatidrv_config));
+ else
+ memcpy(cfg,
+ &(notify_ducatidriver_state.cfg),
+ sizeof(struct notify_ducatidrv_config));
+}
+EXPORT_SYMBOL(notify_ducatidrv_getconfig);
+
+/*
+ * brief Function to open a handle to an existing notify_ducatidrv_object
+ * handling the procId.
+ *
+ * This function returns a handle to an existing notify_ducatidrv
+ * instance created for this procId. It enables other entities to
+ * access and use this notify_ducatidrv instance.
+ */
+int notify_ducatidrv_open(char *driver_name,
+ struct notify_driver_object **handle_ptr)
+{
+ int status = 0;
+ BUG_ON(driver_name == NULL);
+ BUG_ON(handle_ptr == NULL);
+ /* Enter critical section protection. */
+ WARN_ON(mutex_lock_interruptible(notify_ducatidriver_state.
+ gate_handle) != 0);
+ /* Get the handle from Notify module. */
+ status = notify_get_driver_handle(driver_name, handle_ptr);
+ WARN_ON(status < 0);
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ return status;
+}
+
+
+
+
+/*
+ * brief Function to close this handle to the notify_ducatidrv instance.
+ *
+ * This function closes the handle to the notify_ducatidrv instance
+ * obtained through notify_ducatidrv_open call made earlier.
+ */
+int notify_ducatidrv_close(struct notify_driver_object **handle_ptr)
+{
+ int status = 0;
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(*handle_ptr == NULL);
+ *handle_ptr = NULL;
+ return status;
+}
+
+
+
+
+/*
+ * brief Function to initialize the parameters for this notify_ducatidrv
+ * instance.
+ */
+void notify_ducatidrv_params_init(struct notify_driver_object *handle,
+ struct notify_ducatidrv_params *params)
+{
+ struct notify_ducatidrv_object *driver_obj;
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /*FIXME not intialized to be returned */
+ BUG_ON(1);
+ }
+
+ if (handle == NULL) {
+ memcpy(params,
+ &(notify_ducatidriver_state.def_inst_params),
+ sizeof(struct notify_ducatidrv_params));
+ } else {
+ /*Return updated notify_ducatidrv instance specific parameters*/
+ driver_obj = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+ memcpy(params, &(driver_obj->params),
+ sizeof(struct notify_ducatidrv_params));
+ }
+}
+EXPORT_SYMBOL(notify_ducatidrv_params_init);
+
+
+
+/*
+ * brief Function to create an instance of this Notify ducati driver.
+ *
+ */
+struct notify_driver_object *notify_ducatidrv_create(char *driver_name,
+ const struct notify_ducatidrv_params *params)
+{
+
+ int status = 0;
+ struct notify_ducatidrv_object *driver_obj = NULL;
+ struct notify_driver_object *drv_handle = NULL;
+ struct notify_drv_eventlist *event_list = NULL;
+ VOLATILE struct notify_shmdrv_proc_ctrl *ctrl_ptr = NULL;
+ struct notify_driver_attrs drv_attrs;
+ struct notify_interface fxn_table;
+ struct notify_driver_object_list *drv_handle_inst = NULL;
+ int proc_id;
+ int i;
+ u32 shm_va;
+ int tmp_status = NOTIFY_SUCCESS;
+
+ BUG_ON(driver_name == NULL);
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "Module not initialized\n");
+ goto func_end;
+ }
+
+ if (params->num_events > NOTIFYSHMDRV_MAX_EVENTS) {
+ printk(KERN_ERR "More than max number of events passed\n");
+ goto func_end;
+ }
+ WARN_ON(mutex_lock_interruptible(notify_ducatidriver_state.
+ gate_handle) != 0);
+ proc_id = PROC_DUCATI;
+
+ tmp_status = notify_get_driver_handle(driver_name, &drv_handle);
+
+ if (tmp_status != NOTIFY_E_NOTFOUND) {
+ printk(KERN_ERR "Driver handle not found\n");
+ goto error_unlock_and_return;
+ }
+
+ /* Fill in information about driver attributes. */
+ /* This driver supports interaction with one other remote
+ * processor.*/
+
+ for (i = 0 ; i < MULTIPROC_MAXPROCESSORS; i++) {
+ /* Initialize all to invalid. */
+ drv_attrs.proc_info[i].proc_id = (u16)0xFFFF;
+ }
+
+ /*FIXME: Hack to allow SYSM3 and APPM3 events. Re-visit later */
+ if (params->remote_proc_id >= PROCSYSM3) {
+ for (i = PROCSYSM3; i <= PROCAPPM3; i++) {
+ drv_attrs.numProc = 1;
+ drv_attrs.proc_info[i].max_events = params->num_events;
+ drv_attrs.proc_info[i].reserved_events =
+ params->num_reserved_events;
+ /* Events are prioritized. */
+ drv_attrs.proc_info[i].event_priority = true;
+ /* 32-bit payload supported. */
+ drv_attrs.proc_info[i].payload_size = sizeof(int);
+ drv_attrs.proc_info[i].proc_id = i;
+ }
+ }
+
+ /* Function table information */
+ fxn_table.register_event = (void *)&notify_ducatidrv_register_event;
+ fxn_table.unregister_event = (void *)&notify_ducatidrv_unregister_event;
+ fxn_table.send_event = (void *)&notify_ducatidrv_sendevent;
+ fxn_table.disable = (void *)&notify_ducatidrv_disable;
+ fxn_table.restore = (void *)&notify_ducatidrv_restore;
+ fxn_table.disable_event = (void *)&notify_ducatidrv_disable_event;
+ fxn_table.enable_event = (void *)&notify_ducatidrv_enable_event;
+
+ /* Register driver with the Notify module. */
+ status = notify_register_driver(driver_name,
+ &fxn_table,
+ &drv_attrs,
+ &drv_handle);
+ /*FIXME: To take care of already exists case */
+ if ((status != NOTIFY_SUCCESS) && (status != NOTIFY_E_ALREADYEXISTS)) {
+ printk(KERN_ERR "Notify register failed\n");
+ goto error_clean_and_exit;
+ }
+ /* Allocate memory for the notify_ducatidrv_object object. */
+ drv_handle->driver_object = driver_obj =
+ kmalloc(sizeof(struct notify_ducatidrv_object),
+ GFP_ATOMIC);
+
+ if (driver_obj == NULL) {
+ status = -ENOMEM;
+ goto error_clean_and_exit;
+ } else {
+ memcpy(&(driver_obj->params), (void *) params,
+ sizeof(struct notify_ducatidrv_params));
+ }
+
+ if (params->remote_proc_id > multiproc_get_id(NULL)) {
+ driver_obj->self_id = SELF_ID;
+ driver_obj->other_id = OTHER_ID;
+ } else {
+ driver_obj->self_id = OTHER_ID;
+ driver_obj->other_id = SELF_ID;
+ }
+
+ shm_va = get_ducati_virt_mem();
+ driver_obj->ctrl_ptr = (struct notify_shmdrv_ctrl *) shm_va;
+ ctrl_ptr = &(driver_obj->ctrl_ptr->
+ proc_ctrl[driver_obj->self_id]);
+ ctrl_ptr->self_event_chart =
+ (struct notify_shmdrv_event_entry *)
+ ((int)(driver_obj->ctrl_ptr)
+ + sizeof(struct notify_shmdrv_ctrl)+
+ (sizeof(struct
+ notify_shmdrv_event_entry)
+ * params->num_events
+ * driver_obj->other_id));
+
+ ctrl_ptr->other_event_chart =
+ (struct notify_shmdrv_event_entry *)
+ ((int)(driver_obj->ctrl_ptr)
+ + sizeof(struct notify_shmdrv_ctrl) +
+ (sizeof(struct
+ notify_shmdrv_event_entry)
+ * params->num_events
+ * driver_obj->self_id));
+ driver_obj->proc_id = params->remote_proc_id;
+ driver_obj->event_list = kmalloc(
+ (sizeof(struct notify_drv_eventlist)
+ * params->num_events), GFP_ATOMIC);
+ if (driver_obj->event_list == NULL) {
+ status = -ENOMEM;
+ goto error_clean_and_exit;
+ } else {
+ memset(driver_obj->event_list, 0,
+ sizeof(struct notify_drv_eventlist)*params->
+ num_events);
+ }
+
+ driver_obj->reg_chart = kmalloc(sizeof(
+ struct notify_shmdrv_eventreg)
+ *params->num_events,
+ GFP_ATOMIC);
+ if (driver_obj->reg_chart == NULL) {
+ status = -ENOMEM;
+ goto error_clean_and_exit;
+ } else {
+ memset(driver_obj->reg_chart, 0,
+ sizeof(struct notify_shmdrv_eventreg)
+ *params->num_events);
+ }
+
+ event_list = driver_obj->event_list;
+
+ for (i = 0 ; (i < params->num_events) ; i++) {
+ ctrl_ptr->self_event_chart[i].flag = 0;
+ driver_obj->reg_chart[i].reg_event_no = (int) -1;
+ event_list[i].event_handler_count = 0;
+ INIT_LIST_HEAD(&event_list[i].listeners);
+ }
+
+ /*Set up the ISR on the Modena-ducati FIFO */
+ /* Add the driver handle to list */
+ drv_handle_inst = kmalloc(sizeof
+ (struct notify_driver_object_list), GFP_ATOMIC);
+ if (drv_handle_inst == NULL) {
+ status = -ENOMEM;
+ goto error_clean_and_exit;
+ }
+
+ drv_handle_inst->drv_handle = drv_handle;
+ list_add_tail(&(drv_handle_inst->elem),
+ &(notify_ducatidriver_state.drv_handle_list));
+
+ driver_obj = drv_handle->driver_object;
+ ctrl_ptr->reg_mask.mask = 0x0;
+ ctrl_ptr->reg_mask.enable_mask = 0xFFFFFFFF;
+ ctrl_ptr->recv_init_status = NOTIFYSHMDRV_INIT_STAMP;
+ ctrl_ptr->send_init_status = NOTIFYSHMDRV_INIT_STAMP;
+ drv_handle->is_init = NOTIFY_DRIVERINITSTATUS_DONE;
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ omap_mbox_enable_irq(ducati_mbox, IRQ_RX);
+
+ /* Done with initialization. goto function end */
+ goto func_end;
+
+error_clean_and_exit:
+ if (drv_handle != NULL) {
+ /* Unregister driver from the Notify module*/
+ notify_unregister_driver(drv_handle);
+ if (ctrl_ptr != NULL) {
+ /* Clear initialization status in
+ shared memory. */
+ ctrl_ptr->recv_init_status = 0x0;
+ ctrl_ptr->send_init_status = 0x0;
+ ctrl_ptr = NULL;
+ }
+ /* Check if driverObj was allocated. */
+ if (driver_obj != NULL) {
+ /* Check if event List was allocated. */
+ if (driver_obj->event_list != NULL) {
+ /* Check if lists were
+ created. */
+ for (i = 0 ;
+ i < params->num_events ; i++) {
+ list_del(
+ (struct list_head *)
+ &driver_obj->
+ event_list[i].
+ listeners);
+ }
+ kfree(driver_obj->event_list);
+ driver_obj->event_list = NULL;
+ }
+ /* Check if regChart was allocated. */
+ if (driver_obj->reg_chart != NULL) {
+ kfree(driver_obj->reg_chart);
+ driver_obj->reg_chart
+ = NULL;
+ }
+ kfree(driver_obj);
+ }
+ drv_handle->is_init =
+ NOTIFY_DRIVERINITSTATUS_NOTDONE;
+ drv_handle = NULL;
+ }
+
+error_unlock_and_return:
+ /* Leave critical section protection. */
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+func_end:
+ return drv_handle;
+}
+EXPORT_SYMBOL(notify_ducatidrv_create);
+
+/*
+ * brief Function to delete the instance of shared memory driver
+ *
+ */
+int notify_ducatidrv_delete(struct notify_driver_object **handle_ptr)
+{
+ int status = 0;
+ struct notify_driver_object *drv_handle = NULL;
+ struct notify_ducatidrv_object *driver_obj = NULL;
+ struct notify_drv_eventlist *event_list;
+ short int i = 0;
+ struct list_head *elem = NULL;
+ struct notify_driver_object_list *drv_list_entry = NULL;
+ int proc_id;
+
+ if (atomic_cmpmask_and_lt(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /*FIXME not intialized to be returned */
+ return -1;
+ }
+
+ WARN_ON(handle_ptr == NULL);
+ if (handle_ptr == NULL)
+ return -1;
+ driver_obj = (struct notify_ducatidrv_object *)
+ (*handle_ptr)->driver_object;
+ drv_handle = (*handle_ptr);
+ WARN_ON((*handle_ptr)->driver_object == NULL);
+
+ /*Uninstall the ISRs & Disable the Mailbox interrupt.*/
+
+ if (drv_handle != NULL) {
+ list_for_each(elem,
+ &notify_ducatidriver_state.drv_handle_list) {
+ drv_list_entry = container_of(elem,
+ struct notify_driver_object_list, elem);
+ if (drv_list_entry->drv_handle == drv_handle) {
+ list_del(elem);
+ kfree(drv_list_entry);
+ status = notify_unregister_driver(drv_handle);
+ drv_handle = NULL;
+ break;
+ }
+ }
+ }
+
+ if (status != NOTIFY_SUCCESS)
+ printk(KERN_WARNING "driver is not registerd\n");
+
+ if (driver_obj != NULL) {
+ if (driver_obj->ctrl_ptr != NULL) {
+ /* Clear initialization status in shared memory. */
+ driver_obj->ctrl_ptr->proc_ctrl[driver_obj->self_id].
+ recv_init_status = 0x0;
+ driver_obj->ctrl_ptr->proc_ctrl[driver_obj->self_id].
+ send_init_status = 0x0;
+ unmap_ducati_virt_mem((u32)(driver_obj->ctrl_ptr));
+ driver_obj->ctrl_ptr = NULL;
+ }
+
+ event_list = driver_obj->event_list;
+ if (event_list != NULL) {
+ /* Check if lists were created. */
+ for (i = 0 ; i < driver_obj->params.num_events ; i++) {
+ WARN_ON(event_list[i].event_handler_count != 0);
+ event_list[i].event_handler_count = 0;
+ list_del((struct list_head *)
+ &event_list[i].listeners);
+ }
+
+ kfree(event_list);
+ driver_obj->event_list = NULL;
+ }
+
+ /* Check if regChart was allocated. */
+ if (driver_obj->reg_chart != NULL) {
+ kfree(driver_obj->reg_chart);
+ driver_obj->reg_chart = NULL;
+ }
+
+ /* Disable the interrupt, Uninstall the ISR and delete it. */
+ /* Check if ISR was created. */
+ /*Remove the ISR on the Modena-ducati FIFO */
+ proc_id = PROC_DUCATI;
+
+ omap_mbox_disable_irq(ducati_mbox, IRQ_RX);
+
+ kfree(driver_obj);
+ driver_obj = NULL;
+ }
+ return status;
+}
+EXPORT_SYMBOL(notify_ducatidrv_delete);
+
+
+/*
+ * brief Destroy the notify_ducatidrv module.
+ *
+ */
+int notify_ducatidrv_destroy(void)
+{
+ int status = 0;
+ struct list_head *handle_list = NULL;
+ struct notify_driver_object_list *entry_list = NULL;
+ struct notify_driver_object *drv_handle = NULL;
+ struct list_head *entry;
+
+ if (atomic_cmpmask_and_lt(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true)
+ /* FIXME Invalid state to be reuurned. */
+ return -1;
+
+ if (atomic_dec_return(&(notify_ducatidriver_state.ref_count)) ==
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0)) {
+
+ /* Temprarily increment the refcount */
+ atomic_set(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1));
+ handle_list = &(notify_ducatidriver_state.drv_handle_list);
+
+ list_for_each(entry, handle_list) {
+ entry_list = (struct notify_driver_object_list *)
+ container_of(entry,
+ struct notify_driver_object_list, elem);
+ drv_handle = entry_list->drv_handle;
+ notify_ducatidrv_delete(&drv_handle);
+ }
+
+ /* Check if the gate_handle was created internally. */
+
+ if (notify_ducatidriver_state.gate_handle != NULL)
+ kfree(notify_ducatidriver_state.gate_handle);
+
+ atomic_set(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+
+ omap_mbox_put(ducati_mbox);
+ ducati_mbox = NULL;
+ }
+
+
+ return status;
+}
+EXPORT_SYMBOL(notify_ducatidrv_destroy);
+
+
+
+/*
+ * brief Setup the notify_ducatidrv module.
+ *
+ * This function sets up the notify_ducatidrv module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then notify_ducatidrv_getconfig can be called to get
+ * the configuration filled with the default values. After this,
+ * only the required configuration values can be changed. If the
+ * user does not wish to make any change in the default parameters,
+ * the application can simply call notify_ducatidrv_setup with NULL
+ * parameters. The default parameters would get automatically used.
+ */
+int notify_ducatidrv_setup(struct notify_ducatidrv_config *cfg)
+{
+ int status = 0;
+ struct notify_ducatidrv_config tmp_cfg;
+
+ if (cfg == NULL) {
+ notify_ducatidrv_getconfig(&tmp_cfg);
+ cfg = &tmp_cfg;
+ }
+
+ /* Init the ref_count to 0 */
+ atomic_cmpmask_and_set(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+ if (atomic_inc_return(&(notify_ducatidriver_state.ref_count)) !=
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1u)) {
+ return 1;
+ }
+
+
+ /* Create a default gate handle here */
+ notify_ducatidriver_state.gate_handle =
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ mutex_init(notify_ducatidriver_state.gate_handle);
+
+ if (notify_ducatidriver_state.gate_handle == NULL) {
+ atomic_set(&(notify_ducatidriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+ status = -ENOMEM;
+ goto error_exit;
+ } else {
+ memcpy(&notify_ducatidriver_state.cfg,
+ cfg, sizeof(struct notify_ducatidrv_config));
+ }
+
+ INIT_LIST_HEAD(&(notify_ducatidriver_state.
+ drv_handle_list));
+ /* Initialize the maibox modulde for ducati */
+ if (ducati_mbox == NULL) {
+ ducati_mbox = omap_mbox_get("mailbox-2");
+ if (ducati_mbox == NULL) {
+ printk(KERN_ERR "Failed in omap_mbox_get()\n");
+ status = -ENODEV;
+ goto error_mailbox_get_failed;
+ }
+ ducati_mbox->rxq->callback =
+ (int (*)(void *))notify_ducatidrv_isr;
+ }
+
+ return 0;
+
+error_mailbox_get_failed:
+ kfree(notify_ducatidriver_state.gate_handle);
+error_exit:
+ return status;
+}
+EXPORT_SYMBOL(notify_ducatidrv_setup);
+
+
+/*
+* brief register a callback for an event with the Notify driver.
+*
+*/
+int notify_ducatidrv_register_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg)
+{
+ int status = 0;
+ int first_reg = false;
+ bool done = true;
+ struct notify_drv_eventlistner *event_listener;
+ struct notify_drv_eventlist *event_list;
+ struct notify_ducatidrv_object *driver_object;
+ struct notify_shmdrv_eventreg *reg_chart;
+ VOLATILE struct notify_shmdrv_ctrl *ctrl_ptr;
+ VOLATILE struct notify_shmdrv_event_entry *self_event_chart;
+ int i;
+ int j;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->is_init != NOTIFY_DRIVERINITSTATUS_DONE);
+ BUG_ON(handle->driver_object == NULL);
+ BUG_ON(fn_notify_cbck == NULL);
+
+
+ driver_object = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+ /* Allocate memory for event listener. */
+ event_listener = kmalloc(sizeof(struct notify_drv_eventlistner),
+ GFP_ATOMIC);
+
+ if (event_listener == NULL) {
+ status = -ENOMEM;
+ goto func_end;
+ } else {
+ memset(event_listener, 0,
+ sizeof(struct notify_drv_eventlistner));
+ }
+
+ if (mutex_lock_interruptible(notify_ducatidriver_state.gate_handle)
+ != 0)
+ WARN_ON(1);
+
+ event_list = driver_object->event_list;
+ WARN_ON(event_list == NULL);
+ event_listener->fn_notify_cbck = fn_notify_cbck;
+ event_listener->cbck_arg = cbck_arg;
+ /* Check if this is the first registration for this event. */
+
+ if (list_empty((struct list_head *)
+ &event_list[event_no].listeners)) {
+ first_reg = true;
+ self_event_chart = ctrl_ptr->proc_ctrl[driver_object->self_id].
+ self_event_chart;
+ /* Clear any pending unserviced event as there are no listeners
+ * for the pending event
+ */
+ self_event_chart[event_no].flag = DOWN;
+ }
+
+ list_add_tail((struct list_head *)
+ &(event_listener->element),
+ (struct list_head *)
+ &event_list[event_no].listeners);
+ event_list[event_no].event_handler_count++;
+
+
+ if (first_reg == true) {
+ reg_chart = driver_object->reg_chart;
+ for (i = 0 ; i < driver_object->params.num_events ; i++) {
+ /* Find the correct slot in the registration array. */
+ if (reg_chart[i].reg_event_no == (int) -1) {
+ for (j = (i - 1); j >= 0; j--) {
+ if (event_no < reg_chart[j].
+ reg_event_no) {
+ reg_chart[j + 1].reg_event_no =
+ reg_chart[j].
+ reg_event_no;
+ reg_chart[j + 1].reserved =
+ reg_chart[j].reserved;
+ i = j;
+ } else {
+ /* End the loop, slot found. */
+ j = -1;
+ }
+ }
+ reg_chart[i].reg_event_no = event_no;
+ done = true;
+ break;
+ }
+ }
+
+ if (done) {
+ set_bit(event_no, (unsigned long *)
+ &ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.mask);
+ } else {
+ /*retval NOTIFY_E_MAXEVENTS Maximum number of
+ supported events have already been registered. */
+ status = -EINVAL;
+ kfree(event_listener);
+
+ }
+ }
+func_end:
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ return status;
+}
+
+
+/*
+*
+* brief Unregister a callback for an event with the Notify driver.
+*
+*/
+
+int notify_ducatidrv_unregister_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg)
+{
+ int status = 0;
+ struct notify_drv_eventlistner *listener = NULL;
+ int num_events;
+ struct notify_ducatidrv_object *driver_object;
+ struct notify_drv_eventlist *event_list;
+ struct notify_shmdrv_eventreg *reg_chart;
+ VOLATILE struct notify_shmdrv_ctrl *ctrl_ptr = NULL;
+ struct notify_drv_eventlistner unreg_info;
+ VOLATILE struct notify_shmdrv_event_entry *self_event_chart;
+ int i;
+ int j;
+
+ BUG_ON(fn_notify_cbck == NULL);
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+ driver_object = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+ num_events = driver_object->params.num_events;
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+
+ /* Enter critical section protection. */
+ if (mutex_lock_interruptible(notify_ducatidriver_state.gate_handle)
+ != 0)
+ WARN_ON(1);
+
+ event_list = driver_object->event_list;
+
+
+ unreg_info.fn_notify_cbck = fn_notify_cbck;
+ unreg_info.cbck_arg = cbck_arg;
+ notify_ducatidrv_qsearch_elem(&event_list[event_no].listeners,
+ &unreg_info,
+ &listener);
+ if (listener == NULL) {
+ status = -EFAULT;
+ goto func_end;
+ }
+ list_del((struct list_head *)&(listener->element));
+ kfree(listener);
+ event_list[event_no].event_handler_count--;
+
+
+ if (list_empty((struct list_head *)
+ &event_list[event_no].listeners) == true) {
+ clear_bit(event_no, (unsigned long *)
+ &ctrl_ptr->proc_ctrl[driver_object->self_id].reg_mask.
+ mask);
+ self_event_chart = ctrl_ptr->proc_ctrl[driver_object->self_id].
+ self_event_chart;
+ /* Clear any pending unserviced event as there are no
+ * listeners for the pending event
+ */
+ self_event_chart[event_no].flag = DOWN;
+ reg_chart = driver_object->reg_chart;
+ for (i = 0; i < num_events; i++) {
+ /* Find the correct slot in the registration array. */
+ if (event_no == reg_chart[i].reg_event_no) {
+ reg_chart[i].reg_event_no = (int) -1;
+ for (j = (i + 1);
+ (reg_chart[j].reg_event_no != (int) -1)
+ && (j != num_events); j++) {
+ reg_chart[j - 1].reg_event_no =
+ reg_chart[j].reg_event_no;
+ reg_chart[j - 1].reserved =
+ reg_chart[j].reserved;
+ }
+
+ if (j == num_events) {
+ reg_chart[j - 1].reg_event_no =
+ (int) -1;
+ }
+ break;
+ }
+ }
+ }
+
+
+
+func_end:
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ return status;
+}
+
+/*
+* brief Send a notification event to the registered users for this
+* notification on the specified processor.
+*
+*/
+int notify_ducatidrv_sendevent(struct notify_driver_object *handle,
+ short int proc_id, int event_no,
+ int payload, short int wait_clear)
+{
+ int status = 0;
+ struct notify_ducatidrv_object *driver_object;
+ VOLATILE struct notify_shmdrv_ctrl *ctrl_ptr;
+ int max_poll_count;
+ VOLATILE struct notify_shmdrv_event_entry *other_event_chart;
+
+ int i = 0;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+
+ driver_object = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+
+ BUG_ON(event_no > driver_object->params.num_events);
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+ other_event_chart = ctrl_ptr->proc_ctrl[driver_object->self_id].
+ other_event_chart;
+ max_poll_count = driver_object->params.send_event_poll_count;
+
+ /* Check whether driver supports interrupts from this processor to the
+ other processor, and if it is initialized
+ */
+ if (ctrl_ptr->proc_ctrl[driver_object->other_id].recv_init_status
+ != NOTIFYSHMDRV_INIT_STAMP) {
+ status = -ENODEV;
+ /* This may be used for polling till other-side
+ driver is ready, sodo not set failure reason.
+ */
+ } else {
+ /* Check if other side is ready to receive this event. */
+ if ((test_bit(event_no, (unsigned long *)
+ &ctrl_ptr->proc_ctrl[driver_object->other_id].
+ reg_mask.mask) != 1)
+ || (test_bit(event_no, &ctrl_ptr->
+ proc_ctrl[driver_object->other_id].reg_mask.
+ enable_mask) != 1)) {
+ status = -ENODEV;
+ /* This may be used for polling till other-side
+ is ready, so do not set failure reason.*/
+ } else {
+ /* Enter critical section protection. */
+ if (mutex_lock_interruptible(notify_ducatidriver_state.
+ gate_handle) != 0)
+ WARN_ON(1);
+ if (wait_clear == true) {
+ /*Wait for completion of prev
+ event from other side*/
+ while ((other_event_chart[event_no].flag
+ != DOWN)
+ && status == 0) {
+ /* Leave critical section protection
+ Create a window of opportunity
+ for other interrupts to be handled.
+ */
+ mutex_unlock(notify_ducatidriver_state.
+ gate_handle);
+ i++;
+ if ((max_poll_count != (int) -1)
+ && (i == max_poll_count)) {
+ status = -EBUSY;
+ }
+ /* Enter critical section protection. */
+ if (mutex_lock_interruptible(
+ notify_ducatidriver_state.
+ gate_handle) != 0)
+ WARN_ON(1);
+ }
+ }
+ if (status >= 0) {
+ /* Set the event bit field and payload. */
+ other_event_chart[event_no].payload = payload;
+ other_event_chart[event_no].flag = UP;
+ /* Send an interrupt with the event
+ information to theremote processor */
+ status = omap_mbox_msg_send(ducati_mbox,
+ payload);
+ }
+ /* Leave critical section protection. */
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ }
+ }
+
+ return status;
+}
+
+/*
+* brief Disable all events for this Notify driver.
+*
+*/
+void *notify_ducatidrv_disable(struct notify_driver_object *handle)
+{
+
+ omap_mbox_disable_irq(ducati_mbox, IRQ_RX);
+
+ return NULL; /*No flags to be returned. */
+}
+
+/*
+* brief Restore the notify_ducatidrv to the state before the
+* last disable was called.
+*
+*/
+int notify_ducatidrv_restore(struct notify_driver_object *handle,
+ void *flags)
+{
+ (void) handle;
+ (void) flags;
+ /*Enable the receive interrupt for ducati */
+ omap_mbox_enable_irq(ducati_mbox, IRQ_RX);
+ return 0;
+}
+
+/*
+* brief Disable a specific event for this Notify ducati driver
+*
+*/
+int notify_ducatidrv_disable_event(
+ struct notify_driver_object *handle,
+ short int proc_id, int event_no)
+{
+ static int access_count ;
+ signed long int status = 0;
+ struct notify_ducatidrv_object *driver_object;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+ access_count++;
+ driver_object = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+ /* Enter critical section protection. */
+
+ if (mutex_lock_interruptible(notify_ducatidriver_state.
+ gate_handle) != 0)
+ WARN_ON(1);
+
+ clear_bit(event_no, (unsigned long *)
+ &driver_object->ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.enable_mask);
+ /* Leave critical section protection. */
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ return status;
+}
+
+/*
+* brief Enable a specific event for this Notify ducati driver
+*
+*/
+int notify_ducatidrv_enable_event(struct notify_driver_object *handle,
+ short int proc_id, int event_no)
+{
+ int status = 0;
+ struct notify_ducatidrv_object *driver_object;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+ driver_object = (struct notify_ducatidrv_object *)
+ handle->driver_object;
+ /* Enter critical section protection. */
+
+ if (mutex_lock_interruptible(notify_ducatidriver_state.
+ gate_handle) != 0)
+ WARN_ON(1);
+
+ set_bit(event_no, (unsigned long *)
+ &driver_object->ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.enable_mask);
+
+ mutex_unlock(notify_ducatidriver_state.gate_handle);
+ return status;
+}
+
+/*
+* brief Print debug information for the Notify ducati driver
+*
+*/
+int notify_ducatidrv_debug(struct notify_driver_object *handle)
+{
+ int status = 0;
+ printk(KERN_WARNING "ducati Debug: Nothing being printed currently\n");
+ return status;
+}
+
+
+/*
+ *
+ * brief This function implements the interrupt service routine for the
+ * interrupt received from the Ducati processor.
+ *
+ */
+static void notify_ducatidrv_isr(void *ntfy_msg)
+{
+ struct notify_driver_object_list *obj_list;
+ struct list_head *entry = NULL;
+ list_for_each(entry, &(notify_ducatidriver_state.drv_handle_list)) {
+ obj_list = (struct notify_driver_object_list *)
+ container_of(entry,
+ struct notify_driver_object_list, elem);
+ notify_ducatidrv_isr_callback(
+ obj_list->drv_handle->driver_object, ntfy_msg);
+ }
+}
+EXPORT_SYMBOL(notify_ducatidrv_isr);
+
+
+static void notify_ducatidrv_isr_callback(void *ref_data, void* ntfy_msg)
+{
+ int payload = 0;
+ int i = 0;
+ struct list_head *temp;
+ int j = 0;
+ VOLATILE struct notify_shmdrv_event_entry *self_event_chart;
+ struct notify_ducatidrv_object *driver_obj;
+ struct notify_shmdrv_eventreg *reg_chart;
+ VOLATILE struct notify_shmdrv_proc_ctrl *proc_ctrl_ptr;
+ int event_no;
+
+ driver_obj = (struct notify_ducatidrv_object *) ref_data;
+ proc_ctrl_ptr = &(driver_obj->ctrl_ptr->proc_ctrl[driver_obj->self_id]);
+ reg_chart = driver_obj->reg_chart;
+ self_event_chart = proc_ctrl_ptr->self_event_chart;
+
+ /* Execute the loop till no asserted event
+ is found for one complete loop
+ through all registered events
+ */
+ do {
+ /* Check if the entry is a valid registered event.*/
+ event_no = reg_chart[i].reg_event_no;
+ /* Determine the current high priority event.*/
+ /* Check if the event is set and enabled.*/
+ if (self_event_chart[event_no].flag == UP &&
+ test_bit(event_no,
+ (unsigned long *) &proc_ctrl_ptr->reg_mask.enable_mask)
+ && (event_no != (int) -1)) {
+
+ payload = self_event_chart[event_no].
+ payload;
+ /* Acknowledge the event. */
+ payload = (int)ntfy_msg;
+ self_event_chart[event_no].flag = DOWN;
+ /*Call the callbacks associated with the event*/
+ temp = driver_obj->
+ event_list[event_no].
+ listeners.next;
+ if (temp != NULL) {
+ for (j = 0; j < driver_obj->
+ event_list[event_no].
+ event_handler_count;
+ j++) {
+ /* Check for empty list. */
+ if (temp == NULL)
+ continue;
+ /*FIXME: Hack to support SYSM3 and
+ APPM3 */
+ if ((driver_obj->proc_id == PROCAPPM3)
+ && (event_no <= MAX_SUBPROC_EVENTS)) {
+ driver_obj->proc_id = PROCSYSM3;
+ }
+ if ((driver_obj->proc_id == PROCSYSM3)
+ && (event_no > MAX_SUBPROC_EVENTS)) {
+ driver_obj->proc_id = PROCAPPM3;
+ }
+ ((struct notify_drv_eventlistner *)
+ temp)->fn_notify_cbck(
+ driver_obj->proc_id,
+ event_no,
+ ((struct notify_drv_eventlistner *)
+ temp)->cbck_arg,
+ payload);
+ temp = temp->next;
+ }
+ /* reinitialize the event check counter. */
+ i = 0;
+ }
+ } else {
+ /* check for next event. */
+ i++;
+ }
+ } while ((event_no != (int) -1)
+ && (i < driver_obj->params.num_events));
+}
+
+/*
+* brief This function searchs for a element the List.
+*
+*/
+static void notify_ducatidrv_qsearch_elem(struct list_head *list,
+ struct notify_drv_eventlistner *check_obj,
+ struct notify_drv_eventlistner **listener)
+{
+ struct list_head *temp = NULL ;
+ struct notify_drv_eventlistner *l_temp = NULL ;
+ short int found = false;
+
+ BUG_ON(list == NULL);
+ BUG_ON(check_obj == NULL);
+ BUG_ON(listener == NULL);
+
+ *listener = NULL;
+ if ((list != NULL) && (check_obj != NULL)) {
+ if (list_empty((struct list_head *)list) == false) {
+ temp = list->next;
+ while ((found == false) && (temp != NULL)) {
+ l_temp =
+ (struct notify_drv_eventlistner *)
+ (temp);
+ if ((l_temp->fn_notify_cbck ==
+ check_obj->fn_notify_cbck) &&
+ (l_temp->cbck_arg ==
+ check_obj->cbck_arg)) {
+ found = true;
+ } else
+ temp = temp->next;
+ }
+ if (found == true)
+ *listener = l_temp;
+ }
+ }
+ return;
+}
diff --git a/drivers/dsp/syslink/notify_tesladriver/Kbuild b/drivers/dsp/syslink/notify_tesladriver/Kbuild
new file mode 100644
index 000000000000..25a4f52d1c39
--- /dev/null
+++ b/drivers/dsp/syslink/notify_tesladriver/Kbuild
@@ -0,0 +1,18 @@
+
+omap_tesladriver = notify_tesla.o drv_tesla.o
+
+
+obj-$(CONFIG_NOTIFY_TESLA) += notify_tesladriver.o
+notify_tesladriver-objs = $(omap_tesladriver)
+
+
+ccflags-y += -Wno-strict-prototypes
+
+#Machine dependent
+ccflags-y += -DCONFIG_DISABLE_BRIDGE_PM -DDSP_TRACEBUF_DISABLED \
+ -DVPOM4430_1_06
+
+#Header files
+ccflags-y += -Idrivers/dsp/syslink/inc
+ccflags-y += -Iarch/arm/plat-omap/include
+
diff --git a/drivers/dsp/syslink/notify_tesladriver/drv_tesla.c b/drivers/dsp/syslink/notify_tesladriver/drv_tesla.c
new file mode 100755
index 000000000000..143ec768c0ac
--- /dev/null
+++ b/drivers/dsp/syslink/notify_tesladriver/drv_tesla.c
@@ -0,0 +1,79 @@
+/*
+ * drv_notifytesla.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+/* ----------------------------------- OS Specific Headers */
+#include <linux/autoconf.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <linux/io.h>
+#include <asm/pgtable.h>
+#include <syslink/notify_tesladriver.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/GlobalTypes.h>
+
+
+/* Major number of driver */
+static signed long int major = 233 ;
+
+
+/* driver function to open the notify mailbox driver object. */
+static int drvtesla_open(struct inode *inode, struct file *filp);
+
+/* notify mailbox driver initialization function. */
+static int __init drvtesla_initialize_module(void) ;
+
+/* notify mailbox driver cleanup function. */
+static void __exit drvtesla_finalize_module(void) ;
+
+
+/* Function to invoke the APIs through ioctl. */
+static const struct file_operations driver_ops = {
+ .open = drvtesla_open,
+};
+
+/* Initialization function */
+static int __init drvtesla_initialize_module(void)
+{
+ int result = 0;
+
+ result = register_chrdev(major, "notifytesladrv", &driver_ops);
+ if (result < 0)
+ pr_err("Notify tesla driver initialization file\n");
+
+ return result ;
+}
+
+/* Finalization function */
+static void __exit drvtesla_finalize_module(void)
+{
+ unregister_chrdev(major, "notifytesladrv");
+}
+
+static int drvtesla_open(struct inode *inode, struct file *filp)
+{
+ return 0 ;
+}
+
+MODULE_LICENSE("GPL");
+module_init(drvtesla_initialize_module);
+module_exit(drvtesla_finalize_module);
diff --git a/drivers/dsp/syslink/notify_tesladriver/notify_tesla.c b/drivers/dsp/syslink/notify_tesladriver/notify_tesla.c
new file mode 100644
index 000000000000..041b30797725
--- /dev/null
+++ b/drivers/dsp/syslink/notify_tesladriver/notify_tesla.c
@@ -0,0 +1,1108 @@
+/*
+ * notify_mbxDriver.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <mach/mailbox.h>
+
+#include <syslink/notify_driver.h>
+#include <syslink/notifydefs.h>
+#include <syslink/notify_driverdefs.h>
+#include <syslink/notify_tesladriver.h>
+#include <syslink/gt.h>
+#include <syslink/atomic_linux.h>
+
+
+
+#define NOTIFYSHMDRV_MEM_ALIGN 0
+
+#define NOTIFYSHMDRV_MAX_EVENTS 32
+
+#define NOTIFYSHMDRV_INIT_STAMP 0xA9C8B7D6
+
+#define NOTIFYNONSHMDRV_MAX_EVENTS 1
+
+#define NOTIFYNONSHMDRV_RESERVED_EVENTS 1
+
+#define NOTIFYDRV_TESLA_RECV_MBX 1
+
+#define NOTIFYDRV_TESLA_SEND_MBX 0
+
+#define SELF_ID 0
+
+#define OTHER_ID 1
+
+#define UP 1
+
+#define DOWN 0
+
+#define PROC_TESLA 0
+#define PROC_DUCATI 1
+#define PROC_GPP 2
+
+/*FIXME MOVE THIS TO A SUITABLE HEADER */
+#define NOTIFYDRIVERSHM_MODULEID (u32) 0xb9d4
+
+/* Macro to make a correct module magic number with refCount */
+#define NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(x) \
+ ((NOTIFYDRIVERSHM_MODULEID << 12u) | (x))
+
+irqreturn_t(*irq_handler)(int, void *, struct pt_regs *);
+EXPORT_SYMBOL(irq_handler);
+
+
+
+/*
+ * brief NotifyDriverShm instance object.
+ */
+struct notify_tesladrv_object {
+ struct notify_tesladrv_params params;
+ short int proc_id;
+ struct notify_drv_eventlist *event_list;
+ struct notify_shmdrv_ctrl *ctrl_ptr;
+ struct notify_shmdrv_eventreg *reg_chart;
+ struct notify_driver_object *drv_handle;
+ short int self_id;
+ short int other_id;
+};
+
+
+/*
+ * brief Defines the NotifyDriverShm state object, which contains all the
+ * module specific information.
+ */
+struct notify_tesladrv_module {
+ atomic_t ref_count;
+ struct notify_tesladrv_config cfg;
+ struct notify_tesladrv_config def_cfg;
+ struct notify_tesladrv_params def_inst_params;
+ struct mutex *gate_handle;
+} ;
+
+
+static struct notify_tesladrv_module notify_tesladriver_state = {
+ .gate_handle = NULL,
+ .def_inst_params.shared_addr = 0x0,
+ .def_inst_params.shared_addr_size = 0x0,
+ .def_inst_params.num_events = NOTIFYSHMDRV_MAX_EVENTS,
+ .def_inst_params.num_reserved_events = 3,
+ .def_inst_params.send_event_poll_count = (int) -1,
+ .def_inst_params.remote_proc_id = -1,
+ .def_inst_params.recv_int_id = (int) -1,
+ .def_inst_params.send_int_id = (int) -1
+};
+
+
+
+struct omap_mbox *tesla_mbox;
+static struct notify_tesladrv_object *tesla_isr_params[NOTIFY_MAX_DRIVERS];
+static void notify_tesladrv_isr(void *ntfy_msg);
+static void notify_tesladrv_isr_callback(void *ref_data, void* ntfy_msg);
+
+
+
+/*
+ *This function searchs for a element the List.
+ */
+static void notify_tesladrv_qsearch_elem(struct list_head *list,
+ struct notify_drv_eventlistner *check_obj,
+ struct notify_drv_eventlistner **listener);
+
+
+/*!
+ * brief Get the default configuration for the NotifyDriverShm module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to NotifyDriverShm_setup filled in by
+ * the NotifyDriverShm module with the default parameters. If the
+ * user does not wish to make any change in the default parameters,
+ * this API is not required to be called.
+ */
+void notify_tesladrv_getconfig(struct notify_tesladrv_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true)
+ memcpy(cfg,
+ &(notify_tesladriver_state.def_cfg),
+ sizeof(struct notify_tesladrv_config));
+ else
+ memcpy(cfg,
+ &(notify_tesladriver_state.cfg),
+ sizeof(struct notify_tesladrv_config));
+}
+EXPORT_SYMBOL(notify_tesladrv_getconfig);
+
+
+
+
+/*
+ * brief Function to open a handle to an existing NotifyDriverShm object
+ * handling the procId.
+ *
+ * This function returns a handle to an existing NotifyDriverShm
+ * instance created for this procId. It enables other entities to
+ * access and use this NotifyDriverShm instance.
+ *
+ */
+int notify_tesladrv_open(char *driver_name,
+ struct notify_driver_object **handle_ptr)
+{
+ int status = 0;
+ BUG_ON(driver_name == NULL);
+ BUG_ON(handle_ptr == NULL);
+ /* Enter critical section protection. */
+ WARN_ON(mutex_lock_interruptible(notify_tesladriver_state.gate_handle)
+ != 0);
+ /* Get the handle from Notify module. */
+ status = notify_get_driver_handle(driver_name, handle_ptr);
+ if (status < 0)
+ status = -EINVAL;
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return status;
+}
+
+/*
+ * brief Function to close this handle to the NotifyDriverShm instance.
+ *
+ * This function closes the handle to the NotifyDriverShm instance
+ * obtained through NotifyDriverShm_open call made earlier.
+ */
+int notify_tesladrv_close(struct notify_driver_object **handle_ptr)
+{
+ int status = 0;
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(*handle_ptr == NULL);
+ *handle_ptr = NULL;
+ return status;
+}
+
+
+
+
+/*
+ * brief Function to initialize the parameters for this NotifyDriver
+ * instance.
+ *
+ */
+void notify_tesladrv_params_init(struct notify_driver_object *handle,
+ struct notify_tesladrv_params *params)
+{
+ struct notify_tesladrv_object *driver_obj;
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /*FIXME not intialized to be returned */
+ BUG_ON(1);
+ }
+ if (handle == NULL) {
+ memcpy(params,
+ &(notify_tesladriver_state.def_inst_params),
+ sizeof(struct notify_tesladrv_params));
+ } else {
+ /* Return updated NotifyDriverShm instance
+ specific parameters. */
+ driver_obj = (struct notify_tesladrv_object *)
+ handle->driver_object;
+ memcpy(params, &(driver_obj->params),
+ sizeof(struct notify_tesladrv_params));
+ }
+}
+EXPORT_SYMBOL(notify_tesladrv_params_init);
+
+
+
+/*
+ * brief Function to create an instance of this NotifyDriver.
+ *
+ */
+struct notify_driver_object *notify_tesladrv_create(char *driver_name,
+ const struct notify_tesladrv_params *params) {
+
+ int status = 0;
+ struct notify_tesladrv_object *driver_obj = NULL;
+ struct notify_driver_object *drv_handle = NULL;
+ struct notify_drv_eventlist *event_list = NULL;
+ volatile struct notify_shmdrv_proc_ctrl *ctrl_ptr = NULL;
+ struct notify_driver_attrs drv_attrs;
+ struct notify_interface fxn_table;
+ int i;
+ unsigned long int num_events = NOTIFYNONSHMDRV_MAX_EVENTS;
+ int slot = false;
+
+ BUG_ON(driver_name == NULL);
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /*FIXME not intialized to be returned */
+ goto func_end;
+ }
+
+ if (params->num_events > NOTIFYSHMDRV_MAX_EVENTS) {
+ status = -EINVAL;
+ goto func_end;
+ } else {
+
+ if (mutex_lock_interruptible(notify_tesladriver_state.
+ gate_handle) != 0)
+ WARN_ON(1);
+
+ drv_attrs.numProc = 1;
+ drv_attrs.proc_info[PROC_TESLA].max_events = num_events;
+
+ drv_attrs.proc_info[PROC_TESLA].reserved_events =
+ params->num_reserved_events;
+ /* 32-bit payload supported. */
+ drv_attrs.proc_info[PROC_TESLA].payload_size = sizeof(int);
+ drv_attrs.proc_info[PROC_TESLA].proc_id =
+ params->remote_proc_id;
+
+ /* Function table information */
+ fxn_table.register_event = (void *)
+ &notify_tesladrv_register_event;
+ fxn_table.unregister_event = (void *)
+ &notify_tesladrv_unregister_event;
+ fxn_table.send_event = (void *)&notify_tesladrv_sendevent;
+ fxn_table.disable = (void *)&notify_tesladrv_disable;
+ fxn_table.restore = (void *)&notify_tesladrv_restore;
+ fxn_table.disable_event = (void *)
+ &notify_tesladrv_disable_event;
+ fxn_table.enable_event = (void *)&notify_tesladrv_enable_event;
+
+ status = notify_register_driver(driver_name,
+ &fxn_table,
+ &drv_attrs,
+ &drv_handle);
+
+ if (status != NOTIFY_SUCCESS) {
+ /*retval NULL Failed to register
+ driver with Notify module*/
+ printk(KERN_ERR "notify_register_driver"
+ " failed and status = %d\n",
+ status);
+ status = -EINVAL;
+ goto func_end;
+ } else {
+
+ /* Allocate memory for the
+ NotifyDriverShm_Object object. */
+ drv_handle->driver_object = driver_obj =
+ kmalloc(sizeof(struct notify_tesladrv_object),
+ GFP_ATOMIC);
+
+ if (driver_obj == NULL) {
+ status = -ENOMEM;
+ goto func_end;
+ } else {
+ memcpy(&(driver_obj->params), (void *) params,
+ sizeof(struct notify_tesladrv_params));
+
+ }
+ }
+
+ }
+ /*FIXME: Check with MultiProc_getId */
+ driver_obj->self_id = 1;
+ driver_obj->other_id = 0;
+ driver_obj->ctrl_ptr = (struct notify_shmdrv_ctrl *)
+ params->shared_addr;
+
+
+ ctrl_ptr = &(driver_obj->ctrl_ptr->proc_ctrl[driver_obj->self_id]);
+
+
+ ctrl_ptr->self_event_chart = (struct notify_shmdrv_event_entry *)
+ ((int)(driver_obj->ctrl_ptr)
+ + sizeof(struct notify_shmdrv_ctrl)+
+ (sizeof(
+ struct notify_shmdrv_event_entry)
+ * params->num_events
+ * driver_obj->other_id));
+
+
+ ctrl_ptr->other_event_chart = (struct notify_shmdrv_event_entry *)
+ ((int)(driver_obj->ctrl_ptr)
+ + sizeof(struct notify_shmdrv_ctrl) +
+ (sizeof(
+ struct notify_shmdrv_event_entry)
+ * params->num_events
+ * driver_obj->self_id));
+
+ driver_obj->proc_id = params->remote_proc_id;
+
+
+ driver_obj->event_list = kmalloc((sizeof(struct notify_drv_eventlist)
+ * params->num_events), GFP_ATOMIC);
+
+ if (driver_obj->event_list == NULL) {
+
+ status = -ENOMEM;
+ goto func_end;
+ } else {
+ memset(driver_obj->event_list, 0,
+ sizeof(struct notify_drv_eventlist)*params->num_events);
+ }
+
+
+ driver_obj->reg_chart = kmalloc(sizeof(struct notify_shmdrv_eventreg)
+ *params->num_events, GFP_ATOMIC);
+
+
+ if (driver_obj->reg_chart == NULL) {
+
+ status = -ENOMEM;
+ goto func_end;
+ } else {
+ memset(driver_obj->reg_chart, 0,
+ sizeof(struct notify_shmdrv_eventreg)
+ *params->num_events);
+ }
+
+
+ event_list = driver_obj->event_list;
+ for (i = 0 ; (i < params->num_events) ; i++) {
+
+ ctrl_ptr->self_event_chart[i].flag = 0;
+
+ driver_obj->reg_chart[i].reg_event_no = (int) -1;
+
+ event_list[i].event_handler_count = 0;
+ INIT_LIST_HEAD(&event_list[i].listeners);
+ }
+
+
+ ctrl_ptr->reg_mask.mask = 0x0;
+
+ /* Enable all events initially.*/
+ ctrl_ptr->reg_mask.enable_mask = 0xFFFFFFFF;
+
+ tesla_mbox = omap_mbox_get("mailbox-1");
+ if (tesla_mbox == NULL) {
+ status = -ENODEV;
+ goto func_end;
+ }
+ tesla_mbox->rxq->callback = (int (*)(void *))notify_tesladrv_isr;
+
+ /*Set up the ISR on the Modena-Tesla FIFO */
+
+ for (i = 0; i < NOTIFY_MAX_DRIVERS; i++) {
+ if (tesla_isr_params[i] == NULL) {
+ slot = true;
+ break;
+ }
+ }
+
+ if ((!slot) || (i == NOTIFY_MAX_DRIVERS)) {
+ /*FIXME: set a proper error value */
+ printk(KERN_ERR "Error: no free slots\n");
+ status = -ENODEV;
+ goto func_end;
+ }
+ tesla_isr_params[i] = (void *)driver_obj;
+ omap_mbox_enable_irq(tesla_mbox, IRQ_RX);
+
+
+ /*Set up the ISR on the Modena-Ducati FIFO */
+ status = 0;
+
+
+ if (status == 0) {
+ driver_obj = drv_handle->driver_object;
+ ctrl_ptr->reg_mask.mask = 0x0;
+ ctrl_ptr->reg_mask.enable_mask = 0xFFFFFFFF;
+ ctrl_ptr->recv_init_status = NOTIFYSHMDRV_INIT_STAMP;
+ ctrl_ptr->send_init_status = NOTIFYSHMDRV_INIT_STAMP;
+ drv_handle->is_init = NOTIFY_DRIVERINITSTATUS_DONE;
+ }
+
+
+
+func_end:
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return drv_handle;
+}
+EXPORT_SYMBOL(notify_tesladrv_create);
+
+
+
+/*
+ * brief Function to delete the instance of tesla driver
+ *
+ */
+int notify_tesladrv_delete(struct notify_driver_object **handlePtr)
+{
+ int status = 0;
+ struct notify_driver_object *drv_handle = NULL;
+ struct notify_tesladrv_object *driver_obj = NULL;
+ struct notify_drv_eventlist *event_list;
+ short int i;
+ int proc_id;
+
+ if (atomic_cmpmask_and_lt(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /*FIXME not intialized to be returned */
+ return -1;
+ }
+
+ WARN_ON(handlePtr == NULL);
+ if (handlePtr == NULL)
+ return -1;
+ driver_obj = (struct notify_tesladrv_object *)
+ (*handlePtr)->driver_object;
+ drv_handle = (*handlePtr);
+ WARN_ON((*handlePtr)->driver_object == NULL);
+
+ /*Uninstall the ISRs & Disable the Mailbox interrupt.*/
+
+
+ if (drv_handle != NULL) {
+ status = notify_unregister_driver(drv_handle);
+ driver_obj = drv_handle->driver_object;
+ }
+ if (status != NOTIFY_SUCCESS)
+ printk(KERN_WARNING "driver is not registerd\n");
+
+ if (driver_obj != NULL) {
+ if (driver_obj->ctrl_ptr != NULL) {
+ /* Clear initialization status in shared memory. */
+ driver_obj->ctrl_ptr->
+ proc_ctrl[driver_obj->self_id].
+ recv_init_status = 0x0;
+ driver_obj->ctrl_ptr->
+ proc_ctrl[driver_obj->self_id].
+ send_init_status = 0x0;
+ driver_obj->ctrl_ptr = NULL;
+ }
+
+ event_list = driver_obj->event_list;
+ if (event_list != NULL) {
+ /* Check if lists were created. */
+ for (i = 0 ; i < driver_obj->params.num_events ; i++) {
+ WARN_ON(event_list[i].event_handler_count != 0);
+ event_list[i].event_handler_count = 0;
+ list_del((struct list_head *)
+ &event_list[i].listeners);
+ }
+
+ kfree(event_list);
+ driver_obj->event_list = NULL;
+ }
+
+ /* Check if reg_chart was allocated. */
+ if (driver_obj->reg_chart != NULL) {
+ kfree(driver_obj->reg_chart);
+ driver_obj->reg_chart = NULL;
+ }
+
+ /* Disable the interrupt, Uninstall the ISR and delete it. */
+ /* Check if ISR was created. */
+ /*Remove the ISR on the Modena-Tesla FIFO */
+ proc_id = PROC_TESLA;
+
+ omap_mbox_disable_irq(tesla_mbox, IRQ_RX);
+
+ if (mutex_lock_interruptible(
+ notify_tesladriver_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ for (i = 0; i < NOTIFY_MAX_DRIVERS; i++) {
+ if (tesla_isr_params[i] == (void *)driver_obj) {
+ tesla_isr_params[i] = NULL;
+ break;
+ }
+ }
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+
+ if (i == NOTIFY_MAX_DRIVERS) {
+ printk(KERN_ERR "Error: No handle to delete\n");
+ /*FIXME: Exit gracefully */
+ WARN_ON(1);
+ }
+
+ /*Remove the generic ISR */
+ omap_mbox_put(tesla_mbox);
+ tesla_mbox = NULL;
+
+ kfree(driver_obj);
+ driver_obj = NULL;
+ }
+ return status;
+}
+EXPORT_SYMBOL(notify_tesladrv_delete);
+
+
+/*
+ * brief Destroy the notify tesla module.
+ *
+ */
+int notify_tesladrv_destroy(void)
+{
+
+ int status = 0;
+
+ if (atomic_cmpmask_and_lt(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1))
+ == true) {
+ /* FIXME Invalid state to be reuurned. */
+ return -1;
+ }
+
+ if (atomic_dec_return(&(notify_tesladriver_state.ref_count)) ==
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0)) {
+
+ /* Check if the gate_handle was created internally. */
+
+ if (notify_tesladriver_state.gate_handle != NULL)
+ kfree(notify_tesladriver_state.gate_handle);
+ }
+ /* FIXME- Why do we need to reset this if we already
+ * decremented it to 0 */
+ atomic_set(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+
+ return status;
+}
+EXPORT_SYMBOL(notify_tesladrv_destroy);
+
+
+
+/*
+ * brief Setup the notify tesla module.
+ *
+ * This function sets up the notify tesla module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then notify_tesla_get_config can be called to get
+ * the configuration filled with the default values. After this,
+ * only the required configuration values can be changed. If the
+ * user does not wish to make any change in the default parameters,
+ * the application can simply call notify_tesla_setup with NULL
+ * parameters. The default parameters would get automatically used.
+ *
+ */
+int notify_tesladrv_setup(struct notify_tesladrv_config *cfg)
+{
+ int status = 0;
+ int i = 0;
+ struct notify_tesladrv_config tmpCfg;
+
+ if (cfg == NULL) {
+ notify_tesladrv_getconfig(&tmpCfg);
+ cfg = &tmpCfg;
+ }
+
+ /* Init the ref_count to 0 */
+ atomic_cmpmask_and_set(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&(notify_tesladriver_state.ref_count)) !=
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(1u)) {
+ /* FIXME Already exists status to be returned. */
+ return -1;
+ }
+
+ /* Create a default gate handle here */
+ notify_tesladriver_state.gate_handle =
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ mutex_init(notify_tesladriver_state.gate_handle);
+
+
+ if (notify_tesladriver_state.gate_handle == NULL) {
+ atomic_set(&(notify_tesladriver_state.ref_count),
+ NOTIFYDRIVERSHM_MAKE_MAGICSTAMP(0));
+ status = -ENOMEM;
+ } else {
+ memcpy(&notify_tesladriver_state.cfg,
+ cfg, sizeof(struct notify_tesladrv_config));
+ }
+
+ for (i = 0; i < NOTIFY_MAX_DRIVERS; i++)
+ tesla_isr_params[i] = NULL;
+ return status;
+}
+EXPORT_SYMBOL(notify_tesladrv_setup);
+
+
+/*
+* brief Register a callback for an event with the Notify driver.
+*
+*/
+int notify_tesladrv_register_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg)
+{
+ int status = 0;
+ int firstReg = false;
+ bool done = true;
+ struct notify_drv_eventlistner *event_listener;
+ struct notify_drv_eventlist *event_list;
+ struct notify_tesladrv_object *driver_object;
+ struct notify_shmdrv_eventreg *reg_chart;
+ volatile struct notify_shmdrv_ctrl *ctrl_ptr;
+ volatile struct notify_shmdrv_event_entry *self_event_chart;
+ int i;
+ int j;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->is_init != NOTIFY_DRIVERINITSTATUS_DONE);
+ BUG_ON(handle->driver_object == NULL);
+ BUG_ON(fn_notify_cbck == NULL);
+
+
+ driver_object = (struct notify_tesladrv_object *) handle->driver_object;
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+
+ /* Allocate memory for event listener. */
+ event_listener = kmalloc(sizeof(struct notify_drv_eventlistner),
+ GFP_ATOMIC);
+
+ if (event_listener == NULL) {
+ status = -ENOMEM;
+ goto func_end;
+ } else {
+ memset(event_listener, 0,
+ sizeof(struct notify_drv_eventlistner));
+ }
+
+ if (mutex_lock_interruptible(notify_tesladriver_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ event_list = driver_object->event_list;
+ WARN_ON(event_list == NULL);
+ event_listener->fn_notify_cbck = fn_notify_cbck;
+ event_listener->cbck_arg = cbck_arg;
+ /* Check if this is the first registration for this event. */
+
+ if (list_empty((struct list_head *)
+ &event_list[event_no].listeners)) {
+ firstReg = true;
+ self_event_chart = ctrl_ptr->proc_ctrl[driver_object->self_id].
+ self_event_chart;
+ /* Clear any pending unserviced event as there are no listeners
+ * for the pending event
+ */
+ self_event_chart[event_no].flag = DOWN;
+ }
+ list_add_tail((struct list_head *)
+ &(event_listener->element),
+ (struct list_head *)
+ &event_list[event_no].listeners);
+ event_list[event_no].event_handler_count++;
+
+
+ if (firstReg == true) {
+ reg_chart = driver_object->reg_chart;
+ for (i = 0 ; i < driver_object->params.num_events ; i++) {
+ /* Find the correct slot in the registration array. */
+ if (reg_chart[i].reg_event_no == (int) -1) {
+ for (j = (i - 1); j >= 0; j--) {
+ if (event_no < reg_chart[j].
+ reg_event_no) {
+ reg_chart[j + 1].reg_event_no =
+ reg_chart[j].
+ reg_event_no;
+ reg_chart[j + 1].reserved =
+ reg_chart[j].reserved;
+ i = j;
+ } else {
+ /* End the loop, slot found. */
+ j = -1;
+ }
+ }
+
+ reg_chart[i].reg_event_no = event_no;
+ done = true;
+ break;
+ }
+ }
+
+ if (done) {
+ set_bit(event_no, (unsigned long *)
+ &ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.mask);
+ } else {
+ /*! @retval NOTIFY_E_MAXEVENTS Maximum number of
+ supported events have already been registered. */
+ status = -EINVAL;
+ list_del((struct list_head *)&
+ (event_listener->element));
+ kfree(event_listener);
+
+ }
+ }
+
+func_end:
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return status;
+}
+
+
+/*
+*
+* brief unregister a callback for an event with the Notify driver.
+*
+*/
+
+int notify_tesladrv_unregister_event(
+ struct notify_driver_object *handle,
+ short int proc_id,
+ int event_no,
+ fn_notify_cbck fn_notify_cbck,
+ void *cbck_arg)
+{
+ int status = 0;
+ struct notify_drv_eventlistner *listener = NULL;
+ int num_events;
+ struct notify_tesladrv_object *driver_object;
+ struct notify_drv_eventlist *event_list;
+ struct notify_shmdrv_eventreg *reg_chart;
+ volatile struct notify_shmdrv_ctrl *ctrl_ptr = NULL;
+ struct notify_drv_eventlistner unreg_info;
+ volatile struct notify_shmdrv_event_entry *self_event_chart;
+ int i;
+ int j;
+
+ BUG_ON(fn_notify_cbck == NULL);
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+ driver_object = (struct notify_tesladrv_object *) handle->driver_object;
+ num_events = driver_object->params.num_events;
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+
+ /* Enter critical section protection. */
+ if (mutex_lock_interruptible(notify_tesladriver_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ event_list = driver_object->event_list;
+
+
+ unreg_info.fn_notify_cbck = fn_notify_cbck;
+ unreg_info.cbck_arg = cbck_arg;
+ notify_tesladrv_qsearch_elem(&event_list[event_no].listeners,
+ &unreg_info,
+ &listener);
+ if (listener == NULL) {
+ status = -EFAULT;
+ goto func_end;
+ }
+ list_del((struct list_head *)&(listener->element));
+ event_list[event_no].event_handler_count--;
+ kfree(listener);
+
+
+ if (list_empty((struct list_head *)
+ &event_list[event_no].listeners) == true) {
+ clear_bit(event_no, (unsigned long *)
+ &ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.mask);
+ self_event_chart = ctrl_ptr->proc_ctrl[driver_object->self_id].
+ self_event_chart;
+ /* Clear any pending unserviced event as there are no
+ * listeners for the pending event
+ */
+ self_event_chart[event_no].flag = DOWN;
+ reg_chart = driver_object->reg_chart;
+ for (i = 0; i < num_events; i++) {
+ /* Find the correct slot in the registration array. */
+ if (event_no == reg_chart[i].reg_event_no) {
+ reg_chart[i].reg_event_no = (int) -1;
+ for (j = (i + 1);
+ (reg_chart[j].reg_event_no != (int) -1)
+ && (j != num_events); j++) {
+ reg_chart[j - 1].reg_event_no =
+ reg_chart[j].reg_event_no;
+ reg_chart[j - 1].reserved =
+ reg_chart[j].reserved;
+ }
+ if (j == num_events) {
+ reg_chart[j - 1].reg_event_no =
+ (int) -1;
+ }
+
+ break;
+ }
+ }
+ }
+
+func_end:
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return status;
+}
+
+/*
+*brief Send a notification event to the registered users for this
+* notification on the specified processor.
+*
+*/
+int notify_tesladrv_sendevent(struct notify_driver_object *handle,
+ short int proc_id, int event_no,
+ int payload, short int wait_clear)
+{
+ int status = 0;
+ struct notify_tesladrv_object *driver_object;
+ volatile struct notify_shmdrv_ctrl *ctrl_ptr;
+ int max_poll_count;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+ driver_object = (struct notify_tesladrv_object *) handle->driver_object;
+ BUG_ON(event_no > driver_object->params.num_events);
+
+ ctrl_ptr = driver_object->ctrl_ptr;
+ max_poll_count = driver_object->params.send_event_poll_count;
+
+ omap_mbox_msg_send(tesla_mbox, payload);
+ return status;
+}
+
+/*
+* brief Disable all events for this Notify driver.
+*
+*/
+void *notify_tesladrv_disable(struct notify_driver_object *handle, u16 proc_id)
+{
+
+ omap_mbox_disable_irq(tesla_mbox, IRQ_RX);
+
+ return NULL; /*No flags to be returned. */
+}
+
+/*
+* brief Restore the Notify driver to the state before the last disable was
+* called.
+*
+*/
+int notify_tesladrv_restore(struct notify_driver_object *handle,
+ u32 key, u16 proc_id)
+{
+
+ (void) handle;
+ (void) key;
+ (void) proc_id;
+ /*Enable the receive interrupt for Tesla */
+ omap_mbox_enable_irq(tesla_mbox, IRQ_RX);
+ return 0;
+}
+
+/*
+* brief Disable a specific event for this Notify driver.
+*
+*/
+int notify_tesladrv_disable_event(
+ struct notify_driver_object *handle,
+ short int proc_id, int event_no)
+{
+ static int access_count ;
+ signed long int status = 0;
+ struct notify_tesladrv_object *driver_object;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+ access_count++;
+ driver_object = (struct notify_tesladrv_object *) handle->driver_object;
+ /* Enter critical section protection. */
+
+ WARN_ON(mutex_lock_interruptible(notify_tesladriver_state.gate_handle)
+ != 0);
+ clear_bit(event_no, (unsigned long *)
+ &driver_object->ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.enable_mask);
+ /* Leave critical section protection. */
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return status;
+}
+
+/*
+* brief Enable a specific event for this Notify driver.
+*
+*/
+int notify_tesladrv_enable_event(struct notify_driver_object *handle,
+ short int proc_id, int event_no)
+{
+ int status = 0;
+ struct notify_tesladrv_object *driver_object;
+ BUG_ON(handle == NULL);
+ BUG_ON(handle->driver_object == NULL);
+
+ driver_object = (struct notify_tesladrv_object *) handle->driver_object;
+ /* Enter critical section protection. */
+
+ WARN_ON(mutex_lock_interruptible(notify_tesladriver_state.gate_handle)
+ != 0);
+ set_bit(event_no, (unsigned long *)
+ &driver_object->ctrl_ptr->proc_ctrl[driver_object->self_id].
+ reg_mask.enable_mask);
+
+ mutex_unlock(notify_tesladriver_state.gate_handle);
+ return status;
+}
+
+/*
+* brief Print debug information for the Notify driver.
+*
+*/
+int notify_tesladrv_debug(struct notify_driver_object *handle)
+{
+ int status = 0;
+ printk(KERN_WARNING "Tesla Debug: Nothing being printed currently.\n");
+ return status;
+}
+
+
+
+static void notify_tesladrv_isr(void *ntfy_msg)
+{
+ int i = 0;
+ for (i = 0; i < NOTIFY_MAX_DRIVERS; i++) {
+ if (tesla_isr_params[i] != NULL) {
+ notify_tesladrv_isr_callback(tesla_isr_params[i],
+ ntfy_msg);
+ }
+ }
+}
+EXPORT_SYMBOL(notify_tesladrv_isr);
+
+/*
+* brief This function implements the interrupt service routine for the
+* interrupt received from the DSP.
+*
+*/
+static void notify_tesladrv_isr_callback(void *ref_data, void *ntfy_msg)
+{
+ int payload = 0;
+ int i = 0;
+ struct list_head *temp;
+ int j = 0;
+ struct notify_shmdrv_eventreg *reg_chart;
+ int event_no;
+ struct notify_tesladrv_object *drv_object;
+ volatile struct notify_shmdrv_proc_ctrl *ctrl_ptr;
+ int num_events = 0;
+
+ drv_object = (struct notify_tesladrv_object *) ref_data;
+ ctrl_ptr = &(drv_object->ctrl_ptr->proc_ctrl[drv_object->self_id]);
+ reg_chart = drv_object->reg_chart;
+ num_events = drv_object->params.num_events;
+
+
+ /* Commented out, since this function will be called in an ISR */
+
+ BUG_ON(drv_object == NULL);
+
+
+ do {
+ event_no = reg_chart[i].reg_event_no;
+ if (event_no != (unsigned long int) -1) {
+ if (test_bit(event_no, (unsigned long *)
+ &ctrl_ptr->reg_mask.enable_mask) == 1) {
+ payload = (int)ntfy_msg;
+
+ temp = drv_object->event_list[event_no].
+ listeners.next;
+
+ for (j = 0; j <
+ drv_object->
+ event_list[event_no].
+ event_handler_count; j++) {
+ if (temp > (struct list_head *)0) {
+ ((struct
+ notify_drv_eventlistner
+ *)temp)->fn_notify_cbck(
+ drv_object->
+ proc_id,
+ event_no,
+ ((struct
+ notify_drv_eventlistner
+ *)
+ temp)->cbck_arg,
+ payload);
+ temp = temp->next;
+ }
+ }
+ }
+ i++;
+ }
+ } while ((event_no != (unsigned long int) -1) && (i < num_events));
+}
+
+/*
+* brief This function searchs for a element the List.
+*
+*/
+static void notify_tesladrv_qsearch_elem(struct list_head *list,
+ struct notify_drv_eventlistner *check_obj,
+ struct notify_drv_eventlistner **listener)
+{
+ struct list_head *temp = NULL ;
+ struct notify_drv_eventlistner *l_temp = NULL ;
+ short int found = false;
+
+
+ BUG_ON(list == NULL);
+ BUG_ON(check_obj == NULL);
+ WARN_ON(listener == NULL);
+
+ if (listener != NULL)
+ return;
+ *listener = NULL;
+ if ((check_obj != NULL)) {
+ if (list_empty((struct list_head *)list) == false) {
+ temp = list->next;
+ while ((found == false) && (temp != NULL)) {
+ l_temp =
+ (struct notify_drv_eventlistner *)(temp);
+ if ((l_temp->fn_notify_cbck ==
+ check_obj->fn_notify_cbck) &&
+ (l_temp->cbck_arg ==
+ check_obj->cbck_arg)) {
+ found = true;
+ } else
+ temp = temp->next;
+ }
+ if (found == true)
+ *listener = l_temp;
+ }
+ }
+ return;
+}
+
diff --git a/drivers/dsp/syslink/omap_notify/Kbuild b/drivers/dsp/syslink/omap_notify/Kbuild
new file mode 100755
index 000000000000..c1fed9e32f51
--- /dev/null
+++ b/drivers/dsp/syslink/omap_notify/Kbuild
@@ -0,0 +1,19 @@
+libomap_notify = notify_driver.o notify.o drv_notify.o
+
+
+
+obj-$(CONFIG_MPU_BRIDGE_NOTIFY) += omap_notify.o
+omap_notify-objs = $(libomap_notify)
+
+
+ccflags-y += -Wno-strict-prototypes
+
+#Machine dependent
+ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
+ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
+ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS \
+ -DCONFIG_DISABLE_BRIDGE_PM -DDSP_TRACEBUF_DISABLED
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include
+
diff --git a/drivers/dsp/syslink/omap_notify/drv_notify.c b/drivers/dsp/syslink/omap_notify/drv_notify.c
new file mode 100755
index 000000000000..44862049ba3a
--- /dev/null
+++ b/drivers/dsp/syslink/omap_notify/drv_notify.c
@@ -0,0 +1,918 @@
+/*
+ * drv_notify.c
+ *
+ * Syslink support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/autoconf.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/pgtable.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+
+#include <syslink/gt.h>
+#include <syslink/notify_driver.h>
+#include <syslink/notify.h>
+#include <syslink/GlobalTypes.h>
+
+
+/** ============================================================================
+ * Macros and types
+ * ============================================================================
+ */
+#define IPCNOTIFY_NAME "ipcnotify"
+
+static char *driver_name = IPCNOTIFY_NAME;
+
+static s32 driver_major;
+
+static s32 driver_minor;
+
+struct ipcnotify_dev {
+ struct cdev cdev;
+};
+
+static struct ipcnotify_dev *ipcnotify_device;
+
+static struct class *ipcnotify_class;
+
+
+/*
+ * Maximum number of user supported.
+ */
+
+#define MAX_PROCESSES 32
+
+/*Structure of Event Packet read from notify kernel-side..*/
+struct notify_drv_event_packet {
+ struct list_head element;
+ u32 pid;
+ u32 proc_id;
+ u32 event_no;
+ u32 data;
+ notify_callback_fxn func;
+ void *param;
+ bool is_exit;
+};
+
+/*Structure of Event callback argument passed to register fucntion*/
+struct notify_drv_event_cbck {
+ struct list_head element;
+ u32 proc_id;
+ notify_callback_fxn func;
+ void *param;
+ u32 pid;
+};
+
+/*Keeps the information related to Event.*/
+struct notifydrv_event_state {
+ struct list_head buf_list;
+ u32 pid;
+ u32 ref_count;
+ /*Reference count, used when multiple Notify_registerEvent are called
+ from same process space(multi threads/processes). */
+ struct semaphore *semhandle;
+ /* Semphore for waiting on event. */
+ struct semaphore *tersemhandle;
+ /* Termination synchronization semaphore. */
+};
+
+struct notifydrv_moduleobject{
+ bool is_setup;
+ /*Indicates whether the module has been already setup */
+ int open_refcount;
+ /* Open reference count. */
+ struct mutex *gatehandle;
+ /*Handle of gate to be used for local thread safety */
+ struct list_head evt_cbck_list;
+ /*List containg callback arguments for all registered handlers from
+ user mode. */
+ struct notifydrv_event_state event_state[MAX_PROCESSES];
+ /* List for all user processes registered. */
+};
+
+struct notifydrv_moduleobject notifydrv_state = {
+ .is_setup = false,
+ .open_refcount = 0,
+ .gatehandle = NULL,
+};
+
+/*Major number of driver.*/
+int major = 232;
+
+static void notify_drv_setup(void);
+
+static int notify_drv_add_buf_by_pid(u16 procId, u32 pid,
+ u32 eventNo, u32 data, notify_callback_fxn cbFxn, void *param);
+
+/* open the Notify driver object..*/
+static int notify_drv_open(struct inode *inode, struct file *filp) ;
+
+/* close the Notify driver object..*/
+static int notify_drv_close(struct inode *inode, struct file *filp);
+
+/* Linux driver function to map memory regions to user space. */
+static int notify_drv_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/* read function for of Notify driver.*/
+static int notify_drv_read(struct file *filp, char *dst,
+ size_t size, loff_t *offset);
+
+/* ioctl function for of Linux Notify driver.*/
+static int notify_drv_ioctl(struct inode *inode, struct file *filp, u32 cmd,
+ unsigned long args);
+
+/* Module initialization function for Linux driver.*/
+static int __init notify_drv_init_module(void);
+
+/* Module finalization function for Linux driver.*/
+static void __exit notify_drv_finalize_module(void) ;
+
+static void notify_drv_destroy(void);
+
+static int notify_drv_register_driver(void);
+
+static int notify_drv_unregister_driver(void);
+
+/* Attach a process to notify user support framework. */
+static int notify_drv_attach(u32 pid);
+
+/* Detach a process from notify user support framework. */
+static int notify_drv_detach(u32 pid);
+
+
+/* Function to invoke the APIs through ioctl.*/
+static const struct file_operations driver_ops = {
+ .open = notify_drv_open,
+ .ioctl = notify_drv_ioctl,
+ .release = notify_drv_close,
+ .read = notify_drv_read,
+ .mmap = notify_drv_mmap,
+};
+
+static int notify_drv_register_driver(void)
+{
+ notify_drv_setup();
+ return 0;
+}
+
+static int notify_drv_unregister_driver(void)
+{
+ notify_drv_destroy();
+ return 0;
+}
+
+
+/*
+* This function implements the callback registered with IPS. Here
+* to pass event no. back to user function(so that it can do another
+* level of demultiplexing of callbacks)
+*/
+static void notify_drv_cbck(u16 proc_id, u32 event_no,
+ void *arg, u32 payload)
+{
+ struct notify_drv_event_cbck *cbck;
+
+ if (WARN_ON(notifydrv_state.is_setup == false))
+ goto func_end;
+ BUG_ON(arg == NULL);
+ cbck = (struct notify_drv_event_cbck *)arg;
+ notify_drv_add_buf_by_pid(proc_id, cbck->pid, event_no, payload,
+ cbck->func, cbck->param);
+func_end:
+ return;
+}
+
+/*
+ * Linux specific function to open the driver.
+ */
+static int notify_drv_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/*
+ * close the driver
+ */
+static int notify_drv_close(struct inode *inode, struct file *filp)
+{
+ return 0 ;
+}
+
+/*
+ * read data from the driver
+ */
+static int notify_drv_read(struct file *filp, char *dst, size_t size,
+ loff_t *offset)
+{
+
+ bool flag = false;
+ struct notify_drv_event_packet *u_buf = NULL;
+ int ret_val = 0;
+ u32 i;
+ struct list_head *elem;
+ struct notify_drv_event_packet t_buf;
+ if (WARN_ON(notifydrv_state.is_setup == false)) {
+ ret_val = -EFAULT;
+ goto func_end;
+ }
+
+ ret_val = copy_from_user((void *)&t_buf,
+ (void *)dst,
+ sizeof(struct notify_drv_event_packet));
+ WARN_ON(ret_val != 0);
+
+
+ for (i = 0 ; i < MAX_PROCESSES ; i++) {
+ if (notifydrv_state.event_state[i].pid == t_buf.pid) {
+ flag = true;
+ break;
+ }
+ }
+ if (flag == false) {
+ ret_val = -EFAULT;
+ goto func_end;
+ }
+ /* Wait for the event */
+ ret_val = down_interruptible(
+ notifydrv_state.event_state[i].semhandle);
+ if (ret_val < 0) {
+ ret_val = -ERESTARTSYS;
+ goto func_end;
+ }
+ WARN_ON(mutex_lock_interruptible(notifydrv_state.gatehandle));
+ elem = ((struct list_head *)&(notifydrv_state.event_state[i]. \
+ buf_list))->next;
+ u_buf = container_of(elem, struct notify_drv_event_packet,
+ element);
+ list_del(elem);
+ mutex_unlock(notifydrv_state.gatehandle);
+ if (u_buf == NULL) {
+ ret_val = -EFAULT;
+ goto func_end;
+ }
+ ret_val = copy_to_user((void *)dst, u_buf,
+ sizeof(struct notify_drv_event_packet));
+
+ if (WARN_ON(ret_val != 0))
+ ret_val = -EFAULT;
+ if (u_buf->is_exit == true)
+ up(notifydrv_state.event_state[i].tersemhandle);
+
+ kfree(u_buf);
+ u_buf = NULL;
+
+
+func_end:
+ return ret_val ;
+}
+
+static int notify_drv_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+/*
+ * name notify_drv_ioctl
+ *
+ * ioctl function for of Linux Notify driver.
+ *
+*/
+static int notify_drv_ioctl(struct inode *inode, struct file *filp, u32 cmd,
+ unsigned long args)
+{
+ int retval = 0;
+ int status = NOTIFY_SUCCESS;
+ struct notify_cmd_args *cmdArgs = (struct notify_cmd_args *)args;
+ struct notify_cmd_args commonArgs;
+
+ switch (cmd) {
+ case CMD_NOTIFY_GETCONFIG:
+ {
+ struct notify_cmd_args_get_config *src_args =
+ (struct notify_cmd_args_get_config *)args;
+ struct notify_config cfg;
+ notify_get_config(&cfg);
+ retval = copy_to_user((void *) (src_args->cfg),
+ (const void *) &cfg, sizeof(struct notify_config));
+ }
+ break;
+
+ case CMD_NOTIFY_SETUP:
+ {
+ struct notify_cmd_args_setup *src_args =
+ (struct notify_cmd_args_setup *) args;
+ struct notify_config cfg;
+
+ retval = copy_from_user((void *) &cfg,
+ (const void *) (src_args->cfg),
+ sizeof(struct notify_config));
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ notify_setup(&cfg);
+ }
+ break;
+
+ case CMD_NOTIFY_DESTROY:
+ {
+ /* copy_from_user is not needed for Notify_getConfig, since the
+ * user's config is not used.
+ */
+ status = notify_destroy();
+ }
+ break;
+
+ case CMD_NOTIFY_REGISTEREVENT:
+ {
+ struct notify_cmd_args_register_event src_args;
+ struct notify_drv_event_cbck *cbck = NULL;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *) &src_args,
+ (const void *) (args),
+ sizeof(struct notify_cmd_args_register_event));
+
+ if (WARN_ON(retval != 0))
+ goto func_end;
+ cbck = kmalloc(sizeof(struct notify_drv_event_cbck),
+ GFP_ATOMIC);
+ WARN_ON(cbck == NULL);
+ cbck->proc_id = src_args.procId;
+ cbck->func = src_args.fnNotifyCbck;
+ cbck->param = src_args.cbckArg;
+ cbck->pid = src_args.pid;
+ status = notify_register_event(src_args.handle, src_args.procId,
+ src_args.eventNo, notify_drv_cbck, (void *)cbck);
+ if (status < 0) {
+ /* This does not impact return status of this function,
+ * so retval comment is not used.
+ */
+ kfree(cbck);
+ } else {
+ WARN_ON(mutex_lock_interruptible
+ (notifydrv_state.gatehandle));
+ INIT_LIST_HEAD((struct list_head *)&(cbck->element));
+ list_add_tail(&(cbck->element),
+ &(notifydrv_state.evt_cbck_list));
+ mutex_unlock(notifydrv_state.gatehandle);
+ }
+ }
+ break;
+
+ case CMD_NOTIFY_UNREGISTEREVENT:
+ {
+ bool found = false;
+ u32 pid;
+ struct notify_drv_event_cbck *cbck = NULL;
+ struct list_head *entry = NULL;
+ struct notify_cmd_args_unregister_event src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args, (const void *)(args),
+ sizeof(struct notify_cmd_args_unregister_event));
+
+ if (WARN_ON(retval != 0))
+ goto func_end;
+
+ pid = src_args.pid;
+ WARN_ON(mutex_lock_interruptible(notifydrv_state.gatehandle));
+ list_for_each(entry,
+ (struct list_head *)&(notifydrv_state.evt_cbck_list)) {
+ cbck = (struct notify_drv_event_cbck *)(entry);
+ if ((cbck->func == src_args.fnNotifyCbck) &&
+ (cbck->param == src_args.cbckArg) &&
+ (cbck->pid == pid) &&
+ (cbck->proc_id == src_args.procId)) {
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(notifydrv_state.gatehandle);
+ if (found == false) {
+ status = NOTIFY_E_NOTFOUND;
+ goto func_end;
+ }
+ status = notify_unregister_event(src_args.handle,
+ src_args.procId,
+ src_args.eventNo,
+ notify_drv_cbck, (void *) cbck);
+ /* This check is needed at run-time also to propagate the
+ * status to user-side. This must not be optimized out.
+ */
+ if (status < 0)
+ printk(KERN_ERR " notify_unregister_event failed \n");
+ else {
+ WARN_ON(mutex_lock_interruptible
+ (notifydrv_state.gatehandle));
+ list_del((struct list_head *)cbck);
+ mutex_unlock(notifydrv_state.gatehandle);
+ kfree(cbck);
+ }
+ }
+ break;
+
+ case CMD_NOTIFY_SENDEVENT:
+ {
+ struct notify_cmd_args_send_event src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *) &src_args,
+ (const void *) (args),
+ sizeof(struct notify_cmd_args_send_event));
+ if (WARN_ON(retval != 0)) {
+ retval = -EFAULT;
+ goto func_end;
+ }
+ status = notify_sendevent(src_args.handle, src_args.procId,
+ src_args.eventNo, src_args.payload,
+ src_args.waitClear);
+ }
+ break;
+
+ case CMD_NOTIFY_DISABLE:
+ {
+ struct notify_cmd_args_disable src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *) &src_args,
+ (const void *) (args),
+ sizeof(struct notify_cmd_args_disable));
+
+ /* This check is needed at run-time also since it depends on
+ * run environment. It must not be optimized out.
+ */
+ if (WARN_ON(retval != 0)) {
+ retval = -EFAULT;
+ goto func_end;
+ }
+ src_args.flags = notify_disable(src_args.procId);
+
+ /* Copy the full args to user-side */
+ retval = copy_to_user((void *) (args),
+ (const void *) &src_args,
+ sizeof(struct notify_cmd_args_disable));
+ /* This check is needed at run-time also since it depends on
+ * run environment. It must not be optimized out.
+ */
+ if (WARN_ON(retval != 0))
+ retval = -EFAULT;
+ }
+ break;
+
+ case CMD_NOTIFY_RESTORE:
+ {
+ struct notify_cmd_args_restore src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_cmd_args_restore));
+ if (WARN_ON(retval != 0)) {
+ retval = -EFAULT;
+ goto func_end;
+ }
+ notify_restore(src_args.key, src_args.procId);
+ }
+ break;
+
+ case CMD_NOTIFY_DISABLEEVENT:
+ {
+ struct notify_cmd_args_disable_event src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *) &src_args,
+ (const void *)(args),
+ sizeof(struct notify_cmd_args_disable_event));
+
+ /* This check is needed at run-time also since it depends on
+ * run environment. It must not be optimized out.
+ */
+ if (WARN_ON(retval != 0)) {
+ retval = -EFAULT;
+ goto func_end;
+ }
+ notify_disable_event(src_args.handle, src_args.procId,
+ src_args.eventNo);
+ }
+ break;
+
+ case CMD_NOTIFY_ENABLEEVENT:
+ {
+ struct notify_cmd_args_enable_event src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct notify_cmd_args_enable_event));
+ if (WARN_ON(retval != 0)) {
+ retval = -EFAULT;
+ goto func_end;
+ }
+ notify_enable_event(src_args.notify_driver_handle,
+ src_args.procId, src_args.eventNo);
+ }
+ break;
+
+ case CMD_NOTIFY_ATTACH:
+ {
+ /* FIXME: User copy_from_user */
+ u32 pid = *((u32 *)args);
+ status = notify_drv_attach(pid);
+
+ if (status < 0)
+ printk(KERN_ERR "NOTIFY_ATTACH FAILED\n");
+ }
+ break;
+
+ case CMD_NOTIFY_DETACH:
+ {
+ /* FIXME: User copy_from_user */
+ u32 pid = *((u32 *)args);
+ status = notify_drv_detach(pid);
+
+ if (status < 0)
+ printk(KERN_ERR "NOTIFY_DETACH FAILED\n");
+ }
+ break;
+
+ default:
+ {
+ /* This does not impact return status of this function,so retval
+ * comment is not used.
+ */
+ status = NOTIFY_E_INVALIDARG;
+ printk(KERN_ERR "not valid command\n");
+ }
+ break;
+ }
+func_end:
+ /* Set the status and copy the common args to user-side. */
+ commonArgs.apiStatus = status;
+ status = copy_to_user((void *) cmdArgs,
+ (const void *) &commonArgs,
+ sizeof(struct notify_cmd_args));
+ if (status < 0)
+ retval = -EFAULT;
+ return retval;
+}
+
+/*====================
+ * notify_drv_add_buf_by_pid
+ *
+ */
+static int notify_drv_add_buf_by_pid(u16 proc_id, u32 pid,
+ u32 event_no, u32 data, notify_callback_fxn cbFxn, void *param)
+{
+ s32 status = 0;
+ bool flag = false;
+ bool is_exit = false;
+ struct notify_drv_event_packet *u_buf = NULL;
+ u32 i;
+
+ for (i = 0 ; (i < MAX_PROCESSES) && (flag != true) ; i++) {
+ if (notifydrv_state.event_state[i].pid == pid) {
+ flag = true ;
+ break ;
+ }
+ }
+ if (WARN_ON(flag == false)) {
+ status = -EFAULT;
+ goto func_end;
+ }
+ u_buf = kzalloc(sizeof(struct notify_drv_event_packet), GFP_ATOMIC);
+
+ if (u_buf != NULL) {
+ INIT_LIST_HEAD((struct list_head *)&u_buf->element);
+ u_buf->proc_id = proc_id;
+ u_buf->data = data ;
+ u_buf->event_no = event_no ;
+ u_buf->func = cbFxn;
+ u_buf->param = param;
+ if (u_buf->event_no == (u32) -1) {
+ u_buf->is_exit = true;
+ is_exit = true;
+ }
+ if (mutex_lock_interruptible(notifydrv_state.gatehandle))
+ return NOTIFY_E_OSFAILURE;
+ list_add_tail((struct list_head *)&(u_buf->element),
+ (struct list_head *)
+ &(notifydrv_state.event_state[i].buf_list));
+ mutex_unlock(notifydrv_state.gatehandle);
+ up(notifydrv_state.event_state[i].semhandle);
+ /* Termination packet */
+ if (is_exit == true) {
+ if (down_interruptible(notifydrv_state.
+ event_state[i].tersemhandle))
+ status = NOTIFY_E_OSFAILURE;
+ }
+ }
+func_end:
+ return status;
+}
+
+/*
+ * Module setup function.
+ *
+ */
+static void notify_drv_setup(void)
+{
+ int i;
+
+ INIT_LIST_HEAD((struct list_head *)&(notifydrv_state.evt_cbck_list));
+ notifydrv_state.gatehandle = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+ mutex_init(notifydrv_state.gatehandle);
+ for (i = 0; i < MAX_PROCESSES ; i++) {
+ notifydrv_state.event_state[i].pid = -1;
+ notifydrv_state.event_state[i].ref_count = 0;
+ INIT_LIST_HEAD((struct list_head *)
+ &(notifydrv_state.event_state[i].buf_list));
+ }
+ notifydrv_state.is_setup = true;
+}
+
+
+/*
+* brief Module destroy function.
+*/
+static void notify_drv_destroy(void)
+{
+ int i;
+ struct notify_drv_event_packet *packet;
+ struct list_head *entry;
+ struct notify_drv_event_cbck *cbck;
+
+ for (i = 0; i < MAX_PROCESSES ; i++) {
+ list_for_each(entry, (struct list_head *)
+ &(notifydrv_state.event_state[i].buf_list)) {
+ packet = (struct notify_drv_event_packet *)entry;
+ if (packet != NULL)
+ kfree(packet);
+ }
+ INIT_LIST_HEAD(&notifydrv_state.event_state[i].buf_list);
+ }
+ list_for_each(entry,
+ (struct list_head *)&(notifydrv_state.evt_cbck_list)) {
+ cbck = (struct notify_drv_event_cbck *)(entry);
+ if (cbck != NULL)
+ kfree(cbck) ;
+ }
+ INIT_LIST_HEAD(&notifydrv_state.evt_cbck_list);
+ mutex_destroy(notifydrv_state.gatehandle);
+ kfree(notifydrv_state.gatehandle);
+ notifydrv_state.is_setup = false;
+ return;
+}
+
+
+
+
+/*
+ * brief Attach a process to notify user support framework.
+ */
+static int notify_drv_attach(u32 pid)
+{
+ s32 status = NOTIFY_SUCCESS;
+ bool flag = false;
+ bool is_init = false;
+ u32 i;
+ struct semaphore *sem_handle;
+ struct semaphore *ter_sem_handle;
+ int ret_val = 0;
+
+ if (notifydrv_state.is_setup == false) {
+ status = NOTIFY_E_FAIL;
+ } else {
+ WARN_ON(mutex_lock_interruptible(notifydrv_state.gatehandle));
+
+ for (i = 0 ; (i < MAX_PROCESSES) ; i++) {
+ if (notifydrv_state.event_state[i].pid == pid) {
+ notifydrv_state.event_state[i].ref_count++;
+ is_init = true;
+ break;
+ }
+ }
+ mutex_unlock(notifydrv_state.gatehandle);
+
+ if (is_init == true)
+ goto func_end;
+
+ sem_handle = kmalloc(sizeof(struct semaphore), GFP_ATOMIC);
+ ter_sem_handle = kmalloc(sizeof(struct semaphore), GFP_ATOMIC);
+
+ sema_init(sem_handle, 0);
+ /* Create the termination semaphore */
+ sema_init(ter_sem_handle, 0);
+
+ WARN_ON(mutex_lock_interruptible(notifydrv_state.gatehandle));
+ /* Search for an available slot for user process. */
+ for (i = 0 ; i < MAX_PROCESSES ; i++) {
+ if (notifydrv_state.event_state[i].pid == -1) {
+ notifydrv_state.event_state[i].semhandle =
+ sem_handle;
+ notifydrv_state.event_state[i].tersemhandle =
+ ter_sem_handle;
+ notifydrv_state.event_state[i].pid = pid;
+ notifydrv_state.event_state[i].ref_count
+ = 1;
+ INIT_LIST_HEAD(&(notifydrv_state.event_state[i].
+ buf_list));
+ flag = true;
+ break;
+ }
+ }
+ mutex_unlock(notifydrv_state.gatehandle);
+
+ if (WARN_ON(flag != true)) {
+ /* Max users have registered. No more clients
+ * can be supported */
+ status = NOTIFY_E_MAXCLIENTS;
+ }
+
+ if (status == NOTIFY_SUCCESS)
+ ret_val = 0;
+ else {
+ kfree(ter_sem_handle);
+ kfree(sem_handle);
+ ret_val = -EINVAL;
+ }
+
+ }
+func_end:
+ return ret_val;
+}
+
+
+/*
+ * brief Detach a process from notify user support framework.
+ */
+static int notify_drv_detach(u32 pid)
+{
+ s32 status = NOTIFY_SUCCESS;
+ bool flag = false;
+ u32 i;
+ struct semaphore *sem_handle;
+ struct semaphore *ter_sem_handle;
+
+ if (notifydrv_state.is_setup == false) {
+ status = NOTIFY_E_FAIL;
+ goto func_end;
+ }
+
+ /* Send the termination packet to notify thread */
+ status = notify_drv_add_buf_by_pid(0, pid, (u32)-1, (u32)0,
+ NULL, NULL);
+
+ if (status < 0)
+ goto func_end;
+
+ if (mutex_lock_interruptible(notifydrv_state.gatehandle)) {
+ status = NOTIFY_E_OSFAILURE;
+ goto func_end;
+ }
+ for (i = 0; i < MAX_PROCESSES; i++) {
+ if (notifydrv_state.event_state[i].pid == pid) {
+ if (notifydrv_state.event_state[i].ref_count == 1) {
+ /* Last client being unregistered for this
+ * process*/
+ notifydrv_state.event_state[i].pid = -1;
+ notifydrv_state.event_state[i].ref_count = 0;
+ sem_handle =
+ notifydrv_state.event_state[i].semhandle;
+ ter_sem_handle =
+ notifydrv_state.event_state[i].tersemhandle;
+ INIT_LIST_HEAD((struct list_head *)
+ &(notifydrv_state.event_state[i].buf_list));
+ notifydrv_state.event_state[i].semhandle =
+ NULL;
+ notifydrv_state.event_state[i].tersemhandle =
+ NULL;
+ flag = true;
+ break;
+ } else
+ notifydrv_state.event_state[i].ref_count--;
+ }
+ }
+ mutex_unlock(notifydrv_state.gatehandle);
+
+ if ((flag == false) && (i == MAX_PROCESSES)) {
+ /*retval NOTIFY_E_NOTFOUND The specified user process was
+ * not found registered with Notify Driver module. */
+ status = NOTIFY_E_NOTFOUND;
+ } else {
+ kfree(sem_handle);
+ kfree(ter_sem_handle);
+ }
+func_end:
+ return status;
+
+ /*! @retval NOTIFY_SUCCESS Operation successfully completed */
+ return status;
+}
+
+
+/* Module initialization function for Notify driver.*/
+static int __init notify_drv_init_module(void)
+{
+ int result = 0 ;
+ dev_t dev;
+
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ result = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ result = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ ipcnotify_device = kmalloc(sizeof(struct ipcnotify_dev), GFP_KERNEL);
+ if (!ipcnotify_device) {
+ result = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ goto func_end;
+ }
+ memset(ipcnotify_device, 0, sizeof(struct ipcnotify_dev));
+ cdev_init(&ipcnotify_device->cdev, &driver_ops);
+ ipcnotify_device->cdev.owner = THIS_MODULE;
+ ipcnotify_device->cdev.ops = &driver_ops;
+
+ result = cdev_add(&ipcnotify_device->cdev, dev, 1);
+
+ if (result) {
+ printk(KERN_ERR "Failed to add the syslink ipcnotify device \n");
+ goto func_end;
+ }
+
+ /* udev support */
+ ipcnotify_class = class_create(THIS_MODULE, "syslink-ipcnotify");
+
+ if (IS_ERR(ipcnotify_class)) {
+ printk(KERN_ERR "Error creating ipcnotify class \n");
+ goto func_end;
+ }
+ device_create(ipcnotify_class, NULL, MKDEV(driver_major, driver_minor),
+ NULL, IPCNOTIFY_NAME);
+ result = notify_drv_register_driver();
+func_end:
+ return result ;
+}
+
+/* Module finalization function for Notify driver.*/
+static void __exit notify_drv_finalize_module(void)
+{
+ dev_t dev_no;
+
+ notify_drv_unregister_driver();
+
+ dev_no = MKDEV(driver_major, driver_minor);
+ if (ipcnotify_device) {
+ cdev_del(&ipcnotify_device->cdev);
+ kfree(ipcnotify_device);
+ }
+ unregister_chrdev_region(dev_no, 1);
+ if (ipcnotify_class) {
+ /* remove the device from sysfs */
+ device_destroy(ipcnotify_class, MKDEV(driver_major,
+ driver_minor));
+ class_destroy(ipcnotify_class);
+ }
+ return;
+}
+
+
+/*
+ *name module_init/module_exit
+ *
+ *desc Macro calls that indicate initialization and finalization functions
+ *to the kernel.
+ *
+ */
+module_init(notify_drv_init_module) ;
+module_exit(notify_drv_finalize_module) ;
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/dsp/syslink/omap_notify/notify.c b/drivers/dsp/syslink/omap_notify/notify.c
new file mode 100755
index 000000000000..389ee72d997b
--- /dev/null
+++ b/drivers/dsp/syslink/omap_notify/notify.c
@@ -0,0 +1,548 @@
+/*
+ * notify.c
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/pgtable.h>
+
+#include <syslink/notify.h>
+#include <syslink/notify_driver.h>
+#include <syslink/GlobalTypes.h>
+#include <syslink/gt.h>
+#include <syslink/multiproc.h>
+#include <syslink/atomic_linux.h>
+
+/*
+ * func _notify_is_support_proc
+ *
+ *desc Check if specified processor ID is supported by the Notify driver.
+ *
+ */
+static bool _notify_is_support_proc(struct notify_driver_object *drv_handle,
+ int proc_id);
+
+struct notify_module_object notify_state = {
+ .def_cfg.maxDrivers = 2,
+};
+EXPORT_SYMBOL(notify_state);
+
+
+/*
+ * Get the default configuration for the Notify module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to Notify_setup filled in by the
+ * Notify module with the default parameters. If the user
+ * does not wish to make any change in the default parameters, this
+ * API is not required to be called.
+ *
+ * param-cfg :Pointer to the Notify module configuration
+ * structure in which the default config is to be returned.
+ */
+void notify_get_config(struct notify_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true)
+ memcpy(cfg, &notify_state.def_cfg,
+ sizeof(struct notify_config));
+ else
+ memcpy(cfg, &notify_state.cfg, sizeof(struct notify_config));
+}
+EXPORT_SYMBOL(notify_get_config);
+
+/*
+ * Setup the Notify module.
+ *
+ * This function sets up the Notify module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then Notify_getConfig can be called to get the
+ * configuration filled with the default values. After this, only
+ * the required configuration values can be changed. If the user
+ * does not wish to make any change in the default parameters, the
+ * application can simply call Notify_setup with NULL
+ * parameters. The default parameters would get automatically used.
+ *
+ * param -cfg Optional Notify module configuration. If provided as
+ * NULL, default configuration is used.
+ */
+int notify_setup(struct notify_config *cfg)
+{
+ int status = NOTIFY_SUCCESS;
+ struct notify_config tmpCfg;
+
+ atomic_cmpmask_and_set(&notify_state.ref_count,
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&notify_state.ref_count)
+ != NOTIFY_MAKE_MAGICSTAMP(1u)) {
+ status = NOTIFY_S_ALREADYSETUP;
+ } else {
+ if (cfg == NULL) {
+ notify_get_config(&tmpCfg);
+ cfg = &tmpCfg;
+ }
+
+ notify_state.gate_handle = kmalloc(sizeof(struct mutex),
+ GFP_ATOMIC);
+ /*User has not provided any gate handle,
+ so create a default handle.*/
+ mutex_init(notify_state.gate_handle);
+
+ if (WARN_ON(cfg->maxDrivers > NOTIFY_MAX_DRIVERS)) {
+ status = NOTIFY_E_CONFIG;
+ kfree(notify_state.gate_handle);
+ atomic_set(&notify_state.ref_count,
+ NOTIFY_MAKE_MAGICSTAMP(0));
+ goto func_end;
+ }
+ memcpy(&notify_state.cfg, cfg, sizeof(struct notify_config));
+ memset(&notify_state.drivers, 0,
+ (sizeof(struct notify_driver_object) *
+ NOTIFY_MAX_DRIVERS));
+
+ notify_state.disable_depth = 0;
+
+ }
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(notify_setup);
+
+/*
+ * Destroy the Notify module.
+ *
+ * Once this function is called, other Notify module APIs,
+ * except for the Notify_getConfig API cannot be called
+ * anymore.
+ */
+int notify_destroy(void)
+{
+ int i;
+ int status = NOTIFY_SUCCESS;
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ } else {
+ if (atomic_dec_return(&(notify_state.ref_count)) ==
+ NOTIFY_MAKE_MAGICSTAMP(0)) {
+
+ /* Check if any Notify driver instances have
+ * not been deleted so far. If not, assert.
+ */
+ for (i = 0; i < NOTIFY_MAX_DRIVERS; i++)
+ WARN_ON(notify_state.drivers[i].is_init
+ != false);
+
+ if (notify_state.gate_handle != NULL)
+ kfree(notify_state.gate_handle);
+
+ atomic_set(&notify_state.ref_count,
+ NOTIFY_MAKE_MAGICSTAMP(0));
+ }
+ }
+ return status;
+}
+EXPORT_SYMBOL(notify_destroy);
+
+/*
+ * func notify_register_event
+ *
+ * desc This function registers a callback for a specific event with the
+ * Notify module.
+ */
+int notify_register_event(void *notify_driver_handle, u16 proc_id,
+ u32 event_no, notify_callback_fxn notify_callback_fxn, void *cbck_arg)
+{
+ int status = NOTIFY_SUCCESS;
+
+ struct notify_driver_object *drv_handle =
+ (struct notify_driver_object *)notify_driver_handle;
+
+ BUG_ON(drv_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(drv_handle->is_init == false)) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(_notify_is_support_proc(drv_handle, proc_id) != true)) {
+ status = NOTIFY_E_INVALIDARG;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK)
+ >= drv_handle->attrs.proc_info[proc_id].max_events))) {
+ status = NOTIFY_E_INVALIDEVENT;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK) <
+ drv_handle->attrs.proc_info[proc_id].reserved_events) &&
+ ((event_no & NOTIFY_SYSTEM_KEY_MASK) >> sizeof(u16)) !=
+ NOTIFY_SYSTEM_KEY)) {
+ status = NOTIFY_E_RESERVEDEVENT;
+ goto func_end;
+ }
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ status = drv_handle->fn_table.register_event(drv_handle, proc_id,
+ (event_no & NOTIFY_EVENT_MASK), notify_callback_fxn,
+ cbck_arg);
+ mutex_unlock(notify_state.gate_handle);
+ if (WARN_ON(status < 0))
+ status = NOTIFY_E_FAIL;
+ else
+ status = NOTIFY_SUCCESS;
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(notify_register_event);
+
+/*
+ * func notify_unregister_event
+ *
+ * desc This function un-registers the callback for the specific event with
+ * the Notify module.
+ */
+
+int notify_unregister_event(void *notify_driver_handle, u16 proc_id,
+ u32 event_no, notify_callback_fxn notify_callback_fxn, void *cbck_arg)
+{
+ int status = NOTIFY_SUCCESS;
+ struct notify_driver_object *drv_handle =
+ (struct notify_driver_object *)notify_driver_handle;
+ BUG_ON(drv_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(drv_handle->is_init == false)) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(_notify_is_support_proc(drv_handle, proc_id) != true)) {
+ status = NOTIFY_E_INVALIDARG;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK)
+ >= drv_handle->attrs.proc_info[proc_id].max_events))) {
+ status = NOTIFY_E_INVALIDEVENT;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK) <
+ drv_handle->attrs.proc_info[proc_id].reserved_events) &&
+ ((event_no & NOTIFY_SYSTEM_KEY_MASK) >> sizeof(u16)) !=
+ NOTIFY_SYSTEM_KEY)) {
+ status = NOTIFY_E_RESERVEDEVENT;
+ goto func_end;
+ }
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ status = drv_handle->fn_table.unregister_event(drv_handle,
+ proc_id, (event_no & NOTIFY_EVENT_MASK),
+ notify_callback_fxn, cbck_arg);
+ mutex_unlock(notify_state.gate_handle);
+ if (WARN_ON(status < 0))
+ status = NOTIFY_E_FAIL;
+ else
+ status = NOTIFY_SUCCESS;
+
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(notify_unregister_event);
+
+/*
+ * func notify_sendevent
+ *
+ * desc This function sends a notification to the specified event.
+ *
+ *
+ */
+int notify_sendevent(void *notify_driver_handle, u16 proc_id,
+ u32 event_no, u32 payload, bool wait_clear)
+{
+ int status = NOTIFY_SUCCESS;
+ struct notify_driver_object *drv_handle =
+ (struct notify_driver_object *)notify_driver_handle;
+ BUG_ON(drv_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(drv_handle->is_init == false)) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(_notify_is_support_proc(drv_handle, proc_id) != true)) {
+ status = NOTIFY_E_INVALIDARG;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK)
+ >= drv_handle->attrs.proc_info[proc_id].max_events))) {
+ status = NOTIFY_E_INVALIDEVENT;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK) <
+ drv_handle->attrs.proc_info[proc_id].reserved_events) &&
+ ((event_no & NOTIFY_SYSTEM_KEY_MASK) >> sizeof(u16)) !=
+ NOTIFY_SYSTEM_KEY)) {
+ status = NOTIFY_E_RESERVEDEVENT;
+ goto func_end;
+ }
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ status = drv_handle->fn_table.send_event
+ (drv_handle, proc_id, (event_no & NOTIFY_EVENT_MASK),
+ payload, wait_clear);
+ mutex_unlock(notify_state.gate_handle);
+ if (status < 0)
+ status = NOTIFY_E_FAIL;
+ else
+ status = NOTIFY_SUCCESS;
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(notify_sendevent);
+
+/*
+ * func notify_disable
+ *
+ * desc This function disables all events. This is equivalent to global
+ * interrupt disable, however restricted within interrupts handled by
+ * the Notify module. All callbacks registered for all events are
+ * disabled with this API. It is not possible to disable a specific
+ * callback.
+ *
+ */
+u32 notify_disable(u16 proc_id)
+{
+ struct notify_driver_object *drv_handle;
+ int i;
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true)
+ WARN_ON(1);
+
+
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ for (i = 0; i < notify_state.cfg.maxDrivers; i++) {
+ drv_handle = &(notify_state.drivers[i]);
+ WARN_ON(_notify_is_support_proc(drv_handle, proc_id)
+ == false);
+ if (drv_handle->is_init ==
+ NOTIFY_DRIVERINITSTATUS_NOTDONE) {
+ if (drv_handle->fn_table.disable) {
+ drv_handle->disable_flag[notify_state.
+ disable_depth] =
+ (u32 *)drv_handle->fn_table.
+ disable(drv_handle,
+ proc_id);
+ }
+ }
+ }
+ notify_state.disable_depth++;
+ mutex_unlock(notify_state.gate_handle);
+
+ return notify_state.disable_depth;
+}
+EXPORT_SYMBOL(notify_disable);
+
+/*
+ * notify_restore
+ *
+ * desc This function restores the Notify module to the state before the
+ * last notify_disable() was called. This is equivalent to global
+ * interrupt restore, however restricted within interrupts handled by
+ * the Notify module. All callbacks registered for all events as
+ * specified in the flags are enabled with this API. It is not possible
+ * to enable a specific callback.
+ *
+ *
+ */
+void notify_restore(u32 key, u16 proc_id)
+{
+ struct notify_driver_object *drv_handle;
+ int i;
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true)
+ WARN_ON(1);
+
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ notify_state.disable_depth--;
+ for (i = 0; i < notify_state.cfg.maxDrivers; i++) {
+ drv_handle = &(notify_state.drivers[i]);
+ if (drv_handle->fn_table.restore)
+ drv_handle->fn_table.restore(drv_handle,
+ key, proc_id);
+ }
+ mutex_unlock(notify_state.gate_handle);
+ return;
+}
+EXPORT_SYMBOL(notify_restore);
+
+/*
+ *func notify_disable_event
+ *
+ * desc This function disables a specific event. All callbacks registered
+ * for the specific event are disabled with this API. It is not
+ * possible to disable a specific callback.
+ *
+ */
+
+void notify_disable_event(void *notify_driver_handle, u16 proc_id, u32 event_no)
+{
+ int status = 0;
+ struct notify_driver_object *drv_handle =
+ (struct notify_driver_object *)notify_driver_handle;
+ BUG_ON(drv_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+
+ if (WARN_ON(drv_handle->is_init == false)) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+ if (WARN_ON(_notify_is_support_proc(drv_handle, proc_id) != true)) {
+ status = NOTIFY_E_INVALIDARG;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK)
+ >= drv_handle->attrs.proc_info[proc_id].max_events))) {
+ status = NOTIFY_E_INVALIDEVENT;
+ goto func_end;
+ }
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK) <
+ drv_handle->attrs.proc_info[proc_id].reserved_events) &&
+ ((event_no & NOTIFY_SYSTEM_KEY_MASK) >> sizeof(u16)) !=
+ NOTIFY_SYSTEM_KEY)) {
+ status = NOTIFY_E_RESERVEDEVENT;
+ goto func_end;
+ }
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ drv_handle->fn_table.disable_event(drv_handle,
+ proc_id, (event_no & NOTIFY_EVENT_MASK));
+ mutex_unlock(notify_state.gate_handle);
+func_end:
+ return;
+}
+EXPORT_SYMBOL(notify_disable_event);
+
+/*
+ * notify_enable_event
+ *
+ * This function enables a specific event. All callbacks registered for
+ * this specific event are enabled with this API. It is not possible to
+ * enable a specific callback.
+ *
+ */
+void notify_enable_event(void *notify_driver_handle, u16 proc_id, u32 event_no)
+{
+
+ struct notify_driver_object *drv_handle =
+ (struct notify_driver_object *) notify_driver_handle;
+
+ BUG_ON(drv_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ goto func_end;
+ }
+
+ if (WARN_ON(drv_handle->is_init == false))
+ goto func_end;
+ if (WARN_ON(_notify_is_support_proc(drv_handle, proc_id) != true))
+ goto func_end;
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK)
+ >= drv_handle->attrs.proc_info[proc_id].max_events)))
+ goto func_end;
+ if (WARN_ON(((event_no & NOTIFY_EVENT_MASK) <
+ drv_handle->attrs.proc_info[proc_id].reserved_events) &&
+ ((event_no & NOTIFY_SYSTEM_KEY_MASK) >> sizeof(u16)) !=
+ NOTIFY_SYSTEM_KEY))
+ goto func_end;
+
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ if (drv_handle->fn_table.enable_event) {
+ drv_handle->fn_table.enable_event(drv_handle,
+ proc_id, (event_no & NOTIFY_EVENT_MASK));
+ }
+ mutex_unlock(notify_state.gate_handle);
+func_end:
+ return;
+}
+EXPORT_SYMBOL(notify_enable_event);
+
+/*
+ *_notify_is_support_proc
+ *
+ * Check if specified processor ID is supported by the Notify driver.
+ *
+ */
+static bool _notify_is_support_proc(struct notify_driver_object *drv_handle,
+ int proc_id)
+{
+ bool found = false;
+ struct notify_driver_attrs *attrs;
+ int i;
+
+ BUG_ON(drv_handle == NULL);
+ attrs = &(drv_handle->attrs);
+ for (i = 0; i < MULTIPROC_MAXPROCESSORS; i++) {
+ if (attrs->proc_info[i].proc_id == proc_id) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
diff --git a/drivers/dsp/syslink/omap_notify/notify_driver.c b/drivers/dsp/syslink/omap_notify/notify_driver.c
new file mode 100755
index 000000000000..c90c57335918
--- /dev/null
+++ b/drivers/dsp/syslink/omap_notify/notify_driver.c
@@ -0,0 +1,172 @@
+/*
+ * notify_driver.c
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+
+#include <linux/io.h>
+#include <asm/pgtable.h>
+#include <syslink/gt.h>
+
+#include <syslink/notify.h>
+#include <syslink/notify_driver.h>
+#include <syslink/atomic_linux.h>
+
+/*
+ *func notify_register_driver
+ *
+ *desc This function registers a Notify driver with the Notify module.
+ */
+
+int notify_register_driver(char *driver_name,
+ struct notify_interface *fn_table,
+ struct notify_driver_attrs *drv_attrs,
+ struct notify_driver_object **driver_handle)
+{
+ int status = NOTIFY_SUCCESS;
+ struct notify_driver_object *drv_handle = NULL;
+ int i;
+
+ BUG_ON(driver_name == NULL);
+ BUG_ON(fn_table == NULL);
+ BUG_ON(drv_attrs == NULL);
+ BUG_ON(driver_handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ goto func_end;
+ }
+
+ /*Initialize to status that indicates that an empty slot was not
+ *found for the driver.
+ */
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+ status = NOTIFY_E_MAXDRIVERS;
+ for (i = 0; i < notify_state.cfg.maxDrivers; i++) {
+ drv_handle = &(notify_state.drivers[i]);
+
+ if (drv_handle->is_init == NOTIFY_DRIVERINITSTATUS_DONE) {
+ if (strncmp(driver_name, drv_handle->name,
+ NOTIFY_MAX_NAMELEN) == 0) {
+ status = NOTIFY_E_ALREADYEXISTS;
+ goto return_existing_handle;
+ }
+ }
+ if (drv_handle->is_init == NOTIFY_DRIVERINITSTATUS_NOTDONE) {
+ /* Found an empty slot, so block it. */
+ drv_handle->is_init =
+ NOTIFY_DRIVERINITSTATUS_INPROGRESS;
+ status = NOTIFY_SUCCESS;
+ break;
+ }
+ }
+ mutex_unlock(notify_state.gate_handle);
+ WARN_ON(status < 0);
+ /*Complete registration of the driver. */
+ strncpy(drv_handle->name,
+ driver_name, NOTIFY_MAX_NAMELEN);
+ memcpy(&(drv_handle->attrs), drv_attrs,
+ sizeof(struct notify_driver_attrs));
+ memcpy(&(drv_handle->fn_table), fn_table,
+ sizeof(struct notify_interface));
+ drv_handle->driver_object = NULL;
+
+return_existing_handle:
+ /*is_setup is set when driverInit is called. */
+ *driver_handle = drv_handle;
+
+func_end:
+ return status;
+}
+EXPORT_SYMBOL(notify_register_driver);
+
+/*========================================
+ *func notify_unregister_driver
+ *
+ *desc This function un-registers a Notify driver with the Notify module.
+ */
+int notify_unregister_driver(struct notify_driver_object *drv_handle)
+{
+ int status = NOTIFY_SUCCESS;
+
+ BUG_ON(drv_handle == NULL);
+
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ } else {
+ /* Unregister the driver. */
+ drv_handle->is_init = NOTIFY_DRIVERINITSTATUS_NOTDONE;
+
+ }
+ return status;
+}
+EXPORT_SYMBOL(notify_unregister_driver);
+
+
+/*==================================
+ * Function to find and return the driver handle maintained within
+ * the Notify module.
+ *
+ * driver_name Name of the driver to be searched.
+ * handle Return parameter: Handle to the driver.
+ *
+ */
+int notify_get_driver_handle(char *driver_name,
+ struct notify_driver_object **handle)
+{
+ int status = NOTIFY_E_NOTFOUND;
+ struct notify_driver_object *drv_handle;
+ int i;
+
+ BUG_ON(handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&(notify_state.ref_count),
+ NOTIFY_MAKE_MAGICSTAMP(0),
+ NOTIFY_MAKE_MAGICSTAMP(1)) == true) {
+ status = NOTIFY_E_INVALIDSTATE;
+ } else if (WARN_ON(driver_name == NULL))
+ status = NOTIFY_E_INVALIDARG;
+ else {
+ if (mutex_lock_interruptible(notify_state.gate_handle) != 0)
+ WARN_ON(1);
+
+ for (i = 0; i < notify_state.cfg.maxDrivers; i++) {
+ drv_handle = &(notify_state.drivers[i]);
+ /* Check whether the driver handle slot is occupied. */
+ if (drv_handle->is_init == true) {
+ if (strncmp(driver_name, drv_handle->name,
+ NOTIFY_MAX_NAMELEN) == 0) {
+ status = NOTIFY_SUCCESS;
+ *handle = drv_handle;
+ break;
+ }
+ }
+ }
+ mutex_unlock(notify_state.gate_handle);
+ }
+ return status;
+}
+EXPORT_SYMBOL(notify_get_driver_handle);
diff --git a/drivers/dsp/syslink/procmgr/Kbuild b/drivers/dsp/syslink/procmgr/Kbuild
new file mode 100755
index 000000000000..58f6d3155250
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/Kbuild
@@ -0,0 +1,10 @@
+libomap_syslink_proc = processor.o procmgr.o procmgr_drv.o
+
+obj-$(CONFIG_SYSLINK_PROC) += syslink_proc.o
+syslink_proc-objs = $(libomap_syslink_proc)
+
+ccflags-y += -Wno-strict-prototypes
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include/syslink
+
diff --git a/drivers/dsp/syslink/procmgr/proc4430/Kbuild b/drivers/dsp/syslink/procmgr/proc4430/Kbuild
new file mode 100755
index 000000000000..f82f2e23f79a
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/Kbuild
@@ -0,0 +1,10 @@
+libomap_proc4430 = proc4430.o proc4430_drv.o dmm4430.o \
+ ducatienabler.o hw_mmu.o
+
+obj-$(CONFIG_SYSLINK_PROC) += syslink_proc4430.o
+syslink_proc4430-objs = $(libomap_proc4430)
+
+ccflags-y += -Wno-strict-prototypes -DUSE_LEVEL_1_MACROS
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include/syslink
diff --git a/drivers/dsp/syslink/procmgr/proc4430/dmm4430.c b/drivers/dsp/syslink/procmgr/proc4430/dmm4430.c
new file mode 100755
index 000000000000..d2ed9ece2245
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/dmm4430.c
@@ -0,0 +1,355 @@
+/*
+ * dmm4430.c
+ *
+ * Syslink support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+/*
+ * ======== dmm.c ========
+ * Purpose:
+ *The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
+ *space that can be directly mapped to any MPU buffer or memory region
+ *
+ * Public Functions:
+ *dmm_create_tables
+ *dmm_create
+ *dmm_destroy
+ *dmm_exit
+ *dmm_init
+ *dmm_map_memory
+ *DMM_Reset
+ *dmm_reserve_memory
+ *dmm_unmap_memory
+ *dmm_unreserve_memory
+ *
+ * Private Functions:
+ *add_region
+ *create_region
+ *get_region
+ * get_free_region
+ * get_mapped_region
+ *
+ * Notes:
+ *Region: Generic memory entitiy having a start address and a size
+ *Chunk: Reserved region
+ *
+ *!
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <asm/page.h>
+#include "dmm4430.h"
+
+
+#define DMM_ADDR_VIRTUAL(x, a) \
+ do { \
+ x = (((struct map_page *)(a) - p_virt_mapping_tbl) * PAGE_SIZE \
+ + dyn_mem_map_begin);\
+ } while (0)
+
+#define DMM_ADDR_TO_INDEX(i, a) \
+ do { \
+ i = (((a) - dyn_mem_map_begin) / PAGE_SIZE); \
+ } while (0)
+
+struct map_page {
+ u32 region_size:31;
+ u32 b_reserved:1;
+};
+
+/* Create the free list */
+static struct map_page *p_virt_mapping_tbl;
+static u32 i_freeregion; /* The index of free region */
+static u32 i_freesize;
+static u32 table_size;/* The size of virtual and physical pages tables */
+static u32 dyn_mem_map_begin;
+struct mutex *dmm_lock;
+
+static struct map_page *get_free_region(u32 size);
+static struct map_page *get_mapped_region(u32 addr);
+
+/* ======== dmm_create_tables ========
+ * Purpose:
+ *Create table to hold information of the virtual memory that is reserved
+ *for DSP.
+ */
+int dmm_create_tables(u32 addr, u32 size)
+{
+ int status = 0;
+
+ dmm_delete_tables();
+ if (WARN_ON(mutex_lock_interruptible(dmm_lock)) < 0) {
+ status = -EFAULT;
+ goto func_exit;
+ }
+ dyn_mem_map_begin = addr;
+ table_size = (size/PAGE_SIZE) + 1;
+ /* Create the free list */
+ p_virt_mapping_tbl = (struct map_page *)vmalloc(
+ table_size*sizeof(struct map_page));
+ if (WARN_ON(p_virt_mapping_tbl == NULL))
+ status = -ENOMEM;
+ /* On successful allocation,
+ * all entries are zero ('free') */
+ i_freeregion = 0;
+ i_freesize = table_size*PAGE_SIZE;
+ p_virt_mapping_tbl[0].region_size = table_size;
+ mutex_unlock(dmm_lock);
+
+func_exit:
+ return status;
+}
+
+/*
+ * ======== dmm_create ========
+ * Purpose:
+ *Create a dynamic memory manager object.
+ */
+int dmm_create(void)
+{
+ int status = 0;
+ dmm_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (WARN_ON(dmm_lock == NULL)) {
+ status = -EFAULT;
+ goto func_exit;
+ }
+ mutex_init(dmm_lock);
+func_exit:
+ return status;
+}
+
+/*
+ * ======== dmm_destroy ========
+ * Purpose:
+ *Release the communication memory manager resources.
+ */
+void dmm_destroy(void)
+{
+ dmm_delete_tables();
+ kfree(dmm_lock);
+}
+
+
+/*
+ * ======== dmm_delete_tables ========
+ * Purpose:
+ *Delete DMM Tables.
+ */
+void dmm_delete_tables(void)
+{
+ /* Delete all DMM tables */
+ WARN_ON(mutex_lock_interruptible(dmm_lock));
+ if (p_virt_mapping_tbl != NULL) {
+ vfree(p_virt_mapping_tbl);
+ p_virt_mapping_tbl = NULL;
+ }
+ mutex_unlock(dmm_lock);
+}
+
+/*
+ * ======== dmm_init ========
+ * Purpose:
+ *Initializes private state of DMM module.
+ */
+void dmm_init(void)
+{
+ p_virt_mapping_tbl = NULL ;
+ table_size = 0;
+ return;
+}
+
+/*
+ * ======== dmm_reserve_memory ========
+ * Purpose:
+ *Reserve a chunk of virtually contiguous DSP/IVA address space.
+ */
+int dmm_reserve_memory(u32 size, u32 *p_rsv_addr)
+{
+ int status = 0;
+ struct map_page *node;
+ u32 rsv_addr = 0;
+ u32 rsv_size = 0;
+
+ if (WARN_ON(mutex_lock_interruptible(dmm_lock)) < 0) {
+ status = -EFAULT;
+ goto func_exit;
+ }
+
+ /* Try to get a DSP chunk from the free list */
+ node = get_free_region(size);
+ if (node != NULL) {
+ /* DSP chunk of given size is available. */
+ DMM_ADDR_VIRTUAL(rsv_addr, node);
+ /* Calculate the number entries to use */
+ rsv_size = size/PAGE_SIZE;
+ if (rsv_size < node->region_size) {
+ /* Mark remainder of free region */
+ node[rsv_size].b_reserved = false;
+ node[rsv_size].region_size =
+ node->region_size - rsv_size;
+ }
+ /* get_region will return first fit chunk. But we only use what
+ is requested. */
+ node->b_reserved = true;
+ node->region_size = rsv_size;
+ /* Return the chunk's starting address */
+ *p_rsv_addr = rsv_addr;
+ } else
+ /*dSP chunk of given size is not available */
+ status = -ENOMEM;
+
+ mutex_unlock(dmm_lock);
+func_exit:
+ return status;
+}
+
+
+/*
+ * ======== dmm_unreserve_memory ========
+ * Purpose:
+ *Free a chunk of reserved DSP/IVA address space.
+ */
+int dmm_unreserve_memory(u32 rsv_addr, u32 *psize)
+{
+ struct map_page *chunk;
+ int status = 0;
+
+ WARN_ON(mutex_lock_interruptible(dmm_lock));
+
+ /* Find the chunk containing the reserved address */
+ chunk = get_mapped_region(rsv_addr);
+ if (chunk == NULL)
+ status = -ENXIO;
+ WARN_ON(status < 0);
+ if (status == 0) {
+ chunk->b_reserved = false;
+ *psize = chunk->region_size * PAGE_SIZE;
+ /* NOTE: We do NOT coalesce free regions here.
+ * Free regions are coalesced in get_region(), as it traverses
+ *the whole mapping table
+ */
+ }
+ mutex_unlock(dmm_lock);
+ return status;
+}
+
+/*
+ * ======== get_free_region ========
+ * Purpose:
+ * Returns the requested free region
+ */
+static struct map_page *get_free_region(u32 size)
+{
+ struct map_page *curr_region = NULL;
+ u32 i = 0;
+ u32 region_size = 0;
+ u32 next_i = 0;
+
+ if (p_virt_mapping_tbl == NULL)
+ return curr_region;
+ if (size > i_freesize) {
+ /* Find the largest free region
+ * (coalesce during the traversal) */
+ while (i < table_size) {
+ region_size = p_virt_mapping_tbl[i].region_size;
+ next_i = i+region_size;
+ if (p_virt_mapping_tbl[i].b_reserved == false) {
+ /* Coalesce, if possible */
+ if (next_i < table_size &&
+ p_virt_mapping_tbl[next_i].b_reserved
+ == false) {
+ p_virt_mapping_tbl[i].region_size +=
+ p_virt_mapping_tbl[next_i].region_size;
+ continue;
+ }
+ region_size *= PAGE_SIZE;
+ if (region_size > i_freesize) {
+ i_freeregion = i;
+ i_freesize = region_size;
+ }
+ }
+ i = next_i;
+ }
+ }
+ if (size <= i_freesize) {
+ curr_region = p_virt_mapping_tbl + i_freeregion;
+ i_freeregion += (size / PAGE_SIZE);
+ i_freesize -= size;
+ }
+ return curr_region;
+}
+
+/*
+ * ======== get_mapped_region ========
+ * Purpose:
+ * Returns the requestedmapped region
+ */
+static struct map_page *get_mapped_region(u32 addr)
+{
+ u32 i = 0;
+ struct map_page *curr_region = NULL;
+
+ if (p_virt_mapping_tbl == NULL)
+ return curr_region;
+
+ DMM_ADDR_TO_INDEX(i, addr);
+ if (i < table_size && (p_virt_mapping_tbl[i].b_reserved))
+ curr_region = p_virt_mapping_tbl + i;
+ return curr_region;
+}
+
+#ifdef DSP_DMM_DEBUG
+int dmm_mem_map_dump(void)
+{
+ struct map_page *curNode = NULL;
+ u32 i;
+ u32 freemem = 0;
+ u32 bigsize = 0;
+
+ WARN_ON(mutex_lock_interruptible(dmm_lock));
+
+ if (p_virt_mapping_tbl != NULL) {
+ for (i = 0; i < table_size; i +=
+ p_virt_mapping_tbl[i].region_size) {
+ curNode = p_virt_mapping_tbl + i;
+ if (curNode->b_reserved == true) {
+ /*printk("RESERVED size = 0x%x, "
+ "Map size = 0x%x\n",
+ (curNode->region_size * PAGE_SIZE),
+ (curNode->b_mapped == false) ? 0 :
+ (curNode->mapped_size * PAGE_SIZE));
+*/
+ } else {
+/* printk("UNRESERVED size = 0x%x\n",
+ (curNode->region_size * PAGE_SIZE));
+*/
+ freemem += (curNode->region_size * PAGE_SIZE);
+ if (curNode->region_size > bigsize)
+ bigsize = curNode->region_size;
+ }
+ }
+ }
+ printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
+ freemem/(1024*1024));
+ printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
+ (((table_size * PAGE_SIZE)-freemem))/(1024*1024));
+ printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
+ (bigsize*PAGE_SIZE/(1024*1024)));
+ mutex_unlock(dmm_lock);
+
+ return 0;
+}
+#endif
diff --git a/drivers/dsp/syslink/procmgr/proc4430/dmm4430.h b/drivers/dsp/syslink/procmgr/proc4430/dmm4430.h
new file mode 100755
index 000000000000..7d879f4fe123
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/dmm4430.h
@@ -0,0 +1,50 @@
+/*
+ * dmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+
+/*
+ * ======== dmm.h ========
+ * Purpose:
+ *The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
+ *space that can be directly mapped to any MPU buffer or memory region
+ *
+ * Public Functions:
+ *
+ */
+
+#ifndef DMM_4430_
+#define DMM_4430_
+
+#include <linux/types.h>
+
+int dmm_reserve_memory(u32 size, u32 *p_rsv_addr);
+
+int dmm_unreserve_memory(u32 rsv_addr, u32 *psize);
+
+void dmm_destroy(void);
+
+void dmm_delete_tables(void);
+
+int dmm_create(void);
+
+void dmm_init(void);
+
+int dmm_create_tables(u32 addr, u32 size);
+
+#ifdef DSP_DMM_DEBUG
+int dmm_mem_map_dump(void);
+#endif
+#endif/* DMM_4430_ */
diff --git a/drivers/dsp/syslink/procmgr/proc4430/ducatienabler.c b/drivers/dsp/syslink/procmgr/proc4430/ducatienabler.c
new file mode 100644
index 000000000000..a924c0dda60f
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/ducatienabler.c
@@ -0,0 +1,1332 @@
+/*
+ * ducatienabler.c
+ *
+ * Syslink driver support for TI OMAP processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/gfp.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <asm/page.h>
+#include <linux/kernel.h>
+#include <linux/pagemap.h>
+
+
+#include <linux/autoconf.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/syscalls.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+
+#include <syslink/ducatienabler.h>
+
+
+#ifdef DEBUG_DUCATI_IPC
+#define DPRINTK(fmt, args...) printk(KERN_INFO "%s: " fmt, __func__, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+
+#define base_ducati_l2_mmuPhys 0x55082000
+
+/*
+ * Macro to define the physical memory address for the
+ * Ducati Base image. The 74Mb memory is preallocated
+ * during the make menuconfig.
+ *
+ */
+/* #define DUCATI_BASEIMAGE_PHYSICAL_ADDRESS 0x87200000 */
+#define DUCATI_BASEIMAGE_PHYSICAL_ADDRESS 0x88000000
+
+#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
+
+
+/* Attributes used to manage the DSP MMU page tables */
+struct pg_table_attrs {
+ struct sync_cs_object *hcs_object;/* Critical section object handle */
+ u32 l1_base_pa; /* Physical address of the L1 PT */
+ u32 l1_base_va; /* Virtual address of the L1 PT */
+ u32 l1_size; /* Size of the L1 PT */
+ u32 l1_tbl_alloc_pa;
+ /* Physical address of Allocated mem for L1 table. May not be aligned */
+ u32 l1_tbl_alloc_va;
+ /* Virtual address of Allocated mem for L1 table. May not be aligned */
+ u32 l1_tbl_alloc_sz;
+ /* Size of consistent memory allocated for L1 table.
+ * May not be aligned */
+ u32 l2_base_pa; /* Physical address of the L2 PT */
+ u32 l2_base_va; /* Virtual address of the L2 PT */
+ u32 l2_size; /* Size of the L2 PT */
+ u32 l2_tbl_alloc_pa;
+ /* Physical address of Allocated mem for L2 table. May not be aligned */
+ u32 l2_tbl_alloc_va;
+ /* Virtual address of Allocated mem for L2 table. May not be aligned */
+ u32 ls_tbl_alloc_sz;
+ /* Size of consistent memory allocated for L2 table.
+ * May not be aligned */
+ u32 l2_num_pages; /* Number of allocated L2 PT */
+ struct page_info *pg_info;
+};
+
+/* Attributes of L2 page tables for DSP MMU.*/
+struct page_info {
+ /* Number of valid PTEs in the L2 PT*/
+ u32 num_entries;
+};
+
+enum pagetype {
+ SECTION = 0,
+ LARGE_PAGE = 1,
+ SMALL_PAGE = 2,
+ SUPER_SECTION = 3
+};
+
+static struct pg_table_attrs *p_pt_attrs;
+static u32 mmu_index_next;
+static u32 base_ducati_l2_mmu;
+
+static u32 shm_phys_addr;
+static u32 shm_virt_addr;
+
+static void bad_page_dump(u32 pa, struct page *pg)
+{
+ pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
+ pr_emerg("Bad page state in process '%s'\n", current->comm);
+ BUG();
+}
+
+/*============================================
+ * Print the DSP MMU Table Entries
+ */
+void dbg_print_ptes(bool ashow_inv_entries, bool ashow_repeat_entries)
+{
+ u32 pte_val;
+ u32 pte_size;
+ u32 last_sect = 0;
+ u32 this_sect = 0;
+ u32 cur_l1_entry;
+ u32 cur_l2_entry;
+ u32 pg_tbl_va;
+ u32 l1_base_va;
+ u32 l2_base_va = 0;
+ u32 l2_base_pa = 0;
+
+ l1_base_va = p_pt_attrs->l1_base_va;
+ pg_tbl_va = l1_base_va;
+
+ DPRINTK("\n*** Currently programmed PTEs : Max possible L1 Entries"
+ "[%d] ***\n", (p_pt_attrs->l1_size / sizeof(u32)));
+
+ /* Walk all L1 entries, dump out info. Dive into L2 if necessary */
+ for (cur_l1_entry = 0; cur_l1_entry <
+ (p_pt_attrs->l1_size / sizeof(u32)); cur_l1_entry++) {
+ /*pte_val = pL1PgTbl[cur_l1_entry];*/
+ pte_val = *((u32 *)(pg_tbl_va + (cur_l1_entry * sizeof(u32))));
+ pte_size = hw_mmu_pte_sizel1(pte_val);
+
+ if (pte_size == HW_PAGE_SIZE_16MB) {
+ this_sect = hw_mmu_pte_phyaddr(pte_val, pte_size);
+ if (this_sect != last_sect) {
+ last_sect = this_sect;
+ DPRINTK("PTE L1 [16 MB] -> VA = "
+ "0x%x PA = 0x%x\n",
+ cur_l1_entry << 24, this_sect);
+
+ } else if (ashow_repeat_entries != false)
+ DPRINTK(" {REPEAT}\n");
+ } else if (pte_size == HW_PAGE_SIZE_1MB) {
+ this_sect = hw_mmu_pte_phyaddr(pte_val, pte_size);
+ if (this_sect != last_sect) {
+
+ last_sect = this_sect;
+
+ DPRINTK("PTE L1 [1 MB ] -> VA = "
+ "0x%x PA = 0x%x\n",
+ cur_l1_entry << 20, this_sect);
+
+ } else if (ashow_repeat_entries != false)
+ DPRINTK(" {REPEAT}\n");
+
+ } else if (pte_size == HW_MMU_COARSE_PAGE_SIZE) {
+ /* Get the L2 data for this */
+ DPRINTK("PTE L1 [L2 ] -> VA = "
+ "0x%x\n", cur_l1_entry << 20);
+ /* Get the L2 PA from the L1 PTE, and find corresponding L2 VA*/
+ l2_base_pa = hw_mmu_pte_coarsel1(pte_val);
+ l2_base_va = l2_base_pa - p_pt_attrs->l2_base_pa +
+ p_pt_attrs->l2_base_va;
+ for (cur_l2_entry = 0;
+ cur_l2_entry < (HW_MMU_COARSE_PAGE_SIZE / sizeof(u32));
+ cur_l2_entry++) {
+ pte_val = *((u32 *)(l2_base_va +
+ (cur_l2_entry * sizeof(u32))));
+ pte_size = hw_mmu_pte_sizel2(pte_val);
+ if ((pte_size == HW_PAGE_SIZE_64KB) ||
+ (pte_size == HW_PAGE_SIZE_4KB)) {
+ this_sect = hw_mmu_pte_phyaddr
+ (pte_val, pte_size);
+ if (this_sect != last_sect) {
+ last_sect = this_sect;
+ DPRINTK("PTE L2 [%s KB] ->"
+ "VA = 0x%x PA = 0x%x\n",
+ (pte_size ==
+ HW_PAGE_SIZE_64KB) ?
+ "64" : "4",
+ ((cur_l1_entry << 20)
+ | (cur_l2_entry << 12)),
+ this_sect);
+ } else if (ashow_repeat_entries
+ != false)
+
+ DPRINTK("{REPEAT}");
+ } else if (ashow_inv_entries != false) {
+
+ DPRINTK("PTE L2 [INVALID] -> VA = "
+ "0x%x",
+ ((cur_l1_entry << 20) |
+ (cur_l2_entry << 12)));
+ continue;
+ }
+ }
+ } else if (ashow_inv_entries != false) {
+ /* Entry is invalid (not set), skip it */
+ DPRINTK("PTE L1 [INVALID] -> VA = 0x%x",
+ cur_l1_entry << 20);
+ continue;
+ }
+ }
+ /* Dump the TLB entries as well */
+ DPRINTK("\n*** Currently programmed TLBs ***\n");
+ hw_mmu_tlb_dump(base_ducati_l2_mmu, true);
+ DPRINTK("*** DSP MMU DUMP COMPLETED ***\n");
+}
+
+/*============================================
+ * This function calculates PTE address (MPU virtual) to be updated
+ * It also manages the L2 page tables
+ */
+static int pte_set(u32 pa, u32 va, u32 size, struct hw_mmu_map_attrs_t *attrs)
+{
+ u32 i;
+ u32 pte_val;
+ u32 pte_addr_l1;
+ u32 pte_size;
+ u32 pg_tbl_va; /* Base address of the PT that will be updated */
+ u32 l1_base_va;
+ /* Compiler warns that the next three variables might be used
+ * uninitialized in this function. Doesn't seem so. Working around,
+ * anyways. */
+ u32 l2_base_va = 0;
+ u32 l2_base_pa = 0;
+ u32 l2_page_num = 0;
+ struct pg_table_attrs *pt = p_pt_attrs;
+ int status = 0;
+ DPRINTK("> pte_set ppg_table_attrs %x, pa %x, va %x, "
+ "size %x, attrs %x\n", (u32)pt, pa, va, size, (u32)attrs);
+ l1_base_va = pt->l1_base_va;
+ pg_tbl_va = l1_base_va;
+ if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
+ /* Find whether the L1 PTE points to a valid L2 PT */
+ pte_addr_l1 = hw_mmu_pte_addr_l1(l1_base_va, va);
+ if (pte_addr_l1 <= (pt->l1_base_va + pt->l1_size)) {
+ pte_val = *(u32 *)pte_addr_l1;
+ pte_size = hw_mmu_pte_sizel1(pte_val);
+ } else {
+ return -EINVAL;
+ }
+ /* FIX ME */
+ /* TODO: ADD synchronication element*/
+ /* sync_enter_cs(pt->hcs_object);*/
+ if (pte_size == HW_MMU_COARSE_PAGE_SIZE) {
+ /* Get the L2 PA from the L1 PTE, and find
+ * corresponding L2 VA */
+ l2_base_pa = hw_mmu_pte_coarsel1(pte_val);
+ l2_base_va = l2_base_pa - pt->l2_base_pa +
+ pt->l2_base_va;
+ l2_page_num = (l2_base_pa - pt->l2_base_pa) /
+ HW_MMU_COARSE_PAGE_SIZE;
+ } else if (pte_size == 0) {
+ /* L1 PTE is invalid. Allocate a L2 PT and
+ * point the L1 PTE to it */
+ /* Find a free L2 PT. */
+ for (i = 0; (i < pt->l2_num_pages) &&
+ (pt->pg_info[i].num_entries != 0); i++)
+ ;;
+ if (i < pt->l2_num_pages) {
+ l2_page_num = i;
+ l2_base_pa = pt->l2_base_pa + (l2_page_num *
+ HW_MMU_COARSE_PAGE_SIZE);
+ l2_base_va = pt->l2_base_va + (l2_page_num *
+ HW_MMU_COARSE_PAGE_SIZE);
+ /* Endianness attributes are ignored for
+ * HW_MMU_COARSE_PAGE_SIZE */
+ status =
+ hw_mmu_pte_set(l1_base_va, l2_base_pa, va,
+ HW_MMU_COARSE_PAGE_SIZE, attrs);
+ } else {
+ status = -ENOMEM;
+ }
+ } else {
+ /* Found valid L1 PTE of another size.
+ * Should not overwrite it. */
+ status = -EINVAL;
+ }
+ if (status == 0) {
+ pg_tbl_va = l2_base_va;
+ if (size == HW_PAGE_SIZE_64KB)
+ pt->pg_info[l2_page_num].num_entries += 16;
+ else
+ pt->pg_info[l2_page_num].num_entries++;
+
+ DPRINTK("L2 BaseVa %x, BasePa %x, "
+ "PageNum %x num_entries %x\n", l2_base_va,
+ l2_base_pa, l2_page_num,
+ pt->pg_info[l2_page_num].num_entries);
+ }
+/* sync_leave_cs(pt->hcs_object);*/
+ }
+ if (status == 0) {
+ DPRINTK("PTE pg_tbl_va %x, pa %x, va %x, size %x\n",
+ pg_tbl_va, pa, va, size);
+ DPRINTK("PTE endianism %x, element_size %x, "
+ "mixedSize %x\n", attrs->endianism,
+ attrs->element_size, attrs->mixedSize);
+ status = hw_mmu_pte_set(pg_tbl_va, pa, va, size, attrs);
+ if (status == RET_OK)
+ status = 0;
+ }
+ DPRINTK("< pte_set status %x\n", status);
+ return status;
+}
+
+
+/*=============================================
+ * This function calculates the optimum page-aligned addresses and sizes
+ * Caller must pass page-aligned values
+ */
+static int pte_update(u32 pa, u32 va, u32 size,
+ struct hw_mmu_map_attrs_t *map_attrs)
+{
+ u32 i;
+ u32 all_bits;
+ u32 pa_curr = pa;
+ u32 va_curr = va;
+ u32 num_bytes = size;
+ int status = 0;
+ u32 pg_size[] = {HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
+ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB};
+ DPRINTK("> pte_update pa %x, va %x, "
+ "size %x, map_attrs %x\n", pa, va, size, (u32)map_attrs);
+ while (num_bytes && (status == 0)) {
+ /* To find the max. page size with which both PA & VA are
+ * aligned */
+ all_bits = pa_curr | va_curr;
+ DPRINTK("all_bits %x, pa_curr %x, va_curr %x, "
+ "num_bytes %x\n ",
+ all_bits, pa_curr, va_curr, num_bytes);
+
+ for (i = 0; i < 4; i++) {
+ if ((num_bytes >= pg_size[i]) && ((all_bits &
+ (pg_size[i] - 1)) == 0)) {
+ DPRINTK("pg_size %x\n", pg_size[i]);
+ status = pte_set(pa_curr,
+ va_curr, pg_size[i], map_attrs);
+ pa_curr += pg_size[i];
+ va_curr += pg_size[i];
+ num_bytes -= pg_size[i];
+ /* Don't try smaller sizes. Hopefully we have
+ * reached an address aligned to a bigger page
+ * size */
+ break;
+ }
+ }
+ }
+ DPRINTK("< pte_update status %x num_bytes %x\n", status, num_bytes);
+ return status;
+}
+
+/*
+ * ======== ducati_mem_unmap ========
+ * Invalidate the PTEs for the DSP VA block to be unmapped.
+ *
+ * PTEs of a mapped memory block are contiguous in any page table
+ * So, instead of looking up the PTE address for every 4K block,
+ * we clear consecutive PTEs until we unmap all the bytes
+ */
+int ducati_mem_unmap(u32 da, u32 num_bytes)
+{
+ u32 L1_base_va;
+ u32 L2_base_va;
+ u32 L2_base_pa;
+ u32 L2_page_num;
+ u32 pte_val;
+ u32 pte_size;
+ u32 pte_count;
+ u32 pte_addr_l1;
+ u32 pte_addr_l2 = 0;
+ u32 rem_bytes;
+ u32 rem_bytes_l2;
+ u32 vaCurr;
+ struct page *pg = NULL;
+ int status = 0;
+ u32 temp;
+ u32 patemp = 0;
+ u32 pAddr;
+ u32 numof4Kpages = 0;
+ DPRINTK("> ducati_mem_unmap da 0x%x, "
+ "NumBytes 0x%x\n", da, num_bytes);
+ vaCurr = da;
+ rem_bytes = num_bytes;
+ rem_bytes_l2 = 0;
+ L1_base_va = p_pt_attrs->l1_base_va;
+ pte_addr_l1 = hw_mmu_pte_addr_l1(L1_base_va, vaCurr);
+ while (rem_bytes) {
+ u32 vaCurrOrig = vaCurr;
+ /* Find whether the L1 PTE points to a valid L2 PT */
+ pte_addr_l1 = hw_mmu_pte_addr_l1(L1_base_va, vaCurr);
+ pte_val = *(u32 *)pte_addr_l1;
+ pte_size = hw_mmu_pte_sizel1(pte_val);
+ if (pte_size == HW_MMU_COARSE_PAGE_SIZE) {
+ /*
+ * Get the L2 PA from the L1 PTE, and find
+ * corresponding L2 VA
+ */
+ L2_base_pa = hw_mmu_pte_coarsel1(pte_val);
+ L2_base_va = L2_base_pa - p_pt_attrs->l2_base_pa
+ + p_pt_attrs->l2_base_va;
+ L2_page_num = (L2_base_pa - p_pt_attrs->l2_base_pa) /
+ HW_MMU_COARSE_PAGE_SIZE;
+ /*
+ * Find the L2 PTE address from which we will start
+ * clearing, the number of PTEs to be cleared on this
+ * page, and the size of VA space that needs to be
+ * cleared on this L2 page
+ */
+ pte_addr_l2 = hw_mmu_pte_addr_l2(L2_base_va, vaCurr);
+ pte_count = pte_addr_l2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
+ pte_count = (HW_MMU_COARSE_PAGE_SIZE - pte_count) /
+ sizeof(u32);
+ if (rem_bytes < (pte_count * PAGE_SIZE))
+ pte_count = rem_bytes / PAGE_SIZE;
+
+ rem_bytes_l2 = pte_count * PAGE_SIZE;
+ DPRINTK("ducati_mem_unmap L2_base_pa %x, "
+ "L2_base_va %x pte_addr_l2 %x,"
+ "rem_bytes_l2 %x\n", L2_base_pa, L2_base_va,
+ pte_addr_l2, rem_bytes_l2);
+ /*
+ * Unmap the VA space on this L2 PT. A quicker way
+ * would be to clear pte_count entries starting from
+ * pte_addr_l2. However, below code checks that we don't
+ * clear invalid entries or less than 64KB for a 64KB
+ * entry. Similar checking is done for L1 PTEs too
+ * below
+ */
+ while (rem_bytes_l2) {
+ pte_val = *(u32 *)pte_addr_l2;
+ pte_size = hw_mmu_pte_sizel2(pte_val);
+ /* vaCurr aligned to pte_size? */
+ if ((pte_size != 0) && (rem_bytes_l2
+ >= pte_size) &&
+ !(vaCurr & (pte_size - 1))) {
+ /* Collect Physical addresses from VA */
+ pAddr = (pte_val & ~(pte_size - 1));
+ if (pte_size == HW_PAGE_SIZE_64KB)
+ numof4Kpages = 16;
+ else
+ numof4Kpages = 1;
+ temp = 0;
+ while (temp++ < numof4Kpages) {
+ if (pfn_valid
+ (__phys_to_pfn
+ (patemp))) {
+ pg = phys_to_page
+ (pAddr);
+ if (page_count
+ (pg) < 1) {
+ bad_page_dump
+ (pAddr, pg);
+ }
+ SetPageDirty(pg);
+ page_cache_release(pg);
+ }
+ pAddr += HW_PAGE_SIZE_4KB;
+ }
+ if (hw_mmu_pte_clear(pte_addr_l2,
+ vaCurr, pte_size) == RET_OK) {
+ rem_bytes_l2 -= pte_size;
+ vaCurr += pte_size;
+ pte_addr_l2 += (pte_size >> 12)
+ * sizeof(u32);
+ } else {
+ status = -EFAULT;
+ goto EXIT_LOOP;
+ }
+ } else
+ status = -EFAULT;
+ }
+ if (rem_bytes_l2 != 0) {
+ status = -EFAULT;
+ goto EXIT_LOOP;
+ }
+ p_pt_attrs->pg_info[L2_page_num].num_entries -=
+ pte_count;
+ if (p_pt_attrs->pg_info[L2_page_num].num_entries
+ == 0) {
+ /*
+ * Clear the L1 PTE pointing to the
+ * L2 PT
+ */
+ if (RET_OK != hw_mmu_pte_clear(L1_base_va,
+ vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE)) {
+ status = -EFAULT;
+ goto EXIT_LOOP;
+ }
+ }
+ rem_bytes -= pte_count * PAGE_SIZE;
+ DPRINTK("ducati_mem_unmap L2_page_num %x, "
+ "num_entries %x, pte_count %x, status: 0x%x\n",
+ L2_page_num,
+ p_pt_attrs->pg_info[L2_page_num].num_entries,
+ pte_count, status);
+ } else
+ /* vaCurr aligned to pte_size? */
+ /* pte_size = 1 MB or 16 MB */
+ if ((pte_size != 0) && (rem_bytes >= pte_size) &&
+ !(vaCurr & (pte_size - 1))) {
+ if (pte_size == HW_PAGE_SIZE_1MB)
+ numof4Kpages = 256;
+ else
+ numof4Kpages = 4096;
+ temp = 0;
+ /* Collect Physical addresses from VA */
+ pAddr = (pte_val & ~(pte_size - 1));
+ while (temp++ < numof4Kpages) {
+ pg = phys_to_page(pAddr);
+ if (page_count(pg) < 1)
+ bad_page_dump(pAddr, pg);
+ SetPageDirty(pg);
+ page_cache_release(pg);
+ pAddr += HW_PAGE_SIZE_4KB;
+ }
+ if (hw_mmu_pte_clear(L1_base_va, vaCurr,
+ pte_size) == RET_OK) {
+ rem_bytes -= pte_size;
+ vaCurr += pte_size;
+ } else {
+ status = -EFAULT;
+ goto EXIT_LOOP;
+ }
+ } else {
+ status = -EFAULT;
+ }
+ }
+ /*
+ * It is better to flush the TLB here, so that any stale old entries
+ * get flushed
+ */
+EXIT_LOOP:
+ hw_mmu_tlb_flushAll(base_ducati_l2_mmu);
+ DPRINTK("ducati_mem_unmap vaCurr %x, pte_addr_l1 %x "
+ "pte_addr_l2 %x\n", vaCurr, pte_addr_l1, pte_addr_l2);
+ DPRINTK("< ducati_mem_unmap status %x rem_bytes %x, "
+ "rem_bytes_l2 %x\n", status, rem_bytes, rem_bytes_l2);
+ return status;
+}
+
+
+/*
+ * ======== ducati_mem_virtToPhys ========
+ * This funciton provides the translation from
+ * Remote virtual address to Physical address
+ */
+
+inline u32 ducati_mem_virtToPhys(u32 da)
+{
+#if 0
+ /* FIXME: temp work around till L2MMU issue
+ * is resolved
+ */
+ u32 *iopgd = iopgd_offset(ducati_iommu_ptr, da);
+ u32 phyaddress;
+
+ if (*iopgd & IOPGD_TABLE) {
+ u32 *iopte = iopte_offset(iopgd, da);
+ if (*iopte & IOPTE_LARGE) {
+ phyaddress = *iopte & IOLARGE_MASK;
+ phyaddress |= (da & (IOLARGE_SIZE - 1));
+ } else
+ phyaddress = (*iopte) & IOPAGE_MASK;
+ } else {
+ if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
+ phyaddress = *iopgd & IOSUPER_MASK;
+ phyaddress |= (da & (IOSUPER_SIZE - 1));
+ } else {
+ phyaddress = (*iopgd) & IOPGD_MASK;
+ phyaddress |= (da & (IOPGD_SIZE - 1));
+ }
+ }
+#endif
+ return da;
+}
+
+
+/*
+ * ======== user_va2pa ========
+ * Purpose:
+ * This function walks through the Linux page tables to convert a userland
+ * virtual address to physical address
+ */
+u32 user_va2pa(struct mm_struct *mm, u32 address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ pgd = pgd_offset(mm, address);
+ if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
+ pmd = pmd_offset(pgd, address);
+ if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
+ ptep = pte_offset_map(pmd, address);
+ if (ptep) {
+ pte = *ptep;
+ if (pte_present(pte))
+ return pte & PAGE_MASK;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*============================================
+ * This function maps MPU buffer to the DSP address space. It performs
+* linear to physical address translation if required. It translates each
+* page since linear addresses can be physically non-contiguous
+* All address & size arguments are assumed to be page aligned (in proc.c)
+ *
+ */
+int ducati_mem_map(u32 mpu_addr, u32 ul_virt_addr,
+ u32 num_bytes, u32 map_attr)
+{
+ u32 attrs;
+ int status = 0;
+ struct hw_mmu_map_attrs_t hw_attrs;
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ struct task_struct *curr_task = current;
+ u32 write = 0;
+ u32 da = ul_virt_addr;
+ u32 pa = 0;
+ int pg_i = 0;
+ int pg_num = 0;
+ struct page *mappedPage, *pg;
+ int num_usr_pages = 0;
+
+ DPRINTK("> WMD_BRD_MemMap pa %x, va %x, "
+ "size %x, map_attr %x\n", mpu_addr, ul_virt_addr,
+ num_bytes, map_attr);
+ if (num_bytes == 0)
+ return -EINVAL;
+ if (map_attr != 0) {
+ attrs = map_attr;
+ attrs |= DSP_MAPELEMSIZE32;
+ } else {
+ /* Assign default attributes */
+ attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE32;
+ }
+ /* Take mapping properties */
+ if (attrs & DSP_MAPBIGENDIAN)
+ hw_attrs.endianism = HW_BIG_ENDIAN;
+ else
+ hw_attrs.endianism = HW_LITTLE_ENDIAN;
+
+ hw_attrs.mixedSize = (enum hw_mmu_mixed_size_t)
+ ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
+ /* Ignore element_size if mixedSize is enabled */
+ if (hw_attrs.mixedSize == 0) {
+ if (attrs & DSP_MAPELEMSIZE8) {
+ /* Size is 8 bit */
+ hw_attrs.element_size = HW_ELEM_SIZE_8BIT;
+ } else if (attrs & DSP_MAPELEMSIZE16) {
+ /* Size is 16 bit */
+ hw_attrs.element_size = HW_ELEM_SIZE_16BIT;
+ } else if (attrs & DSP_MAPELEMSIZE32) {
+ /* Size is 32 bit */
+ hw_attrs.element_size = HW_ELEM_SIZE_32BIT;
+ } else if (attrs & DSP_MAPELEMSIZE64) {
+ /* Size is 64 bit */
+ hw_attrs.element_size = HW_ELEM_SIZE_64BIT;
+ } else {
+ /* Mixedsize isn't enabled, so size can't be
+ * zero here */
+ DPRINTK("WMD_BRD_MemMap: MMU element size is zero\n");
+ return -EINVAL;
+ }
+ }
+ /*
+ * Do OS-specific user-va to pa translation.
+ * Combine physically contiguous regions to reduce TLBs.
+ * Pass the translated pa to PteUpdate.
+ */
+ if ((attrs & DSP_MAPPHYSICALADDR)) {
+ status = pte_update(mpu_addr, ul_virt_addr, num_bytes,
+ &hw_attrs);
+ goto func_cont;
+ }
+ /*
+ * Important Note: mpu_addr is mapped from user application process
+ * to current process - it must lie completely within the current
+ * virtual memory address space in order to be of use to us here!
+ */
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, mpu_addr);
+ /*
+ * It is observed that under some circumstances, the user buffer is
+ * spread across several VMAs. So loop through and check if the entire
+ * user buffer is covered
+ */
+ while ((vma) && (mpu_addr + num_bytes > vma->vm_end)) {
+ /* jump to the next VMA region */
+ vma = find_vma(mm, vma->vm_end + 1);
+ }
+ if (!vma) {
+ status = -EINVAL;
+ up_read(&mm->mmap_sem);
+ goto func_cont;
+ }
+ if (vma->vm_flags & VM_IO) {
+ num_usr_pages = num_bytes / PAGE_SIZE;
+ /* Get the physical addresses for user buffer */
+ for (pg_i = 0; pg_i < num_usr_pages; pg_i++) {
+ pa = user_va2pa(mm, mpu_addr);
+ if (!pa) {
+ status = -EFAULT;
+ pr_err("DSPBRIDGE: VM_IO mapping physical"
+ "address is invalid\n");
+ break;
+ }
+ if (pfn_valid(__phys_to_pfn(pa))) {
+ pg = phys_to_page(pa);
+ get_page(pg);
+ if (page_count(pg) < 1) {
+ pr_err("Bad page in VM_IO buffer\n");
+ bad_page_dump(pa, pg);
+ }
+ }
+ status = pte_set(pa, da, HW_PAGE_SIZE_4KB, &hw_attrs);
+ if (WARN_ON(status < 0))
+ break;
+ mpu_addr += HW_PAGE_SIZE_4KB;
+ da += HW_PAGE_SIZE_4KB;
+ }
+ } else {
+ num_usr_pages = num_bytes / PAGE_SIZE;
+ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
+ write = 1;
+
+ for (pg_i = 0; pg_i < num_usr_pages; pg_i++) {
+ pg_num = get_user_pages(curr_task, mm, mpu_addr, 1,
+ write, 1, &mappedPage, NULL);
+ if (pg_num > 0) {
+ if (page_count(mappedPage) < 1) {
+ pr_err("Bad page count after doing"
+ "get_user_pages on"
+ "user buffer\n");
+ bad_page_dump(page_to_phys(mappedPage),
+ mappedPage);
+ }
+ status = pte_set(page_to_phys(mappedPage), da,
+ HW_PAGE_SIZE_4KB, &hw_attrs);
+ if (WARN_ON(status < 0))
+ break;
+ da += HW_PAGE_SIZE_4KB;
+ mpu_addr += HW_PAGE_SIZE_4KB;
+ } else {
+ pr_err("DSPBRIDGE: get_user_pages FAILED,"
+ "MPU addr = 0x%x,"
+ "vma->vm_flags = 0x%lx,"
+ "get_user_pages Err"
+ "Value = %d, Buffer"
+ "size=0x%x\n", mpu_addr,
+ vma->vm_flags, pg_num,
+ num_bytes);
+ status = -EFAULT;
+ break;
+ }
+ }
+ }
+ up_read(&mm->mmap_sem);
+func_cont:
+ /* Don't propogate Linux or HW status to upper layers */
+ if (status < 0) {
+ /*
+ * Roll out the mapped pages incase it failed in middle of
+ * mapping
+ */
+ if (pg_i)
+ ducati_mem_unmap(ul_virt_addr, (pg_i * PAGE_SIZE));
+ }
+ /* In any case, flush the TLB
+ * This is called from here instead from pte_update to avoid unnecessary
+ * repetition while mapping non-contiguous physical regions of a virtual
+ * region */
+ hw_mmu_tlb_flushAll(base_ducati_l2_mmu);
+ WARN_ON(status < 0);
+ DPRINTK("< WMD_BRD_MemMap status %x\n", status);
+ return status;
+}
+
+ /*=========================================
+ * Decides a TLB entry size
+ *
+ */
+static int get_mmu_entry_size(u32 phys_addr, u32 size, enum pagetype *size_tlb,
+ u32 *entry_size)
+{
+ int status = 0;
+ bool page_align_4kb = false;
+ bool page_align_64kb = false;
+ bool page_align_1mb = false;
+ bool page_align_16mb = false;
+
+ /* First check the page alignment*/
+ if ((phys_addr % PAGE_SIZE_4KB) == 0)
+ page_align_4kb = true;
+ if ((phys_addr % PAGE_SIZE_64KB) == 0)
+ page_align_64kb = true;
+ if ((phys_addr % PAGE_SIZE_1MB) == 0)
+ page_align_1mb = true;
+ if ((phys_addr % PAGE_SIZE_16MB) == 0)
+ page_align_16mb = true;
+
+ if ((!page_align_64kb) && (!page_align_1mb) && (!page_align_4kb)) {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ if (status == 0) {
+ /* Now decide the entry size */
+ if (size >= PAGE_SIZE_16MB) {
+ if (page_align_16mb) {
+ *size_tlb = SUPER_SECTION;
+ *entry_size = PAGE_SIZE_16MB;
+ } else if (page_align_1mb) {
+ *size_tlb = SECTION;
+ *entry_size = PAGE_SIZE_1MB;
+ } else if (page_align_64kb) {
+ *size_tlb = LARGE_PAGE;
+ *entry_size = PAGE_SIZE_64KB;
+ } else if (page_align_4kb) {
+ *size_tlb = SMALL_PAGE;
+ *entry_size = PAGE_SIZE_4KB;
+ } else {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ } else if (size >= PAGE_SIZE_1MB && size < PAGE_SIZE_16MB) {
+ if (page_align_1mb) {
+ *size_tlb = SECTION;
+ *entry_size = PAGE_SIZE_1MB;
+ } else if (page_align_64kb) {
+ *size_tlb = LARGE_PAGE;
+ *entry_size = PAGE_SIZE_64KB;
+ } else if (page_align_4kb) {
+ *size_tlb = SMALL_PAGE;
+ *entry_size = PAGE_SIZE_4KB;
+ } else {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ } else if (size > PAGE_SIZE_4KB &&
+ size < PAGE_SIZE_1MB) {
+ if (page_align_64kb) {
+ *size_tlb = LARGE_PAGE;
+ *entry_size = PAGE_SIZE_64KB;
+ } else if (page_align_4kb) {
+ *size_tlb = SMALL_PAGE;
+ *entry_size = PAGE_SIZE_4KB;
+ } else {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ } else if (size == PAGE_SIZE_4KB) {
+ if (page_align_4kb) {
+ *size_tlb = SMALL_PAGE;
+ *entry_size = PAGE_SIZE_4KB;
+ } else {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ } else {
+ status = -EINVAL;
+ goto error_exit;
+ }
+ }
+ DPRINTK("< GetMMUEntrySize status %x\n", status);
+ return 0;
+error_exit:
+ DPRINTK("< GetMMUEntrySize FAILED !!!!!!\n");
+ return status;
+}
+
+/*=========================================
+ * Add DSP MMU entries corresponding to given MPU-Physical address
+ * and DSP-virtual address
+ */
+static int add_dsp_mmu_entry(u32 *phys_addr, u32 *dsp_addr,
+ u32 size)
+{
+ u32 mapped_size = 0;
+ enum pagetype size_tlb = SECTION;
+ u32 entry_size = 0;
+ int status = 0;
+ u32 page_size = HW_PAGE_SIZE_1MB;
+ struct hw_mmu_map_attrs_t map_attrs = { HW_LITTLE_ENDIAN,
+ HW_ELEM_SIZE_16BIT,
+ HW_MMU_CPUES };
+
+ DPRINTK("Entered add_dsp_mmu_entry phys_addr = "
+ "0x%x, dsp_addr = 0x%x,size = 0x%x\n",
+ *phys_addr, *dsp_addr, size);
+
+ while ((mapped_size < size) && (status == 0)) {
+ status = get_mmu_entry_size(*phys_addr,
+ (size - mapped_size), &size_tlb, &entry_size);
+
+ if (size_tlb == SUPER_SECTION)
+ page_size = HW_PAGE_SIZE_16MB;
+
+ else if (size_tlb == SECTION)
+ page_size = HW_PAGE_SIZE_1MB;
+
+ else if (size_tlb == LARGE_PAGE)
+ page_size = HW_PAGE_SIZE_64KB;
+
+ else if (size_tlb == SMALL_PAGE)
+ page_size = HW_PAGE_SIZE_4KB;
+ if (status == 0) {
+ hw_mmu_tlb_add((base_ducati_l2_mmu),
+ *phys_addr, *dsp_addr,
+ page_size, mmu_index_next++,
+ &map_attrs, HW_SET, HW_SET);
+ mapped_size += entry_size;
+ *phys_addr += entry_size;
+ *dsp_addr += entry_size;
+ if (mmu_index_next > 32) {
+ status = -EINVAL;
+ break;
+ }
+ /* Lock the base counter*/
+ hw_mmu_numlocked_set(base_ducati_l2_mmu,
+ mmu_index_next);
+
+ hw_mmu_victim_numset(base_ducati_l2_mmu,
+ mmu_index_next);
+ }
+ }
+ DPRINTK("Exited add_dsp_mmu_entryphys_addr = \
+ 0x%x, dsp_addr = 0x%x\n",
+ *phys_addr, *dsp_addr);
+ return status;
+ }
+
+
+/*=============================================
+ * Add DSP MMU entries corresponding to given MPU-Physical address
+ * and DSP-virtual address
+ *
+ */
+#if 0
+static int add_entry_ext(u32 *phys_addr, u32 *dsp_addr,
+ u32 size)
+{
+ u32 mapped_size = 0;
+ enum pagetype size_tlb = SECTION;
+ u32 entry_size = 0;
+ int status = 0;
+ u32 page_size = HW_PAGE_SIZE_1MB;
+ u32 flags = 0;
+
+ flags = (DSP_MAPELEMSIZE32 | DSP_MAPLITTLEENDIAN |
+ DSP_MAPPHYSICALADDR);
+ while ((mapped_size < size) && (status == 0)) {
+
+ /* get_mmu_entry_size fills the size_tlb and entry_size
+ based on alignment and size of memory to map
+ to DSP - size */
+ status = get_mmu_entry_size(*phys_addr,
+ (size - mapped_size),
+ &size_tlb,
+ &entry_size);
+
+ if (size_tlb == SUPER_SECTION)
+ page_size = HW_PAGE_SIZE_16MB;
+ else if (size_tlb == SECTION)
+ page_size = HW_PAGE_SIZE_1MB;
+ else if (size_tlb == LARGE_PAGE)
+ page_size = HW_PAGE_SIZE_64KB;
+ else if (size_tlb == SMALL_PAGE)
+ page_size = HW_PAGE_SIZE_4KB;
+
+ if (status == 0) {
+
+ ducati_mem_map(*phys_addr,
+ *dsp_addr, page_size, flags);
+ mapped_size += entry_size;
+ *phys_addr += entry_size;
+ *dsp_addr += entry_size;
+ }
+ }
+ return status;
+}
+#endif
+/*================================
+ * Initialize the Ducati MMU.
+ */
+int ducati_mmu_init(u32 a_phy_addr)
+{
+ int ret_val = 0;
+ u32 ducati_mmu_linear_addr = base_ducati_l2_mmu;
+ u32 reg_value = 0;
+ u32 phys_addr = 0;
+ u32 num_l4_entries;
+ u32 i = 0;
+ u32 map_attrs;
+ u32 num_l3_mem_entries = 0;
+ u32 virt_addr = 0;
+#if 0
+ u32 tiler_mapbeg = 0;
+ u32 tiler_totalsize = 0;
+#endif
+
+ num_l4_entries = (sizeof(l4_map) / sizeof(struct mmu_entry));
+ num_l3_mem_entries = sizeof(l3_memory_regions) /
+ sizeof(struct memory_entry);
+
+ DPRINTK("\n Programming Ducati MMU using linear address [0x%x]",
+ ducati_mmu_linear_addr);
+
+ /* Disable the MMU & TWL */
+ hw_mmu_disable(base_ducati_l2_mmu);
+ hw_mmu_twl_disable(base_ducati_l2_mmu);
+
+ mmu_index_next = 0;
+ phys_addr = a_phy_addr;
+
+ printk(KERN_ALERT " Programming Ducati memory regions\n");
+ printk(KERN_ALERT "=========================================\n");
+ for (i = 0; i < num_l3_mem_entries; i++) {
+
+ printk(KERN_ALERT "VA = [0x%x] of size [0x%x] at PA = [0x%x]\n",
+ l3_memory_regions[i].ul_virt_addr,
+ l3_memory_regions[i].ul_size, phys_addr);
+
+#if 0
+ /* OMAP4430 original code */
+ if (l3_memory_regions[i].ul_virt_addr == DUCATI_SHARED_IPC_ADDR)
+ shm_phys_addr = phys_addr;
+ */
+#endif
+ /* OMAP4430 SDC code */
+ /* Adjust below logic if using cacheable shared memory */
+ if (l3_memory_regions[i].ul_virt_addr == \
+ DUCATI_MEM_IPC_HEAP0_ADDR) {
+ shm_phys_addr = phys_addr;
+ }
+ virt_addr = l3_memory_regions[i].ul_virt_addr;
+ ret_val = add_dsp_mmu_entry(&phys_addr, &virt_addr,
+ (l3_memory_regions[i].ul_size));
+
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+ }
+
+#if 0
+ /* OMAP4430 original code */
+ tiler_mapbeg = L3_TILER_VIEW0_ADDR;
+ tiler_totalsize = DUCATIVA_TILER_VIEW0_LEN;
+ phys_addr = L3_TILER_VIEW0_ADDR;
+
+ printk(KERN_ALERT " Programming TILER memory region at "
+ "[VA = 0x%x] of size [0x%x] at [PA = 0x%x]\n",
+ tiler_mapbeg, tiler_totalsize, phys_addr);
+ ret_val = add_entry_ext(&phys_addr, &tiler_mapbeg, tiler_totalsize);
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+#endif
+
+ map_attrs = 0x00000000;
+ map_attrs |= DSP_MAPLITTLEENDIAN;
+ map_attrs |= DSP_MAPPHYSICALADDR;
+ map_attrs |= DSP_MAPELEMSIZE32;
+ printk(KERN_ALERT " Programming Ducati L4 peripherals\n");
+ printk(KERN_ALERT "=========================================\n");
+ for (i = 0; i < num_l4_entries; i++) {
+ printk(KERN_INFO "PA [0x%x] VA [0x%x] size [0x%x]\n",
+ l4_map[i].ul_phy_addr, l4_map[i].ul_virt_addr,
+ l4_map[i].ul_size);
+ virt_addr = l4_map[i].ul_virt_addr;
+ phys_addr = l4_map[i].ul_phy_addr;
+ ret_val = add_dsp_mmu_entry(&phys_addr,
+ &virt_addr, (l4_map[i].ul_size));
+ if (WARN_ON(ret_val < 0)) {
+
+ DPRINTK("**** Failed to map Peripheral ****");
+ DPRINTK("Phys addr [0x%x] Virt addr [0x%x] size [0x%x]",
+ l4_map[i].ul_phy_addr, l4_map[i].ul_virt_addr,
+ l4_map[i].ul_size);
+ DPRINTK(" Status [0x%x]", ret_val);
+ goto error_exit;
+ }
+ }
+
+ /* Set the TTB to point to the L1 page table's physical address */
+ hw_mmu_ttbset(ducati_mmu_linear_addr, p_pt_attrs->l1_base_pa);
+
+ /* Enable the TWL */
+ hw_mmu_twl_enable(ducati_mmu_linear_addr);
+
+ hw_mmu_enable(ducati_mmu_linear_addr);
+
+ /* MMU Debug Statements */
+ reg_value = *((REG u32 *)(ducati_mmu_linear_addr + 0x40));
+ DPRINTK(" Ducati TWL Status [0x%x]\n", reg_value);
+
+ reg_value = *((REG u32 *)(ducati_mmu_linear_addr + 0x4C));
+ DPRINTK(" Ducati TTB Address [0x%x]\n", reg_value);
+
+ reg_value = *((REG u32 *)(ducati_mmu_linear_addr + 0x44));
+ DPRINTK(" Ducati MMU Status [0x%x]\n", reg_value);
+
+ /* Dump the MMU Entries */
+ dbg_print_ptes(false, false);
+
+ return 0;
+error_exit:
+ return ret_val;
+}
+
+
+/*========================================
+ * This sets up the Ducati processor MMU Page tables
+ *
+ */
+int init_mmu_page_attribs(u32 l1_size, u32 l1_allign, u32 ls_num_of_pages)
+{
+ u32 pg_tbl_pa;
+ u32 pg_tbl_va;
+ u32 align_size;
+ int status = 0;
+
+ base_ducati_l2_mmu = (u32)ioremap(base_ducati_l2_mmuPhys, 0x4000);
+ p_pt_attrs = kmalloc(sizeof(struct pg_table_attrs), GFP_ATOMIC);
+ if (p_pt_attrs)
+ memset(p_pt_attrs, 0, sizeof(struct pg_table_attrs));
+ else {
+ status = -ENOMEM;
+ goto error_exit;
+ }
+ p_pt_attrs->l1_size = l1_size;
+ align_size = p_pt_attrs->l1_size;
+ /* Align sizes are expected to be power of 2 */
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32)__get_dma_pages(GFP_KERNEL,
+ get_order(p_pt_attrs->l1_size));
+ if (pg_tbl_va == (u32)NULL) {
+ DPRINTK("dma_alloc_coherent failed 0x%x\n", pg_tbl_va);
+ status = -ENOMEM;
+ goto error_exit;
+ }
+ pg_tbl_pa = __pa(pg_tbl_va);
+ /* Check if the PA is aligned for us */
+ if ((pg_tbl_pa) & (align_size-1)) {
+ /* PA not aligned to page table size ,*/
+ /* try with more allocation and align */
+ free_pages(pg_tbl_va, get_order(p_pt_attrs->l1_size));
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32)__get_dma_pages(GFP_KERNEL,
+ get_order(p_pt_attrs->l1_size * 2));
+ if (pg_tbl_va == (u32)NULL) {
+ DPRINTK("__get_dma_pages failed 0x%x\n", pg_tbl_va);
+ status = -ENOMEM;
+ goto error_exit;
+ }
+ pg_tbl_pa = __pa(pg_tbl_va);
+ /* We should be able to get aligned table now */
+ p_pt_attrs->l1_tbl_alloc_pa = pg_tbl_pa;
+ p_pt_attrs->l1_tbl_alloc_va = pg_tbl_va;
+ p_pt_attrs->l1_tbl_alloc_sz = p_pt_attrs->l1_size * 2;
+ /* Align the PA to the next 'align' boundary */
+ p_pt_attrs->l1_base_pa = ((pg_tbl_pa) + (align_size-1)) &
+ (~(align_size-1));
+ p_pt_attrs->l1_base_va = pg_tbl_va + (p_pt_attrs->l1_base_pa -
+ pg_tbl_pa);
+ } else {
+ /* We got aligned PA, cool */
+ p_pt_attrs->l1_tbl_alloc_pa = pg_tbl_pa;
+ p_pt_attrs->l1_tbl_alloc_va = pg_tbl_va;
+ p_pt_attrs->l1_tbl_alloc_sz = p_pt_attrs->l1_size;
+ p_pt_attrs->l1_base_pa = pg_tbl_pa;
+ p_pt_attrs->l1_base_va = pg_tbl_va;
+ }
+ if (p_pt_attrs->l1_base_va)
+ memset((u8 *)p_pt_attrs->l1_base_va, 0x00, p_pt_attrs->l1_size);
+ p_pt_attrs->l2_num_pages = ls_num_of_pages;
+ p_pt_attrs->l2_size = HW_MMU_COARSE_PAGE_SIZE *
+ p_pt_attrs->l2_num_pages;
+ align_size = 4; /* Make it u32 aligned */
+ /* we like to get aligned on L1 table size */
+ pg_tbl_va = (u32)__get_dma_pages(GFP_KERNEL,
+ get_order(p_pt_attrs->l2_size));
+ if (pg_tbl_va == (u32)NULL) {
+ DPRINTK("dma_alloc_coherent failed 0x%x\n", pg_tbl_va);
+ status = -ENOMEM;
+ goto error_exit;
+ }
+ pg_tbl_pa = __pa(pg_tbl_va);
+ p_pt_attrs->l2_tbl_alloc_pa = pg_tbl_pa;
+ p_pt_attrs->l2_tbl_alloc_va = pg_tbl_va;
+ p_pt_attrs->ls_tbl_alloc_sz = p_pt_attrs->l2_size;
+ p_pt_attrs->l2_base_pa = pg_tbl_pa;
+ p_pt_attrs->l2_base_va = pg_tbl_va;
+ if (p_pt_attrs->l2_base_va)
+ memset((u8 *)p_pt_attrs->l2_base_va, 0x00, p_pt_attrs->l2_size);
+
+ p_pt_attrs->pg_info = kmalloc(sizeof(struct page_info), GFP_ATOMIC);
+ if (p_pt_attrs->pg_info)
+ memset(p_pt_attrs->pg_info, 0, sizeof(struct page_info));
+ else {
+ DPRINTK("memory allocation fails for p_pt_attrs->pg_info ");
+ status = -ENOMEM;
+ goto error_exit;
+ }
+ DPRINTK("L1 pa %x, va %x, size %x\n L2 pa %x, va "
+ "%x, size %x\n", p_pt_attrs->l1_base_pa,
+ p_pt_attrs->l1_base_va, p_pt_attrs->l1_size,
+ p_pt_attrs->l2_base_pa, p_pt_attrs->l2_base_va,
+ p_pt_attrs->l2_size);
+ DPRINTK("p_pt_attrs %x L2 NumPages %x pg_info %x\n",
+ (u32)p_pt_attrs, p_pt_attrs->l2_num_pages,
+ (u32)p_pt_attrs->pg_info);
+ return 0;
+error_exit:
+ kfree(p_pt_attrs->pg_info);
+ if (p_pt_attrs->l1_base_va) {
+ free_pages(p_pt_attrs->l1_base_va,
+ get_order(p_pt_attrs->l1_tbl_alloc_sz));
+ }
+ if (p_pt_attrs->l2_base_va) {
+ free_pages(p_pt_attrs->l2_base_va,
+ get_order(p_pt_attrs->ls_tbl_alloc_sz));
+ }
+ WARN_ON(1);
+ printk(KERN_ALERT "init_mmu_page_attribs FAILED !!!!!\n");
+ return status;
+}
+
+/*========================================
+ * This sets up the Ducati processor
+ *
+ */
+int ducati_setup(void)
+{
+ int ret_val = 0;
+ ret_val = init_mmu_page_attribs(0x8000, 14, 128);
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+ ret_val = ducati_mmu_init(DUCATI_BASEIMAGE_PHYSICAL_ADDRESS);
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+ return 0;
+error_exit:
+ WARN_ON(1);
+ printk(KERN_ERR "DUCATI SETUP FAILED !!!!!\n");
+ return ret_val;
+}
+EXPORT_SYMBOL(ducati_setup);
+
+/*============================================
+ * De-Initialize the Ducati MMU and free the
+ * memory allocation for L1 and L2 pages
+ *
+ */
+void ducati_destroy(void)
+{
+ DPRINTK(" Freeing memory allocated in mmu_de_init\n");
+ if (p_pt_attrs->l2_tbl_alloc_va) {
+ free_pages(p_pt_attrs->l2_tbl_alloc_va,
+ get_order(p_pt_attrs->ls_tbl_alloc_sz));
+ }
+ if (p_pt_attrs->l1_tbl_alloc_va) {
+ free_pages(p_pt_attrs->l1_tbl_alloc_va,
+ get_order(p_pt_attrs->l1_tbl_alloc_sz));
+ }
+ if (p_pt_attrs)
+ kfree((void *)p_pt_attrs);
+ iounmap((unsigned int *)base_ducati_l2_mmu);
+ return;
+}
+EXPORT_SYMBOL(ducati_destroy);
+
+/*============================================
+ * Returns the ducati virtual address for IPC shared memory
+ *
+ */
+u32 get_ducati_virt_mem()
+{
+ /*shm_virt_addr = (u32)ioremap(shm_phys_addr, DUCATI_SHARED_IPC_LEN);*/
+ shm_virt_addr = (u32)ioremap(shm_phys_addr, DUCATI_MEM_IPC_SHMEM_LEN);
+ return shm_virt_addr;
+}
+EXPORT_SYMBOL(get_ducati_virt_mem);
+
+/*============================================
+ * Unmaps the ducati virtual address for IPC shared memory
+ *
+ */
+void unmap_ducati_virt_mem(u32 shm_virt_addr)
+{
+ iounmap((unsigned int *) shm_virt_addr);
+ return;
+}
+EXPORT_SYMBOL(unmap_ducati_virt_mem);
diff --git a/drivers/dsp/syslink/procmgr/proc4430/hw_mmu.c b/drivers/dsp/syslink/procmgr/proc4430/hw_mmu.c
new file mode 100755
index 000000000000..f2e4ccbe860f
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/hw_mmu.c
@@ -0,0 +1,643 @@
+/*
+ * hw_mbox.c
+ *
+ * Syslink driver support for OMAP Processors.
+ *
+ * Copyright (C) 2008-2009 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.
+ */
+
+#include<linux/kernel.h>
+#include<linux/module.h>
+
+#include <syslink/GlobalTypes.h>
+#include <syslink/MMURegAcM.h>
+#include <syslink/hw_defs.h>
+#include <syslink/hw_mmu.h>
+
+#define MMU_BASE_VAL_MASK 0xFC00
+#define MMU_PAGE_MAX 3
+#define MMU_ELEMENTSIZE_MAX 3
+#define MMU_ADDR_MASK 0xFFFFF000
+#define MMU_TTB_MASK 0xFFFFC000
+#define MMU_SECTION_ADDR_MASK 0xFFF00000
+#define MMU_SSECTION_ADDR_MASK 0xFF000000
+#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
+#define MMU_LARGE_PAGE_MASK 0xFFFF0000
+#define MMU_SMALL_PAGE_MASK 0xFFFFF000
+
+#define MMU_LOAD_TLB 0x00000001
+#define NUM_TLB_ENTRIES 32
+
+
+
+/*
+* type: hw_mmu_pgsiz_t
+*
+* desc: Enumerated Type used to specify the MMU Page Size(SLSS)
+*
+*
+*/
+enum hw_mmu_pgsiz_t {
+ HW_MMU_SECTION,
+ HW_MMU_LARGE_PAGE,
+ HW_MMU_SMALL_PAGE,
+ HW_MMU_SUPERSECTION
+
+};
+
+/*
+* function : mmu_flsh_entry
+*/
+
+static hw_status mmu_flsh_entry(const u32 base_address);
+
+ /*
+* function : mme_set_cam_entry
+*
+*/
+
+static hw_status mme_set_cam_entry(const u32 base_address,
+ const u32 page_size,
+ const u32 preserve_bit,
+ const u32 valid_bit,
+ const u32 virt_addr_tag);
+
+/*
+* function : mmu_set_ram_entry
+*/
+static hw_status mmu_set_ram_entry(const u32 base_address,
+ const u32 physical_addr,
+ enum hw_endianism_t endianism,
+ enum hw_elemnt_siz_t element_size,
+ enum hw_mmu_mixed_size_t mixedSize);
+
+/*
+* hw functions
+*
+*/
+
+hw_status hw_mmu_enable(const u32 base_address)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_CNTLMMUEnableWrite32(base_address, HW_SET);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_enable);
+
+hw_status hw_mmu_disable(const u32 base_address)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_CNTLMMUEnableWrite32(base_address, HW_CLEAR);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_disable);
+
+hw_status hw_mmu_autoidle_en(const u32 base_address)
+{
+ hw_status status;
+
+ status = mmu_sisconf_auto_idle_set32(base_address, HW_SET);
+ status = RET_OK;
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_autoidle_en);
+
+hw_status hw_mmu_nulck_set(const u32 base_address, u32 *num_lcked_entries)
+{
+ hw_status status = RET_OK;
+
+ *num_lcked_entries = MMUMMU_LOCKBaseValueRead32(base_address);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_nulck_set);
+
+
+hw_status hw_mmu_numlocked_set(const u32 base_address, u32 num_lcked_entries)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_LOCKBaseValueWrite32(base_address, num_lcked_entries);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_numlocked_set);
+
+
+hw_status hw_mmu_vctm_numget(const u32 base_address, u32 *vctm_entry_num)
+{
+ hw_status status = RET_OK;
+
+ *vctm_entry_num = MMUMMU_LOCKCurrentVictimRead32(base_address);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_vctm_numget);
+
+
+hw_status hw_mmu_victim_numset(const u32 base_address, u32 vctm_entry_num)
+{
+ hw_status status = RET_OK;
+
+ mmu_lck_crnt_vctmwite32(base_address, vctm_entry_num);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_victim_numset);
+
+hw_status hw_mmu_tlb_flushAll(const u32 base_address)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_GFLUSHGlobalFlushWrite32(base_address, HW_SET);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_tlb_flushAll);
+
+hw_status hw_mmu_eventack(const u32 base_address, u32 irq_mask)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_IRQSTATUSWriteRegister32(base_address, irq_mask);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_eventack);
+
+hw_status hw_mmu_event_disable(const u32 base_address, u32 irq_mask)
+{
+ hw_status status = RET_OK;
+ u32 irqReg;
+ irqReg = MMUMMU_IRQENABLEReadRegister32(base_address);
+
+ MMUMMU_IRQENABLEWriteRegister32(base_address, irqReg & ~irq_mask);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_event_disable);
+
+hw_status hw_mmu_event_enable(const u32 base_address, u32 irq_mask)
+{
+ hw_status status = RET_OK;
+ u32 irqReg;
+
+ irqReg = MMUMMU_IRQENABLEReadRegister32(base_address);
+
+ MMUMMU_IRQENABLEWriteRegister32(base_address, irqReg | irq_mask);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_event_enable);
+
+hw_status hw_mmu_event_status(const u32 base_address, u32 *irq_mask)
+{
+ hw_status status = RET_OK;
+
+ *irq_mask = MMUMMU_IRQSTATUSReadRegister32(base_address);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_event_status);
+
+hw_status hw_mmu_flt_adr_rd(const u32 base_address, u32 *addr)
+{
+ hw_status status = RET_OK;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ /* read values from register */
+ *addr = MMUMMU_FAULT_ADReadRegister32(base_address);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_flt_adr_rd);
+
+
+hw_status hw_mmu_ttbset(const u32 base_address, u32 ttb_phys_addr)
+{
+ hw_status status = RET_OK;
+ u32 loadTTB;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ loadTTB = ttb_phys_addr & ~0x7FUL;
+ /* write values to register */
+ MMUMMU_TTBWriteRegister32(base_address, loadTTB);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_ttbset);
+
+hw_status hw_mmu_twl_enable(const u32 base_address)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_CNTLTWLEnableWrite32(base_address, HW_SET);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_twl_enable);
+
+hw_status hw_mmu_twl_disable(const u32 base_address)
+{
+ hw_status status = RET_OK;
+
+ MMUMMU_CNTLTWLEnableWrite32(base_address, HW_CLEAR);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_twl_disable);
+
+
+hw_status hw_mmu_tlb_flush(const u32 base_address,
+ u32 virtual_addr,
+ u32 page_size)
+{
+ hw_status status = RET_OK;
+ u32 virt_addr_tag;
+ enum hw_mmu_pgsiz_t pg_sizeBits;
+
+ switch (page_size) {
+ case HW_PAGE_SIZE_4KB:
+ pg_sizeBits = HW_MMU_SMALL_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ pg_sizeBits = HW_MMU_LARGE_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ pg_sizeBits = HW_MMU_SECTION;
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ pg_sizeBits = HW_MMU_SUPERSECTION;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ /* Generate the 20-bit tag from virtual address */
+ virt_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
+
+ mme_set_cam_entry(base_address, pg_sizeBits, 0, 0, virt_addr_tag);
+
+ mmu_flsh_entry(base_address);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_tlb_flush);
+
+
+hw_status hw_mmu_tlb_add(const u32 base_address,
+ u32 physical_addr,
+ u32 virtual_addr,
+ u32 page_size,
+ u32 entryNum,
+ struct hw_mmu_map_attrs_t *map_attrs,
+ enum hw_set_clear_t preserve_bit,
+ enum hw_set_clear_t valid_bit)
+{
+ hw_status status = RET_OK;
+ u32 lockReg;
+ u32 virt_addr_tag;
+ enum hw_mmu_pgsiz_t mmu_pg_size;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(page_size, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(map_attrs->element_size,
+ MMU_ELEMENTSIZE_MAX, RET_PARAM_OUT_OF_RANGE,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ switch (page_size) {
+ case HW_PAGE_SIZE_4KB:
+ mmu_pg_size = HW_MMU_SMALL_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ mmu_pg_size = HW_MMU_LARGE_PAGE;
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ mmu_pg_size = HW_MMU_SECTION;
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ mmu_pg_size = HW_MMU_SUPERSECTION;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ lockReg = mmu_lckread_reg_32(base_address);
+
+ /* Generate the 20-bit tag from virtual address */
+ virt_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
+
+ /* Write the fields in the CAM Entry Register */
+ mme_set_cam_entry(base_address, mmu_pg_size, preserve_bit, valid_bit,
+ virt_addr_tag);
+
+ /* Write the different fields of the RAM Entry Register */
+ /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit) */
+ mmu_set_ram_entry(base_address, physical_addr,
+ map_attrs->endianism, map_attrs->element_size, map_attrs->mixedSize);
+
+ /* Update the MMU Lock Register */
+ /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1) */
+ mmu_lck_crnt_vctmwite32(base_address, entryNum);
+
+ /* Enable loading of an entry in TLB by writing 1 into LD_TLB_REG
+ register */
+ mmu_ld_tlbwrt_reg32(base_address, MMU_LOAD_TLB);
+
+
+ mmu_lck_write_reg32(base_address, lockReg);
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_tlb_add);
+
+
+
+hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
+ u32 physical_addr,
+ u32 virtual_addr,
+ u32 page_size,
+ struct hw_mmu_map_attrs_t *map_attrs)
+{
+ hw_status status = RET_OK;
+ u32 pte_addr, pte_val;
+ long int num_entries = 1;
+
+ switch (page_size) {
+
+ case HW_PAGE_SIZE_4KB:
+ pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, virtual_addr &
+ MMU_SMALL_PAGE_MASK);
+ pte_val = ((physical_addr & MMU_SMALL_PAGE_MASK) |
+ (map_attrs->endianism << 9) |
+ (map_attrs->element_size << 4) |
+ (map_attrs->mixedSize << 11) | 2
+ );
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ num_entries = 16;
+ pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, virtual_addr &
+ MMU_LARGE_PAGE_MASK);
+ pte_val = ((physical_addr & MMU_LARGE_PAGE_MASK) |
+ (map_attrs->endianism << 9) |
+ (map_attrs->element_size << 4) |
+ (map_attrs->mixedSize << 11) | 1
+ );
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, virtual_addr &
+ MMU_SECTION_ADDR_MASK);
+ pte_val = ((((physical_addr & MMU_SECTION_ADDR_MASK) |
+ (map_attrs->endianism << 15) |
+ (map_attrs->element_size << 10) |
+ (map_attrs->mixedSize << 17)) &
+ ~0x40000) | 0x2
+ );
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ num_entries = 16;
+ pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, virtual_addr &
+ MMU_SSECTION_ADDR_MASK);
+ pte_val = (((physical_addr & MMU_SSECTION_ADDR_MASK) |
+ (map_attrs->endianism << 15) |
+ (map_attrs->element_size << 10) |
+ (map_attrs->mixedSize << 17)
+ ) | 0x40000 | 0x2
+ );
+ break;
+
+ case HW_MMU_COARSE_PAGE_SIZE:
+ pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, virtual_addr &
+ MMU_SECTION_ADDR_MASK);
+ pte_val = (physical_addr & MMU_PAGE_TABLE_MASK) | 1;
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ while (--num_entries >= 0)
+ ((u32 *)pte_addr)[num_entries] = pte_val;
+
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_pte_set);
+
+hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
+ u32 virtual_addr,
+ u32 pg_size)
+{
+ hw_status status = RET_OK;
+ u32 pte_addr;
+ long int num_entries = 1;
+
+ switch (pg_size) {
+ case HW_PAGE_SIZE_4KB:
+ pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
+ virtual_addr & MMU_SMALL_PAGE_MASK);
+ break;
+
+ case HW_PAGE_SIZE_64KB:
+ num_entries = 16;
+ pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
+ virtual_addr & MMU_LARGE_PAGE_MASK);
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ case HW_MMU_COARSE_PAGE_SIZE:
+ pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
+ virtual_addr & MMU_SECTION_ADDR_MASK);
+ break;
+
+ case HW_PAGE_SIZE_16MB:
+ num_entries = 16;
+ pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
+ virtual_addr & MMU_SSECTION_ADDR_MASK);
+ break;
+
+ default:
+ return RET_FAIL;
+ }
+
+ while (--num_entries >= 0)
+ ((u32 *)pte_addr)[num_entries] = 0;
+
+ return status;
+}
+EXPORT_SYMBOL(hw_mmu_pte_clear);
+
+/*
+* function: mmu_flsh_entry
+*/
+static hw_status mmu_flsh_entry(const u32 base_address)
+{
+ hw_status status = RET_OK;
+ u32 flushEntryData = 0x1;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ /* write values to register */
+ MMUMMU_FLUSH_ENTRYWriteRegister32(base_address, flushEntryData);
+
+ return status;
+}
+EXPORT_SYMBOL(mmu_flsh_entry);
+/*
+* function : mme_set_cam_entry
+*/
+static hw_status mme_set_cam_entry(const u32 base_address,
+ const u32 page_size,
+ const u32 preserve_bit,
+ const u32 valid_bit,
+ const u32 virt_addr_tag)
+{
+ hw_status status = RET_OK;
+ u32 mmuCamReg;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+ mmuCamReg = (virt_addr_tag << 12);
+ mmuCamReg = (mmuCamReg) | (page_size) | (valid_bit << 2)
+ | (preserve_bit << 3);
+
+ /* write values to register */
+ MMUMMU_CAMWriteRegister32(base_address, mmuCamReg);
+
+ return status;
+}
+EXPORT_SYMBOL(mme_set_cam_entry);
+/*
+* function: mmu_set_ram_entry
+*/
+static hw_status mmu_set_ram_entry(const u32 base_address,
+ const u32 physical_addr,
+ enum hw_endianism_t endianism,
+ enum hw_elemnt_siz_t element_size,
+ enum hw_mmu_mixed_size_t mixedSize)
+{
+ hw_status status = RET_OK;
+ u32 mmuRamReg;
+
+ /*Check the input Parameters*/
+ CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+ CHECK_INPUT_RANGE_MIN0(element_size, MMU_ELEMENTSIZE_MAX,
+ RET_PARAM_OUT_OF_RANGE,
+ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
+
+
+ mmuRamReg = (physical_addr & MMU_ADDR_MASK);
+ mmuRamReg = (mmuRamReg) | ((endianism << 9) | (element_size << 7)
+ | (mixedSize << 6));
+
+ /* write values to register */
+ MMUMMU_RAMWriteRegister32(base_address, mmuRamReg);
+
+ return status;
+
+}
+EXPORT_SYMBOL(mmu_set_ram_entry);
+
+long hw_mmu_tlb_dump(const u32 base_address, bool shw_inv_entries)
+{
+ u32 i;
+ u32 lockSave;
+ u32 cam;
+ u32 ram;
+
+
+ /* Save off the lock register contents,
+ we'll restore it when we are done */
+
+ lockSave = mmu_lckread_reg_32(base_address);
+
+ printk(KERN_INFO "TLB locked entries = %u, current victim = %u\n",
+ ((lockSave & MMU_MMU_LOCK_BaseValue_MASK)
+ >> MMU_MMU_LOCK_BaseValue_OFFSET),
+ ((lockSave & MMU_MMU_LOCK_CurrentVictim_MASK)
+ >> MMU_MMU_LOCK_CurrentVictim_OFFSET));
+ printk(KERN_INFO "=============================================\n");
+ for (i = 0; i < NUM_TLB_ENTRIES; i++) {
+ mmu_lck_crnt_vctmwite32(base_address, i);
+ cam = MMUMMU_CAMReadRegister32(base_address);
+ ram = MMUMMU_RAMReadRegister32(base_address);
+
+ if ((cam & 0x4) != 0) {
+ printk(KERN_INFO "TLB Entry [0x%x]: VA = 0x%x"
+ "PA = 0x%x Protected = 0x%x\n)",
+ i, (cam & MMU_ADDR_MASK), (ram & MMU_ADDR_MASK),
+ (cam & 0x8) ? 1 : 0);
+
+ } else if (shw_inv_entries != false)
+ printk(KERN_ALERT "TLB Entry [0x%x]: <INVALID>\n", i);
+ }
+ mmu_lck_write_reg32(base_address, lockSave);
+ return RET_OK;
+}
+EXPORT_SYMBOL(hw_mmu_tlb_dump);
+
+u32 hw_mmu_pte_phyaddr(u32 pte_val, u32 pte_size)
+{
+ u32 ret_val = 0;
+
+ switch (pte_size) {
+
+ case HW_PAGE_SIZE_4KB:
+ ret_val = pte_val & MMU_SMALL_PAGE_MASK;
+ break;
+ case HW_PAGE_SIZE_64KB:
+ ret_val = pte_val & MMU_LARGE_PAGE_MASK;
+ break;
+
+ case HW_PAGE_SIZE_1MB:
+ ret_val = pte_val & MMU_SECTION_ADDR_MASK;
+ break;
+ case HW_PAGE_SIZE_16MB:
+ ret_val = pte_val & MMU_SSECTION_ADDR_MASK;
+ break;
+ default:
+ /* Invalid */
+ break;
+
+ }
+
+ return ret_val;
+}
+EXPORT_SYMBOL(hw_mmu_pte_phyaddr);
diff --git a/drivers/dsp/syslink/procmgr/proc4430/proc4430.c b/drivers/dsp/syslink/procmgr/proc4430/proc4430.c
new file mode 100644
index 000000000000..50b241cea866
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/proc4430.c
@@ -0,0 +1,1021 @@
+/*
+ * proc4430.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+/* Module level headers */
+#include "../procdefs.h"
+#include "../processor.h"
+#include <procmgr.h>
+#include "../procmgr_drvdefs.h"
+#include "proc4430.h"
+#include "dmm4430.h"
+#include <syslink/multiproc.h>
+#include <syslink/ducatienabler.h>
+#include <syslink/platform_mem.h>
+#include <syslink/atomic_linux.h>
+
+#define DUCATI_DMM_START_ADDR 0xa0000000
+#define DUCATI_DMM_POOL_SIZE 0x6000000
+
+#define SYS_M3 2
+#define APP_M3 3
+#define CORE_PRM_BASE IO_ADDRESS(0x4a306700)
+#define CORE_CM2_DUCATI_CLKSTCTRL IO_ADDRESS(0x4A008900)
+#define CORE_CM2_DUCATI_CLKCTRL IO_ADDRESS(0x4A008920)
+#define RM_MPU_M3_RSTCTRL_OFFSET 0x210
+#define RM_MPU_M3_RSTST_OFFSET 0x214
+#define RM_MPU_M3_RST1 0x1
+#define RM_MPU_M3_RST2 0x2
+#define RM_MPU_M3_RST3 0x4
+
+#define OMAP4430PROC_MODULEID (u16) 0xbbec
+
+/* Macro to make a correct module magic number with refCount */
+#define OMAP4430PROC_MAKE_MAGICSTAMP(x) ((OMAP4430PROC_MODULEID << 12u) | (x))
+
+/*OMAP4430 Module state object */
+struct proc4430_module_object {
+ u32 config_size;
+ /* Size of configuration structure */
+ struct proc4430_config cfg;
+ /* OMAP4430 configuration structure */
+ struct proc4430_config def_cfg;
+ /* Default module configuration */
+ struct proc4430_params def_inst_params;
+ /* Default parameters for the OMAP4430 instances */
+ void *proc_handles[MULTIPROC_MAXPROCESSORS];
+ /* Processor handle array. */
+ struct mutex *gate_handle;
+ /* void * of gate to be used for local thread safety */
+ atomic_t ref_count;
+};
+
+/*
+ OMAP4430 instance object.
+ */
+struct proc4430_object {
+ struct proc4430_params params;
+ /* Instance parameters (configuration values) */
+};
+
+
+/* =================================
+ * Globals
+ * =================================
+ */
+/*
+ OMAP4430 state object variable
+ */
+
+static struct proc4430_module_object proc4430_state = {
+ .config_size = sizeof(struct proc4430_config),
+ .gate_handle = NULL,
+ .def_inst_params.num_mem_entries = 0u,
+ .def_inst_params.mem_entries = NULL,
+ .def_inst_params.reset_vector_mem_entry = 0
+};
+
+
+/* =================================
+ * APIs directly called by applications
+ * =================================
+ */
+/*
+ * Function to get the default configuration for the OMAP4430
+ * module.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to proc4430_setup filled in by the
+ * OMAP4430 module with the default parameters. If the user
+ * does not wish to make any change in the default parameters, this
+ * API is not required to be called.
+ */
+void proc4430_get_config(struct proc4430_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+ memcpy(cfg, &(proc4430_state.def_cfg),
+ sizeof(struct proc4430_config));
+}
+EXPORT_SYMBOL(proc4430_get_config);
+
+/*
+ * Function to setup the OMAP4430 module.
+ *
+ * This function sets up the OMAP4430 module. This function
+ * must be called before any other instance-level APIs can be
+ * invoked.
+ * Module-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then proc4430_get_config can be called to get the
+ * configuration filled with the default values. After this, only
+ * the required configuration values can be changed. If the user
+ * does not wish to make any change in the default parameters, the
+ * application can simply call proc4430_setup with NULL
+ * parameters. The default parameters would get automatically used.
+ */
+int proc4430_setup(struct proc4430_config *cfg)
+{
+ int retval = 0;
+ struct proc4430_config tmp_cfg;
+ atomic_cmpmask_and_set(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&proc4430_state.ref_count) !=
+ OMAP4430PROC_MAKE_MAGICSTAMP(1)) {
+ return 1;
+ }
+
+ if (cfg == NULL) {
+ proc4430_get_config(&tmp_cfg);
+ cfg = &tmp_cfg;
+ }
+
+ dmm_create();
+ dmm_create_tables(DUCATI_DMM_START_ADDR, DUCATI_DMM_POOL_SIZE);
+
+ /* Create a default gate handle for local module protection. */
+ proc4430_state.gate_handle =
+ kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (proc4430_state.gate_handle == NULL) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ mutex_init(proc4430_state.gate_handle);
+
+ /* Initialize the name to handles mapping array. */
+ memset(&proc4430_state.proc_handles, 0,
+ (sizeof(void *) * MULTIPROC_MAXPROCESSORS));
+
+ /* Copy the user provided values into the state object. */
+ memcpy(&proc4430_state.cfg, cfg,
+ sizeof(struct proc4430_config));
+
+ return 0;
+
+error:
+ atomic_dec_return(&proc4430_state.ref_count);
+ dmm_delete_tables();
+ dmm_destroy();
+
+ return retval;
+}
+EXPORT_SYMBOL(proc4430_setup);
+
+/*
+ * Function to destroy the OMAP4430 module.
+ *
+ * Once this function is called, other OMAP4430 module APIs,
+ * except for the proc4430_get_config API cannot be called
+ * anymore.
+ */
+int proc4430_destroy(void)
+{
+ int retval = 0;
+ u16 i;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ retval = -ENODEV;
+ goto exit;
+ }
+ if (!(atomic_dec_return(&proc4430_state.ref_count)
+ == OMAP4430PROC_MAKE_MAGICSTAMP(0))) {
+
+ retval = 1;
+ goto exit;
+ }
+
+ /* Check if any OMAP4430 instances have not been
+ * deleted so far. If not,delete them.
+ */
+
+ for (i = 0; i < MULTIPROC_MAXPROCESSORS; i++) {
+ if (proc4430_state.proc_handles[i] == NULL)
+ continue;
+ proc4430_delete(&(proc4430_state.proc_handles[i]));
+ }
+
+ /* Check if the gate_handle was created internally. */
+ if (proc4430_state.gate_handle != NULL) {
+ mutex_destroy(proc4430_state.gate_handle);
+ kfree(proc4430_state.gate_handle);
+ }
+
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(proc4430_destroy);
+
+/*=================================================
+ * Function to initialize the parameters for this Processor
+ * instance.
+ */
+void proc4430_params_init(void *handle, struct proc4430_params *params)
+{
+ struct proc4430_object *proc_object = (struct proc4430_object *)handle;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_params_init failed "
+ "Module not initialized");
+ return;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ printk(KERN_ERR "proc4430_params_init failed "
+ "Argument of type proc4430_params * "
+ "is NULL");
+ return;
+ }
+
+ if (handle == NULL)
+ memcpy(params, &(proc4430_state.def_inst_params),
+ sizeof(struct proc4430_params));
+ else
+ memcpy(params, &(proc_object->params),
+ sizeof(struct proc4430_params));
+}
+EXPORT_SYMBOL(proc4430_params_init);
+
+/*===================================================
+ *Function to create an instance of this Processor.
+ *
+ */
+void *proc4430_create(u16 proc_id, const struct proc4430_params *params)
+{
+ struct processor_object *handle = NULL;
+ struct proc4430_object *object = NULL;
+
+ BUG_ON(!IS_VALID_PROCID(proc_id));
+ BUG_ON(params == NULL);
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_create failed "
+ "Module not initialized");
+ goto error;
+ }
+
+ /* Enter critical section protection. */
+ WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle));
+ if (proc4430_state.proc_handles[proc_id] != NULL) {
+ handle = proc4430_state.proc_handles[proc_id];
+ goto func_end;
+ } else {
+ handle = (struct processor_object *)
+ vmalloc(sizeof(struct processor_object));
+ if (WARN_ON(handle == NULL))
+ goto func_end;
+
+ handle->proc_fxn_table.attach = &proc4430_attach;
+ handle->proc_fxn_table.detach = &proc4430_detach;
+ handle->proc_fxn_table.start = &proc4430_start;
+ handle->proc_fxn_table.stop = &proc4430_stop;
+ handle->proc_fxn_table.read = &proc4430_read;
+ handle->proc_fxn_table.write = &proc4430_write;
+ handle->proc_fxn_table.control = &proc4430_control;
+ handle->proc_fxn_table.translateAddr =
+ &proc4430_translate_addr;
+ handle->proc_fxn_table.map = &proc4430_map;
+ handle->proc_fxn_table.unmap = &proc4430_unmap;
+ handle->proc_fxn_table.procinfo = &proc4430_proc_info;
+ handle->proc_fxn_table.virt_to_phys = &proc4430_virt_to_phys;
+ handle->state = PROC_MGR_STATE_UNKNOWN;
+ handle->object = vmalloc(sizeof(struct proc4430_object));
+ handle->proc_id = proc_id;
+ object = (struct proc4430_object *)handle->object;
+ if (params != NULL) {
+ /* Copy params into instance object. */
+ memcpy(&(object->params), (void *)params,
+ sizeof(struct proc4430_params));
+ }
+ if ((params != NULL) && (params->mem_entries != NULL)
+ && (params->num_mem_entries > 0)) {
+ /* Allocate memory for, and copy mem_entries table*/
+ object->params.mem_entries = vmalloc(sizeof(struct
+ proc4430_mem_entry) *
+ params->num_mem_entries);
+ memcpy(object->params.mem_entries,
+ params->mem_entries,
+ (sizeof(struct proc4430_mem_entry) *
+ params->num_mem_entries));
+ }
+ handle->boot_mode = PROC_MGR_BOOTMODE_NOLOAD;
+ /* Set the handle in the state object. */
+ proc4430_state.proc_handles[proc_id] = handle;
+ }
+
+func_end:
+ mutex_unlock(proc4430_state.gate_handle);
+error:
+ return (void *)handle;
+}
+EXPORT_SYMBOL(proc4430_create);
+
+/*=================================================
+ * Function to delete an instance of this Processor.
+ *
+ * The user provided pointer to the handle is reset after
+ * successful completion of this function.
+ *
+ */
+int proc4430_delete(void **handle_ptr)
+{
+ int retval = 0;
+ struct proc4430_object *object = NULL;
+ struct processor_object *handle;
+
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(*handle_ptr == NULL);
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_delete failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ handle = (struct processor_object *)(*handle_ptr);
+ BUG_ON(!IS_VALID_PROCID(handle->proc_id));
+ /* Enter critical section protection. */
+ WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle));
+ /* Reset handle in PwrMgr handle array. */
+ proc4430_state.proc_handles[handle->proc_id] = NULL;
+ /* Free memory used for the OMAP4430 object. */
+ if (handle->object != NULL) {
+ object = (struct proc4430_object *)handle->object;
+ if (object->params.mem_entries != NULL) {
+ vfree(object->params.mem_entries);
+ object->params.mem_entries = NULL;
+ }
+ vfree(handle->object);
+ handle->object = NULL;
+ }
+ /* Free memory used for the Processor object. */
+ vfree(handle);
+ *handle_ptr = NULL;
+ /* Leave critical section protection. */
+ mutex_unlock(proc4430_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc4430_delete);
+
+/*===================================================
+ * Function to open a handle to an instance of this Processor. This
+ * function is called when access to the Processor is required from
+ * a different process.
+ */
+int proc4430_open(void **handle_ptr, u16 proc_id)
+{
+ int retval = 0;
+
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(!IS_VALID_PROCID(proc_id));
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_open failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ /* Initialize return parameter handle. */
+ *handle_ptr = NULL;
+
+ /* Check if the PwrMgr exists and return the handle if found. */
+ if (proc4430_state.proc_handles[proc_id] == NULL) {
+ retval = -ENODEV;
+ goto func_exit;
+ } else
+ *handle_ptr = proc4430_state.proc_handles[proc_id];
+func_exit:
+ return retval;
+}
+EXPORT_SYMBOL(proc4430_open);
+
+/*===============================================
+ * Function to close a handle to an instance of this Processor.
+ *
+ */
+int proc4430_close(void *handle)
+{
+ int retval = 0;
+
+ BUG_ON(handle == NULL);
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_close failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ /* nothing to be done for now */
+ return retval;
+}
+EXPORT_SYMBOL(proc4430_close);
+
+/* =================================
+ * APIs called by Processor module (part of function table interface)
+ * =================================
+ */
+/*================================
+ * Function to initialize the slave processor
+ *
+ */
+int proc4430_attach(void *handle, struct processor_attach_params *params)
+{
+ int retval = 0;
+
+ struct processor_object *proc_handle = NULL;
+ struct proc4430_object *object = NULL;
+ u32 map_count = 0;
+ u32 i;
+ memory_map_info map_info;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_attach failed"
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ if (WARN_ON(handle == NULL)) {
+ printk(KERN_ERR "proc4430_attach failed"
+ "Driver handle is NULL");
+ return -EINVAL;
+ }
+
+ if (WARN_ON(params == NULL)) {
+ printk(KERN_ERR "proc4430_attach failed"
+ "Argument processor_attach_params * is NULL");
+ return -EINVAL;
+ }
+
+ proc_handle = (struct processor_object *)handle;
+
+ object = (struct proc4430_object *)proc_handle->object;
+ /* Return memory information in params. */
+ for (i = 0; (i < object->params.num_mem_entries); i++) {
+ /* If the configured master virtual address is invalid, get the
+ * actual address by mapping the physical address into master
+ * kernel memory space.
+ */
+ if ((object->params.mem_entries[i].master_virt_addr == (u32)-1)
+ && (object->params.mem_entries[i].shared == true)) {
+ map_info.src = object->params.mem_entries[i].phys_addr;
+ map_info.size = object->params.mem_entries[i].size;
+ map_info.is_cached = false;
+ retval = platform_mem_map(&map_info);
+ if (retval != 0) {
+ printk(KERN_ERR "proc4430_attach failed\n");
+ return -EFAULT;
+ }
+ map_count++;
+ object->params.mem_entries[i].master_virt_addr =
+ map_info.dst;
+ params->mem_entries[i].addr
+ [PROC_MGR_ADDRTYPE_MASTERKNLVIRT] =
+ map_info.dst;
+ params->mem_entries[i].addr
+ [PROC_MGR_ADDRTYPE_SLAVEVIRT] =
+ (object->params.mem_entries[i].slave_virt_addr);
+ /* User virtual will be filled by user side. For now,
+ fill in the physical address so that it can be used
+ by mmap to remap this region into user-space */
+ params->mem_entries[i].addr
+ [PROC_MGR_ADDRTYPE_MASTERUSRVIRT] = \
+ object->params.mem_entries[i].phys_addr;
+ params->mem_entries[i].size =
+ object->params.mem_entries[i].size;
+ }
+ }
+ params->num_mem_entries = map_count;
+ return retval;
+}
+
+
+/*==========================================
+ * Function to detach from the Processor.
+ *
+ */
+int proc4430_detach(void *handle)
+{
+ struct processor_object *proc_handle = NULL;
+ struct proc4430_object *object = NULL;
+ u32 i;
+ memory_unmap_info unmap_info;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+
+ printk(KERN_ERR "proc4430_detach failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ if (WARN_ON(handle == NULL)) {
+ printk(KERN_ERR "proc4430_detach failed "
+ "Argument Driverhandle is NULL");
+ return -EINVAL;
+ }
+
+ proc_handle = (struct processor_object *)handle;
+ object = (struct proc4430_object *)proc_handle->object;
+ for (i = 0; (i < object->params.num_mem_entries); i++) {
+ if ((object->params.mem_entries[i].master_virt_addr > 0)
+ && (object->params.mem_entries[i].shared == true)) {
+ unmap_info.addr =
+ object->params.mem_entries[i].master_virt_addr;
+ unmap_info.size = object->params.mem_entries[i].size;
+ platform_mem_unmap(&unmap_info);
+ object->params.mem_entries[i].master_virt_addr =
+ (u32)-1;
+ }
+ }
+ return 0;
+}
+
+/*==========================================
+ * Function to start the slave processor
+ *
+ * Start the slave processor running from its entry point.
+ * Depending on the boot mode, this involves configuring the boot
+ * address and releasing the slave from reset.
+ *
+ */
+int proc4430_start(void *handle, u32 entry_pt,
+ struct processor_start_params *start_params)
+{
+ u32 reg;
+ int counter = 10;
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+
+ printk(KERN_ERR "proc4430_start failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ /*FIXME: Remove handle and entry_pt if not used */
+ if (WARN_ON(start_params == NULL)) {
+ printk(KERN_ERR "proc4430_start failed "
+ "Argument processor_start_params * is NULL");
+ return -EINVAL;
+ }
+ switch (start_params->params->proc_id) {
+ case SYS_M3:
+ /* Module is managed automatically by HW */
+ __raw_writel(0x01, CORE_CM2_DUCATI_CLKCTRL);
+ /* Enable the M3 clock */
+ __raw_writel(0x02, CORE_CM2_DUCATI_CLKSTCTRL);
+ do {
+ reg = __raw_readl(CORE_CM2_DUCATI_CLKSTCTRL);
+ if (reg & 0x100) {
+ printk(KERN_INFO "M3 clock enabled:"
+ "CORE_CM2_DUCATI_CLKSTCTRL = 0x%x\n", reg);
+ break;
+ }
+ msleep(1);
+ } while (--counter);
+ if (counter == 0) {
+ printk(KERN_ERR "FAILED TO ENABLE DUCATI M3 CLOCK !\n");
+ return -EFAULT;
+ }
+ /* De-assert RST 3 */
+ __raw_writel(0x3, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET);
+ ducati_setup();
+ printk(KERN_INFO "De-assert RST1\n");
+ __raw_writel(0x2, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET);
+ return 0;
+ break;
+ case APP_M3:
+ __raw_writel(0x0, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET);
+ printk(KERN_INFO "De-assert RST2\n");
+ break;
+ default:
+ printk(KERN_ERR "proc4430_start: ERROR input\n");
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * Function to stop the slave processor
+ *
+ * Stop the execution of the slave processor. Depending on the boot
+ * mode, this may result in placing the slave processor in reset.
+ *
+ * @param handle void * to the Processor instance
+ *
+ * @sa proc4430_start, OMAP3530_halResetCtrl
+ */
+int
+proc4430_stop(void *handle, struct processor_stop_params *stop_params)
+{
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_stop failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+ switch (stop_params->params->proc_id) {
+ case SYS_M3:
+ ducati_destroy();
+ printk(KERN_INFO "Assert RST1 and RST2 and RST3\n");
+ __raw_writel(0x7, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET);
+ /* Disable the M3 clock */
+ __raw_writel(0x01, CORE_CM2_DUCATI_CLKSTCTRL);
+ break;
+ case APP_M3:
+ printk(KERN_INFO "Assert RST2\n");
+ __raw_writel(0x2, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET);
+ break;
+ default:
+ printk(KERN_ERR "proc4430_stop: ERROR input\n");
+ break;
+ }
+ return 0;
+}
+
+
+/*==============================================
+ * Function to read from the slave processor's memory.
+ *
+ * Read from the slave processor's memory and copy into the
+ * provided buffer.
+ */
+int proc4430_read(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer)
+{
+ int retval = 0;
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_read failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ /* TODO */
+ return retval;
+}
+
+
+/*==============================================
+ * Function to write into the slave processor's memory.
+ *
+ * Read from the provided buffer and copy into the slave
+ * processor's memory.
+ *
+ */
+int proc4430_write(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer)
+{
+ int retval = 0;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_write failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ /* TODO */
+ return retval;
+}
+
+
+/*=========================================================
+ * Function to perform device-dependent operations.
+ *
+ * Performs device-dependent control operations as exposed by this
+ * implementation of the Processor module.
+ */
+int proc4430_control(void *handle, int cmd, void *arg)
+{
+ int retval = 0;
+
+ /*FIXME: Remove handle,etc if not used */
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_control failed "
+ "Module not initialized");
+ return -ENODEV;
+ }
+
+ return retval;
+}
+
+
+/*=====================================================
+ * Function to translate between two types of address spaces.
+ *
+ * Translate between the specified address spaces.
+ */
+int proc4430_translate_addr(void *handle,
+ void **dst_addr, enum proc_mgr_addr_type dst_addr_type,
+ void *src_addr, enum proc_mgr_addr_type src_addr_type)
+{
+ int retval = 0;
+ struct processor_object *proc_handle = NULL;
+ struct proc4430_object *object = NULL;
+ struct proc4430_mem_entry *entry = NULL;
+ bool found = false;
+ u32 fm_addr_base = (u32)NULL;
+ u32 to_addr_base = (u32)NULL;
+ u32 i;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_translate_addr failed "
+ "Module not initialized");
+ retval = -ENODEV;
+ goto error_exit;
+ }
+
+ if (WARN_ON(handle == NULL)) {
+ retval = -EINVAL;
+ goto error_exit;
+ }
+ if (WARN_ON(dst_addr == NULL)) {
+ retval = -EINVAL;
+ goto error_exit;
+ }
+ if (WARN_ON(dst_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) {
+ retval = -EINVAL;
+ goto error_exit;
+ }
+ if (WARN_ON(src_addr == NULL)) {
+ retval = -EINVAL;
+ goto error_exit;
+ }
+ if (WARN_ON(src_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) {
+ retval = -EINVAL;
+ goto error_exit;
+ }
+
+ proc_handle = (struct processor_object *)handle;
+ object = (struct proc4430_object *)proc_handle->object;
+ *dst_addr = NULL;
+ for (i = 0 ; i < object->params.num_mem_entries ; i++) {
+ entry = &(object->params.mem_entries[i]);
+ fm_addr_base =
+ (src_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ?
+ entry->master_virt_addr : entry->slave_virt_addr;
+ to_addr_base =
+ (dst_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ?
+ entry->master_virt_addr : entry->slave_virt_addr;
+ /* Determine whether which way to convert */
+ if (((u32)src_addr < (fm_addr_base + entry->size)) &&
+ ((u32)src_addr >= fm_addr_base)) {
+ found = true;
+ *dst_addr = (void *)(((u32)src_addr - fm_addr_base)
+ + to_addr_base);
+ break;
+ }
+ }
+
+ /* This check must not be removed even with build optimize. */
+ if (WARN_ON(found == false)) {
+ /*Failed to translate address. */
+ retval = -ENXIO;
+ goto error_exit;
+ }
+ return 0;
+
+error_exit:
+ return retval;
+}
+
+
+/*=================================================
+ * Function to map slave address to host address space
+ *
+ * Map the provided slave address to master address space. This
+ * function also maps the specified address to slave MMU space.
+ */
+int proc4430_map(void *handle, u32 proc_addr,
+ u32 size, u32 *mapped_addr, u32 *mapped_size, u32 map_attribs)
+{
+ int retval = 0;
+ u32 da_align;
+ u32 da;
+ u32 va_align;
+ u32 size_align;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_map failed "
+ "Module not initialized");
+ retval = -ENODEV;
+ goto error_exit;
+ }
+
+ /*FIXME: Remove handle,etc if not used */
+
+ /* FIX ME: Temporary work around until the dynamic memory mapping
+ * for Tiler address space is available
+ */
+ if ((map_attribs & DSP_MAPTILERADDR)) {
+ da_align = user_va2pa(current->mm, proc_addr);
+ *mapped_addr = (da_align | (proc_addr & (PAGE_SIZE - 1)));
+ printk(KERN_INFO "proc4430_map -tiler: user_va2pa: mapped_addr"
+ "= 0x%x\n", *mapped_addr);
+ return 0;
+ }
+
+ /* Calculate the page-aligned PA, VA and size */
+ va_align = PG_ALIGN_LOW(proc_addr, PAGE_SIZE);
+ size_align = PG_ALIGN_HIGH(size + (u32)proc_addr - va_align, PAGE_SIZE);
+
+ dmm_reserve_memory(size_align, &da);
+ da_align = PG_ALIGN_LOW((u32)da, PAGE_SIZE);
+ retval = ducati_mem_map(va_align, da_align, size_align, map_attribs);
+
+ /* Mapped address = MSB of DA | LSB of VA */
+ *mapped_addr = (da_align | (proc_addr & (PAGE_SIZE - 1)));
+
+error_exit:
+ return retval;
+}
+
+/*=================================================
+ * Function to unmap slave address to host address space
+ *
+ * UnMap the provided slave address to master address space. This
+ * function also unmaps the specified address to slave MMU space.
+ */
+int proc4430_unmap(void *handle, u32 mapped_addr)
+{
+ int da_align;
+ int ret_val = 0;
+ int size_align;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_map failed "
+ "Module not initialized");
+ ret_val = -1;
+ goto error_exit;
+ }
+
+ /*FIXME: Remove handle,etc if not used */
+
+ da_align = PG_ALIGN_LOW((u32)mapped_addr, PAGE_SIZE);
+ ret_val = dmm_unreserve_memory(da_align, &size_align);
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+ ret_val = ducati_mem_unmap(da_align, size_align);
+ if (WARN_ON(ret_val < 0))
+ goto error_exit;
+ return 0;
+
+error_exit:
+ printk(KERN_WARNING "proc4430_unmap failed !!!!\n");
+ return ret_val;
+}
+
+/*=================================================
+ * Function to return list of translated mem entries
+ *
+ * This function takes the remote processor address as
+ * an input and returns the mapped Page entries in the
+ * buffer passed
+ */
+int proc4430_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries)
+{
+ int da_align;
+ int i;
+ int ret_val = 0;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_virt_to_phys failed "
+ "Module not initialized");
+ ret_val = -EFAULT;
+ goto error_exit;
+ }
+
+ if (handle == NULL || mapped_entries == NULL || num_of_entries == 0) {
+ ret_val = -EFAULT;
+ goto error_exit;
+ }
+ da_align = PG_ALIGN_LOW((u32)da, PAGE_SIZE);
+ for (i = 0; i < num_of_entries; i++) {
+ mapped_entries[i] = ducati_mem_virtToPhys(da_align);
+ da_align += PAGE_SIZE;
+ }
+ return 0;
+
+error_exit:
+ printk(KERN_WARNING "proc4430_virtToPhys failed !!!!\n");
+ return ret_val;
+}
+
+
+/*=================================================
+ * Function to return PROC4430 mem_entries info
+ *
+ */
+int proc4430_proc_info(void *handle, struct proc_mgr_proc_info *procinfo)
+{
+ struct processor_object *proc_handle = NULL;
+ struct proc4430_object *object = NULL;
+ struct proc4430_mem_entry *entry = NULL;
+ int i;
+
+ if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
+ OMAP4430PROC_MAKE_MAGICSTAMP(0),
+ OMAP4430PROC_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc4430_proc_info failed "
+ "Module not initialized");
+ goto error_exit;
+ }
+
+ if (WARN_ON(handle == NULL))
+ goto error_exit;
+ if (WARN_ON(procinfo == NULL))
+ goto error_exit;
+
+ proc_handle = (struct processor_object *)handle;
+
+ object = (struct proc4430_object *)proc_handle->object;
+
+ for (i = 0 ; i < object->params.num_mem_entries ; i++) {
+ entry = &(object->params.mem_entries[i]);
+ procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_MASTERKNLVIRT]
+ = entry->master_virt_addr;
+ procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_SLAVEVIRT]
+ = entry->slave_virt_addr;
+ procinfo->mem_entries[i].size = entry->size;
+ }
+ procinfo->num_mem_entries = object->params.num_mem_entries;
+ procinfo->boot_mode = proc_handle->boot_mode;
+ return 0;
+
+error_exit:
+ printk(KERN_WARNING "proc4430_proc_info failed !!!!\n");
+ return -EFAULT;
+}
diff --git a/drivers/dsp/syslink/procmgr/proc4430/proc4430.h b/drivers/dsp/syslink/procmgr/proc4430/proc4430.h
new file mode 100755
index 000000000000..5903daeadaa3
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/proc4430.h
@@ -0,0 +1,147 @@
+/*
+ * proc4430.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+
+
+
+#ifndef _SYSLINK_PROC_4430_H_
+#define _SYSLINK_PROC_4430_H_
+
+
+/* Module headers */
+#include <procmgr.h>
+#include "../procdefs.h"
+#include <linux/types.h>
+
+/*
+ Module configuration structure.
+ */
+struct proc4430_config {
+ struct mutex *gate_handle;
+ /* void * of gate to be used for local thread safety */
+};
+
+/*
+ Memory entry for slave memory map configuration
+ */
+struct proc4430_mem_entry {
+ char name[PROCMGR_MAX_STRLEN];
+ /* Name identifying the memory region. */
+ u32 phys_addr;
+ /* Physical address of the memory region. */
+ u32 slave_virt_addr;
+ /* Slave virtual address of the memory region. */
+ u32 master_virt_addr;
+ /* Master virtual address of the memory region. If specified as -1,
+ * the master virtual address is assumed to be invalid, and shall be
+ * set internally within the Processor module. */
+ u32 size;
+ /* Size (in bytes) of the memory region. */
+ bool shared;
+ /* Flag indicating whether the memory region is shared between master
+ * and slave. */
+};
+
+/*
+ Configuration parameters specific to this processor.
+ */
+struct proc4430_params {
+ int num_mem_entries;
+ /* Number of memory regions to be configured. */
+ struct proc4430_mem_entry *mem_entries;
+ /* Array of information structures for memory regions
+ * to be configured. */
+ u32 reset_vector_mem_entry;
+ /* Index of the memory entry within the mem_entries array,
+ * which is the resetVector memory region. */
+};
+
+
+/* Function to initialize the slave processor */
+int proc4430_attach(void *handle, struct processor_attach_params *params);
+
+/* Function to finalize the slave processor */
+int proc4430_detach(void *handle);
+
+/* Function to start the slave processor */
+int proc4430_start(void *handle, u32 entry_pt,
+ struct processor_start_params *params);
+
+/* Function to start the stop processor */
+int proc4430_stop(void *handle,
+ struct processor_stop_params *params);
+
+/* Function to read from the slave processor's memory. */
+int proc4430_read(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer);
+
+/* Function to write into the slave processor's memory. */
+int proc4430_write(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer);
+
+/* Function to perform device-dependent operations. */
+int proc4430_control(void *handle, int cmd, void *arg);
+
+/* Function to translate between two types of address spaces. */
+int proc4430_translate_addr(void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dst_addr_type,
+ void *src_addr, enum proc_mgr_addr_type src_addr_type);
+
+/* Function to map slave address to host address space */
+int proc4430_map(void *handle, u32 proc_addr, u32 size, u32 *mapped_addr,
+ u32 *mapped_size, u32 map_attribs);
+
+/* Function to unmap the slave address to host address space */
+int proc4430_unmap(void *handle, u32 mapped_addr);
+
+/* Function to retrive physical address translations */
+int proc4430_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries);
+
+/* =================================================
+ * APIs
+ * =================================================
+ */
+
+/* Function to get the default configuration for the OMAP4430PROC module */
+void proc4430_get_config(struct proc4430_config *cfg);
+
+/* Function to setup the OMAP4430PROC module. */
+int proc4430_setup(struct proc4430_config *cfg);
+
+/* Function to destroy the OMAP4430PROC module. */
+int proc4430_destroy(void);
+
+/* Function to initialize the parameters for this processor instance. */
+void proc4430_params_init(void *handle,
+ struct proc4430_params *params);
+
+/* Function to create an instance of this processor. */
+void *proc4430_create(u16 proc_id, const struct proc4430_params *params);
+
+/* Function to delete an instance of this processor. */
+int proc4430_delete(void **handle_ptr);
+
+/* Function to open an instance of this processor. */
+int proc4430_open(void **handle_ptr, u16 proc_id);
+
+/* Function to close an instance of this processor. */
+int proc4430_close(void *handle);
+
+/* Function to get the proc info */
+int proc4430_proc_info(void *handle, struct proc_mgr_proc_info *procinfo);
+
+#endif
diff --git a/drivers/dsp/syslink/procmgr/proc4430/proc4430_drv.c b/drivers/dsp/syslink/procmgr/proc4430/proc4430_drv.c
new file mode 100755
index 000000000000..92fc35b9e684
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/proc4430_drv.c
@@ -0,0 +1,400 @@
+/*
+ * proc4430_drv.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+
+
+/* Module headers */
+#include "proc4430.h"
+#include "proc4430_drvdefs.h"
+
+
+
+/** ============================================================================
+ * Macros and types
+ * ============================================================================
+ */
+#define PROC4430_NAME "syslink-proc4430"
+
+static char *driver_name = PROC4430_NAME;
+
+static s32 driver_major;
+
+static s32 driver_minor;
+
+struct proc_4430_dev {
+ struct cdev cdev;
+};
+
+static struct proc_4430_dev *proc_4430_device;
+
+static struct class *proc_4430_class;
+
+
+
+/** ============================================================================
+ * Forward declarations of internal functions
+ * ============================================================================
+ */
+/* Linux driver function to open the driver object. */
+static int proc4430_drv_open(struct inode *inode, struct file *filp);
+
+/* Linux driver function to close the driver object. */
+static int proc4430_drv_release(struct inode *inode, struct file *filp);
+
+/* Linux driver function to invoke the APIs through ioctl. */
+static int proc4430_drv_ioctl(struct inode *inode,
+ struct file *filp, unsigned int cmd,
+ unsigned long args);
+
+/* Linux driver function to map memory regions to user space. */
+static int proc4430_drv_mmap(struct file *filp,
+ struct vm_area_struct *vma);
+
+/* Module initialization function for Linux driver. */
+static int __init proc4430_drv_initializeModule(void);
+
+/* Module finalization function for Linux driver. */
+static void __exit proc4430_drv_finalizeModule(void);
+
+
+
+/** ============================================================================
+ * Globals
+ * ============================================================================
+ */
+
+/*
+ File operations table for PROC4430.
+ */
+static const struct file_operations proc_4430_fops = {
+ .open = proc4430_drv_open,
+ .release = proc4430_drv_release,
+ .ioctl = proc4430_drv_ioctl,
+ .mmap = proc4430_drv_mmap,
+};
+
+static int proc4430_drv_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int proc4430_drv_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+/*
+ Linux driver function to invoke the APIs through ioctl.
+ *
+ */
+static int proc4430_drv_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int retval = 0;
+ struct proc_mgr_cmd_args *cmd_args = (struct proc_mgr_cmd_args *)args;
+ struct proc_mgr_cmd_args command_args;
+
+ switch (cmd) {
+ case CMD_PROC4430_GETCONFIG:
+ {
+ struct proc4430_cmd_args_get_config *src_args =
+ (struct proc4430_cmd_args_get_config *)args;
+ struct proc4430_config cfg;
+
+ /* copy_from_useris not needed for
+ * proc4430_get_config, since the
+ * user's config is not used.
+ */
+ proc4430_get_config(&cfg);
+
+ retval = copy_to_user((void *)(src_args->cfg),
+ (const void *)&cfg,
+ sizeof(struct proc4430_config));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ }
+ break;
+
+ case CMD_PROC4430_SETUP:
+ {
+ struct proc4430_cmd_args_setup *src_args =
+ (struct proc4430_cmd_args_setup *)args;
+ struct proc4430_config cfg;
+
+ retval = copy_from_user((void *)&cfg,
+ (const void *)(src_args->cfg),
+ sizeof(struct proc4430_config));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ proc4430_setup(&cfg);
+ }
+ break;
+
+ case CMD_PROC4430_DESTROY:
+ {
+ proc4430_destroy();
+ }
+ break;
+
+ case CMD_PROC4430_PARAMS_INIT:
+ {
+ struct proc4430_cmd_args_params_init src_args;
+ struct proc4430_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc4430_cmd_args_params_init));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ proc4430_params_init(src_args.handle, &params);
+ retval = copy_to_user((void *)(src_args.params),
+ (const void *) &params,
+ sizeof(struct proc4430_params));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ }
+ break;
+
+ case CMD_PROC4430_CREATE:
+ {
+ struct proc4430_cmd_args_create src_args;
+ struct proc4430_params params;
+ struct proc4430_mem_entry *entries = NULL;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc4430_cmd_args_create));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_from_user((void *) &params,
+ (const void *)(src_args.params),
+ sizeof(struct proc4430_params));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ /* Copy the contents of mem_entries from user-side */
+ if (params.num_mem_entries) {
+ entries = vmalloc(params.num_mem_entries * \
+ sizeof(struct proc4430_mem_entry));
+ if (WARN_ON(!entries))
+ goto func_exit;
+ retval = copy_from_user((void *) (entries),
+ (const void *)(params.mem_entries),
+ params.num_mem_entries * \
+ sizeof(struct proc4430_mem_entry));
+ if (WARN_ON(retval < 0)) {
+ vfree(entries);
+ goto func_exit;
+ }
+ params.mem_entries = entries;
+ }
+ src_args.handle = proc4430_create(src_args.proc_id,
+ &params);
+ if (WARN_ON(src_args.handle == NULL))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc4430_cmd_args_create));
+ /* Free the memory created */
+ if (params.num_mem_entries)
+ vfree(entries);
+ }
+ break;
+
+ case CMD_PROC4430_DELETE:
+ {
+ struct proc4430_cmd_args_delete src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc4430_cmd_args_delete));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = proc4430_delete(&(src_args.handle));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROC4430_OPEN:
+ {
+ struct proc4430_cmd_args_open src_args;
+
+ /*Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc4430_cmd_args_open));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = proc4430_open(&(src_args.handle),
+ src_args.proc_id);
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc4430_cmd_args_open));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROC4430_CLOSE:
+ {
+ struct proc4430_cmd_args_close src_args;
+
+ /*Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc4430_cmd_args_close));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = proc4430_close(src_args.handle);
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ default:
+ {
+ printk(KERN_ERR "unsupported ioctl\n");
+ }
+ break;
+ }
+func_exit:
+ /* Set the status and copy the common args to user-side. */
+ command_args.api_status = retval;
+ retval = copy_to_user((void *) cmd_args,
+ (const void *) &command_args,
+ sizeof(struct proc_mgr_cmd_args));
+ WARN_ON(retval < 0);
+ return retval;
+}
+
+
+/*
+ Linux driver function to map memory regions to user space.
+ *
+ */
+static int proc4430_drv_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma,
+ vma->vm_start,
+ vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+
+/** ==================================================================
+ * Functions required for multiple .ko modules configuration
+ * ==================================================================
+ */
+/*
+ Module initialization function for Linux driver.
+ */
+static int __init proc4430_drv_initializeModule(void)
+{
+ dev_t dev = 0 ;
+ int retval;
+
+ /* Display the version info and created date/time */
+ printk(KERN_INFO "proc4430_drv_initializeModule\n");
+
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ retval = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ retval = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ proc_4430_device = kmalloc(sizeof(struct proc_4430_dev), GFP_KERNEL);
+ if (!proc_4430_device) {
+ retval = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ goto exit;
+ }
+ memset(proc_4430_device, 0, sizeof(struct proc_4430_dev));
+ cdev_init(&proc_4430_device->cdev, &proc_4430_fops);
+ proc_4430_device->cdev.owner = THIS_MODULE;
+ proc_4430_device->cdev.ops = &proc_4430_fops;
+
+ retval = cdev_add(&proc_4430_device->cdev, dev, 1);
+
+ if (retval) {
+ printk(KERN_ERR "Failed to add the syslink proc_4430 device \n");
+ goto exit;
+ }
+
+ /* udev support */
+ proc_4430_class = class_create(THIS_MODULE, "syslink-proc4430");
+
+ if (IS_ERR(proc_4430_class)) {
+ printk(KERN_ERR "Error creating bridge class \n");
+ goto exit;
+ }
+ device_create(proc_4430_class, NULL, MKDEV(driver_major, driver_minor),
+ NULL, PROC4430_NAME);
+exit:
+ return 0;
+}
+
+/*
+ function to finalize the driver module.
+ */
+static void __exit proc4430_drv_finalizeModule(void)
+{
+ dev_t devno = 0;
+
+ /* FIX ME: THIS MIGHT NOT BE THE RIGHT PLACE TO CALL THE SETUP */
+ proc4430_destroy();
+
+ devno = MKDEV(driver_major, driver_minor);
+ if (proc_4430_device) {
+ cdev_del(&proc_4430_device->cdev);
+ kfree(proc_4430_device);
+ }
+ unregister_chrdev_region(devno, 1);
+ if (proc_4430_class) {
+ /* remove the device from sysfs */
+ device_destroy(proc_4430_class, MKDEV(driver_major,
+ driver_minor));
+ class_destroy(proc_4430_class);
+ }
+ return;
+}
+
+/*
+ Macro calls that indicate initialization and finalization functions
+ * to the kernel.
+ */
+MODULE_LICENSE("GPL v2");
+module_init(proc4430_drv_initializeModule);
+module_exit(proc4430_drv_finalizeModule);
diff --git a/drivers/dsp/syslink/procmgr/proc4430/proc4430_drvdefs.h b/drivers/dsp/syslink/procmgr/proc4430/proc4430_drvdefs.h
new file mode 100755
index 000000000000..4176d731f1d4
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/proc4430/proc4430_drvdefs.h
@@ -0,0 +1,169 @@
+/*
+ * proc4430_drvdefs.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+
+#ifndef _SYSLINK_PROC4430_H
+#define _SYSLINK_PROC4430_H
+
+
+/* Module headers */
+#include "../procmgr_drvdefs.h"
+#include "proc4430.h"
+
+
+/* ----------------------------------------------------------------------------
+ * IOCTL command IDs for OMAP4430PROC
+ * ----------------------------------------------------------------------------
+ */
+/*
+ * Base command ID for OMAP4430PROC
+ */
+#define PROC4430_BASE_CMD 0x200
+
+/*
+ * Command for PROC4430_getConfig
+ */
+#define CMD_PROC4430_GETCONFIG (PROC4430_BASE_CMD + 1)
+
+/*
+ * Command for PROC4430_setup
+ */
+#define CMD_PROC4430_SETUP (PROC4430_BASE_CMD + 2)
+
+/*
+ * Command for PROC4430_setup
+ */
+#define CMD_PROC4430_DESTROY (PROC4430_BASE_CMD + 3)
+
+/*
+ * Command for PROC4430_destroy
+ */
+#define CMD_PROC4430_PARAMS_INIT (PROC4430_BASE_CMD + 4)
+
+/*
+ * Command for PROC4430_create
+ */
+#define CMD_PROC4430_CREATE (PROC4430_BASE_CMD + 5)
+
+/*
+ * Command for PROC4430_delete
+ */
+#define CMD_PROC4430_DELETE (PROC4430_BASE_CMD + 6)
+
+/*
+ * Command for PROC4430_open
+ */
+#define CMD_PROC4430_OPEN (PROC4430_BASE_CMD + 7)
+
+/*
+ * Command for PROC4430_close
+ */
+#define CMD_PROC4430_CLOSE (PROC4430_BASE_CMD + 8)
+
+
+/* ---------------------------------------------------
+ * Command arguments for OMAP4430PROC
+ * ---------------------------------------------------
+ */
+/*
+ * Command arguments for PROC4430_getConfig
+ */
+struct proc4430_cmd_args_get_config {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ struct proc4430_config *cfg;
+ /* Pointer to the OMAP4430PROC module configuration structure
+ * in which the default config is to be returned. */
+};
+
+/*
+ * Command arguments for PROC4430_setup
+ */
+struct proc4430_cmd_args_setup {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ struct proc4430_config *cfg;
+ /* Optional OMAP4430PROC module configuration. If provided as NULL,
+ * default configuration is used. */
+};
+
+/*
+ * Command arguments for PROC4430_destroy
+ */
+struct proc4430_cmd_args_destroy {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+};
+
+/*
+ * Command arguments for struct struct proc4430_params_init
+ */
+struct proc4430_cmd_args_params_init {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ void *handle;
+ /* void * to the processor instance. */
+ struct proc4430_params *params;
+ /* Configuration parameters. */
+};
+
+/*
+ * Command arguments for PROC4430_create
+ */
+struct proc4430_cmd_args_create {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ u16 proc_id;
+ /* Processor ID for which this processor instance is required. */
+ struct proc4430_params *params;
+ /*Configuration parameters. */
+ void *handle;
+ /* void * to the created processor instance. */
+};
+
+/*
+ * Command arguments for PROC4430_delete
+ */
+struct proc4430_cmd_args_delete {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ void *handle;
+ /* Pointer to handle to the processor instance */
+};
+
+/*
+ * Command arguments for PROC4430_open
+ */
+struct proc4430_cmd_args_open {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ u16 proc_id;
+ /* Processor ID addressed by this OMAP4430PROC instance. */
+ void *handle;
+ /* Return parameter: void * to the processor instance */
+};
+
+/*
+ * Command arguments for PROC4430_close
+ */
+struct proc4430_cmd_args_close {
+ struct proc_mgr_cmd_args command_args;
+ /* Common command args */
+ void *handle;
+ /* void * to the processor instance */
+};
+
+#endif
diff --git a/drivers/dsp/syslink/procmgr/procdefs.h b/drivers/dsp/syslink/procmgr/procdefs.h
new file mode 100755
index 000000000000..eb73626d27e1
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/procdefs.h
@@ -0,0 +1,203 @@
+/*
+ * procdefs.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#ifndef SYSLINK_PROCDEFS_H
+#define SYSLINK_PROCDEFS_H
+
+#include <linux/types.h>
+
+/* Module level headers */
+#include <procmgr.h>
+
+
+/* =============================
+ * Macros and types
+ * =============================
+ */
+/*
+ * Enumerates the types of Endianism of slave processor.
+ */
+enum processor_endian{
+ PROCESSOR_ENDIAN_DEFAULT = 0,
+ /* Default endianism (no conversion required) */
+ PROCESSOR_ENDIAN_BIG = 1,
+ /* Big endian */
+ PROCESSOR_ENDIAN_LITTLE = 2,
+ /* Little endian */
+ PROCESSOR_ENDIAN_ENDVALUE = 3
+ /* End delimiter indicating start of invalid values for this enum */
+};
+
+
+/*
+ * Configuration parameters for attaching to the slave Processor
+ */
+struct processor_attach_params {
+ struct proc_mgr_attach_params *params;
+ /* Common attach parameters for ProcMgr */
+ u16 num_mem_entries;
+ /* Number of valid memory entries */
+ struct proc_mgr_addr_info mem_entries[PROCMGR_MAX_MEMORY_REGIONS];
+ /* Configuration of memory regions */
+};
+
+/*
+ *Configuration parameters for starting the slave Processor
+ */
+struct processor_start_params {
+ struct proc_mgr_start_params *params;
+ /* Common start parameters for ProcMgr */
+};
+
+/*
+ *Configuration parameters for stopping the slave Processor
+ */
+struct processor_stop_params {
+ struct proc_mgr_stop_params *params;
+ /* Common start parameters for ProcMgr */
+};
+/*
+ * Function pointer type for the function to attach to the processor.
+ */
+typedef int (*processor_attach_fxn) (void *handle,
+ struct processor_attach_params *params);
+
+/*
+ * Function pointer type for the function to detach from the
+ * procssor
+ */
+typedef int (*processor_detach_fxn) (void *handle);
+
+/*
+ * Function pointer type for the function to start the processor.
+ */
+typedef int (*processor_start_fxn) (void *handle, u32 entry_pt,
+ struct processor_start_params *params);
+
+/*
+ *Function pointer type for the function to stop the processor.
+ */
+typedef int (*processor_stop_fxn) (void *handle,
+ struct processor_stop_params *params);
+
+/*
+ * Function pointer type for the function to read from the slave
+ * processor's memory.
+ */
+typedef int (*processor_read_fxn) (void *handle, u32 proc_addr,
+ u32 *num_bytes, void *buffer);
+
+/*
+ *Function pointer type for the function to write into the slave
+ *processor's memory.
+ */
+typedef int (*processor_write_fxn) (void *handle, u32 proc_addr,
+ u32 *num_bytes, void *buffer);
+
+/*
+ *Function pointer type for the function to perform device-dependent
+ * operations.
+ */
+typedef int (*processor_control_fxn) (void *handle, int cmd, void *arg);
+
+/*
+ *Function pointer type for the function to translate between
+ * two types of address spaces.
+ */
+typedef int (*processor_translate_addr_fxn) (void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dstAddrType, void *srcAddr,
+ enum proc_mgr_addr_type srcAddrType);
+
+/*
+ *Function pointer type for the function to map address to slave
+ * address space
+ */
+typedef int (*processor_map_fxn) (void *handle, u32 proc_addr, u32 size,
+ u32 *mapped_addr, u32 *mapped_size, u32 map_attribs);
+
+/*
+ *Function pointer type for the function to map address to slave
+ * address space
+ */
+typedef int (*processor_unmap_fxn) (void *handle, u32 mapped_addr);
+
+/*
+ *Function pointer type for the function that returns proc info
+ */
+typedef int (*processor_proc_info) (void *handle,
+ struct proc_mgr_proc_info *proc_info);
+
+/*
+ *Function pointer type for the function that returns proc info
+ */
+typedef int (*processor_virt_to_phys_fxn) (void *handle, u32 da,
+ u32 *mapped_entries, u32 num_of_entries);
+
+
+/* =============================
+ * Function table interface
+ * =============================
+ */
+/*
+ *Function table interface for Processor.
+ */
+struct processor_fxn_table {
+ processor_attach_fxn attach;
+ /* Function to attach to the slave processor */
+ processor_detach_fxn detach;
+ /* Function to detach from the slave processor */
+ processor_start_fxn start;
+ /* Function to start the slave processor */
+ processor_stop_fxn stop;
+ /* Function to stop the slave processor */
+ processor_read_fxn read;
+ /* Function to read from the slave processor's memory */
+ processor_write_fxn write;
+ /* Function to write into the slave processor's memory */
+ processor_control_fxn control;
+ /* Function to perform device-dependent control function */
+ processor_translate_addr_fxn translateAddr;
+ /* Function to translate between address ranges */
+ processor_map_fxn map;
+ /* Function to map slave addresses to master address space */
+ processor_unmap_fxn unmap;
+ /* Function to unmap slave addresses to master address space */
+ processor_proc_info procinfo;
+ /* Function to convert Virtual to Physical pages */
+ processor_virt_to_phys_fxn virt_to_phys;
+};
+
+/* =============================
+ * Processor structure
+ * =============================
+ */
+/*
+ * Generic Processor object. This object defines the handle type for all
+ * Processor operations.
+ */
+struct processor_object {
+ struct processor_fxn_table proc_fxn_table;
+ /* interface function table to plug into the generic Processor. */
+ enum proc_mgr_state state;
+ /* State of the slave processor */
+ enum proc_mgr_boot_mode boot_mode;
+ /* Boot mode for the slave processor. */
+ void *object;
+ /* Pointer to Processor-specific object. */
+ u16 proc_id;
+ /* Processor ID addressed by this Processor instance. */
+};
+#endif
diff --git a/drivers/dsp/syslink/procmgr/processor.c b/drivers/dsp/syslink/procmgr/processor.c
new file mode 100755
index 000000000000..4548d12ad967
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/processor.c
@@ -0,0 +1,398 @@
+/*
+ * processor.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+/* Module level headers */
+#include "procdefs.h"
+#include "processor.h"
+
+
+
+/* =========================================
+ * Functions called by ProcMgr
+ * =========================================
+ */
+/*
+ * Function to attach to the Processor.
+ *
+ * This function calls into the specific Processor implementation
+ * to attach to it.
+ * This function is called from the ProcMgr attach function, and
+ * hence is used to perform any activities that may be required
+ * once the slave is powered up.
+ * Depending on the type of Processor, this function may or may not
+ * perform any activities.
+ */
+inline int processor_attach(void *handle,
+ struct processor_attach_params *params)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(params == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.attach == NULL);
+
+ proc_handle->boot_mode = params->params->boot_mode;
+ retval = proc_handle->proc_fxn_table.attach(handle, params);
+
+ if (proc_handle->boot_mode == PROC_MGR_BOOTMODE_BOOT)
+ proc_handle->state = PROC_MGR_STATE_POWERED;
+ else if (proc_handle->boot_mode == PROC_MGR_BOOTMODE_NOLOAD)
+ proc_handle->state = PROC_MGR_STATE_LOADED;
+ else if (proc_handle->boot_mode == PROC_MGR_BOOTMODE_NOBOOT)
+ proc_handle->state = PROC_MGR_STATE_RUNNNING;
+ return retval;
+}
+
+
+/*
+ * Function to detach from the Processor.
+ *
+ * This function calls into the specific Processor implementation
+ * to detach from it.
+ * This function is called from the ProcMgr detach function, and
+ * hence is useful to perform any activities that may be required
+ * before the slave is powered down.
+ * Depending on the type of Processor, this function may or may not
+ * perform any activities.
+ */
+inline int processor_detach(void *handle)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.detach == NULL);
+
+ retval = proc_handle->proc_fxn_table.detach(handle);
+ /* For all boot modes, at the end of detach, the Processor is in
+ * unknown state.
+ */
+ proc_handle->state = PROC_MGR_STATE_UNKNOWN;
+ return retval;
+}
+
+
+/*
+ * Function to start the processor.
+ *
+ * This function calls into the specific Processor implementation
+ * to start the slave processor running.
+ * This function starts the slave processor running, in most
+ * devices, by programming its entry point into the boot location
+ * of the slave processor and releasing it from reset.
+ * The handle specifies the specific Processor instance to be used.
+ *
+ * @param handle void * to the Processor object
+ * @param entryPt Entry point of the file loaded on the slave Processor
+ *
+ * @sa Processor_stop
+ */
+inline int processor_start(void *handle, u32 entry_pt,
+ struct processor_start_params *params)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ /* entryPt may be 0 for some devices. Cannot check for valid/invalid. */
+ BUG_ON(params == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.start == NULL);
+ retval = proc_handle->proc_fxn_table.start(handle, entry_pt, params);
+
+ if ((proc_handle->boot_mode == PROC_MGR_BOOTMODE_BOOT)
+ || (proc_handle->boot_mode == PROC_MGR_BOOTMODE_NOLOAD))
+ proc_handle->state = PROC_MGR_STATE_RUNNNING;
+
+ return retval;
+}
+
+
+/*
+ * Function to stop the processor.
+ *
+ * This function calls into the specific Processor implementation
+ * to stop the slave processor.
+ * This function stops the slave processor running, in most
+ * devices, by placing it in reset.
+ * The handle specifies the specific Processor instance to be used.
+ */
+inline int processor_stop(void *handle,
+ struct processor_stop_params *params)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.stop == NULL);
+
+ retval = proc_handle->proc_fxn_table.stop(handle, params);
+
+ if ((proc_handle->boot_mode == PROC_MGR_BOOTMODE_BOOT)
+ || (proc_handle->boot_mode == PROC_MGR_BOOTMODE_NOLOAD))
+ proc_handle->state = PROC_MGR_STATE_RESET;
+
+ return retval;
+}
+
+
+/*
+ * Function to read from the slave processor's memory.
+ *
+ * This function calls into the specific Processor implementation
+ * to read from the slave processor's memory. It reads from the
+ * specified address in the processor's address space and copies
+ * the required number of bytes into the specified buffer.
+ * It returns the number of bytes actually read in the num_bytes
+ * parameter.
+ * Depending on the processor implementation, it may result in
+ * reading from shared memory or across a peripheral physical
+ * connectivity.
+ * The handle specifies the specific Processor instance to be used.
+ */
+inline int processor_read(void *handle, u32 proc_addr,
+ u32 *num_bytes, void *buffer)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_addr == 0);
+ BUG_ON(num_bytes == 0);
+ BUG_ON(buffer == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.read == NULL);
+
+ retval = proc_handle->proc_fxn_table.read(handle, proc_addr,
+ num_bytes, buffer);
+ return retval;
+}
+
+
+/*
+ * Function to write into the slave processor's memory.
+ *
+ * This function calls into the specific Processor implementation
+ * to write into the slave processor's memory. It writes into the
+ * specified address in the processor's address space and copies
+ * the required number of bytes from the specified buffer.
+ * It returns the number of bytes actually written in the num_bytes
+ * parameter.
+ * Depending on the processor implementation, it may result in
+ * writing into shared memory or across a peripheral physical
+ * connectivity.
+ * The handle specifies the specific Processor instance to be used.
+ */
+inline int processor_write(void *handle, u32 proc_addr, u32 *num_bytes,
+ void *buffer)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_addr == 0);
+ BUG_ON(num_bytes == 0);
+ BUG_ON(buffer == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.write == NULL);
+
+ retval = proc_handle->proc_fxn_table.write(handle, proc_addr,
+ num_bytes, buffer);
+ return retval;
+}
+
+
+/*
+ * Function to get the current state of the slave Processor.
+ *
+ * This function gets the state of the slave processor as
+ * maintained on the master Processor state machine. It does not
+ * go to the slave processor to get its actual state at the time
+ * when this API is called.
+ */
+enum proc_mgr_state processor_get_state(void *handle)
+{
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+
+ return proc_handle->state;
+}
+
+
+/*
+ * Function to set the current state of the slave Processor
+ * to specified value.
+ *
+ * This function is used to set the state of the processor to the
+ * value as specified. This function may be used by external
+ * entities that affect the state of the slave processor, such as
+ * PwrMgr, error handler, or ProcMgr.
+ */
+void processor_set_state(void *handle, enum proc_mgr_state state)
+{
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ proc_handle->state = state;
+}
+
+
+/*
+ * Function to perform device-dependent operations.
+ *
+ * This function calls into the specific Processor implementation
+ * to perform device dependent control operations. The control
+ * operations supported by the device are exposed directly by the
+ * specific implementation of the Processor interface. These
+ * commands and their specific argument types are used with this
+ * function.
+ */
+inline int processor_control(void *handle, int cmd, void *arg)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.control == NULL);
+
+ retval = proc_handle->proc_fxn_table.control(handle, cmd, arg);
+ return retval;
+}
+
+
+/*
+ * Function to translate between two types of address spaces.
+ *
+ * This function translates addresses between two types of address
+ * spaces. The destination and source address types are indicated
+ * through parameters specified in this function.
+ */
+inline int processor_translate_addr(void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dst_addr_type, void *src_addr,
+ enum proc_mgr_addr_type src_addr_type)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(dst_addr == NULL);
+ BUG_ON(src_addr == NULL);
+ BUG_ON(dst_addr_type >= PROC_MGR_ADDRTYPE_ENDVALUE);
+ BUG_ON(src_addr_type >= PROC_MGR_ADDRTYPE_ENDVALUE);
+ BUG_ON(proc_handle->proc_fxn_table.translateAddr == NULL);
+
+ retval = proc_handle->proc_fxn_table.translateAddr(handle,
+ dst_addr, dst_addr_type, src_addr, src_addr_type);
+ return retval;
+}
+
+
+/*
+ * Function to map address to slave address space.
+ *
+ * This function maps the provided slave address to a host address
+ * and returns the mapped address and size.
+ */
+inline int processor_map(void *handle, u32 proc_addr, u32 size,
+ u32 *mapped_addr, u32 *mapped_size, u32 map_attribs)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_addr == 0);
+ BUG_ON(size == 0);
+ BUG_ON(mapped_addr == NULL);
+ BUG_ON(mapped_size == NULL);
+ BUG_ON(proc_handle->proc_fxn_table.map == NULL);
+
+ retval = proc_handle->proc_fxn_table.map(handle, proc_addr,
+ size, mapped_addr, mapped_size, map_attribs);
+ return retval;
+}
+
+/*
+ * Function to unmap address to slave address space.
+ *
+ * This function unmap the provided slave address
+ */
+inline int processor_unmap(void *handle, u32 mapped_addr)
+{
+ int retval = 0;
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+
+ retval = proc_handle->proc_fxn_table.unmap(handle, mapped_addr);
+ return retval;
+}
+
+/*
+ * Function that registers for notification when the slave
+ * processor transitions to any of the states specified.
+ *
+ * This function allows the user application to register for
+ * changes in processor state and take actions accordingly.
+
+ */
+inline int processor_register_notify(void *handle, proc_mgr_callback_fxn fxn,
+ void *args, enum proc_mgr_state state[])
+{
+ int retval = 0;
+
+ BUG_ON(handle == NULL);
+ BUG_ON(fxn == NULL);
+
+ /* TODO: TBD: To be implemented. */
+ return retval;
+}
+
+/*
+ * Function that returns the proc instance mem info
+ */
+int processor_get_proc_info(void *handle, struct proc_mgr_proc_info *procinfo)
+{
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+ int retval;
+ retval = proc_handle->proc_fxn_table.procinfo(proc_handle, procinfo);
+ return retval;
+}
+
+/*
+ * Function that returns the address translations
+ */
+int processor_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries)
+{
+ struct processor_object *proc_handle =
+ (struct processor_object *)handle;
+ int retval;
+ retval = proc_handle->proc_fxn_table.virt_to_phys(handle, da,
+ mapped_entries, num_of_entries);
+ return retval;
+}
diff --git a/drivers/dsp/syslink/procmgr/processor.h b/drivers/dsp/syslink/procmgr/processor.h
new file mode 100755
index 000000000000..b4f78581839e
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/processor.h
@@ -0,0 +1,84 @@
+/*
+ * processor.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#ifndef SYSLINK_PROCESSOR_H_
+#define SYSLINK_PROCESSOR_H_
+
+#include <linux/types.h>
+
+/* Module level headers */
+#include "procdefs.h"
+
+/* ===================================
+ * APIs
+ * ===================================
+ */
+/* Function to attach to the Processor. */
+int processor_attach(void *handle, struct processor_attach_params *params);
+
+/* Function to detach from the Processor. */
+int processor_detach(void *handle);
+
+/* Function to start the processor. */
+int processor_start(void *handle, u32 entry_pt,
+ struct processor_start_params *params);
+
+/* Function to stop the processor. */
+int processor_stop(void *handle,
+ struct processor_stop_params *params);
+
+/* Function to read from the slave processor's memory. */
+int processor_read(void *handle, u32 proc_addr, u32 *num_bytes, void *buffer);
+
+/* Function to read write into the slave processor's memory. */
+int processor_write(void *handle, u32 proc_addr, u32 *num_bytes, void *buffer);
+
+/* Function to get the current state of the slave Processor as maintained on
+ * the master Processor state machine.
+ */
+enum proc_mgr_state processor_get_state(void *handle);
+
+/* Function to set the current state of the slave Processor to specified value.
+ */
+void processor_set_state(void *handle, enum proc_mgr_state state);
+
+/* Function to perform device-dependent operations. */
+int processor_control(void *handle, int cmd, void *arg);
+
+/* Function to translate between two types of address spaces. */
+int processor_translate_addr(void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dst_addr_type, void *src_addr,
+ enum proc_mgr_addr_type src_addr_type);
+
+/* Function to map address to slave address space */
+int processor_map(void *handle, u32 proc_addr, u32 size, u32 *mapped_addr,
+ u32 *mapped_size, u32 map_attribs);
+/* Function to unmap address to slave address space */
+int processor_unmap(void *handle, u32 mapped_addr);
+
+/* Function that registers for notification when the slave processor
+ * transitions to any of the states specified.
+ */
+int processor_register_notify(void *handle, proc_mgr_callback_fxn fxn,
+ void *args, enum proc_mgr_state state[]);
+
+/* Function that returns the return value of specific processor info
+ */
+int processor_get_proc_info(void *handle, struct proc_mgr_proc_info *procinfo);
+
+int processor_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries);
+#endif
diff --git a/drivers/dsp/syslink/procmgr/procmgr.c b/drivers/dsp/syslink/procmgr/procmgr.c
new file mode 100755
index 000000000000..a7124c5b9028
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/procmgr.c
@@ -0,0 +1,957 @@
+/*
+ * procmgr.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <asm/atomic.h>
+
+/* Module level headers */
+#include <procmgr.h>
+#include "procdefs.h"
+#include "processor.h"
+#include <syslink/atomic_linux.h>
+
+/* ================================
+ * Macros and types
+ * ================================
+ */
+/*! @brief Macro to make a correct module magic number with refCount */
+#define PROCMGR_MAKE_MAGICSTAMP(x) ((PROCMGR_MODULEID << 12u) | (x))
+
+/*
+ * ProcMgr Module state object
+ */
+struct proc_mgr_module_object {
+ atomic_t ref_count;
+ u32 config_size;
+ /* Size of configuration structure */
+ struct proc_mgr_config cfg;
+ /* ProcMgr configuration structure */
+ struct proc_mgr_config def_cfg;
+ /* Default module configuration */
+ struct proc_mgr_params def_inst_params;
+ /* Default parameters for the ProcMgr instances */
+ struct proc_mgr_attach_params def_attach_params;
+ /* Default parameters for the ProcMgr attach function */
+ struct proc_mgr_start_params def_start_params;
+ /* Default parameters for the ProcMgr start function */
+ struct proc_mgr_stop_params def_stop_params;
+ /* Default parameters for the ProcMgr stop function */
+ struct mutex *gate_handle;
+ /* handle of gate to be used for local thread safety */
+ void *proc_handles[MULTIPROC_MAXPROCESSORS];
+ /* Array of handles of ProcMgr instances */
+};
+
+/*
+ * ProcMgr instance object
+ */
+struct proc_mgr_object {
+ u16 proc_id;
+ /* Processor ID associated with this ProcMgr. */
+ struct processor_object *proc_handle;
+ /* Processor ID of the processor being represented by this instance. */
+ void *loader_handle;
+ /*!< Handle to the Loader object associated with this ProcMgr. */
+ void *pwr_handle;
+ /*!< Handle to the PwrMgr object associated with this ProcMgr. */
+ /*!< Processor ID of the processor being represented by this instance */
+ struct proc_mgr_params params;
+ /* ProcMgr instance params structure */
+ struct proc_mgr_attach_params attach_params;
+ /* ProcMgr attach params structure */
+ struct proc_mgr_start_params start_params;
+ /* ProcMgr start params structure */
+ struct proc_mgr_stop_params stop_params;
+ /* ProcMgr start params structure */
+ u32 file_id;
+ /*!< File ID of the loaded static executable */
+ u16 num_mem_entries;
+ /* Number of valid memory entries */
+ struct proc_mgr_addr_info mem_entries[PROCMGR_MAX_MEMORY_REGIONS];
+ /* Configuration of memory regions */
+};
+
+struct proc_mgr_module_object proc_mgr_obj_state = {
+ .config_size = sizeof(struct proc_mgr_config),
+ .def_cfg.gate_handle = NULL,
+ .gate_handle = NULL,
+ .def_inst_params.proc_handle = NULL,
+ .def_attach_params.boot_mode = PROC_MGR_BOOTMODE_BOOT,
+ .def_start_params.proc_id = 0
+};
+
+
+/*======================================
+ * Function to get the default configuration for the ProcMgr
+ * module.
+ *
+* This function can be called by the application to get their
+* configuration parameter to ProcMgr_setup filled in by the
+* ProcMgr module with the default parameters. If the user does
+* not wish to make any change in the default parameters, this API
+* is not required to be called.
+ */
+void proc_mgr_get_config(struct proc_mgr_config *cfg)
+{
+ BUG_ON(cfg == NULL);
+ memcpy(cfg, &proc_mgr_obj_state.def_cfg,
+ sizeof(struct proc_mgr_config));
+ return;
+}
+EXPORT_SYMBOL(proc_mgr_get_config);
+
+/*
+ * Function to setup the ProcMgr module.
+ *
+ *This function sets up the ProcMgr module. This function must
+ *be called before any other instance-level APIs can be invoked.
+ *Module-level configuration needs to be provided to this
+ *function. If the user wishes to change some specific config
+ *parameters, then ProcMgr_getConfig can be called to get the
+ *configuration filled with the default values. After this, only
+ *the required configuration values can be changed. If the user
+ *does not wish to make any change in the default parameters, the
+ *application can simply call ProcMgr_setup with NULL parameters.
+ *The default parameters would get automatically used.
+ */
+int proc_mgr_setup(struct proc_mgr_config *cfg)
+{
+ int retval = 0;
+ struct proc_mgr_config tmp_cfg;
+
+ /* This sets the refCount variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of refCount variable.
+ */
+ atomic_cmpmask_and_set(&proc_mgr_obj_state.ref_count,
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&proc_mgr_obj_state.ref_count)
+ != PROCMGR_MAKE_MAGICSTAMP(1u))
+ return 0;
+ if (cfg == NULL) {
+ proc_mgr_get_config(&tmp_cfg);
+ cfg = &tmp_cfg;
+ }
+ if (cfg->gate_handle != NULL) {
+ proc_mgr_obj_state.gate_handle = cfg->gate_handle;
+ } else {
+ /* User has not provided any gate handle, so create a
+ *default handle.
+ */
+ proc_mgr_obj_state.gate_handle = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+ mutex_init(proc_mgr_obj_state.gate_handle);
+ }
+ memcpy(&proc_mgr_obj_state.cfg, cfg, sizeof(struct proc_mgr_config));
+ /* Initialize the procHandles array. */
+ memset(&proc_mgr_obj_state.proc_handles, 0,
+ (sizeof(void *) * MULTIPROC_MAXPROCESSORS));
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_setup);
+
+/*==================================
+ * Function to destroy the ProcMgr module.
+ *
+ * Once this function is called, other ProcMgr module APIs, except
+ * for the proc_mgr_get_config API cannot be called anymore.
+ */
+int proc_mgr_destroy(void)
+{
+ int retval = 0;
+ int i;
+
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_destroy: Error - module not initialized\n");
+ return -EFAULT;
+ }
+ if (atomic_dec_return(&proc_mgr_obj_state.ref_count)
+ == PROCMGR_MAKE_MAGICSTAMP(0)) {
+
+ /* Check if any ProcMgr instances have not been deleted so far
+ *. If not,delete them
+ */
+ for (i = 0 ; i < MULTIPROC_MAXPROCESSORS; i++) {
+ if (proc_mgr_obj_state.proc_handles[i] != NULL)
+ proc_mgr_delete
+ (&(proc_mgr_obj_state.proc_handles[i]));
+ }
+
+ mutex_destroy(proc_mgr_obj_state.gate_handle);
+ kfree(proc_mgr_obj_state.gate_handle);
+ /* Decrease the refCount */
+ atomic_set(&proc_mgr_obj_state.ref_count,
+ PROCMGR_MAKE_MAGICSTAMP(0));
+ }
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_destroy);
+
+/*=====================================
+ * Function to initialize the parameters for the ProcMgr instance.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to ProcMgr_create filled in by the
+ * ProcMgr module with the default parameters.
+ */
+void proc_mgr_params_init(void *handle, struct proc_mgr_params *params)
+{
+ struct proc_mgr_object *proc_handle = (struct proc_mgr_object *)handle;
+
+ if (WARN_ON(params == NULL))
+ goto exit;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_params_init: Error - module not initialized\n");
+ }
+ if (handle == NULL) {
+ memcpy(params, &(proc_mgr_obj_state.def_inst_params),
+ sizeof(struct proc_mgr_params));
+ } else {
+ /* Return updated ProcMgr instance specific parameters. */
+ memcpy(params, &(proc_handle->params),
+ sizeof(struct proc_mgr_params));
+ }
+exit:
+ return;
+}
+EXPORT_SYMBOL(proc_mgr_params_init);
+
+/*=====================================
+ * Function to create a ProcMgr object for a specific slave
+ * processor.
+ *
+ * This function creates an instance of the ProcMgr module and
+ * returns an instance handle, which is used to access the
+ * specified slave processor. The processor ID specified here is
+ * the ID of the slave processor as configured with the MultiProc
+ * module.
+ * Instance-level configuration needs to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then struct proc_mgr_params_init can be called to get the
+ * configuration filled with the default values. After this, only
+ * the required configuration values can be changed. For this
+ * API, the params argument is not optional, since the user needs
+ * to provide some essential values such as loader, PwrMgr and
+ * Processor instances to be used with this ProcMgr instance.
+ */
+void *proc_mgr_create(u16 proc_id, const struct proc_mgr_params *params)
+{
+ struct proc_mgr_object *handle = NULL;
+
+ BUG_ON(!IS_VALID_PROCID(proc_id));
+ BUG_ON(params == NULL);
+ BUG_ON(params->proc_handle == NULL);
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_create: Error - module not initialized\n");
+ return NULL;
+ }
+ if (proc_mgr_obj_state.proc_handles[proc_id] != NULL) {
+ handle = proc_mgr_obj_state.proc_handles[proc_id];
+ printk(KERN_WARNING "proc_mgr_create:"
+ "Processor already exists for specified"
+ "%d proc_id, handle = 0x%x\n", proc_id, (u32)handle);
+ return handle;
+ }
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ handle = (struct proc_mgr_object *)
+ vmalloc(sizeof(struct proc_mgr_object));
+ BUG_ON(handle == NULL);
+ memset(handle, 0, sizeof(struct proc_mgr_object));
+ memcpy(&(handle->params), params, sizeof(struct proc_mgr_params));
+ handle->proc_id = proc_id;
+ handle->proc_handle = params->proc_handle;
+ handle->loader_handle = params->loader_handle;
+ handle->pwr_handle = params->pwr_handle;
+ proc_mgr_obj_state.proc_handles[proc_id] = handle;
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return handle;
+}
+EXPORT_SYMBOL(proc_mgr_create);
+
+/*===================================
+ * Function to delete a ProcMgr object for a specific slave
+ * processor.
+ *
+ * Once this function is called, other ProcMgr instance level APIs
+ * that require the instance handle cannot be called.
+ *
+ */
+int
+proc_mgr_delete(void **handle_ptr)
+{
+ int retval = 0;
+ struct proc_mgr_object *handle;
+
+ BUG_ON(handle_ptr == NULL);
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_delete: Error - module not initialized\n");
+ return -EFAULT;
+ }
+
+ handle = (struct proc_mgr_object *)(*handle_ptr);
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ proc_mgr_obj_state.proc_handles[handle->proc_id] = NULL;
+ vfree(handle);
+ *handle_ptr = NULL;
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_delete);
+
+/*======================================
+ * Function to open a handle to an existing ProcMgr object handling
+ * the proc_id.
+ *
+ * This function returns a handle to an existing ProcMgr instance
+ * created for this proc_id. It enables other entities to access
+ * and use this ProcMgr instance.
+ */
+int proc_mgr_open(void **handle_ptr, u16 proc_id)
+{
+ int retval = 0;
+
+ BUG_ON(handle_ptr == NULL);
+ BUG_ON(!IS_VALID_PROCID(proc_id));
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_open: Error - module not initialized\n");
+ return -EFAULT;
+ }
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ *handle_ptr = proc_mgr_obj_state.proc_handles[proc_id];
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_open);
+
+/*=====================================
+ * Function to close this handle to the ProcMgr instance.
+ *
+ * This function closes the handle to the ProcMgr instance
+ * obtained through proc_mgr_open call made earlier.
+ */
+int proc_mgr_close(void *handle)
+{
+ int retval = 0;
+
+ BUG_ON(handle == NULL);
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_close: Error - module not initialized\n");
+ return -EFAULT;
+ }
+ /* Nothing to be done for closing the handle. */
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_close);
+
+/*========================================
+ * Function to initialize the parameters for the ProcMgr attach
+ * function.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to proc_mgr_attach filled in by the
+ * ProcMgr module with the default parameters. If the user does
+ * not wish to make any change in the default parameters, this API
+ * is not required to be called.
+ */
+void proc_mgr_get_attach_params(void *handle,
+ struct proc_mgr_attach_params *params)
+{
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ BUG_ON(params == NULL);
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_get_attach_params:"
+ "Error - module not initialized\n");
+ }
+ if (handle == NULL) {
+ memcpy(params, &(proc_mgr_obj_state.def_attach_params),
+ sizeof(struct proc_mgr_attach_params));
+ } else {
+ /* Return updated ProcMgr instance specific parameters. */
+ memcpy(params, &(proc_mgr_handle->attach_params),
+ sizeof(struct proc_mgr_attach_params));
+ }
+ return;
+}
+EXPORT_SYMBOL(proc_mgr_get_attach_params);
+
+/*
+ * Function to attach the client to the specified slave and also
+ * initialize the slave (if required).
+ *
+ * This function attaches to an instance of the ProcMgr module and
+ * performs any hardware initialization required to power up the
+ * slave device. This function also performs the required state
+ * transitions for this ProcMgr instance to ensure that the local
+ * object representing the slave device correctly indicates the
+ * state of the slave device. Depending on the slave boot mode
+ * being used, the slave may be powered up, in reset, or even
+ * running state.
+ * Configuration parameters need to be provided to this
+ * function. If the user wishes to change some specific config
+ * parameters, then proc_mgr_get_attach_params can be called to get
+ * the configuration filled with the default values. After this,
+ * only the required configuration values can be changed. If the
+ * user does not wish to make any change in the default parameters,
+ * the application can simply call proc_mgr_attach with NULL
+ * parameters.
+ * The default parameters would get automatically used.
+ */
+int proc_mgr_attach(void *handle, struct proc_mgr_attach_params *params)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ struct proc_mgr_attach_params tmp_params;
+ struct processor_attach_params proc_attach_params;
+
+ if (params == NULL) {
+ proc_mgr_get_attach_params(handle, &tmp_params);
+ params = &tmp_params;
+ }
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_attach:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ if (WARN_ON(handle == NULL)) {
+ retval = -EFAULT;
+ goto exit;
+ }
+ if (WARN_ON(params->boot_mode == PROC_MGR_BOOTMODE_ENDVALUE)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ /* Copy the user provided values into the instance object. */
+ memcpy(&(proc_mgr_handle->attach_params), params,
+ sizeof(struct proc_mgr_attach_params));
+ proc_attach_params.params = params;
+ proc_attach_params.num_mem_entries = 0;
+ /* Attach to the specified Processor instance. */
+ retval = processor_attach(proc_mgr_handle->proc_handle,
+ &proc_attach_params);
+ proc_mgr_handle->num_mem_entries = proc_attach_params.num_mem_entries;
+ printk(KERN_INFO "proc_mgr_attach:proc_mgr_handle->num_mem_entries = %d\n",
+ proc_mgr_handle->num_mem_entries);
+ /* Store memory information in local object.*/
+ memcpy(&(proc_mgr_handle->mem_entries),
+ &(proc_attach_params.mem_entries),
+ sizeof(proc_mgr_handle->mem_entries));
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+exit:
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_attach);
+
+/*===================================
+ * Function to detach the client from the specified slave and also
+ * finalze the slave (if required).
+ *
+ * This function detaches from an instance of the ProcMgr module
+ * and performs any hardware finalization required to power down
+ * the slave device. This function also performs the required state
+ * transitions for this ProcMgr instance to ensure that the local
+ * object representing the slave device correctly indicates the
+ * state of the slave device. Depending on the slave boot mode
+ * being used, the slave may be powered down, in reset, or left in
+ * its original state.
+*/
+int proc_mgr_detach(void *handle)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_detach:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ /* Detach from the Processor. */
+ retval = processor_detach(proc_mgr_handle->proc_handle);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_detach);
+
+/*===============================
+ * Function to initialize the parameters for the ProcMgr start
+ * function.
+ *
+ * This function can be called by the application to get their
+ * configuration parameter to proc_mgr_start filled in by the
+ * ProcMgr module with the default parameters. If the user does
+ * not wish to make any change in the default parameters, this API
+ * is not required to be called.
+ *
+ */
+void proc_mgr_get_start_params(void *handle,
+ struct proc_mgr_start_params *params)
+{
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_get_start_params:"
+ "Error - module not initialized\n");
+ }
+ BUG_ON(params == NULL);
+
+ if (handle == NULL) {
+ memcpy(params, &(proc_mgr_obj_state.def_start_params),
+ sizeof(struct proc_mgr_start_params));
+ } else {
+ /* Return updated ProcMgr instance specific parameters. */
+ memcpy(params, &(proc_mgr_handle->start_params),
+ sizeof(struct proc_mgr_start_params));
+ }
+ return;
+}
+EXPORT_SYMBOL(proc_mgr_get_start_params);
+
+/*==========================================
+ * Function to start the slave processor running.
+ *
+ * Function to start execution of the loaded code on the slave
+ * from the entry point specified in the slave executable loaded
+ * earlier by call to proc_mgr_load ().
+ * After successful completion of this function, the ProcMgr
+ * instance is expected to be in the proc_mgr_State_Running state.
+ */
+int proc_mgr_start(void *handle, u32 entry_point,
+ struct proc_mgr_start_params *params)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ struct proc_mgr_start_params tmp_params;
+ struct processor_start_params proc_params;
+
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_start:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+
+ if (params == NULL) {
+ proc_mgr_get_start_params(handle, &tmp_params);
+ params = &tmp_params;
+ }
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ memcpy(&(proc_mgr_handle->start_params), params,
+ sizeof(struct proc_mgr_start_params));
+ /* Start the slave processor running. */
+ proc_params.params = params;
+ retval = processor_start(proc_mgr_handle->proc_handle,
+ entry_point, &proc_params);
+
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_start);
+
+/*========================================
+ * Function to stop the slave processor.
+ *
+ * Function to stop execution of the slave processor.
+ * Depending on the boot mode, after successful completion of this
+ * function, the ProcMgr instance may be in the proc_mgr_State_Reset
+ * state.
+ *
+ */
+int proc_mgr_stop(void *handle, struct proc_mgr_stop_params *params)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ struct processor_stop_params proc_params;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_stop:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ proc_params.params = params;
+ retval = processor_stop(proc_mgr_handle->proc_handle,
+ &proc_params);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_stop);
+
+/*===================================
+ * Function to get the current state of the slave Processor.
+ *
+ * This function gets the state of the slave processor as
+ * maintained on the master Processor state machine. It does not
+ * go to the slave processor to get its actual state at the time
+ * when this API is called.
+ *
+ */
+enum proc_mgr_state proc_mgr_get_state(void *handle)
+{
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ enum proc_mgr_state state = PROC_MGR_STATE_UNKNOWN;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_get_state:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ state = processor_get_state(proc_mgr_handle->proc_handle);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return state;
+}
+EXPORT_SYMBOL(proc_mgr_get_state);
+
+/*==================================================
+ * Function to read from the slave processor's memory.
+ *
+ * This function reads from the specified address in the
+ * processor's address space and copies the required number of
+ * bytes into the specified buffer.
+ * It returns the number of bytes actually read in thenum_bytes
+ * parameter.
+ */
+int proc_mgr_read(void *handle, u32 proc_addr, u32 *num_bytes, void *buffer)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_read:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_addr == 0);
+ BUG_ON(num_bytes == NULL);
+ BUG_ON(buffer == NULL);
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+
+ retval = processor_read(proc_mgr_handle->proc_handle, proc_addr,
+ num_bytes, buffer);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_read);
+
+/*
+ * Function to write into the slave processor's memory.
+ *
+ * This function writes into the specified address in the
+ * processor's address space and copies the required number of
+ * bytes from the specified buffer.
+ * It returns the number of bytes actually written in thenum_bytes
+ * parameter.
+ */
+int proc_mgr_write(void *handle, u32 proc_addr, u32 *num_bytes, void *buffer)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_write:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(proc_addr == 0);
+ BUG_ON(num_bytes == NULL);
+ BUG_ON(buffer == NULL);
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ retval = processor_write(proc_mgr_handle->proc_handle, proc_addr,
+ num_bytes, buffer);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_write);
+
+
+/*===================================
+ * Function to perform device-dependent operations.
+ *
+ * This function performs control operations supported by the
+ * as exposed directly by the specific implementation of the
+ * Processor interface. These commands and their specific argument
+ * types are used with this function.
+ */
+int proc_mgr_control(void *handle, int cmd, void *arg)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle
+ = (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_control:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ /* Perform device-dependent control operation. */
+ retval = processor_control(proc_mgr_handle->proc_handle, cmd, arg);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_control);
+
+/*========================================
+ * Function to translate between two types of address spaces.
+ *
+ * This function translates addresses between two types of address
+ * spaces. The destination and source address types are indicated
+ * through parameters specified in this function.
+ */
+int proc_mgr_translate_addr(void *handle, void **dst_addr,
+ enum proc_mgr_addr_type dst_addr_type, void *src_addr,
+ enum proc_mgr_addr_type src_addr_type)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_translate_addr:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(dst_addr == NULL);
+ BUG_ON(handle == NULL);
+ BUG_ON(dst_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE);
+ BUG_ON(src_addr == NULL);
+ BUG_ON(src_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE);
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ /* Translate the address. */
+ retval = processor_translate_addr(proc_mgr_handle->proc_handle,
+ dst_addr, dst_addr_type, src_addr, src_addr_type);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_translate_addr);
+
+/*============================================
+ * Function to map address to slave address space.
+ *
+ * This function maps the provided slave address to a host address
+ * and returns the mapped address and size.
+ *
+ */
+int proc_mgr_map(void *handle, u32 proc_addr, u32 size, u32 *mapped_addr,
+ u32 *mapped_size, u32 map_attribs)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_map:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ BUG_ON(proc_addr == 0);
+ BUG_ON(mapped_addr == NULL);
+ BUG_ON(mapped_size == NULL);
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+
+ /* Map to host address space. */
+ retval = processor_map(proc_mgr_handle->proc_handle, proc_addr,
+ size, mapped_addr, mapped_size, map_attribs);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_map);
+
+/*============================================
+ * Function to unmap address to slave address space.
+ *
+ * This function unmaps the provided slave address to a host address
+ *
+ */
+int proc_mgr_unmap(void *handle, u32 mapped_addr)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_unmap:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+
+ /* Map to host address space. */
+ retval = processor_unmap(proc_mgr_handle->proc_handle, mapped_addr);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_unmap);
+
+/*=================================
+ * Function that registers for notification when the slave
+ * processor transitions to any of the states specified.
+ *
+ * This function allows the user application to register for
+ * changes in processor state and take actions accordingly.
+ *
+ */
+int proc_mgr_register_notify(void *handle, proc_mgr_callback_fxn fxn,
+ void *args, enum proc_mgr_state state[])
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle
+ = (struct proc_mgr_object *)handle;
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_register_notify:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ BUG_ON(handle == NULL);
+ BUG_ON(fxn == NULL);
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+ retval = processor_register_notify(proc_mgr_handle->proc_handle, fxn,
+ args, state);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;
+}
+EXPORT_SYMBOL(proc_mgr_register_notify);
+
+/*
+ * Function that returns information about the characteristics of
+ * the slave processor.
+ */
+int proc_mgr_get_proc_info(void *handle, struct proc_mgr_proc_info *proc_info)
+{
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+ struct processor_object *proc_handle;
+
+ struct proc_mgr_proc_info proc_info_test;
+
+ if (atomic_cmpmask_and_lt(&(proc_mgr_obj_state.ref_count),
+ PROCMGR_MAKE_MAGICSTAMP(0), PROCMGR_MAKE_MAGICSTAMP(1))
+ == true) {
+ printk(KERN_ERR "proc_mgr_get_proc_info:"
+ "Error - module not initialized\n");
+ return -EFAULT;
+ }
+ if (WARN_ON(handle == NULL))
+ goto error_exit;
+ if (WARN_ON(proc_info == NULL))
+ goto error_exit;
+ proc_handle = proc_mgr_handle->proc_handle;
+ if (WARN_ON(proc_handle == NULL))
+ goto error_exit;
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+
+ processor_get_proc_info(proc_handle, &proc_info_test);
+ /* Return bootMode information. */
+ proc_info->boot_mode = proc_mgr_handle->attach_params.boot_mode;
+ /* Return memory information. */
+ proc_info->num_mem_entries = proc_mgr_handle->num_mem_entries;
+ memcpy(&(proc_info->mem_entries),
+ &(proc_mgr_handle->mem_entries),
+ sizeof(proc_mgr_handle->mem_entries));
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return 0;
+error_exit:
+ return -EFAULT;
+}
+EXPORT_SYMBOL(proc_mgr_get_proc_info);
+
+/*============================================
+ * Function to get virtual to physical address translations
+ *
+ * This function retrieves physical entries
+ *
+ */
+int proc_mgr_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
+ u32 num_of_entries)
+{
+ int retval = 0;
+ struct proc_mgr_object *proc_mgr_handle =
+ (struct proc_mgr_object *)handle;
+
+ WARN_ON(mutex_lock_interruptible(proc_mgr_obj_state.gate_handle));
+
+ /* Map to host address space. */
+ retval = processor_virt_to_phys(proc_mgr_handle->proc_handle, da,
+ mapped_entries, num_of_entries);
+ WARN_ON(retval < 0);
+ mutex_unlock(proc_mgr_obj_state.gate_handle);
+ return retval;;
+}
+EXPORT_SYMBOL(proc_mgr_virt_to_phys);
+
diff --git a/drivers/dsp/syslink/procmgr/procmgr_drv.c b/drivers/dsp/syslink/procmgr/procmgr_drv.c
new file mode 100755
index 000000000000..d019a53cce98
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/procmgr_drv.c
@@ -0,0 +1,757 @@
+/*
+ * procmgr_drv.c
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+
+/* Module headers */
+#include <procmgr.h>
+#include "procmgr_drvdefs.h"
+
+#define PROCMGR_NAME "syslink-procmgr"
+
+static char *driver_name = PROCMGR_NAME;
+
+static s32 driver_major;
+
+static s32 driver_minor;
+
+struct procmgr_dev {
+ struct cdev cdev;
+};
+
+struct platform_device *omap_proc_dev;
+static struct platform_device *procmgr_pdev;
+static struct procmgr_dev *procmgr_device;
+
+static struct class *proc_mgr_class;
+
+
+/** ====================================
+ * Forward declarations of internal functions
+ * ====================================
+ */
+/* Linux driver function to open the driver object. */
+static int proc_mgr_drv_open(struct inode *inode, struct file *filp);
+
+/* Linux driver function to close the driver object. */
+static int proc_mgr_drv_release(struct inode *inode, struct file *filp);
+
+/* Linux driver function to invoke the APIs through ioctl. */
+static int proc_mgr_drv_ioctl(struct inode *inode,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args);
+
+/* Linux driver function to map memory regions to user space. */
+static int proc_mgr_drv_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/* Module initialization function for Linux driver. */
+static int __init proc_mgr_drv_initialize_module(void);
+
+/* Module finalization function for Linux driver. */
+static void __exit proc_mgr_drv_finalize_module(void);
+
+/* Platform driver probe function */
+static int __devinit proc_mgr_probe(struct platform_device *pdev);
+
+/* Platform driver remove function */
+static int __devexit proc_mgr_remove(struct platform_device *pdev);
+
+/*
+ * name DriverOps
+ *
+ * desc Function to invoke the APIs through ioctl
+ *
+ */
+static const struct file_operations procmgr_fops = {
+ .open = proc_mgr_drv_open,
+ .ioctl = proc_mgr_drv_ioctl,
+ .release = proc_mgr_drv_release,
+ .mmap = proc_mgr_drv_mmap,
+} ;
+
+/* Imtiaz changed places */
+static struct platform_driver procmgr_driver_ldm = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = PROCMGR_NAME,
+ },
+ .probe = proc_mgr_probe,
+ .remove = __devexit_p(proc_mgr_remove),
+ .shutdown = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+};
+
+/*
+* brief Linux specific function to open the driver.
+ */
+static int proc_mgr_drv_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/*
+* brief Linux driver function to close the driver object.
+ */
+static int proc_mgr_drv_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/*
+* Linux driver function to invoke the APIs through ioctl.
+ */
+static int proc_mgr_drv_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ int retval = 0;
+ struct proc_mgr_cmd_args *cmd_args = (struct proc_mgr_cmd_args *)args;
+ struct proc_mgr_cmd_args command_args;
+
+ switch (cmd) {
+ case CMD_PROCMGR_GETCONFIG:
+ {
+ struct proc_mgr_cmd_args_get_config *src_args =
+ (struct proc_mgr_cmd_args_get_config *)args;
+ struct proc_mgr_config cfg;
+
+ /* copy_from_user is not needed for proc_mgr_get_config,
+ * since the user's config is not used.
+ */
+ proc_mgr_get_config(&cfg);
+
+ retval = copy_to_user((void *)(src_args->cfg),
+ (const void *)&cfg,
+ sizeof(struct proc_mgr_config));
+
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_SETUP:
+ {
+ struct proc_mgr_cmd_args_setup *src_args =
+ (struct proc_mgr_cmd_args_setup *)args;
+ struct proc_mgr_config cfg;
+
+ retval = copy_from_user((void *)&cfg,
+ (const void *)(src_args->cfg),
+ sizeof(struct proc_mgr_config));
+
+ /* This check is needed at run-time also since it
+ * depends on run environment.
+ * It must not be optimized out.
+ */
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+
+ retval = proc_mgr_setup(&cfg);
+ }
+ break;
+
+ case CMD_PROCMGR_DESTROY:
+ {
+ retval = proc_mgr_destroy();
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_PARAMS_INIT:
+ {
+ struct proc_mgr_cmd_args_params_init src_args;
+ struct proc_mgr_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_params_init));
+
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+
+ proc_mgr_params_init(src_args.handle, &params);
+
+ /* Copy only the params to user-side */
+ retval = copy_to_user((void *)(src_args.params),
+ (const void *)&params,
+ sizeof(struct proc_mgr_params));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_CREATE:
+ {
+ struct proc_mgr_cmd_args_create src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_create));
+
+ src_args.handle = proc_mgr_create(src_args.proc_id,
+ &(src_args.params));
+ if (src_args.handle == NULL) {
+ retval = -EFAULT;
+ goto func_exit;
+ }
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_create));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_DELETE:
+ {
+ struct proc_mgr_cmd_args_delete src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_delete));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+
+ retval = proc_mgr_delete(&(src_args.handle));
+ }
+ break;
+
+ case CMD_PROCMGR_OPEN:
+ {
+ struct proc_mgr_cmd_args_open src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_open));
+
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_open(&(src_args.handle),
+ src_args.proc_id);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = proc_mgr_get_proc_info(src_args.handle,
+ &(src_args.proc_info));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args), (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_open));
+ WARN_ON(retval);
+ }
+ break;
+
+ case CMD_PROCMGR_CLOSE:
+ {
+ struct proc_mgr_cmd_args_close src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_close));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_close(&(src_args.handle));
+ }
+ break;
+
+ case CMD_PROCMGR_GETATTACHPARAMS:
+ {
+ struct proc_mgr_cmd_args_get_attach_params src_args;
+ struct proc_mgr_attach_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_get_attach_params));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ proc_mgr_get_attach_params(src_args.handle, &params);
+ retval = copy_to_user((void *)(src_args.params),
+ (const void *)&params,
+ sizeof(struct proc_mgr_attach_params));
+ WARN_ON(retval);
+ }
+ break;
+
+ case CMD_PROCMGR_ATTACH:
+ {
+ struct proc_mgr_cmd_args_attach src_args;
+ struct proc_mgr_attach_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_attach));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ /* Copy params from user-side. */
+ retval = copy_from_user((void *)&params,
+ (const void *)(src_args.params),
+ sizeof(struct proc_mgr_attach_params));
+ retval = proc_mgr_attach(src_args.handle, &params);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ /* Get memory information. */
+ retval = proc_mgr_get_proc_info(src_args.handle,
+ &(src_args.proc_info));
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_attach));
+ }
+ break;
+
+ case CMD_PROCMGR_DETACH:
+ {
+ struct proc_mgr_cmd_args_detach src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_detach));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_detach(src_args.handle);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ }
+ break;
+
+ case CMD_PROCMGR_GETSTARTPARAMS:
+ {
+ struct proc_mgr_cmd_args_get_start_params src_args;
+ struct proc_mgr_start_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_get_start_params));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ proc_mgr_get_start_params(src_args.handle, &params);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(src_args.params),
+ (const void *)&params,
+ sizeof(struct proc_mgr_start_params));
+ WARN_ON(retval);
+ }
+ break;
+
+ case CMD_PROCMGR_START:
+ {
+ struct proc_mgr_cmd_args_start src_args;
+ struct proc_mgr_start_params params;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_start));
+ /* Copy params from user-side. */
+ retval = copy_from_user((void *)&params,
+ (const void *)(src_args.params),
+ sizeof(struct proc_mgr_start_params));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_start(src_args.handle,
+ src_args.entry_point, &params);
+
+ WARN_ON(retval);
+ }
+ break;
+
+ case CMD_PROCMGR_STOP:
+ {
+ struct proc_mgr_cmd_args_stop src_args;
+
+ struct proc_mgr_stop_params params;
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_stop));
+ /* Copy params from user-side. */
+ retval = copy_from_user((void *)&params,
+ (const void *)(src_args.params),
+ sizeof(struct proc_mgr_stop_params));
+
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_stop(src_args.handle, &params);
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_GETSTATE:
+ {
+ struct proc_mgr_cmd_args_get_state src_args;
+ enum proc_mgr_state procmgrstate;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_get_state));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ procmgrstate = proc_mgr_get_state(src_args.handle);
+ src_args.proc_mgr_state = procmgrstate;
+ retval = copy_to_user((void *)(args), (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_get_state));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_READ:
+ {
+ struct proc_mgr_cmd_args_read src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_read));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_read(src_args.handle,
+ src_args.proc_addr, &(src_args.num_bytes),
+ src_args.buffer);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_read));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_WRITE:
+ {
+ struct proc_mgr_cmd_args_write src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_write));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_write(src_args.handle,
+ src_args.proc_addr, &(src_args.num_bytes),
+ src_args.buffer);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_write));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_CONTROL:
+ {
+ struct proc_mgr_cmd_args_control src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_control));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_control(src_args.handle,
+ src_args.cmd, src_args.arg);
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_TRANSLATEADDR:
+ {
+ struct proc_mgr_cmd_args_translate_addr src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_translate_addr));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_translate_addr(src_args.handle,
+ &(src_args.dst_addr), src_args.dst_addr_type,
+ src_args.src_addr, src_args.src_addr_type);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args, sizeof
+ (struct proc_mgr_cmd_args_translate_addr));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_MAP:
+ {
+ struct proc_mgr_cmd_args_map src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_map));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_map(src_args.handle,
+ src_args.proc_addr, src_args.size,
+ &(src_args.mapped_addr),
+ &(src_args.mapped_size),
+ src_args.map_attribs);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args),
+ (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_map));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_UNMAP:
+ {
+ struct proc_mgr_cmd_args_unmap src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_unmap));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_unmap(src_args.handle,
+ (src_args.mapped_addr));
+ WARN_ON(retval < 0);
+ }
+
+ case CMD_PROCMGR_REGISTERNOTIFY:
+ {
+ struct proc_mgr_cmd_args_register_notify src_args;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_register_notify));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_register_notify(src_args.handle,
+ src_args.callback_fxn,
+ src_args.args, src_args.state);
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_GETPROCINFO:
+ {
+ struct proc_mgr_cmd_args_get_proc_info src_args;
+ struct proc_mgr_proc_info proc_info;
+
+ /* Copy the full args from user-side. */
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_get_proc_info));
+ if (WARN_ON(retval != 0))
+ goto func_exit;
+ retval = proc_mgr_get_proc_info
+ (src_args.handle, &proc_info);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(src_args.proc_info),
+ (const void *) &proc_info,
+ sizeof(struct proc_mgr_proc_info));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ case CMD_PROCMGR_GETVIRTTOPHYS:
+ {
+ struct proc_mgr_cmd_args_get_virt_to_phys src_args;
+
+ retval = copy_from_user((void *)&src_args,
+ (const void *)(args),
+ sizeof(struct proc_mgr_cmd_args_get_virt_to_phys));
+ retval = proc_mgr_virt_to_phys(src_args.handle,
+ src_args.da, (src_args.mem_entries),
+ src_args.num_of_entries);
+ if (WARN_ON(retval < 0))
+ goto func_exit;
+ retval = copy_to_user((void *)(args), (const void *)&src_args,
+ sizeof(struct proc_mgr_cmd_args_get_virt_to_phys));
+ WARN_ON(retval < 0);
+ }
+ break;
+
+ default:
+ printk(KERN_ERR"PROC_MGR_DRV: WRONG IOCTL !!!!\n");
+ BUG_ON(1);
+ break;
+ }
+func_exit:
+ /* Set the retval and copy the common args to user-side. */
+ command_args.api_status = retval;
+ retval = copy_to_user((void *)cmd_args,
+ (const void *)&command_args, sizeof(struct proc_mgr_cmd_args));
+
+ WARN_ON(retval < 0);
+ return retval;
+}
+
+
+/*
+ Driver function to map memory regions to user space.
+ */
+static int proc_mgr_drv_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma,
+ vma->vm_start,
+ vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int __devinit proc_mgr_probe(struct platform_device *pdev)
+{
+ dev_t dev = 0 ;
+ int retval = -ENOMEM;
+
+ /* Display the version info and created date/time */
+ dev_dbg(&omap_proc_dev->dev, "Entering %s function\n\n", __func__);
+
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ retval = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ retval = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ procmgr_device = kmalloc(sizeof(struct procmgr_dev), GFP_KERNEL);
+ if (!procmgr_device) {
+ retval = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ goto exit;
+ }
+ memset(procmgr_device, 0, sizeof(struct procmgr_dev));
+ cdev_init(&procmgr_device->cdev, &procmgr_fops);
+ procmgr_device->cdev.owner = THIS_MODULE;
+ procmgr_device->cdev.ops = &procmgr_fops;
+
+ retval = cdev_add(&procmgr_device->cdev, dev, 1);
+
+ if (retval) {
+ printk(KERN_ERR "Failed to add the syslink procmgr device \n");
+ goto exit;
+ }
+
+ /* udev support */
+ proc_mgr_class = class_create(THIS_MODULE, "syslink-procmgr");
+
+ if (IS_ERR(proc_mgr_class)) {
+ printk(KERN_ERR "Error creating bridge class \n");
+ goto exit;
+ }
+ device_create(proc_mgr_class, NULL, MKDEV(driver_major, driver_minor),
+ NULL, PROCMGR_NAME);
+
+exit:
+ dev_dbg(&omap_proc_dev->dev, "Leaving %s function\n\n", __func__);
+ return retval;
+}
+
+
+static int __devexit proc_mgr_remove(struct platform_device *pdev)
+{
+ dev_t devno = 0;
+
+ dev_dbg(&omap_proc_dev->dev, "Entering %s function\n", __func__);
+ devno = MKDEV(driver_major, driver_minor);
+ if (procmgr_device) {
+ cdev_del(&procmgr_device->cdev);
+ kfree(procmgr_device);
+ }
+ unregister_chrdev_region(devno, 1);
+ if (proc_mgr_class) {
+ /* remove the device from sysfs */
+ device_destroy(proc_mgr_class, MKDEV(driver_major,
+ driver_minor));
+ class_destroy(proc_mgr_class);
+ }
+ dev_dbg(&omap_proc_dev->dev, "Entering %s function\n", __func__);
+ return 0;
+}
+
+/*
+* Module initialization function for Linux driver.
+ */
+static int __init proc_mgr_drv_initialize_module(void)
+{
+ int retval = -ENOMEM;
+
+ procmgr_pdev = platform_device_alloc(PROCMGR_NAME, -1);
+ if (!procmgr_pdev) {
+ printk(KERN_ERR "%s:device allocation failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = platform_device_add(procmgr_pdev);
+ if (retval)
+ goto err_out;
+
+ /*Saving the context for future use*/
+ omap_proc_dev = procmgr_pdev;
+
+ retval = platform_driver_register(&procmgr_driver_ldm);
+ if (!retval)
+ return retval;
+err_out:
+ platform_device_put(procmgr_pdev);
+ return retval;
+}
+
+/*
+* driver function to finalize the driver module.
+ */
+static void __exit proc_mgr_drv_finalize_module(void)
+{
+
+ dev_dbg(&omap_proc_dev->dev, "Entering %s function\n", __func__);
+ platform_device_unregister(procmgr_pdev);
+ platform_driver_unregister(&procmgr_driver_ldm);
+ dev_dbg(&omap_proc_dev->dev, "Leaving %s function\n", __func__);
+}
+
+/*
+* brief Macro calls that indicate initialization and finalization functions
+ * to the kernel.
+ */
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mugdha Kamoolkar");
+module_init(proc_mgr_drv_initialize_module);
+module_exit(proc_mgr_drv_finalize_module);
diff --git a/drivers/dsp/syslink/procmgr/procmgr_drvdefs.h b/drivers/dsp/syslink/procmgr/procmgr_drvdefs.h
new file mode 100755
index 000000000000..2be14bf7a20e
--- /dev/null
+++ b/drivers/dsp/syslink/procmgr/procmgr_drvdefs.h
@@ -0,0 +1,541 @@
+/*
+ * procmgr_drvdefs.h
+ *
+ * Syslink driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2010 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.
+ */
+
+
+#ifndef SYSLINK_PROCMGR_DRVDEFS_H
+#define SYSLINK_PROCMGR_DRVDEFS_H
+
+#include <linux/types.h>
+
+/* Module headers */
+#include <procmgr.h>
+
+
+/* =================================
+ * Macros and types
+ * =================================
+ */
+/*
+ * Base structure for ProcMgr command args. This needs to be the first
+ * field in all command args structures.
+ */
+struct proc_mgr_cmd_args {
+ int api_status;
+ /*Status of the API being called. */
+};
+
+/* --------------------------------------
+ * IOCTL command IDs for ProcMgr
+ * ---------------------------------------
+ */
+/*
+ * Base command ID for ProcMgr
+ */
+#define PROCMGR_BASE_CMD 0x100
+
+/*
+ * Command for ProcMgr_getConfig
+ */
+#define CMD_PROCMGR_GETCONFIG (PROCMGR_BASE_CMD + 1)
+
+/*
+ * Command for ProcMgr_setup
+ */
+#define CMD_PROCMGR_SETUP (PROCMGR_BASE_CMD + 2)
+
+/*
+ * Command for ProcMgr_setup
+ */
+#define CMD_PROCMGR_DESTROY (PROCMGR_BASE_CMD + 3)
+
+/*
+ * Command for ProcMgr_destroy
+ */
+#define CMD_PROCMGR_PARAMS_INIT (PROCMGR_BASE_CMD + 4)
+
+/*
+ * Command for ProcMgr_create
+ */
+#define CMD_PROCMGR_CREATE (PROCMGR_BASE_CMD + 5)
+
+/*
+ * Command for ProcMgr_delete
+ */
+#define CMD_PROCMGR_DELETE (PROCMGR_BASE_CMD + 6)
+
+/*
+ * Command for ProcMgr_open
+ */
+#define CMD_PROCMGR_OPEN (PROCMGR_BASE_CMD + 7)
+
+/*
+ * Command for ProcMgr_close
+ */
+#define CMD_PROCMGR_CLOSE (PROCMGR_BASE_CMD + 8)
+
+/*
+ * Command for ProcMgr_getAttachParams
+ */
+#define CMD_PROCMGR_GETATTACHPARAMS (PROCMGR_BASE_CMD + 9)
+
+/*
+ * Command for ProcMgr_attach
+ */
+#define CMD_PROCMGR_ATTACH (PROCMGR_BASE_CMD + 10)
+
+/*
+ * Command for ProcMgr_detach
+ */
+#define CMD_PROCMGR_DETACH (PROCMGR_BASE_CMD + 11)
+
+/*
+ * Command for ProcMgr_load
+ */
+#define CMD_PROCMGR_LOAD (PROCMGR_BASE_CMD + 12)
+
+/*
+ * Command for ProcMgr_unload
+ */
+#define CMD_PROCMGR_UNLOAD (PROCMGR_BASE_CMD + 13)
+
+/*
+ * Command for ProcMgr_getStartParams
+ */
+#define CMD_PROCMGR_GETSTARTPARAMS (PROCMGR_BASE_CMD + 14)
+
+/*
+ * Command for ProcMgr_start
+ */
+#define CMD_PROCMGR_START (PROCMGR_BASE_CMD + 15)
+
+/*
+ * Command for ProcMgr_stop
+ */
+#define CMD_PROCMGR_STOP (PROCMGR_BASE_CMD + 16)
+
+/*
+ * Command for ProcMgr_getState
+ */
+#define CMD_PROCMGR_GETSTATE (PROCMGR_BASE_CMD + 17)
+
+/*
+ * Command for ProcMgr_read
+ */
+#define CMD_PROCMGR_READ (PROCMGR_BASE_CMD + 18)
+
+/*
+ * Command for ProcMgr_write
+ */
+#define CMD_PROCMGR_WRITE (PROCMGR_BASE_CMD + 19)
+
+/*
+ * Command for ProcMgr_control
+ */
+#define CMD_PROCMGR_CONTROL (PROCMGR_BASE_CMD + 20)
+
+/*
+ * Command for ProcMgr_translateAddr
+ */
+#define CMD_PROCMGR_TRANSLATEADDR (PROCMGR_BASE_CMD + 22)
+
+/*
+ * Command for ProcMgr_getSymbolAddress
+ */
+#define CMD_PROCMGR_GETSYMBOLADDRESS (PROCMGR_BASE_CMD + 23)
+
+/*
+ * Command for ProcMgr_map
+ */
+#define CMD_PROCMGR_MAP (PROCMGR_BASE_CMD + 24)
+
+/*
+ * Command for ProcMgr_registerNotify
+ */
+#define CMD_PROCMGR_REGISTERNOTIFY (PROCMGR_BASE_CMD + 25)
+
+/*
+ * Command for ProcMgr_getProcInfo
+ */
+#define CMD_PROCMGR_GETPROCINFO (PROCMGR_BASE_CMD + 26)
+
+/*
+ * Command for ProcMgr_unmap
+ */
+#define CMD_PROCMGR_UNMAP (PROCMGR_BASE_CMD + 27)
+
+/*
+ * Command for ProcMgr_getVirtToPhysPages
+ */
+#define CMD_PROCMGR_GETVIRTTOPHYS (PROCMGR_BASE_CMD + 28)
+
+
+
+
+/* ----------------------------------------------------------------------------
+ * Command arguments for ProcMgr
+ * ----------------------------------------------------------------------------
+ */
+/*
+ * Command arguments for ProcMgr_getConfig
+ */
+struct proc_mgr_cmd_args_get_config {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ struct proc_mgr_config *cfg;
+ /*Pointer to the ProcMgr module configuration structure in which the
+ default config is to be returned. */
+};
+
+/*
+ * Command arguments for ProcMgr_setup
+ */
+struct proc_mgr_cmd_args_setup {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ struct proc_mgr_config *cfg;
+ /*Optional ProcMgr module configuration. If provided as NULL, default
+ configuration is used. */
+};
+
+/*
+ * Command arguments for ProcMgr_destroy
+ */
+struct proc_mgr_cmd_args_destroy {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+};
+
+/*
+ * Command arguments for ProcMgr_Params_init
+ */
+struct proc_mgr_cmd_args_params_init {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object. */
+ struct proc_mgr_params *params;
+ /*Pointer to the ProcMgr instance params structure in which the default
+ params is to be returned. */
+};
+
+/*
+ * Command arguments for ProcMgr_create
+ */
+struct proc_mgr_cmd_args_create {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ u16 proc_id;
+ /*Processor ID represented by this ProcMgr instance */
+ struct proc_mgr_params params;
+ /*ProcMgr instance configuration parameters. */
+ void *handle;
+ /*Handle to the created ProcMgr object */
+};
+
+/*
+ * Command arguments for ProcMgr_delete
+ */
+struct proc_mgr_cmd_args_delete{
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Pointer to Handle to the ProcMgr object */
+};
+
+/*
+ * Command arguments for ProcMgr_open
+ */
+struct proc_mgr_cmd_args_open {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ u16 proc_id;
+ /*Processor ID represented by this ProcMgr instance */
+ void *handle;
+ /*Handle to the opened ProcMgr object. */
+ struct proc_mgr_proc_info proc_info;
+ /*Processor information. */
+};
+
+/*
+ * Command arguments for ProcMgr_close
+ */
+struct proc_mgr_cmd_args_close{
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_proc_info proc_info;
+ /*Processor information. */
+};
+
+/*
+ * Command arguments for ProcMgr_getAttachParams
+ */
+struct proc_mgr_cmd_args_get_attach_params{
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object. */
+ struct proc_mgr_attach_params *params;
+ /*Pointer to the ProcMgr attach params structure in which the default
+ params is to be returned. */
+};
+
+/*
+ * Command arguments for ProcMgr_attach
+ */
+struct proc_mgr_cmd_args_attach {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object. */
+ struct proc_mgr_attach_params *params;
+ /*Optional ProcMgr attach parameters. */
+ struct proc_mgr_proc_info proc_info;
+ /*Processor information. */
+};
+
+/*
+ * Command arguments for ProcMgr_detach
+ */
+struct proc_mgr_cmd_args_detach {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_proc_info proc_info;
+ /*Processor information. */
+};
+
+
+/*
+ * Command arguments for ProcMgr_getStartParams
+ */
+struct proc_mgr_cmd_args_get_start_params {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Entry point for the image*/
+ u32 entry_point;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_start_params *params;
+ /*Pointer to the ProcMgr start params structure in which the default
+ params is to be returned. */
+};
+
+/*
+ * Command arguments for ProcMgr_start
+ */
+struct proc_mgr_cmd_args_start {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Entry point for the image*/
+ u32 entry_point;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_start_params *params;
+ /*Optional ProcMgr start parameters. */
+};
+
+/*
+ * Command arguments for ProcMgr_stop
+ */
+struct proc_mgr_cmd_args_stop {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_stop_params *params;
+ /*Optional ProcMgr stop parameters. */
+};
+
+/*
+ * Command arguments for ProcMgr_getState
+ */
+struct proc_mgr_cmd_args_get_state {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /* Handle to the ProcMgr object */
+ enum proc_mgr_state proc_mgr_state;
+ /*Current state of the ProcMgr object. */
+};
+
+/*
+ * Command arguments for ProcMgr_read
+ */
+struct proc_mgr_cmd_args_read {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ u32 proc_addr;
+ /*Address in space processor's address space of the memory region to
+ read from. */
+ u32 num_bytes;
+ /*IN/OUT parameter. As an IN-parameter, it takes in the number of bytes
+ to be read. When the function returns, this parameter contains the
+ number of bytes actually read. */
+ void *buffer;
+ /*User-provided buffer in which the slave processor's memory contents
+ are to be copied. */
+};
+
+/*
+ * Command arguments for ProcMgr_write
+ */
+struct proc_mgr_cmd_args_write {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ u32 proc_addr;
+ /*Address in space processor's address space of the memory region to
+ write into. */
+ u32 num_bytes;
+ /*IN/OUT parameter. As an IN-parameter, it takes in the number of bytes
+ to be written. When the function returns, this parameter contains the
+ number of bytes actually written. */
+ void *buffer;
+ /*User-provided buffer from which the data is to be written into the
+ slave processor's memory. */
+};
+
+/*
+ * Command arguments for ProcMgr_control
+ */
+struct proc_mgr_cmd_args_control {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ int cmd;
+ /*Device specific processor command */
+ void *arg;
+ /*Arguments specific to the type of command. */
+};
+
+/*
+ * Command arguments for ProcMgr_translateAddr
+ */
+struct proc_mgr_cmd_args_translate_addr {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ void *dst_addr;
+ /*Return parameter: Pointer to receive the translated address. */
+ enum proc_mgr_addr_type dst_addr_type;
+ /*Destination address type requested */
+ void *src_addr;
+ /*Source address in the source address space */
+ enum proc_mgr_addr_type src_addr_type;
+ /*Source address type */
+};
+
+/*
+ * Command arguments for ProcMgr_getSymbolAddress
+ */
+struct proc_mgr_cmd_args_get_symbol_address {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ u32 file_id;
+ /*ID of the file received from the load function */
+ char *symbol_name;
+ /*Name of the symbol */
+ u32 sym_value;
+ /*Return parameter: Symbol address */
+};
+
+/*
+ * Command arguments for ProcMgr_map
+ */
+struct proc_mgr_cmd_args_map {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ u32 proc_addr;
+ /*Slave address to be mapped */
+ u32 size;
+ /*Size (in bytes) of region to be mapped */
+ u32 mapped_addr;
+ /*Return parameter: Mapped address in host address space */
+ u32 mapped_size;
+ /*Return parameter: Mapped size */
+ u32 map_attribs;
+ /*Type of mapping. */
+};
+
+/*
+ * Command arguments for ProcMgr_map
+ */
+struct proc_mgr_cmd_args_unmap {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ u32 mapped_addr;
+ /* Mapped address in host address space */
+};
+
+/*
+ * Command arguments for ProcMgr_registerNotify
+ */
+struct proc_mgr_cmd_args_register_notify {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ int (*callback_fxn)(u16 proc_id, void *handle,
+ enum proc_mgr_state from_state, enum proc_mgr_state to_state);
+ /*Handling function to be registered. */
+ void *args;
+ /*Optional arguments associated with the handler fxn. */
+ enum proc_mgr_state state[];
+ /*Array of target states for which registration is required. */
+};
+
+/*
+ * Command arguments for ProcMgr_getProcInfo
+ */
+struct proc_mgr_cmd_args_get_proc_info {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ /*Handle to the ProcMgr object */
+ struct proc_mgr_proc_info *proc_info;
+ /*Pointer to the ProcInfo object to be populated. */
+};
+
+/*
+ * Command arguments for ProcMgr_virtToPhys
+ */
+struct proc_mgr_cmd_args_get_virt_to_phys {
+ struct proc_mgr_cmd_args commond_args;
+ /*Common command args */
+ void *handle;
+ u32 da;
+ /* mem entries buffer */
+ u32 *mem_entries;
+ /* number of entries */
+ u32 num_of_entries;
+};
+
+#endif
+
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index afad14792141..a93a36303e44 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -34,7 +34,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
/*
@@ -80,7 +80,7 @@ static unsigned int gpio_usage_count;
*/
static inline int gpio_twl4030_write(u8 address, u8 data)
{
- return twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+ return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
}
/*----------------------------------------------------------------------*/
@@ -117,7 +117,7 @@ static inline int gpio_twl4030_read(u8 address)
u8 data;
int ret = 0;
- ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+ ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
return (ret < 0) ? ret : data;
}
@@ -142,7 +142,7 @@ static void twl4030_led_set_value(int led, int value)
cached_leden &= ~mask;
else
cached_leden |= mask;
- status = twl4030_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+ status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
TWL4030_LED_LEDEN);
mutex_unlock(&gpio_lock);
}
@@ -223,23 +223,23 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
}
/* initialize PWM to always-drive */
- status = twl4030_i2c_write_u8(module, 0x7f,
+ status = twl_i2c_write_u8(module, 0x7f,
TWL4030_PWMx_PWMxOFF);
if (status < 0)
goto done;
- status = twl4030_i2c_write_u8(module, 0x7f,
+ status = twl_i2c_write_u8(module, 0x7f,
TWL4030_PWMx_PWMxON);
if (status < 0)
goto done;
/* init LED to not-driven (high) */
module = TWL4030_MODULE_LED;
- status = twl4030_i2c_read_u8(module, &cached_leden,
+ status = twl_i2c_read_u8(module, &cached_leden,
TWL4030_LED_LEDEN);
if (status < 0)
goto done;
cached_leden &= ~ledclr_mask;
- status = twl4030_i2c_write_u8(module, cached_leden,
+ status = twl_i2c_write_u8(module, cached_leden,
TWL4030_LED_LEDEN);
if (status < 0)
goto done;
@@ -250,7 +250,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
/* on first use, turn GPIO module "on" */
if (!gpio_usage_count) {
- struct twl4030_gpio_platform_data *pdata;
+ struct twl_gpio_platform_data *pdata;
u8 value = MASK_GPIO_CTRL_GPIO_ON;
/* optionally have the first two GPIOs switch vMMC1
@@ -370,7 +370,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
message[i] = bit_mask;
}
- return twl4030_i2c_write(TWL4030_MODULE_GPIO, message,
+ return twl_i2c_write(TWL4030_MODULE_GPIO, message,
REG_GPIOPUPDCTR1, 5);
}
@@ -387,7 +387,7 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
debounce >>= 8;
message[3] = (debounce & 0x03);
- return twl4030_i2c_write(TWL4030_MODULE_GPIO, message,
+ return twl_i2c_write(TWL4030_MODULE_GPIO, message,
REG_GPIO_DEBEN1, 3);
}
@@ -395,7 +395,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev);
static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
{
- struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct twl_gpio_platform_data *pdata = pdev->dev.platform_data;
int ret;
/* maybe setup IRQs */
@@ -462,7 +462,7 @@ no_irqs:
static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
{
- struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct twl_gpio_platform_data *pdata = pdev->dev.platform_data;
int status;
if (pdata->teardown) {
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 827da0858136..ee3e06c83b06 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -27,7 +27,6 @@
* 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/delay.h>
#include <linux/i2c.h>
@@ -48,12 +47,36 @@
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
+#define OMAP_I2C_WE_REG 0x0c
+#ifdef CONFIG_ARCH_OMAP4
+#define OMAP_I2C_REVNB_LO 0x00
+#define OMAP_I2C_REVNB_HI 0x04
+#define OMAP_I2C_IV_REG 0x34
+#define OMAP_I2C_IRQSTATUS_RAW 0x24
+#define OMAP_I2C_STAT_REG 0x28
+#define OMAP_I2C_IRQENABLE_SET 0x2C
+#define OMAP_I2C_IRQENABLE_CLR 0x30
+#define OMAP_I2C_SYSS_REG 0x90
+#define OMAP_I2C_BUF_REG 0x94
+#define OMAP_I2C_CNT_REG 0x98
+#define OMAP_I2C_DATA_REG 0x9C
+#define OMAP_I2C_SYSC_REG 0x10
+#define OMAP_I2C_CON_REG 0xA4
+#define OMAP_I2C_OA_REG 0xA8
+#define OMAP_I2C_SA_REG 0xAC
+#define OMAP_I2C_PSC_REG 0xB0
+#define OMAP_I2C_SCLL_REG 0xB4
+#define OMAP_I2C_SCLH_REG 0xB8
+#define OMAP_I2C_SYSTEST_REG 0xBC
+#define OMAP_I2C_BUFSTAT_REG 0xC0
+#define OMAP_I2C_IE_REG OMAP_I2C_IRQENABLE_SET
+#define OMAP_I2C_REV_REG OMAP_I2C_REVNB_HI
+#else
#define OMAP_I2C_REV_REG 0x00
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
@@ -67,7 +90,8 @@
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
#define OMAP_I2C_BUFSTAT_REG 0x40
-
+#define OMAP_I2C_IRQENABLE_CLR OMAP_I2C_IE_REG
+#endif
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
@@ -242,7 +266,10 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
WARN_ON(dev->idle);
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
- omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+ if (cpu_is_omap44xx())
+ omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+ else
+ omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev < OMAP_I2C_REV_2) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
@@ -282,10 +309,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
/* SYSC register is cleared by the reset; rewrite it */
if (dev->rev == OMAP_I2C_REV_ON_2430) {
-
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
SYSC_AUTOIDLE_MASK);
-
} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
u32 v;
@@ -302,6 +327,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* WFI instruction.
* REVISIT: Some wkup sources might not be needed.
*/
+ if (!cpu_is_omap44xx())
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
OMAP_I2C_WE_ALL);
@@ -331,7 +357,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
- if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
/*
* HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -345,7 +371,10 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
internal_clk = 9600;
else
internal_clk = 4000;
- fclk_rate = clk_get_rate(dev->fclk) / 1000;
+ if (cpu_is_omap44xx())
+ fclk_rate = 96000;
+ else
+ fclk_rate = clk_get_rate(dev->fclk) / 1000;
/* Compute prescaler divisor */
psc = fclk_rate / internal_clk;
@@ -718,7 +747,8 @@ complete:
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
- !cpu_is_omap34xx()) {
+ !cpu_is_omap34xx()
+ && !cpu_is_omap44xx()) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
@@ -758,7 +788,8 @@ complete:
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
- !cpu_is_omap34xx()) {
+ !cpu_is_omap34xx() &&
+ !cpu_is_omap44xx()) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
@@ -871,15 +902,20 @@ omap_i2c_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, dev);
-
- if ((r = omap_i2c_get_clocks(dev)) != 0)
- goto err_iounmap;
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx()) {
+ if ((r = omap_i2c_get_clocks(dev)) != 0)
+ goto err_iounmap;
+ }
omap_i2c_unidle(dev);
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
- if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
u16 s;
/* Set up the fifo size - Get total size */
@@ -891,8 +927,13 @@ omap_i2c_probe(struct platform_device *pdev)
* size. This is to ensure that we can handle the status on int
* call back latencies.
*/
- dev->fifo_size = (dev->fifo_size / 2);
- dev->b_hw = 1; /* Enable hardware fixes */
+ if (cpu_is_omap44xx()) {
+ dev->fifo_size = 0;
+ dev->b_hw = 0; /* Enable hardware fixes */
+ } else {
+ dev->fifo_size = (dev->fifo_size / 2);
+ dev->b_hw = 1; /* Enable hardware fixes */
+ }
}
/* reset ASAP, clearing any IRQs */
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a6b989a9dc07..630f49db3ec1 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -322,7 +322,7 @@ config KEYBOARD_SH_KEYSC
config KEYBOARD_OMAP
tristate "TI OMAP keypad support"
- depends on (ARCH_OMAP1 || ARCH_OMAP2)
+ depends on (ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP4)
help
Say Y here if you want to use the OMAP keypad.
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 87ec7b18ac69..fc96c7128172 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -44,6 +44,36 @@
#undef NEW_BOARD_LEARNING_MODE
+#define OMAP4_KBDOCP_BASE 0x4A31C000
+#define OMAP4_KBD_REVISION 0x00
+#define OMAP4_KBD_SYSCONFIG 0x10
+#define OMAP4_KBD_SYSSTATUS 0x14
+#define OMAP4_KBD_IRQSTATUS 0x18
+#define OMAP4_KBD_IRQENABLE 0x1C
+#define OMAP4_KBD_WAKEUPENABLE 0x20
+#define OMAP4_KBD_PENDING 0x24
+#define OMAP4_KBD_CTRL 0x28
+#define OMAP4_KBD_DEBOUNCINGTIME 0x2C
+#define OMAP4_KBD_LONGKEYTIME 0x30
+#define OMAP4_KBD_TIMEOUT 0x34
+#define OMAP4_KBD_STATEMACHINE 0x38
+#define OMAP4_KBD_ROWINPUTS 0x3C
+#define OMAP4_KBD_COLUMNOUTPUTS 0x40
+#define OMAP4_KBD_FULLCODE31_0 0x44
+#define OMAP4_KBD_FULLCODE63_32 0x48
+
+#define OMAP4_KBD_SYSCONFIG_SOFTRST (1 << 1)
+#define OMAP4_KBD_SYSCONFIG_ENAWKUP (1 << 2)
+#define OMAP4_KBD_IRQENABLE_EVENTEN (1 << 0)
+#define OMAP4_KBD_IRQENABLE_LONGKEY (1 << 1)
+#define OMAP4_KBD_IRQENABLE_TIMEOUTEN (1 << 2)
+#define OMAP4_KBD_CTRL_NOSOFTMODE (1 << 1)
+#define OMAP4_KBD_CTRLPTVVALUE (1 << 2)
+#define OMAP4_KBD_CTRLPTV (1 << 1)
+#define OMAP4_KBD_IRQDISABLE 0x00
+
+#define OMAP4_KBD_IRQSTATUSDISABLE 0xffff
+
static void omap_kp_tasklet(unsigned long);
static void omap_kp_timer(unsigned long);
@@ -114,6 +144,13 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
else
disable_irq(gpio_irq);
}
+ } else if (cpu_is_omap44xx()) {
+ /* disable keyboard interrupt and schedule for handling */
+ omap_writel(OMAP4_KBD_IRQDISABLE, OMAP4_KBDOCP_BASE +
+ OMAP4_KBD_IRQENABLE);
+
+ omap_writel(omap_readl(OMAP4_KBDOCP_BASE + OMAP4_KBD_IRQSTATUS),
+ OMAP4_KBDOCP_BASE + OMAP4_KBD_IRQSTATUS);
} else
/* disable keyboard interrupt and schedule for handling */
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
@@ -131,7 +168,7 @@ static void omap_kp_timer(unsigned long data)
static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
{
int col = 0;
-
+ u32 *p = (u32 *) state;
/* read the keypad status */
if (cpu_is_omap24xx()) {
/* read the keypad status */
@@ -141,6 +178,10 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
}
set_col_gpio_val(omap_kp, 0);
+ } else if (cpu_is_omap44xx()) {
+ *p = omap_readl(OMAP4_KBDOCP_BASE + OMAP4_KBD_FULLCODE31_0);
+ *(p + 1) = omap_readl(OMAP4_KBDOCP_BASE +
+ OMAP4_KBD_FULLCODE63_32);
} else {
/* disable keyboard interrupt and schedule for handling */
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
@@ -198,7 +239,12 @@ static void omap_kp_tasklet(unsigned long data)
row, (new_state[col] & (1 << row)) ?
"pressed" : "released");
#else
- key = omap_kp_find_key(col, row);
+ /* Keymappings have changed in omap4.*/
+ if (cpu_is_omap44xx())
+ key = omap_kp_find_key(row, col);
+ else
+ key = omap_kp_find_key(col, row);
+
if (key < 0) {
printk(KERN_WARNING
"omap-keypad: Spurious key event %d-%d\n",
@@ -213,8 +259,14 @@ static void omap_kp_tasklet(unsigned long data)
continue;
kp_cur_group = key & GROUP_MASK;
- input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
- new_state[col] & (1 << row));
+ if (cpu_is_omap44xx())
+ input_report_key(omap_kp_data->input,
+ key & ~GROUP_MASK, new_state[col]
+ & (1 << row));
+ else
+ input_report_key(omap_kp_data->input,
+ key & ~GROUP_MASK, new_state[col]
+ & (1 << row));
#endif
}
}
@@ -233,10 +285,18 @@ static void omap_kp_tasklet(unsigned long data)
int i;
for (i = 0; i < omap_kp_data->rows; i++)
enable_irq(gpio_to_irq(row_gpios[i]));
- } else {
- omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
- kp_cur_group = -1;
- }
+
+ } else if (cpu_is_omap44xx()) {
+ omap_writew(OMAP4_KBD_IRQENABLE_EVENTEN |
+ OMAP4_KBD_IRQENABLE_LONGKEY,
+ OMAP4_KBDOCP_BASE +
+ OMAP4_KBD_IRQENABLE);
+ kp_cur_group = -1;
+ } else {
+ omap_writew(0, OMAP_MPUIO_BASE +
+ OMAP_MPUIO_KBD_MASKIT);
+ kp_cur_group = -1;
+ }
}
}
@@ -316,7 +376,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
omap_kp->input = input_dev;
/* Disable the interrupt for the MPUIO keyboard */
- if (!cpu_is_omap24xx())
+ if (!cpu_is_omap24xx() && !cpu_is_omap44xx())
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
keymap = pdata->keymap;
@@ -390,19 +450,33 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
goto err3;
}
- if (pdata->dbounce)
- omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
-
+ if (pdata->dbounce) {
+ if (cpu_is_omap44xx())
+ omap_writew(0xff, OMAP_MPUIO_BASE +
+ OMAP4_KBD_DEBOUNCINGTIME);
+ else
+ omap_writew(0xff, OMAP_MPUIO_BASE +
+ OMAP_MPUIO_GPIO_DEBOUNCING);
+ }
/* scan current status and enable interrupt */
omap_kp_scan_keypad(omap_kp, keypad_state);
+
+ /* Configuring OMAP4 keypad registers */
+ if (cpu_is_omap44xx()) {
+ omap_writew(OMAP4_KBD_SYSCONFIG_SOFTRST |
+ OMAP4_KBD_SYSCONFIG_ENAWKUP, OMAP4_KBDOCP_BASE
+ + OMAP4_KBD_SYSCONFIG);
+ omap_writew((OMAP4_KBD_CTRLPTVVALUE << OMAP4_KBD_CTRLPTV) |
+ OMAP4_KBD_CTRL_NOSOFTMODE,
+ OMAP4_KBDOCP_BASE + OMAP4_KBD_CTRL);
+ }
if (!cpu_is_omap24xx()) {
omap_kp->irq = platform_get_irq(pdev, 0);
- if (omap_kp->irq >= 0) {
- if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
+ if (request_irq(152, omap_kp_interrupt, 0,
"omap-keypad", omap_kp) < 0)
goto err4;
- }
- omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+ if (!cpu_is_omap44xx())
+ omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
} else {
for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
if (request_irq(gpio_to_irq(row_gpios[irq_idx]),
@@ -412,6 +486,11 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
goto err5;
}
}
+ if (cpu_is_omap44xx()) {
+ omap_writew(OMAP4_KBD_IRQENABLE_EVENTEN |
+ OMAP4_KBD_IRQENABLE_LONGKEY, OMAP4_KBDOCP_BASE +
+ OMAP4_KBD_IRQENABLE);
+ }
return 0;
err5:
for (i = irq_idx - 1; i >=0; i--)
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index ba69beeb0e21..9318e73fde87 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -5,6 +5,7 @@
menuconfig MEDIA_SUPPORT
tristate "Multimedia support"
depends on HAS_IOMEM
+ default y
help
If you want to use Video for Linux, DVB for Linux, or DAB adapters,
enable this option and other options below.
@@ -19,6 +20,7 @@ comment "Multimedia core support"
config VIDEO_DEV
tristate "Video For Linux"
+ default y
---help---
V4L core support for video capture and overlay devices, webcams and
AM/FM radio cards.
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index dcf9fa9264bb..3ce58780d6df 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -718,6 +718,18 @@ config VIDEO_CAFE_CCIC
CMOS camera controller. This is the controller found on first-
generation OLPC systems.
+config VIDEO_OMAP3
+ bool "OMAP2/OMAP3/OMAP4 Camera and V4L2-DSS drivers"
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_SG
+ select OMAP2_DSS
+ depends on VIDEO_DEV && (ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4)
+ default y
+ ---help---
+ V4L2 DSS and Camera driver support for OMAP2/3/4 based boards.
+
+source "drivers/media/video/omap/Kconfig"
+
config SOC_CAMERA
tristate "SoC camera support"
depends on VIDEO_V4L2 && HAS_DMA && I2C
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 2edebf371274..ceff5fcc2e1b 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -117,6 +117,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+obj-$(CONFIG_VIDEO_OMAP3) += omap/
+
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
new file mode 100644
index 000000000000..d7293a46839e
--- /dev/null
+++ b/drivers/media/video/omap/Kconfig
@@ -0,0 +1,27 @@
+config VIDEO_OMAP_VIDEOLIB
+ tristate "OMAP Video out library"
+ depends on VIDEO_OMAP3
+ default VIDEO_OMAP3
+
+config VIDEO_OMAP_VIDEOOUT
+ tristate "OMAP Video out driver"
+ select VIDEOBUF_DMA_SG
+ select VIDEOBUF_GEN
+ depends on VIDEO_OMAP3
+ default VIDEO_OMAP3
+
+choice
+ prompt "TV Mode"
+ default NTSC_M
+
+config NTSC_M
+ bool "Use NTSC_M mode"
+ help
+ Select this option if you want NTSC_M mode on TV
+
+config PAL_BDGHI
+ bool "Use PAL_BDGHI mode"
+ help
+ Select this option if you want PAL_BDGHI mode on TV
+
+endchoice
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
new file mode 100644
index 000000000000..75e01d346c4d
--- /dev/null
+++ b/drivers/media/video/omap/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_VIDEO_OMAP_VIDEOLIB) += omap_voutlib.o
+obj-$(CONFIG_VIDEO_OMAP_VIDEOOUT) += omap_vout.o
+
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
new file mode 100644
index 000000000000..4597b7a66c4b
--- /dev/null
+++ b/drivers/media/video/omap/omap_vout.c
@@ -0,0 +1,3078 @@
+/*
+ * drivers/media/video/omap/omap_vout.c
+ *
+ * Copyright (C) 2005-2009 Texas Instruments.
+ *
+ * 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.
+ *
+ * Leveraged code from the OMAP2 camera driver
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP24xx camera controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * History:
+ * 20-APR-2006 Khasim Modified VRFB based Rotation,
+ * The image data is always read from 0 degree
+ * view and written
+ * to the virtual space of desired rotation angle
+ * 4-DEC-2006 Jian Changed to support better memory management
+ *
+ * 17-Nov-2008 Hardik Changed to used the new DSS paches by Tomi
+ * Changed driver to use video_ioctl2
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/videodev2.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/irq.h>
+
+#include <media/videobuf-dma-sg.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+
+#include <asm/processor.h>
+#include <mach/dma.h>
+#include <mach/vram.h>
+
+#ifdef CONFIG_ARCH_OMAP4 /* TODO: correct this!*/
+#include "../tiler/dmm_def.h"
+#endif
+#include <mach/vrfb.h>
+
+#define TILER_ALLOCATE_V4L2
+/* #define TILER_TEST */
+
+#ifdef TILER_TEST
+#include <linux/io.h>
+#endif
+
+#include <mach/display.h>
+#include "omap_voutlib.h"
+#include "omap_voutdef.h"
+MODULE_AUTHOR("Texas Instruments.");
+MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
+MODULE_LICENSE("GPL");
+
+#define OMAP_VIDEO1 0
+#define OMAP_VIDEO2 1
+#ifdef CONFIG_ARCH_OMAP4
+#define OMAP_VIDEO3 2
+#endif
+
+
+/* configuration macros */
+#define VOUT_NAME "omap_vout"
+
+#define QQVGA_WIDTH 160
+#define QQVGA_HEIGHT 120
+
+#ifdef CONFIG_ARCH_OMAP4
+#define NUM_OF_VIDEO_CHANNELS 3
+#else
+#define NUM_OF_VIDEO_CHANNELS 2
+#endif
+
+#define VID_MAX_WIDTH 1280 /* Largest width */
+#define VID_MAX_HEIGHT 720/* Largest height */
+
+/* Mimimum requirement is 2x2 for DSS */
+#define VID_MIN_WIDTH 2
+#define VID_MIN_HEIGHT 2
+
+/* 2048 x 2048 is max res supported by OMAP display controller */
+#define DMA_CHAN_ALLOTED 1
+#define DMA_CHAN_NOT_ALLOTED 0
+#define MAX_PIXELS_PER_LINE 2048
+#define VRFB_TX_TIMEOUT 1000
+
+/* IRQ Bits mask of DSS */
+#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
+
+static struct videobuf_queue_ops video_vbq_ops;
+
+static u32 video1_numbuffers = 3;
+static u32 video2_numbuffers = 3;
+static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+#ifdef CONFIG_ARCH_OMAP4
+static u32 video3_numbuffers = 3;
+static u32 video3_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+#endif
+static u32 vid1_static_vrfb_alloc;
+static u32 vid2_static_vrfb_alloc;
+static int debug;
+
+/* Module parameters */
+module_param(video1_numbuffers, uint, S_IRUGO);
+MODULE_PARM_DESC(video1_numbuffers, "Number of buffers to be allocated at \
+ init time for Video1 device.");
+
+module_param(video2_numbuffers, uint, S_IRUGO);
+MODULE_PARM_DESC(video2_numbuffers, "Number of buffers to be allocated at \
+ init time for Video2 device.");
+
+module_param(video1_bufsize, uint, S_IRUGO);
+MODULE_PARM_DESC(video1_bufsize, "Size of the buffer to be allocated for \
+ video1 device");
+
+module_param(video2_bufsize, uint, S_IRUGO);
+MODULE_PARM_DESC(video2_bufsize, "Size of the buffer to be allocated for \
+ video2 device");
+
+#ifdef CONFIG_ARCH_OMAP4
+module_param(video3_numbuffers, uint, S_IRUGO);
+MODULE_PARM_DESC(video3_numbuffers, "Number of buffers to be allocated at \
+ init time for Video3 device.");
+
+module_param(video3_bufsize, uint, S_IRUGO);
+MODULE_PARM_DESC(video1_bufsize, "Size of the buffer to be allocated for \
+ video3 device");
+#endif
+
+module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
+MODULE_PARM_DESC(vid1_static_vrfb_alloc, "Static allocation of the VRFB \
+ buffer for video1 device");
+
+module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
+MODULE_PARM_DESC(vid2_static_vrfb_alloc, "Static allocation of the VRFB \
+ buffer for video2 device");
+
+module_param(debug, bool, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/* Local Helper functions */
+static int omap_vout_create_video_devices(struct platform_device *pdev);
+static int omapvid_apply_changes(struct omap_vout_device *vout);
+static int omapvid_init(struct omap_vout_device *vout, u32 addr, u32 uv_addr);
+static int omapvid_setup_overlay(struct omap_vout_device *vout,
+ struct omap_overlay *ovl, int posx, int posy,
+ int outw, int outh, u32 addr, u32 uv_addr);
+static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device
+ *vout);
+static void omap_vout_isr(void *arg, unsigned int irqstatus);
+static void omap_vout_cleanup_device(struct omap_vout_device *vout);
+
+/*
+ * Maximum amount of memory to use for rendering buffers.
+ * Default is enough to four (RGB24) DVI 720P buffers.
+ */
+#define MAX_ALLOWED_VIDBUFFERS 4
+
+/* list of image formats supported by OMAP2 video pipelines */
+const static struct v4l2_fmtdesc omap_formats[] = {
+ {
+ /* Note: V4L2 defines RGB565 as:
+ *
+ * Byte 0 Byte 1
+ * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3
+ *
+ * We interpret RGB565 as:
+ *
+ * Byte 0 Byte 1
+ * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3
+ */
+ .description = "RGB565, le",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ },
+ {
+ /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use
+ * this for RGB24 unpack mode, the last 8 bits are ignored
+ * */
+ .description = "RGB32, le",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ },
+ {
+ /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use
+ * this for RGB24 packed mode
+ *
+ */
+ .description = "RGB24, le",
+ .pixelformat = V4L2_PIX_FMT_RGB24,
+ },
+ {
+ .description = "YUYV (YUV 4:2:2), packed",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ },
+ {
+ .description = "UYVY, packed",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ },
+ {
+ .description = "NV12 - YUV420 format",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ },
+
+};
+
+#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
+
+/* Allocate buffers */
+static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
+{
+ unsigned long virt_addr, addr;
+ u32 order, size;
+
+ size = PAGE_ALIGN(buf_size);
+ order = get_order(size);
+ virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
+ addr = virt_addr;
+ if (virt_addr) {
+ while (size > 0) {
+ SetPageReserved(virt_to_page(addr));
+ addr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ }
+ *phys_addr = (u32) virt_to_phys((void *) virt_addr);
+ return virt_addr;
+}
+
+/* Free buffers */
+static void omap_vout_free_buffer(unsigned long virtaddr, u32 phys_addr,
+ u32 buf_size)
+{
+ unsigned long addr = virtaddr;
+ u32 order, size;
+
+ size = PAGE_ALIGN(buf_size);
+ order = get_order(size);
+ while (size > 0) {
+ ClearPageReserved(virt_to_page(addr));
+ addr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ free_pages((unsigned long) virtaddr, order);
+}
+
+/* Function for allocating video buffers */
+static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
+ int count, int startindex)
+{
+ int i, j;
+
+ for (i = 0; i < count; i++) {
+ if (!vout->smsshado_virt_addr[i]) {
+ vout->smsshado_virt_addr[i] =
+ omap_vout_alloc_buffer(vout->smsshado_size,
+ &vout->smsshado_phy_addr[i]);
+ }
+ if (!vout->smsshado_virt_addr[i] && startindex != -1) {
+ if (V4L2_MEMORY_MMAP == vout->memory
+ && i >= startindex)
+ break;
+ }
+ if (!vout->smsshado_virt_addr[i]) {
+ for (j = 0; j < i; j++) {
+ omap_vout_free_buffer(
+ vout->smsshado_virt_addr[j],
+ vout->smsshado_phy_addr[j],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[j] = 0;
+ vout->smsshado_phy_addr[j] = 0;
+ }
+ count = 0;
+ return -ENOMEM;
+ }
+ memset((void *) vout->smsshado_virt_addr[i], 0,
+ vout->smsshado_size);
+ }
+ return 0;
+}
+
+/* Try format */
+static int omap_vout_try_format(struct v4l2_pix_format *pix)
+{
+ int ifmt, bpp = 0;
+
+ pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
+ (u32)VID_MAX_HEIGHT);
+ pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
+
+ for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
+ if (pix->pixelformat == omap_formats[ifmt].pixelformat)
+ break;
+ }
+
+ if (ifmt == NUM_OUTPUT_FORMATS)
+ ifmt = 0;
+
+ pix->pixelformat = omap_formats[ifmt].pixelformat;
+ pix->field = V4L2_FIELD_ANY;
+ pix->priv = 0;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ default:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ bpp = YUYV_BPP;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ bpp = RGB565_BPP;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ bpp = RGB24_BPP;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ bpp = RGB32_BPP;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ bpp = 3/2; /* TODO: check this? */
+ break;
+ }
+ if (V4L2_PIX_FMT_NV12 == pix->pixelformat)
+ pix->bytesperline = pix->width * 3/2;
+ else
+ pix->bytesperline = pix->width * bpp;
+
+ pix->sizeimage = pix->bytesperline * pix->height;
+
+ return bpp;
+}
+
+/*
+ * omap_vout_uservirt_to_phys: This inline function is used to convert user
+ * space virtual address to physical address.
+ */
+static inline u32 omap_vout_uservirt_to_phys(u32 virtp)
+{
+ unsigned long physp = 0;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+
+ vma = find_vma(mm, virtp);
+ /* For kernel direct-mapped memory, take the easy way */
+ if (virtp >= PAGE_OFFSET) {
+ physp = virt_to_phys((void *) virtp);
+ } else if ((vma) && (vma->vm_flags & VM_IO)
+ && (vma->vm_pgoff)) {
+ /* this will catch, kernel-allocated,
+ mmaped-to-usermode addresses */
+ physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+ } else {
+ /* otherwise, use get_user_pages() for general userland pages */
+ int res, nr_pages = 1;
+ struct page *pages;
+ down_read(&current->mm->mmap_sem);
+
+ res = get_user_pages(current, current->mm, virtp, nr_pages,
+ 1, 0, &pages, NULL);
+ up_read(&current->mm->mmap_sem);
+
+ if (res == nr_pages) {
+ physp = __pa(page_address(&pages[0]) +
+ (virtp & ~PAGE_MASK));
+ } else {
+ printk(KERN_WARNING VOUT_NAME
+ "omap_vout_uservirt_to_phys:\
+ get_user_pages failed\n");
+ return 0;
+ }
+ }
+
+ return physp;
+}
+
+/* This functions wakes up the application once
+ * the DMA transfer to VRFB space is completed. */
+static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+ struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
+
+ t->tx_status = 1;
+ wake_up_interruptible(&t->wait);
+}
+
+/* Release the VRFB context once the module exits */
+static void omap_vout_release_vrfb(struct omap_vout_device *vout)
+{
+#ifndef CONFIG_ARCH_OMAP4
+/* TODO: this is temporary disabling of vrfb to test V4L2: needs to be
+ corrected for future
+*/
+ int i;
+ for (i = 0; i < 4; i++)
+ omap_vrfb_release_ctx(&vout->vrfb_context[i]);
+#endif
+ if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+ omap_free_dma(vout->vrfb_dma_tx.dma_ch);
+ }
+
+}
+
+/* Return true if rotation is 90 or 270 */
+static inline int rotate_90_or_270(struct omap_vout_device *vout)
+{
+ return (vout->rotation == dss_rotation_90_degree ||
+ vout->rotation == dss_rotation_270_degree);
+}
+
+/* Return true if rotation is enabled */
+static inline int rotation_enabled(struct omap_vout_device *vout)
+{
+ return vout->rotation || vout->mirror;
+}
+
+/* Reverse the rotation degree if mirroring is enabled */
+static inline int calc_rotation(struct omap_vout_device *vout)
+{
+#ifndef CONFIG_ARCH_OMAP4
+ if (!vout->mirror)
+ return vout->rotation;
+ switch (vout->rotation) {
+ case dss_rotation_90_degree:
+ return dss_rotation_270_degree;
+ case dss_rotation_270_degree:
+ return dss_rotation_90_degree;
+ case dss_rotation_180_degree:
+ return dss_rotation_0_degree;
+ default:
+ return dss_rotation_180_degree;
+ }
+#else
+ return vout->rotation;
+#endif
+}
+
+/* Free the V4L2 buffers */
+static void omap_vout_free_buffers(struct omap_vout_device *vout)
+{
+ int i, numbuffers;
+
+ /* Allocate memory for the buffes */
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_VIDEO3 == vout->vid) {
+ numbuffers = video3_numbuffers;
+ vout->buffer_size = video3_bufsize;
+ } else
+#endif
+ {
+ numbuffers = (vout->vid) ? video2_numbuffers
+ : video1_numbuffers;
+ vout->buffer_size = (vout->vid) ? video2_bufsize
+ : video1_bufsize;
+ }
+ for (i = 0; i < numbuffers; i++) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i], vout->buffer_size);
+ vout->buf_phy_addr[i] = 0;
+ vout->buf_virt_addr[i] = 0;
+ }
+}
+
+/* Free VRFB buffers */
+static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
+{
+ int j;
+
+ for (j = 0; j < 4; j++) {
+ omap_vout_free_buffer(vout->smsshado_virt_addr[j],
+ vout->smsshado_phy_addr[j],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[j] = 0;
+ vout->smsshado_phy_addr[j] = 0;
+ }
+}
+
+/* Allocate the buffers for the VRFB space. Data is copied from V4L2
+ * buffers to the VRFB buffers using the DMA engine.*/
+static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
+ unsigned int *count, unsigned int startindex)
+{
+ int i;
+
+ /* Allocate the VRFB buffers only if the buffers are not
+ * allocated during init time.
+ */
+ if ((rotation_enabled(vout)) &&
+ !vout->vrfb_static_allocation)
+ if (omap_vout_allocate_vrfb_buffers(vout, *count, startindex))
+ return -ENOMEM;
+
+#ifndef CONFIG_ARCH_OMAP4
+/* TODO: this is temporary disabling of vrfb to test V4L2: needs to be
+ corrected for future
+*/
+ for (i = 0; i < *count; i++) {
+ omap_vrfb_setup(&vout->vrfb_context[i],
+ vout->smsshado_phy_addr[i],
+ vout->pix.width, vout->pix.height,
+ vout->dss_mode);
+ }
+#endif
+ return 0;
+}
+
+/* Allocate the buffers for TILER space. Ideally, the buffers will be ONLY
+ in tiler space, with different rotated views available by just a convert.
+ */
+static int omap_vout_tiler_buffer_setup(struct omap_vout_device *vout,
+ unsigned int *count, unsigned int startindex)
+{
+ int i, j;
+ enum tiler_fmt fmt;
+
+ printk(KERN_INFO VOUT_NAME "tiler buffer setup:\n");
+ printk(KERN_INFO VOUT_NAME "count - %d, start -%d :\n",
+ *count, startindex);
+
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode)
+ fmt = TILFMT_8BIT; /* Y-buffer*/
+ else {
+ switch (vout->bpp) {
+ case 1:
+ fmt = TILFMT_8BIT;
+ break;
+ case 2:
+ fmt = TILFMT_16BIT;
+ break;
+ case 3:
+ case 4:
+ fmt = TILFMT_32BIT;
+ break;
+ default:
+ return -ENOMEM;
+ }
+ }
+
+ for (i = 0; i < *count; i++) {
+ if (!vout->buf_phy_addr[i]) {
+
+ if (DMM_NO_ERROR != tiler_alloc_buf(fmt,
+ vout->pix.width, vout->pix.height,
+ &vout->buf_phy_addr[i])) {
+ vout->buf_phy_addr[i] = 0;
+ } else
+ printk(KERN_INFO VOUT_NAME
+ " tiler buffer[%d] = 0x%lx\n", i,
+ vout->buf_phy_addr[i]);
+
+ }
+
+ if (!vout->buf_phy_addr[i] && startindex != -1) {
+ if (V4L2_MEMORY_MMAP == vout->memory
+ && i >= startindex)
+ break; /* TODO: check this logic */
+ }
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ if (!vout->buf_phy_uv_addr[i]) { /* UV-buffer */
+ if (DMM_NO_ERROR !=
+ tiler_alloc_buf(TILFMT_16BIT,
+ vout->pix.width, (vout->pix.height / 2),
+ &vout->buf_phy_uv_addr[i])) {
+ vout->buf_phy_uv_addr[i] = 0;
+ } else
+ printk(KERN_INFO VOUT_NAME
+ " tiler uv buffer[%d] = 0x%lx\n", i,
+ vout->buf_phy_uv_addr[i]);
+ }
+
+ /* if either Y- UV- buffer is not allocated,
+ free all allocated buffers */
+ if (!vout->buf_phy_addr[i] ||
+ !vout->buf_phy_uv_addr[i]) {
+ for (j = 0; j < i; j++) {
+ tiler_free_buf(vout->buf_phy_addr[j]);
+ tiler_free_buf(
+ vout->buf_phy_uv_addr[j]);
+ vout->buf_phy_addr[j] = 0;
+ vout->buf_phy_uv_addr[j] = 0;
+ }
+ *count = 0;
+ return -ENOMEM;
+ }
+ }
+
+ if (!vout->buf_phy_addr[i]) {
+ for (j = 0; j < i; j++) {
+ tiler_free_buf(vout->buf_phy_addr[j]);
+ vout->buf_phy_addr[j] = 0;
+ }
+ *count = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+/* Free tiler buffers */
+static void omap_vout_free_tiler_buffers(struct omap_vout_device *vout)
+{
+ int j;
+
+ for (j = 0; j < vout->buffer_allocated; j++) {
+ tiler_free_buf(vout->buf_phy_addr[j]);
+ tiler_free_buf(vout->buf_phy_uv_addr[j]);
+ vout->buf_phy_addr[j] = 0;
+ }
+ vout->buffer_allocated = 0;
+}
+
+
+/* Convert V4L2 rotation to DSS rotation
+ * V4L2 understand 0, 90, 180, 270.
+ * convert to 0, 1, 2 and 3 repsectively for DSS */
+static int v4l2_rot_to_dss_rot(int v4l2_rotation, enum dss_rotation *rotation,
+ bool mirror)
+{
+ switch (v4l2_rotation) {
+ case 90:
+ *rotation = dss_rotation_90_degree;
+ return 0;
+ case 180:
+ *rotation = dss_rotation_180_degree;
+ return 0;
+ case 270:
+ *rotation = dss_rotation_270_degree;
+ return 0;
+ case 0:
+ *rotation = dss_rotation_0_degree;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+}
+
+/* Calculate the buffer offsets from which the streaming should
+ * start. This offset calculation is mainly required because of
+ * the VRFB 32 pixels alignment with rotation.
+ */
+static int omap_vout_calculate_offset(struct omap_vout_device *vout)
+{
+ struct v4l2_pix_format *pix = &(vout->pix);
+ struct v4l2_rect *crop = &(vout->crop);
+ enum dss_rotation rotation;
+ bool mirroring = vout->mirror;
+ int vr_ps = 1, ps = 2, temp_ps = 2;
+ int offset = 0, ctop = 0, cleft = 0, line_length = 0;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_dss_device *cur_display;
+ int *cropped_offset = &(vout->cropped_offset);
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+ /* get the display device attached to the overlay */
+ if (!ovl->manager || !ovl->manager->device)
+ return -1;
+ cur_display = ovl->manager->device;
+
+ rotation = calc_rotation(vout);
+
+ if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
+ V4L2_PIX_FMT_UYVY == pix->pixelformat) {
+ if (rotation_enabled(vout)) {
+ /*
+ * ps - Actual pixel size for YUYV/UYVY for
+ * VRFB/Mirroring is 4 bytes
+ * vr_ps - Virtually pixel size for YUYV/UYVY is
+ * 2 bytes
+ */
+ ps = 4;
+ vr_ps = 2;
+ } else {
+ ps = 2; /* otherwise the pixel size is 2 byte */
+ }
+ } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
+ ps = 4;
+ } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
+ ps = 3;
+ }
+ vout->ps = ps;
+ vout->vr_ps = vr_ps;
+ if (rotation_enabled(vout)) {
+ line_length = MAX_PIXELS_PER_LINE;
+ ctop = (pix->height - crop->height) - crop->top;
+ cleft = (pix->width - crop->width) - crop->left;
+ } else {
+ line_length = pix->width;
+ }
+ vout->line_length = line_length;
+#ifndef CONFIG_ARCH_OMAP4
+ switch (rotation) {
+ case dss_rotation_90_degree:
+ offset = vout->vrfb_context[0].yoffset *
+ vout->vrfb_context[0].bytespp;
+ temp_ps = ps / vr_ps;
+ if (mirroring == 0) {
+ *cropped_offset = offset + line_length *
+ temp_ps * cleft + crop->top * temp_ps;
+ } else {
+ *cropped_offset = offset + line_length * temp_ps *
+ cleft + crop->top * temp_ps + (line_length *
+ ((crop->width / (vr_ps)) - 1) * ps);
+ }
+ break;
+ case dss_rotation_180_degree:
+ offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
+ vout->vrfb_context[0].bytespp) +
+ (vout->vrfb_context[0].xoffset *
+ vout->vrfb_context[0].bytespp));
+ if (mirroring == 0) {
+ *cropped_offset = offset + (line_length * ps * ctop) +
+ (cleft / vr_ps) * ps;
+
+ } else {
+ *cropped_offset = offset + (line_length * ps * ctop) +
+ (cleft / vr_ps) * ps + (line_length *
+ (crop->height - 1) * ps);
+ }
+ break;
+ case dss_rotation_270_degree:
+ offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
+ vout->vrfb_context[0].bytespp;
+ temp_ps = ps / vr_ps;
+ if (mirroring == 0) {
+ *cropped_offset = offset + line_length *
+ temp_ps * crop->left + ctop * ps;
+ } else {
+ *cropped_offset = offset + line_length *
+ temp_ps * crop->left + ctop * ps +
+ (line_length * ((crop->width / vr_ps) - 1) *
+ ps);
+ }
+ break;
+ case dss_rotation_0_degree:
+ if (mirroring == 0) {
+ *cropped_offset = (line_length * ps) *
+ crop->top + (crop->left / vr_ps) * ps;
+ } else {
+ *cropped_offset = (line_length * ps) *
+ crop->top + (crop->left / vr_ps) * ps +
+ (line_length * (crop->height - 1) * ps);
+ }
+ break;
+ default:
+ *cropped_offset = (line_length * ps * crop->top) /
+ vr_ps + (crop->left * ps) / vr_ps +
+ ((crop->width / vr_ps) - 1) * ps;
+ break;
+ }
+#endif
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "%s Offset:%x\n", __func__, *cropped_offset);
+ return 0;
+}
+
+/* Initialize the overlay structure */
+int omapvid_init(struct omap_vout_device *vout, u32 addr, u32 uv_addr)
+{
+ int r = 0;
+ struct omapvideo_info *ovid = &(vout->vid_info);
+ struct omap_overlay *ovl;
+ int posx, posy;
+ int outw, outh, temp, rotation;
+ int i;
+ struct v4l2_window *win;
+ struct omap_video_timings *timing;
+
+ win = &vout->win;
+ rotation = vout->rotation;
+ for (i = 0; i < ovid->num_overlays; i++) {
+ ovl = ovid->overlays[i];
+ if (!ovl->manager || !ovl->manager->device)
+ return -EINVAL;
+
+ timing = &ovl->manager->device->panel.timings;
+
+ outw = win->w.width;
+ outh = win->w.height;
+ switch (rotation) {
+
+ case dss_rotation_90_degree:
+ /* Invert the height and widht for 90
+ * and 270 degree rotation
+ */
+ temp = outw;
+ outw = outh;
+ outh = temp;
+ posy = (timing->y_res - win->w.width)-
+ win->w.left;
+ posx = win->w.top;
+ break;
+
+ case dss_rotation_180_degree:
+ posx = (timing->x_res - win->w.width) -
+ win->w.left;
+ posy = (timing->y_res - win->w.height) -
+ win->w.top;
+ break;
+
+ case dss_rotation_270_degree:
+ temp = outw;
+ outw = outh;
+ outh = temp;
+ posy = win->w.left;
+ posx = (timing->x_res - win->w.height)
+ - win->w.top;
+ break;
+
+ default:
+ posx = win->w.left;
+ posy = win->w.top;
+ break;
+ }
+
+ r = omapvid_setup_overlay(vout, ovl, posx, posy, outw,
+ outh, addr, uv_addr);
+ if (r)
+ goto err;
+ }
+ return 0;
+err:
+ printk(KERN_WARNING VOUT_NAME "apply_changes failed\n");
+ return r;
+}
+
+/* Apply the changes set the go bit of DSS */
+int omapvid_apply_changes(struct omap_vout_device *vout)
+{
+ struct omapvideo_info *ovid = &(vout->vid_info);
+ struct omap_overlay *ovl;
+ int i;
+
+ for (i = 0; i < ovid->num_overlays; i++) {
+ ovl = ovid->overlays[i];
+ if (!ovl->manager || !ovl->manager->device)
+ return -EINVAL;
+ ovl->manager->apply(ovl->manager);
+ }
+ return 0;
+
+}
+
+/* helper function: for NV12, returns uv buffer address given single buffer
+ * for yuv - y buffer will still be in the input.
+ * used only for non-TILER case
+*/
+u32 omapvid_get_uvbase_nv12(u32 paddr, int height, int width)
+{
+ u32 puv_addr = 0;
+
+ puv_addr = (paddr + (height * width));
+ return puv_addr;
+}
+
+/* Setup the overlay */
+int omapvid_setup_overlay(struct omap_vout_device *vout,
+ struct omap_overlay *ovl, int posx, int posy, int outw,
+ int outh, u32 addr, u32 uv_addr)
+{
+ int r = 0;
+ enum dss_rotation rotation;
+ bool mirror;
+ int cropheight, cropwidth, pixheight, pixwidth;
+ struct omap_overlay_info info;
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
+ (outw != vout->pix.width || outh != vout->pix.height)) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ vout->dss_mode = video_mode_to_dss_mode(vout);
+
+ if (vout->dss_mode == -EINVAL) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ rotation = vout->rotation;
+ mirror = vout->mirror;
+
+ /* Setup the input plane parameters according to
+ * rotation value selected.
+ */
+ if (rotate_90_or_270(vout)) {
+ cropheight = vout->crop.width;
+ cropwidth = vout->crop.height;
+ pixheight = vout->pix.width;
+ pixwidth = vout->pix.height;
+ } else {
+ cropheight = vout->crop.height;
+ cropwidth = vout->crop.width;
+ pixheight = vout->pix.height;
+ pixwidth = vout->pix.width;
+ }
+
+ ovl->get_overlay_info(ovl, &info);
+ info.paddr = addr;
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode)
+ info.p_uv_addr = uv_addr;
+ else
+ info.p_uv_addr = NULL;
+#endif
+ info.vaddr = NULL;
+ info.width = cropwidth;
+ info.height = cropheight;
+ info.color_mode = vout->dss_mode;
+ info.mirror = mirror;
+ info.pos_x = posx;
+ info.pos_y = posy;
+ info.out_width = outw;
+ info.out_height = outh;
+ info.global_alpha = vout->win.global_alpha;
+ if (!rotation_enabled(vout)) {
+ info.rotation = 0;
+ info.rotation_type = OMAP_DSS_ROT_DMA;
+ info.screen_width = pixwidth;
+ } else {
+ info.rotation = vout->rotation;
+#ifdef CONFIG_ARCH_OMAP4
+ info.rotation_type = OMAP_DSS_ROT_TILER;
+ info.screen_width = pixwidth;
+#else
+ info.rotation_type = OMAP_DSS_ROT_VRFB;
+ info.screen_width = 2048;
+#endif
+ }
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "%s info.enable=%d info.addr=%x info.width=%d\n info.height=%d \
+ info.color_mode=%d info.rotation=%d info.mirror=%d\n \
+ info.posx=%d info.posy=%d info.out_width = %d info.out_height=%d\n \
+ info.rotation_type=%d info.screen_width=%d\n", __func__, info.enabled,
+ info.paddr, info.width, info.height, info.color_mode, info.rotation,
+ info.mirror, info.pos_x, info.pos_y, info.out_width, info.out_height,
+ info.rotation_type, info.screen_width);
+
+#ifdef CONFIG_ARCH_OMAP4
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "info.puvaddr=%x\n",
+ info.p_uv_addr);
+#endif
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ goto err;
+
+ return 0;
+err:
+ printk(KERN_WARNING VOUT_NAME "setup_overlay failed\n");
+ return r;
+}
+
+/* convert V4L2 pixel format to DSS pixel format */
+static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device
+ *vout)
+{
+ struct v4l2_pix_format *pix = &vout->pix;
+
+ switch (pix->pixelformat) {
+#ifdef CONFIG_ARCH_OMAP4
+ case V4L2_PIX_FMT_NV12:
+ return OMAP_DSS_COLOR_NV12;
+#endif
+ case 0:
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ return OMAP_DSS_COLOR_YUV2;
+
+ case V4L2_PIX_FMT_UYVY:
+ return OMAP_DSS_COLOR_UYVY;
+
+ case V4L2_PIX_FMT_RGB565:
+ return OMAP_DSS_COLOR_RGB16;
+
+ case V4L2_PIX_FMT_RGB24:
+ return OMAP_DSS_COLOR_RGB24P;
+
+ case V4L2_PIX_FMT_RGB32: /* TODO: OMAP4: check this ??*/
+ return (vout->vid == OMAP_VIDEO1) ?
+ OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
+ case V4L2_PIX_FMT_BGR32:
+ return OMAP_DSS_COLOR_RGBX32;
+
+ default:
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+/* Video buffer call backs */
+
+/* Buffer setup function is called by videobuf layer when REQBUF ioctl is
+ * called. This is used to setup buffers and return size and count of
+ * buffers allocated. After the call to this buffer, videobuf layer will
+ * setup buffer queue depending on the size and count of buffers
+ */
+static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size)
+{
+ struct omap_vout_device *vout = q->priv_data;
+ int startindex = 0, i, j;
+ u32 phy_addr = 0, virt_addr = 0;
+
+ if (!vout)
+ return -EINVAL;
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
+ return -EINVAL;
+
+#ifndef TILER_ALLOCATE_V4L2
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_VIDEO3 == vout->vid)
+ startindex = video3_numbuffers;
+ else
+#endif
+ startindex = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+
+ if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
+ *count = startindex;
+
+#ifndef CONFIG_ARCH_OMAP4
+ if ((rotation_enabled(vout))
+ && *count > 4)
+ *count = 4;
+
+ /* If rotation is enabled, allocate memory for VRFB space also */
+ if (rotation_enabled(vout)) {
+ if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
+ return -ENOMEM;
+ }
+
+ /* Now allocated the V4L2 buffers */
+ *size = vout->buffer_size;
+
+ startindex = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+ for (i = startindex; i < *count; i++) {
+ vout->buffer_size = *size;
+
+ virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
+ &phy_addr);
+ if (!virt_addr) {
+ printk(KERN_WARNING VOUT_NAME
+ "Memory not available: virt address "
+ "problem in buffer setup\n");
+ if (!rotation_enabled(vout))
+ break;
+ /* Free the VRFB buffers if no space for V4L2 buffers */
+ for (j = i; j < *count; j++) {
+ omap_vout_free_buffer(
+ vout->smsshado_virt_addr[j],
+ vout->smsshado_phy_addr[j],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[j] = 0;
+ vout->smsshado_phy_addr[j] = 0;
+ }
+ }
+ vout->buf_virt_addr[i] = virt_addr;
+ vout->buf_phy_addr[i] = phy_addr;
+ }
+ *count = vout->buffer_allocated = i;
+#endif /* CONFIG_ARCH_OMAP4 */
+
+#else /* TILER_ALLOCATE_V4L2 */
+
+ /* tiler_alloc_buf to be called here
+ pre-requisites: rotation, format?
+ based on that buffers will be allocated.
+ */
+ /* Now allocated the V4L2 buffers */
+ /* i is the block-width - either 4K or 8K, depending upon input width*/
+ i = (vout->pix.width +
+ TILER_PAGESIZE - 1) & ~(TILER_PAGESIZE - 1);
+
+ /* for NV12 format, buffer is height + height / 2*/
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode)
+ *size = vout->buffer_size = (vout->pix.height * 3/2 * i);
+ else
+ *size = vout->buffer_size = (vout->pix.height * i);
+
+ printk(KERN_INFO "\nheight=%d, size = %d, vout->buffer_sz=%d\n",
+ vout->pix.height, *size, vout->buffer_size);
+ if (omap_vout_tiler_buffer_setup(vout, count, 0))
+ return -ENOMEM;
+#endif /* TILER_ALLOCATE_V4L2 */
+
+ if (V4L2_MEMORY_MMAP != vout->memory)
+ return 0;
+
+ return 0;
+}
+
+/* Free the V4L2 buffers additionally allocated than default
+ * number of buffers and free all the VRFB buffers */
+static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
+{
+ int num_buffers = 0, i;
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_VIDEO3 == vout->vid)
+ num_buffers = video3_numbuffers;
+ else
+#endif
+ num_buffers = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+ for (i = num_buffers; i < vout->buffer_allocated; i++) {
+ if (vout->buf_virt_addr[i]) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i], vout->buffer_size);
+ }
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+ /* Free the VRFB buffers only if they are allocated
+ * during reqbufs. Don't free if init time allocated
+ */
+ if (!vout->vrfb_static_allocation) {
+ for (i = 0; i < 4; i++) {
+ if (vout->smsshado_virt_addr[i]) {
+ omap_vout_free_buffer(
+ vout->smsshado_virt_addr[i],
+ vout->smsshado_phy_addr[i],
+ vout->smsshado_size);
+ vout->smsshado_virt_addr[i] = 0;
+ vout->smsshado_phy_addr[i] = 0;
+ }
+ }
+ }
+ vout->buffer_allocated = num_buffers;
+}
+
+/* This function will be called when VIDIOC_QBUF ioctl is called.
+ * It prepare buffers before give out for the display. This function
+ * user space virtual address into physical address if userptr memory
+ * exchange mechanism is used. If rotation is enabled, it copies entire
+ * buffer into VRFB memory space before giving it to the DSS.
+ */
+static int omap_vout_buffer_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct omap_vout_device *vout = q->priv_data;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+#ifdef TILER_TEST
+ int i, j;
+ void __iomem *pMemoryLCD;
+ unsigned short uReadWord;
+ static unsigned uWriteWord = 0x001f;
+#endif
+
+#ifndef CONFIG_ARCH_OMAP4
+ u32 dest_frame_index = 0, src_element_index = 0;
+ u32 dest_element_index = 0, src_frame_index = 0;
+ u32 elem_count = 0, frame_count = 0, pixsize = 2;
+ enum dss_rotation rotation;
+ struct vid_vrfb_dma *tx;
+#endif
+ if (VIDEOBUF_NEEDS_INIT == vb->state) {
+ vb->width = vout->pix.width;
+ vb->height = vout->pix.height;
+ vb->size = vb->width * vb->height * vout->bpp;
+ vb->field = field;
+ }
+ vb->state = VIDEOBUF_PREPARED;
+
+#ifndef TILER_ALLOCATE_V4L2
+ /* if user pointer memory mechanism is used, get the physical
+ * address of the buffer
+ */
+ if (V4L2_MEMORY_USERPTR == vb->memory) {
+ if (0 == vb->baddr)
+ return -EINVAL;
+ /* Virtual address */
+ /* priv points to struct videobuf_pci_sg_memory. But we went
+ * pointer to videobuf_dmabuf, which is member of
+ * videobuf_pci_sg_memory */
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+ dmabuf->vmalloc = (void *) vb->baddr;
+
+ /* Physical address */
+ dmabuf->bus_addr =
+ (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr);
+ }
+
+ if (!rotation_enabled(vout)) {
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+
+ vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
+ return 0;
+ }
+#ifndef CONFIG_ARCH_OMAP4
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+ /* If rotation is enabled, copy input buffer into VRFB
+ * memory space using DMA. We are copying input buffer
+ * into VRFB memory space of desired angle and DSS will
+ * read image VRFB memory for 0 degree angle
+ */
+ pixsize = vout->bpp * vout->vrfb_bpp;
+ /*
+ * DMA transfer in double index mode
+ */
+
+ /* Frame index */
+ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
+ (vout->pix.width * vout->bpp)) + 1;
+
+ /* Source and destination parameters */
+ src_element_index = 0;
+ src_frame_index = 0;
+ dest_element_index = 1;
+ /* Number of elements per frame */
+ elem_count = vout->pix.width * vout->bpp;
+ frame_count = vout->pix.height;
+ tx = &vout->vrfb_dma_tx;
+ tx->tx_status = 0;
+ omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
+ (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
+ tx->dev_id, 0x0);
+ /* src_port required only for OMAP1 */
+ omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+ dmabuf->bus_addr, src_element_index, src_frame_index);
+ /*set dma source burst mode for VRFB */
+ omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
+ rotation = calc_rotation(vout);
+
+ /* dest_port required only for OMAP1 */
+ omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
+ vout->vrfb_context[vb->i].paddr[0], dest_element_index,
+ dest_frame_index);
+ /*set dma dest burst mode for VRFB */
+ omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
+ omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
+
+ omap_start_dma(tx->dma_ch);
+ interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
+
+ if (tx->tx_status == 0) {
+ omap_stop_dma(tx->dma_ch);
+ return -EINVAL;
+ }
+ /* Store buffers physical address into an array. Addresses
+ * from this array will be used to configure DSS */
+ vout->queued_buf_addr[vb->i] = (u8 *)
+ vout->vrfb_context[vb->i].paddr[rotation];
+#endif
+#else /* TILER to be used */
+
+ /* Here, we need to use the physical addresses given by Tiler:
+ */
+ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
+ vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
+ vout->queued_buf_uv_addr[vb->i] = (u8 *) dmabuf->vmalloc;
+
+#ifdef TILER_TEST
+ {
+ uWriteWord = uWriteWord + 0x20;
+ printk(KERN_INFO "\nbefore ioremap: 0x%x\n", dmabuf->bus_addr);
+ pMemoryLCD = ioremap(dmabuf->bus_addr,
+ (32768 * vout->pix.height));
+ for (i = 0; i < vout->pix.height; i++) {
+ for (j = 0; j < vout->pix.width; j++) {
+ writew(uWriteWord,
+ (unsigned short *)pMemoryLCD +
+ i*16384 + j);
+ uReadWord = readw((unsigned short *)pMemoryLCD +
+ i*16384 + j);
+ }
+ }
+ iounmap(pMemoryLCD);
+ printk(KERN_INFO "\nafter ioremap\n");
+ }
+#endif
+
+
+#endif
+ return 0;
+}
+
+/* Buffer queue funtion will be called from the videobuf layer when _QBUF
+ * ioctl is called. It is used to enqueue buffer, which is ready to be
+ * displayed. */
+static void omap_vout_buffer_queue(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct omap_vout_device *vout = q->priv_data;
+
+ /* Driver is also maintainig a queue. So enqueue buffer in the driver
+ * queue */
+ list_add_tail(&vb->queue, &vout->dma_queue);
+
+ vb->state = VIDEOBUF_PREPARED;
+}
+
+/* Buffer release function is called from videobuf layer to release buffer
+ * which are already allocated */
+static void omap_vout_buffer_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct omap_vout_device *vout = q->priv_data;
+
+ vb->state = VIDEOBUF_NEEDS_INIT;
+
+ if (V4L2_MEMORY_MMAP != vout->memory)
+ return;
+}
+
+/*
+ * File operations
+ */
+static void omap_vout_vm_open(struct vm_area_struct *vma)
+{
+ struct omap_vout_device *vout = vma->vm_private_data;
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
+ vout->mmap_count++;
+}
+
+static void omap_vout_vm_close(struct vm_area_struct *vma)
+{
+ struct omap_vout_device *vout = vma->vm_private_data;
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
+ vout->mmap_count--;
+}
+
+static struct vm_operations_struct omap_vout_vm_ops = {
+ .open = omap_vout_vm_open,
+ .close = omap_vout_vm_close,
+};
+
+static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct omap_vout_device *vout = file->private_data;
+ struct videobuf_queue *q = &vout->vbq;
+ unsigned long size = (vma->vm_end - vma->vm_start);
+ unsigned long start = vma->vm_start;
+ int i;
+ void *pos;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+ int j = 0, k = 0, m = 0, p = 0, m_increment = 0;
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__,
+ vma->vm_pgoff, vma->vm_start, vma->vm_end);
+
+ /* look for the buffer to map */
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+ if (V4L2_MEMORY_MMAP != q->bufs[i]->memory)
+ continue;
+ if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT))
+ break;
+ }
+
+ if (VIDEO_MAX_FRAME == i) {
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "offset invalid [offset=0x%lx]\n",
+ (vma->vm_pgoff << PAGE_SHIFT));
+ return -EINVAL;
+ }
+ q->bufs[i]->baddr = vma->vm_start;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_ops = &omap_vout_vm_ops;
+ vma->vm_private_data = (void *) vout;
+ dmabuf = videobuf_to_dma(q->bufs[i]);
+
+ pos = dmabuf->vmalloc;
+
+#ifndef TILER_ALLOCATE_V4L2
+ vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;
+ while (size > 0) {
+ unsigned long pfn;
+ pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT;
+ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+#else
+ pos = dmabuf->bus_addr;
+ /* get line width */
+ /* for NV12, Y buffer is 1bpp*/
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ p = (vout->pix.width +
+ TILER_PAGESIZE - 1) & ~(TILER_PAGESIZE - 1);
+ m_increment = 64 * TILER_WIDTH;
+ } else {
+ p = (vout->pix.width * vout->bpp +
+ TILER_PAGESIZE - 1) & ~(TILER_PAGESIZE - 1);
+
+ if (vout->bpp > 1)
+ m_increment = 2*64*TILER_WIDTH;
+ else
+ m_increment = 64 * TILER_WIDTH;
+ }
+
+ for (j = 0; j < vout->pix.height; j++) {
+ /* map each page of the line */
+ if (0)
+ printk(KERN_NOTICE
+ "Y buffer %s::%s():%d: vm_start+%d = 0x%lx,"
+ "dma->vmalloc+%d = 0x%lx, w=0x%x\n",
+ __FILE__, __func__, __LINE__,
+ k, vma->vm_start + k, m,
+ (pos + m), p);
+ vma->vm_pgoff =
+ ((unsigned long)pos + m) >> PAGE_SHIFT;
+ if (remap_pfn_range(vma, vma->vm_start + k,
+ ((unsigned long)pos + m) >> PAGE_SHIFT,
+ p, vma->vm_page_prot))
+ return -EAGAIN;
+ k += p;
+ m += m_increment;
+ }
+ m = 0;
+
+ /* UV Buffer in case of NV12 format */
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ pos = dmabuf->vmalloc;
+ /* UV buffer is 2 bpp */
+ p = (vout->pix.width * 2 +
+ TILER_PAGESIZE - 1) & ~(TILER_PAGESIZE - 1);
+
+ m_increment = 2*64*TILER_WIDTH;
+
+ /* UV buffer is height / 2*/
+ for (j = 0; j < vout->pix.height / 2; j++) {
+ /* map each page of the line */
+ if (0)
+ printk(KERN_NOTICE
+ "UV buffer %s::%s():%d: vm_start+%d = 0x%lx,"
+ "dma->vmalloc+%d = 0x%lx, w=0x%x\n",
+ __FILE__, __func__, __LINE__,
+ k, vma->vm_start + k, m,
+ (pos + m), p);
+ vma->vm_pgoff =
+ ((unsigned long)pos + m) >> PAGE_SHIFT;
+ if (remap_pfn_range(vma, vma->vm_start + k,
+ ((unsigned long)pos + m) >> PAGE_SHIFT,
+ p, vma->vm_page_prot))
+ return -EAGAIN;
+ k += p;
+
+ m += m_increment;
+ }
+
+ }
+
+#endif
+ vout->mmap_count++;
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
+ return 0;
+}
+
+static int omap_vout_release(struct file *file)
+{
+
+ struct omap_vout_device *vout = file->private_data;
+ struct videobuf_queue *q;
+ unsigned int t;
+ struct omapvideo_info *ovid;
+ unsigned int r;
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
+ ovid = &(vout->vid_info);
+
+ if (!vout)
+ return 0;
+ q = &vout->vbq;
+
+ /* Disable all the overlay managers connected with this interface */
+ for (t = 0; t < ovid->num_overlays; t++) {
+ struct omap_overlay *ovl = ovid->overlays[t];
+ if (ovl->manager && ovl->manager->device) {
+ struct omap_overlay_info info;
+ ovl->get_overlay_info(ovl, &info);
+ info.enabled = 0;
+ ovl->set_overlay_info(ovl, &info);
+ }
+
+ }
+ /* Turn off the pipeline */
+ r = omapvid_apply_changes(vout);
+ if (r)
+ printk(KERN_WARNING VOUT_NAME "Unable to apply changes\n");
+
+ /* Free all buffers */
+ omap_vout_free_allbuffers(vout);
+ videobuf_mmap_free(q);
+
+ /* Even if apply changes fails we should continue
+ freeing allocated memeory */
+ if (vout->streaming) {
+ u32 mask = 0;
+
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
+ DISPC_IRQ_EVSYNC_ODD;
+ omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
+ vout->streaming = 0;
+
+ videobuf_streamoff(q);
+ videobuf_queue_cancel(q);
+
+ }
+
+ if (vout->mmap_count != 0)
+ vout->mmap_count = 0;
+
+ vout->opened -= 1;
+ file->private_data = NULL;
+
+ if (vout->buffer_allocated)
+ videobuf_mmap_free(q);
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
+ return r;
+}
+
+static int omap_vout_open(struct file *file)
+{
+ struct omap_vout_device *vout = NULL;
+ struct videobuf_queue *q;
+
+ vout = video_drvdata(file);
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
+
+ if (vout == NULL)
+ return -ENODEV;
+
+ /* for now, we only support single open */
+ if (vout->opened)
+ return -EBUSY;
+
+ vout->opened += 1;
+
+ file->private_data = vout;
+ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ q = &vout->vbq;
+ video_vbq_ops.buf_setup = omap_vout_buffer_setup;
+ video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
+ video_vbq_ops.buf_release = omap_vout_buffer_release;
+ video_vbq_ops.buf_queue = omap_vout_buffer_queue;
+ spin_lock_init(&vout->vbq_lock);
+
+ videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock,
+ vout->type, V4L2_FIELD_NONE, sizeof
+ (struct videobuf_buffer), vout);
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
+ return 0;
+}
+
+/* V4L2 ioctls */
+static int vidioc_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct omap_vout_device *vout = fh;
+
+ strlcpy(cap->driver, VOUT_NAME,
+ sizeof(cap->driver));
+ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
+ cap->bus_info[0] = '\0';
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+ return 0;
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_fmtdesc *fmt)
+{
+ int index = fmt->index;
+ enum v4l2_buf_type type = fmt->type;
+
+ fmt->index = index;
+ fmt->type = type;
+ if (index >= NUM_OUTPUT_FORMATS)
+ return -EINVAL;
+
+ fmt->flags = omap_formats[index].flags;
+ strlcpy(fmt->description, omap_formats[index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat = omap_formats[index].pixelformat;
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct omap_vout_device *vout = fh;
+
+ f->fmt.pix = vout->pix;
+ return 0;
+
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct omap_vout_device *vout = fh;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_video_timings *timing;
+
+ if (vout->streaming)
+ return -EBUSY;
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ if (!ovl->manager || !ovl->manager->device)
+ return -EINVAL;
+ /* get the display device attached to the overlay */
+ timing = &ovl->manager->device->panel.timings;
+
+ vout->fbuf.fmt.height = timing->y_res;
+ vout->fbuf.fmt.width = timing->x_res;
+
+ omap_vout_try_format(&f->fmt.pix);
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct omap_vout_device *vout = fh;
+ int bpp;
+ int r;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_video_timings *timing;
+
+ if (vout->streaming)
+ return -EBUSY;
+
+ mutex_lock(&vout->lock);
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ /* get the display device attached to the overlay */
+ if (!ovl->manager || !ovl->manager->device) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ timing = &ovl->manager->device->panel.timings;
+
+ /* TODO: check if TILER ADAPTATION is needed here. */
+ /* We dont support RGB24-packed mode if vrfb rotation
+ * is enabled*/
+ if ((rotation_enabled(vout)) &&
+ f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+
+ /* get the framebuffer parameters */
+
+ if (rotate_90_or_270(vout)) {
+ vout->fbuf.fmt.height = timing->x_res;
+ vout->fbuf.fmt.width = timing->y_res;
+ } else {
+ vout->fbuf.fmt.height = timing->y_res;
+ vout->fbuf.fmt.width = timing->x_res;
+ }
+
+ /* change to samller size is OK */
+
+ bpp = omap_vout_try_format(&f->fmt.pix);
+ if (V4L2_PIX_FMT_NV12 == f->fmt.pix.pixelformat)
+ f->fmt.pix.sizeimage = f->fmt.pix.width *
+ f->fmt.pix.height * 3/2;
+ else
+ f->fmt.pix.sizeimage = f->fmt.pix.width *
+ f->fmt.pix.height * bpp;
+
+ /* try & set the new output format */
+ vout->bpp = bpp;
+ vout->pix = f->fmt.pix;
+ vout->vrfb_bpp = 1;
+
+ /* If YUYV then vrfb bpp is 2, for others its 1 */
+ if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
+ V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
+ vout->vrfb_bpp = 2;
+
+ /* set default crop and win */
+ omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
+
+ /* Save the changes in the overlay strcuture */
+ r = omapvid_init(vout, 0, 0);
+ if (r) {
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&vout->lock);
+ return 0;
+}
+
+static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ int err = -EINVAL;
+ struct omap_vout_device *vout = fh;
+ struct v4l2_window *win = &f->fmt.win;
+
+ err = omap_vout_try_window(&vout->fbuf, win);
+
+ if (err)
+ return err;
+
+ if (vout->vid == OMAP_VIDEO1)
+ win->global_alpha = 255;
+ else
+ win->global_alpha = f->fmt.win.global_alpha;
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct omap_vout_device *vout = fh;
+ int err = -EINVAL;
+ struct omap_overlay *ovl;
+ struct omapvideo_info *ovid;
+ struct v4l2_window *win = &f->fmt.win;
+
+ mutex_lock(&vout->lock);
+ ovid = &vout->vid_info;
+ ovl = ovid->overlays[0];
+ err = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
+ if (err) {
+ mutex_unlock(&vout->lock);
+ return err;
+ }
+ if (ovl->id == OMAP_DSS_VIDEO1)
+ vout->win.global_alpha = 255;
+ else
+ vout->win.global_alpha = f->fmt.win.global_alpha;
+
+ vout->win.chromakey = f->fmt.win.chromakey;
+ mutex_unlock(&vout->lock);
+ return 0;
+}
+
+static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh,
+ struct v4l2_fmtdesc *fmt)
+{
+ int index = fmt->index;
+ enum v4l2_buf_type type = fmt->type;
+
+ fmt->index = index;
+ fmt->type = type;
+ if (index >= NUM_OUTPUT_FORMATS)
+ return -EINVAL;
+
+ fmt->flags = omap_formats[index].flags;
+ strlcpy(fmt->description, omap_formats[index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat = omap_formats[index].pixelformat;
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct omap_vout_device *vout = fh;
+ struct omap_overlay *ovl;
+ struct omapvideo_info *ovid;
+ struct omap_overlay_manager_info info;
+ struct v4l2_window *win = &f->fmt.win;
+ u32 key_value = 0;
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ win->w = vout->win.w;
+ win->field = vout->win.field;
+ win->global_alpha = vout->win.global_alpha;
+
+ if (ovl->manager && ovl->manager->get_manager_info) {
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ key_value = info.trans_key;
+ }
+ win->chromakey = key_value;
+ return 0;
+}
+
+static int vidioc_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *cropcap)
+{
+ struct omap_vout_device *vout = fh;
+ enum v4l2_buf_type type = cropcap->type;
+ struct v4l2_pix_format *pix = &vout->pix;
+
+ cropcap->type = type;
+ if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ /* Width and height are always even */
+ cropcap->bounds.width = pix->width & ~1;
+ cropcap->bounds.height = pix->height & ~1;
+
+ omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect);
+ cropcap->pixelaspect.numerator = 1;
+ cropcap->pixelaspect.denominator = 1;
+ return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *fh,
+ struct v4l2_crop *crop)
+{
+ struct omap_vout_device *vout = fh;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+ crop->c = vout->crop;
+ return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *fh,
+ struct v4l2_crop *crop)
+{
+ struct omap_vout_device *vout = fh;
+ int err = -EINVAL;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_video_timings *timing;
+
+ if (vout->streaming)
+ return -EBUSY;
+
+ mutex_lock(&vout->lock);
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ if (!ovl->manager || !ovl->manager->device) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ /* get the display device attached to the overlay */
+ timing = &ovl->manager->device->panel.timings;
+
+ if (rotate_90_or_270(vout)) {
+ vout->fbuf.fmt.height = timing->x_res;
+ vout->fbuf.fmt.width = timing->y_res;
+ } else {
+ vout->fbuf.fmt.height = timing->y_res;
+ vout->fbuf.fmt.width = timing->x_res;
+ }
+
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ err = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
+ &vout->fbuf, &crop->c);
+ mutex_unlock(&vout->lock);
+ return err;
+ } else {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+ struct v4l2_queryctrl *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_ROTATE:
+ v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0);
+ break;
+ case V4L2_CID_BG_COLOR:
+ v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0);
+ break;
+ case V4L2_CID_VFLIP:
+ v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
+ default:
+ ctrl->name[0] = '\0';
+ return -EINVAL;
+
+ }
+ return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
+{
+ struct omap_vout_device *vout = fh;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ROTATE:
+ ctrl->value = vout->control[0].value;
+ return 0;
+ case V4L2_CID_BG_COLOR:
+ {
+ struct omap_overlay_manager_info info;
+ struct omap_overlay *ovl;
+ ovl = vout->vid_info.overlays[0];
+
+ if (!ovl->manager || !ovl->manager->get_manager_info)
+ return -EINVAL;
+
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ ctrl->value = info.default_color;
+ return 0;
+ }
+
+ case V4L2_CID_VFLIP:
+ ctrl->value = vout->control[2].value;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
+{
+ struct omap_vout_device *vout = fh;
+
+ switch (a->id) {
+ case V4L2_CID_ROTATE:
+ {
+ int rotation = a->value;
+
+ mutex_lock(&vout->lock);
+
+ if (rotation &&
+ vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+
+ if ((v4l2_rot_to_dss_rot(rotation, &vout->rotation,
+ vout->mirror))) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ vout->control[0].value = rotation;
+ mutex_unlock(&vout->lock);
+ return 0;
+ }
+ case V4L2_CID_BG_COLOR:
+ {
+ unsigned int color = a->value;
+ struct omap_overlay_manager_info info;;
+ struct omap_overlay *ovl;
+ ovl = vout->vid_info.overlays[0];
+
+ mutex_lock(&vout->lock);
+ if (!ovl->manager || !ovl->manager->get_manager_info) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ info.default_color = color;
+ if (ovl->manager->set_manager_info(ovl->manager, &info)) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+
+ vout->control[1].value = color;
+ mutex_unlock(&vout->lock);
+ return 0;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ unsigned int mirror = a->value;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ mutex_lock(&vout->lock);
+
+ if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+ vout->mirror = mirror;
+ vout->control[2].value = mirror;
+ mutex_unlock(&vout->lock);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+}
+
+static int vidioc_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *req)
+{
+ struct omap_vout_device *vout = fh;
+ struct videobuf_queue *q = &(vout->vbq);
+ unsigned int i, num_buffers = 0;
+ int ret = 0;
+ struct videobuf_dmabuf *dmabuf = NULL;
+
+ printk(KERN_INFO VOUT_NAME
+ "entered REQbuf: \n");
+
+ if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0))
+ return -EINVAL;
+ /* if memory is not mmp or userptr
+ return error */
+ if ((V4L2_MEMORY_MMAP != req->memory) &&
+ (V4L2_MEMORY_USERPTR != req->memory))
+ return -EINVAL;
+
+ mutex_lock(&vout->lock);
+ /* Cannot be requested when streaming is on */
+ if (vout->streaming) {
+ mutex_unlock(&vout->lock);
+ return -EBUSY;
+ }
+
+ /* If buffers are already allocated free them */
+ if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) {
+ if (vout->mmap_count) {
+ mutex_unlock(&vout->lock);
+ return -EBUSY;
+ }
+
+#ifndef TILER_ALLOCATE_V4L2
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_VIDEO3 == vout->vid)
+ num_buffers = video3_numbuffers;
+ else
+#endif
+ num_buffers = (vout->vid == OMAP_VIDEO1) ?
+ video1_numbuffers : video2_numbuffers;
+
+ for (i = num_buffers; i < vout->buffer_allocated; i++) {
+ dmabuf = videobuf_to_dma(q->bufs[i]);
+ omap_vout_free_buffer((u32)dmabuf->vmalloc,
+ dmabuf->bus_addr, vout->buffer_size);
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+ vout->buffer_allocated = num_buffers;
+#else /* TILER_ALLOCATE_V4L2*/
+ for (i = 0; i < vout->buffer_allocated; i++) {
+ tiler_free_buf(vout->buf_phy_addr[i]);
+ tiler_free_buf(vout->buf_phy_uv_addr[i]);
+ vout->buf_phy_addr[i] = 0;
+ vout->buf_phy_uv_addr[i] = 0;
+ }
+ vout->buffer_allocated = 0;
+
+#endif /* TILER_ALLOCATE_V4L2*/
+ videobuf_mmap_free(q);
+
+
+ } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) {
+ if (vout->buffer_allocated) {
+ videobuf_mmap_free(q);
+ for (i = 0; i < vout->buffer_allocated; i++) {
+ kfree(q->bufs[i]);
+ q->bufs[i] = NULL;
+ }
+ vout->buffer_allocated = 0;
+ }
+ }
+ /*store the memory type in data structure */
+ vout->memory = req->memory;
+
+ INIT_LIST_HEAD(&vout->dma_queue);
+
+ /* call videobuf_reqbufs api */
+ ret = videobuf_reqbufs(q, req);
+ if (ret < 0) {
+ mutex_unlock(&vout->lock);
+ return ret;
+ }
+
+ vout->buffer_allocated = req->count;
+ for (i = 0; i < req->count; i++) {
+ dmabuf = videobuf_to_dma(q->bufs[i]);
+#ifdef CONFIG_ARCH_OMAP4
+ if (V4L2_PIX_FMT_NV12 == vout->pix.pixelformat) {
+#ifndef TILER_ALLOCATE_V4L2
+ dmabuf->vmalloc = (void *) omapvid_get_uvbase_nv12(
+ vout->buf_phy_addr[i],
+ vout->pix.height,
+ vout->pix.width);
+#else
+ dmabuf->vmalloc = (void *) vout->buf_phy_uv_addr[i];
+#endif /* TILER_ALLOCATE_V4L2 */
+ } else
+ dmabuf->vmalloc = NULL;
+#else
+ dmabuf->vmalloc = (void *) vout->buf_virt_addr[i];
+#endif
+ dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i];
+ dmabuf->sglen = 1;
+ }
+ mutex_unlock(&vout->lock);
+ return 0;
+}
+
+static int vidioc_querybuf(struct file *file, void *fh,
+ struct v4l2_buffer *b)
+{
+ struct omap_vout_device *vout = fh;
+
+ return videobuf_querybuf(&(vout->vbq), b);
+}
+
+static int vidioc_qbuf(struct file *file, void *fh,
+ struct v4l2_buffer *buffer)
+{
+ struct omap_vout_device *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+ int ret = 0;
+
+ printk(KERN_INFO VOUT_NAME
+ "entered qbuf: buffer address: %x \n", (unsigned int) buffer);
+
+ if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) ||
+ (buffer->index >= vout->buffer_allocated) ||
+
+ (q->bufs[buffer->index]->memory != buffer->memory)) {
+ return -EINVAL;
+ }
+ if (V4L2_MEMORY_USERPTR == buffer->memory) {
+ if ((buffer->length < vout->pix.sizeimage) ||
+ (0 == buffer->m.userptr)) {
+ return -EINVAL;
+ }
+ }
+
+#ifndef CONFIG_ARCH_OMAP4
+ if ((rotation_enabled(vout)) &&
+ vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) {
+ printk(KERN_WARNING VOUT_NAME
+ "DMA Channel not allocated for Rotation\n");
+ return -EINVAL;
+ }
+#endif
+ ret = videobuf_qbuf(q, buffer);
+ return ret;
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh,
+ struct v4l2_buffer *b)
+{
+ struct omap_vout_device *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+ int ret = 0;
+
+ printk(KERN_INFO VOUT_NAME
+ "entered DQbuf: buffer address: %x \n", (unsigned int) b);
+
+ if (!vout->streaming)
+ return -EINVAL;
+
+ if (file->f_flags & O_NONBLOCK)
+ /* Call videobuf_dqbuf for non blocking mode */
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
+ else
+ /* Call videobuf_dqbuf for blocking mode */
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+ return ret;
+}
+
+static int vidioc_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct omap_vout_device *vout = fh;
+ struct videobuf_queue *q = &vout->vbq;
+ u32 addr = 0, uv_addr = 0;
+ int r = 0;
+ int t;
+ struct omapvideo_info *ovid = &(vout->vid_info);
+ u32 mask = 0;
+
+ mutex_lock(&vout->lock);
+
+ if (vout->streaming) {
+ mutex_unlock(&vout->lock);
+ return -EBUSY;
+ }
+
+ r = videobuf_streamon(q);
+ if (r < 0) {
+ mutex_unlock(&vout->lock);
+ return r;
+ }
+
+ if (list_empty(&vout->dma_queue)) {
+ mutex_unlock(&vout->lock);
+ return -EIO;
+ }
+ /* Get the next frame from the buffer queue */
+ vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ /* Remove buffer from the buffer queue */
+ list_del(&vout->cur_frm->queue);
+ /* Mark state of the current frame to active */
+ vout->cur_frm->state = VIDEOBUF_ACTIVE;
+ /* Initialize field_id and started member */
+ vout->field_id = 0;
+
+ /* set flag here. Next QBUF will start DMA */
+ vout->streaming = 1;
+
+ vout->first_int = 1;
+
+#ifndef CONFIG_ARCH_OMAP4
+ if (omap_vout_calculate_offset(vout)) {
+ mutex_unlock(&vout->lock);
+ return -EINVAL;
+ }
+#endif
+ addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
+ + vout->cropped_offset;
+ uv_addr = (unsigned long) vout->queued_buf_uv_addr[vout->cur_frm->i];
+ /* OMAP4: check if cropped_offset is needed? */
+
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
+ DISPC_IRQ_EVSYNC_ODD;
+
+ omap_dispc_register_isr(omap_vout_isr, vout, mask);
+
+ for (t = 0; t < ovid->num_overlays; t++) {
+ struct omap_overlay *ovl = ovid->overlays[t];
+ if (ovl->manager && ovl->manager->device) {
+ struct omap_overlay_info info;
+ ovl->get_overlay_info(ovl, &info);
+ info.enabled = 1;
+ info.paddr = addr;
+ info.p_uv_addr = uv_addr;
+ if (ovl->set_overlay_info(ovl, &info))
+ return -EINVAL;
+ }
+ }
+
+ /* First save the configuration in ovelray structure */
+ r = omapvid_init(vout, addr, uv_addr);
+ if (r)
+ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n");
+ /* Enable the pipeline and set the Go bit */
+ r = omapvid_apply_changes(vout);
+ if (r)
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+
+ mutex_unlock(&vout->lock);
+ return r;
+}
+
+static int vidioc_streamoff(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct omap_vout_device *vout = fh;
+ int t, r = 0;
+ struct omapvideo_info *ovid = &(vout->vid_info);
+ u32 mask = 0;
+
+ if (!vout->streaming)
+ return -EINVAL;
+
+ vout->streaming = 0;
+ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
+ DISPC_IRQ_EVSYNC_ODD;
+
+ omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
+
+ for (t = 0; t < ovid->num_overlays; t++) {
+ struct omap_overlay *ovl = ovid->overlays[t];
+ if (ovl->manager && ovl->manager->device) {
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+ info.enabled = 0;
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r) {
+ printk(KERN_ERR VOUT_NAME "failed to \
+ update overlay info\n");
+ return r;
+ }
+ }
+
+ /* Turn of the pipeline */
+ r = omapvid_apply_changes(vout);
+ if (r) {
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+ return r;
+ }
+ videobuf_streamoff(&vout->vbq);
+ videobuf_queue_cancel(&vout->vbq);
+ }
+ return 0;
+}
+
+static int vidioc_s_fbuf(struct file *file, void *fh,
+ struct v4l2_framebuffer *a)
+{
+ struct omap_vout_device *vout = fh;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_overlay_manager_info info;
+ enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+ int enable = 0;
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ /* OMAP DSS doesn't support Source and Destination color
+ key together */
+ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
+ (a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
+ return -EINVAL;
+ /* OMAP DSS Doesn't support the Destination color key
+ and alpha blending together */
+ if (a->flags & V4L2_FBUF_FLAG_CHROMAKEY &&
+ (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
+ return -EINVAL;
+
+ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
+ vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+ key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
+ } else
+ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+
+ if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
+ vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+ key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+ } else
+ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
+
+ if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
+ V4L2_FBUF_FLAG_SRC_CHROMAKEY))
+ enable = 1;
+ else
+ enable = 0;
+
+ if (ovl->manager && ovl->manager->get_manager_info &&
+ ovl->manager->set_manager_info) {
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ info.trans_enabled = enable;
+ info.trans_key_type = key_type;
+ info.trans_key = vout->win.chromakey;
+ if (ovl->manager->set_manager_info(ovl->manager, &info))
+ return -EINVAL;
+ }
+
+ if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
+ vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ enable = 1;
+ } else {
+ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ enable = 0;
+ }
+ if (ovl->manager && ovl->manager->get_manager_info &&
+ ovl->manager->set_manager_info) {
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ info.alpha_enabled = enable;
+ if (ovl->manager->set_manager_info(ovl->manager, &info))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vidioc_g_fbuf(struct file *file, void *fh,
+ struct v4l2_framebuffer *a)
+{
+ struct omap_vout_device *vout = fh;
+ struct omap_overlay_manager_info info;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ enum omap_dss_trans_key_type key_type;
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+
+ a->flags = 0x0;
+
+ a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
+ | V4L2_FBUF_CAP_SRC_CHROMAKEY;
+
+ if (ovl->manager && ovl->manager->get_manager_info) {
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
+ a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
+ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
+ a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+
+ }
+ if (ovl->manager && ovl->manager->get_manager_info) {
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ if (info.alpha_enabled)
+ a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops vout_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_fbuf = vidioc_s_fbuf,
+ .vidioc_g_fbuf = vidioc_g_fbuf,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
+ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
+ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
+ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+};
+
+static const struct v4l2_file_operations omap_vout_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = video_ioctl2,
+ .mmap = omap_vout_mmap,
+ .open = omap_vout_open,
+ .release = omap_vout_release,
+};
+
+/* Init functions used during driver intitalization */
+/* Initial setup of video_data */
+static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
+{
+ struct v4l2_pix_format *pix;
+ struct video_device *vfd;
+ struct v4l2_control *control;
+ struct omap_dss_device *display =
+ vout->vid_info.overlays[0]->manager->device;
+
+ /* set the default pix */
+ pix = &vout->pix;
+
+ /* Set the default picture of QVGA */
+ pix->width = QQVGA_WIDTH;
+ pix->height = QQVGA_HEIGHT;
+
+ /* Default pixel format is RGB 5-6-5 */
+ pix->pixelformat = V4L2_PIX_FMT_RGB565;
+ pix->field = V4L2_FIELD_ANY;
+ pix->bytesperline = pix->width * 2;
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->priv = 0;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ vout->bpp = RGB565_BPP;
+ vout->fbuf.fmt.width = display->panel.timings.x_res;
+ vout->fbuf.fmt.height = display->panel.timings.y_res;
+
+ /* Set the data structures for the overlay parameters*/
+ vout->win.global_alpha = 255;
+ vout->fbuf.flags = 0;
+ vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
+ V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY;
+ vout->win.chromakey = 0;
+
+ omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
+
+ /*Disable the rotation. */
+ control = vout->control;
+
+ control[0].id = V4L2_CID_ROTATE;
+ control[0].value = 0;
+ vout->rotation = -1;
+ vout->mirror = 0;
+ vout->vrfb_bpp = 2;
+
+ control[1].id = V4L2_CID_BG_COLOR;
+ control[1].value = 0;
+
+ /* initialize the video_device struct */
+ vfd = vout->vfd = video_device_alloc();
+
+ if (!vfd) {
+ printk(KERN_ERR VOUT_NAME ": could not allocate\
+ video device struct\n");
+ return -ENOMEM;
+ }
+ vfd->release = video_device_release;
+ vfd->ioctl_ops = &vout_ioctl_ops;
+
+ strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
+ vfd->vfl_type = VFL_TYPE_GRABBER;
+
+ /* need to register for a VID_HARDWARE_* ID in videodev.h */
+ vfd->fops = &omap_vout_fops;
+ mutex_init(&vout->lock);
+
+ vfd->minor = -1;
+ return 0;
+
+}
+
+/* Setup video buffers */
+static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
+ int vid_num)
+{
+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
+ omap2video_device, v4l2_dev);
+ struct omap_vout_device *vout;
+ int i, r = 0;
+ unsigned numbuffers;
+ struct video_device *vfd;
+#ifndef CONFIG_ARCH_OMAP4 /* TODO: related to rotation */
+ int j;
+ int image_width, image_height;
+ int static_vrfb_allocation = 0, vrfb_num_bufs = 4;
+#endif
+ vout = vid_dev->vouts[vid_num];
+ vfd = vout->vfd;
+
+#ifndef TILER_ALLOCATE_V4L2
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_VIDEO3 == vid_num) {
+ numbuffers = video3_numbuffers;
+ vout->buffer_size = video3_bufsize;
+ } else
+#endif
+ {
+ numbuffers = (vid_num == 0) ? video1_numbuffers
+ : video2_numbuffers;
+ vout->buffer_size = (vid_num == 0) ? video1_bufsize
+ : video2_bufsize;
+ }
+ printk(KERN_INFO VOUT_NAME "Buffer Size = %d\n", vout->buffer_size);
+ for (i = 0; i < numbuffers; i++) {
+ vout->buf_virt_addr[i] =
+ omap_vout_alloc_buffer(vout->buffer_size,
+ (u32 *) &vout->buf_phy_addr[i]);
+ if (!vout->buf_virt_addr[i]) {
+ numbuffers = i;
+ r = -ENOMEM;
+ goto free_buffers;
+ }
+ }
+ for (i = 0; i < 4; i++) {
+
+ if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
+ printk(KERN_INFO VOUT_NAME ": VRFB Region allocation \
+ for rotation failed\n");
+ r = -ENOMEM;
+ break;
+ }
+ }
+ if (r == -ENOMEM) {
+ for (j = 0; j < i; j++)
+ omap_vrfb_release_ctx(&vout->vrfb_context[j]);
+
+ goto free_buffers;
+ }
+
+ vout->cropped_offset = 0;
+
+ /* Calculate VRFB memory size */
+ /* allocate for worst case size */
+ image_width = VID_MAX_WIDTH / TILE_SIZE;
+ if (VID_MAX_WIDTH % TILE_SIZE)
+ image_width++;
+
+ image_width = image_width * TILE_SIZE;
+ image_height = VID_MAX_HEIGHT / TILE_SIZE;
+
+ if (VID_MAX_HEIGHT % TILE_SIZE)
+ image_height++;
+
+ image_height = image_height * TILE_SIZE;
+ vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
+
+ /*
+ * Request and Initialize DMA, for DMA based VRFB transfer
+ */
+ vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
+ vout->vrfb_dma_tx.dma_ch = -1;
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
+ r = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
+ omap_vout_vrfb_dma_tx_callback,
+ (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
+ if (r < 0) {
+ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
+ printk(KERN_INFO VOUT_NAME ": DMA Channel not alloted\
+ for video%d [v4l2]\n", vfd->minor);
+ }
+ init_waitqueue_head(&vout->vrfb_dma_tx.wait);
+
+ /* Allocate VRFB buffers if selected through bootargs */
+ static_vrfb_allocation = (vid_num == 0) ?
+ vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
+
+ /* statically allocated the VRFB buffer is done through
+ commands line aruments */
+ if (static_vrfb_allocation) {
+ if (omap_vout_allocate_vrfb_buffers(vout, vrfb_num_bufs, -1)) {
+ r = -ENOMEM;
+ goto free_buffers;
+ }
+ vout->vrfb_static_allocation = 1;
+ }
+#endif /* TILER_ALLOCATE_V4L2 */
+
+/* NOTE: OMAP4, if TILER allocation, then nothing to pre-allocate */
+
+ return 0;
+
+free_buffers:
+ for (i = 0; i < numbuffers; i++) {
+ omap_vout_free_buffer(vout->buf_virt_addr[i],
+ vout->buf_phy_addr[i], vout->buffer_size);
+ vout->buf_virt_addr[i] = 0;
+ vout->buf_phy_addr[i] = 0;
+ }
+ return r;
+
+}
+
+/* Create video out devices */
+static int __init omap_vout_create_video_devices(struct platform_device *pdev)
+{
+ int r = 0, k;
+ struct omap_vout_device *vout;
+ struct video_device *vfd = NULL;
+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+
+ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
+ omap2video_device, v4l2_dev);
+ for (k = 0; k < pdev->num_resources; k++) {
+
+ vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
+ if (!vout) {
+ printk(KERN_ERR VOUT_NAME ": could not allocate \
+ memory\n");
+ return -ENOMEM;
+ }
+
+ memset(vout, 0, sizeof(struct omap_vout_device));
+
+ vout->vid = k;
+ vid_dev->vouts[k] = vout;
+ vout->vid_dev = vid_dev;
+/* TODO: OMAP4: check?? */
+ if (pdev->num_resources == 1)
+ vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
+ else
+ /* Else select video1 and video2 one by one. */
+ vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
+ vout->vid_info.num_overlays = 1;
+ vout->vid_info.id = k + 1;
+ vid_dev->num_videos++;
+
+ /* Setup the default configuration for the video devices
+ */
+ if (omap_vout_setup_video_data(vout) != 0) {
+ r = -ENOMEM;
+ goto error;
+ }
+
+ /* Allocate default number of buffers for the video streaming
+ * and reserve the VRFB space for rotation
+ */
+ if (omap_vout_setup_video_bufs(pdev, k) != 0) {
+ r = -ENOMEM;
+ goto error1;
+ }
+
+ /* Register the Video device with V4L2
+ */
+ vfd = vout->vfd;
+ if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) {
+ printk(KERN_ERR VOUT_NAME ": could not register \
+ Video for Linux device\n");
+ vfd->minor = -1;
+ r = -ENODEV;
+ goto error2;
+ }
+ video_set_drvdata(vfd, vout);
+
+ /* Configure the overlay structure */
+ r = omapvid_init(vid_dev->vouts[k], 0, 0);
+
+ if (r)
+ goto error2;
+ else
+ goto success;
+error2:
+#ifndef CONFIG_ARCH_OMAP4
+ omap_vout_release_vrfb(vout);
+#endif
+ omap_vout_free_buffers(vout);
+error1:
+ video_device_release(vfd);
+error:
+ kfree(vout);
+ return r;
+
+success:
+ printk(KERN_INFO VOUT_NAME ": registered and initialized\
+ video device %d [v4l2]\n", vfd->minor);
+ if (k == (pdev->num_resources - 1))
+ return 0;
+ }
+ return -ENODEV;
+
+}
+/* Driver functions */
+static int omap_vout_remove(struct platform_device *pdev)
+{
+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
+ omap2video_device, v4l2_dev);
+ int k;
+
+ v4l2_device_unregister(v4l2_dev);
+ for (k = 0; k < pdev->num_resources; k++)
+ omap_vout_cleanup_device(vid_dev->vouts[k]);
+
+ for (k = 0; k < vid_dev->num_displays; k++) {
+ if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
+ vid_dev->displays[k]->disable(vid_dev->displays[k]);
+
+ omap_dss_put_device(vid_dev->displays[k]);
+ }
+ kfree(vid_dev);
+ return 0;
+}
+
+static int __init omap_vout_probe(struct platform_device *pdev)
+{
+ int r = 0, i;
+ struct omap2video_device *vid_dev = NULL;
+ struct omap_overlay *ovl;
+ struct omap_dss_device *def_display;
+ struct omap_dss_device *dssdev;
+
+ if (pdev->num_resources == 0) {
+ dev_err(&pdev->dev, "probed for an unknown device\n");
+ r = -ENODEV;
+ return r;
+ }
+
+ vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
+ if (vid_dev == NULL) {
+ r = -ENOMEM;
+ return r;
+ }
+
+ vid_dev->num_displays = 0;
+ dssdev = NULL;
+ for_each_dss_dev(dssdev) {
+ omap_dss_get_device(dssdev);
+ vid_dev->displays[vid_dev->num_displays++] = dssdev;
+ }
+
+ if (vid_dev->num_displays == 0) {
+ dev_err(&pdev->dev, "no displays\n");
+ r = -EINVAL;
+ goto error0;
+ }
+
+ vid_dev->num_overlays = omap_dss_get_num_overlays();
+ for (i = 0; i < vid_dev->num_overlays; i++)
+ vid_dev->overlays[i] = omap_dss_get_overlay(i);
+
+ vid_dev->num_managers = omap_dss_get_num_overlay_managers();
+ for (i = 0; i < vid_dev->num_managers; i++)
+ vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
+
+ /* Get the Video1, video2 (and Video3 for OMAP4) overlay.
+ * Setup the Display attached to that overlays
+ */
+ for (i = 1; i < (NUM_OF_VIDEO_CHANNELS + 1); i++) {
+ ovl = omap_dss_get_overlay(i);
+ if (ovl->manager && ovl->manager->device) {
+ def_display = ovl->manager->device;
+ } else {
+ dev_warn(&pdev->dev, "cannot find display\n");
+ def_display = NULL;
+ }
+ if (def_display) {
+ r = def_display->enable(def_display);
+ if (r) {
+ /* Here we are not considering a error as display may be
+ enabled by frame buffer driver */
+ dev_warn(&pdev->dev,
+ "'%s' Display already enabled\n",
+ def_display->name);
+ }
+ /* set the update mode */
+ if (def_display->caps &
+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(
+ def_display,
+ OMAP_DSS_UPDATE_AUTO);
+ if (def_display->enable_te)
+ def_display->enable_te(def_display, 1);
+#else
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(
+ def_display,
+ OMAP_DSS_UPDATE_MANUAL);
+ if (def_display->enable_te)
+ def_display->enable_te(def_display, 0);
+#endif
+ } else {
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(
+ def_display,
+ OMAP_DSS_UPDATE_AUTO);
+ }
+ }
+ }
+
+ if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
+ printk(KERN_ERR VOUT_NAME
+ "v4l2_device_register unsuccessful\n");
+ return -ENODEV;
+ }
+
+ r = omap_vout_create_video_devices(pdev);
+ if (r)
+ goto error0;
+
+ for (i = 0; i < vid_dev->num_displays; i++) {
+ struct omap_dss_device *display = vid_dev->displays[i];
+
+ if (display->update)
+ display->update(display, 0, 0,
+ display->panel.timings.x_res,
+ display->panel.timings.y_res);
+ }
+ printk(KERN_INFO VOUT_NAME "display->updated\n");
+ return 0;
+
+error0:
+ kfree(vid_dev);
+ return r;
+}
+
+static struct platform_driver omap_vout_driver = {
+ .driver = {
+ .name = VOUT_NAME,
+ },
+ .probe = omap_vout_probe,
+ .remove = omap_vout_remove,
+};
+
+void omap_vout_isr(void *arg, unsigned int irqstatus)
+{
+ int r;
+ struct timeval timevalue;
+ struct omap_vout_device *vout =
+ (struct omap_vout_device *) arg;
+ u32 addr, fid, uv_addr;
+ struct omapvideo_info *ovid;
+ struct omap_overlay *ovl;
+ struct omap_dss_device *cur_display;
+
+ if (!vout->streaming)
+ return;
+
+ ovid = &(vout->vid_info);
+ ovl = ovid->overlays[0];
+ /* get the display device attached to the overlay */
+ if (!ovl->manager || !ovl->manager->device)
+ return;
+ cur_display = ovl->manager->device;
+
+ spin_lock(&vout->vbq_lock);
+ do_gettimeofday(&timevalue);
+
+ if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) {
+ if (!(irqstatus & DISPC_IRQ_VSYNC))
+ return;
+ if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
+ vout->cur_frm->ts = timevalue;
+ vout->cur_frm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->cur_frm->done);
+ vout->cur_frm = vout->next_frm;
+ }
+ vout->first_int = 0;
+ if (list_empty(&vout->dma_queue)) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+
+ vout->next_frm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ list_del(&vout->next_frm->queue);
+
+ vout->next_frm->state = VIDEOBUF_ACTIVE;
+
+ addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
+ + vout->cropped_offset;
+
+ uv_addr = (unsigned long) vout->queued_buf_uv_addr[
+ vout->next_frm->i];
+ /* TODO: check the cropped offset part*/
+
+ /* First save the configuration in ovelray structure */
+ r = omapvid_init(vout, addr, uv_addr);
+ if (r)
+ printk(KERN_ERR VOUT_NAME
+ "failed to set overlay info\n");
+ /* Enable the pipeline and set the Go bit */
+ r = omapvid_apply_changes(vout);
+ if (r)
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+ } else {
+
+ if (vout->first_int) {
+ vout->first_int = 0;
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ if (irqstatus & DISPC_IRQ_EVSYNC_ODD) {
+ fid = 1;
+ } else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) {
+ fid = 0;
+ } else {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->field_id ^= 1;
+ if (fid != vout->field_id) {
+ if (0 == fid)
+ vout->field_id = fid;
+
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ if (0 == fid) {
+ if (vout->cur_frm == vout->next_frm) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->cur_frm->ts = timevalue;
+ vout->cur_frm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->cur_frm->done);
+ vout->cur_frm = vout->next_frm;
+ } else if (1 == fid) {
+ if (list_empty(&vout->dma_queue) ||
+ (vout->cur_frm != vout->next_frm)) {
+ spin_unlock(&vout->vbq_lock);
+ return;
+ }
+ vout->next_frm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ list_del(&vout->next_frm->queue);
+
+ vout->next_frm->state = VIDEOBUF_ACTIVE;
+ addr = (unsigned long)
+ vout->queued_buf_addr[vout->next_frm->i] +
+ vout->cropped_offset;
+ uv_addr = (unsigned long)
+ vout->queued_buf_uv_addr[vout->next_frm->i];
+
+ /* TODO: check the cropped offset part*/
+
+ /* First save the configuration in ovelray structure */
+ r = omapvid_init(vout, addr, uv_addr);
+ if (r)
+ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n");
+ /* Enable the pipeline and set the Go bit */
+ r = omapvid_apply_changes(vout);
+ if (r)
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
+ }
+
+ }
+ spin_unlock(&vout->vbq_lock);
+}
+
+static void omap_vout_cleanup_device(struct omap_vout_device *vout)
+{
+
+ struct video_device *vfd;
+
+ if (!vout)
+ return;
+ vfd = vout->vfd;
+
+ if (vfd) {
+ if (vfd->minor == -1) {
+ /*
+ * The device was never registered, so release the
+ * video_device struct directly.
+ */
+ video_device_release(vfd);
+ } else {
+ /*
+ * The unregister function will release the video_device
+ * struct as well as unregistering it.
+ */
+ video_unregister_device(vfd);
+ }
+ }
+
+#ifndef CONFIG_ARCH_OMAP4
+ omap_vout_release_vrfb(vout);
+#endif
+ omap_vout_free_buffers(vout);
+#ifdef CONFIG_ARCH_OMAP4
+ omap_vout_free_tiler_buffers(vout);
+ /* TODO: check if this needs to be done? */
+#else
+ /* Free the VRFB buffer if allocated
+ * init time
+ */
+ if (vout->vrfb_static_allocation)
+ omap_vout_free_vrfb_buffers(vout);
+#endif
+ kfree(vout);
+}
+
+static int __init omap_vout_init(void)
+{
+
+ if (platform_driver_register(&omap_vout_driver) != 0) {
+ printk(KERN_ERR VOUT_NAME ": could not register \
+ Video driver\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void omap_vout_cleanup(void)
+{
+ platform_driver_unregister(&omap_vout_driver);
+}
+
+late_initcall(omap_vout_init);
+module_exit(omap_vout_cleanup);
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
new file mode 100644
index 000000000000..700d6ccd347c
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -0,0 +1,160 @@
+/*
+ * drivers/media/video/omap/omap_voutdef.h
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef OMAP_VOUTDEF_H
+#define OMAP_VOUTDEF_H
+
+#include <mach/display.h>
+
+#define YUYV_BPP 2
+#define RGB565_BPP 2
+#define RGB24_BPP 3
+#define RGB32_BPP 4
+#define TILE_SIZE 32
+#define YUYV_VRFB_BPP 2
+#define RGB_VRFB_BPP 1
+#define MAX_CID 3
+
+#define MAC_VRFB_CTXS 4
+
+#ifdef CONFIG_ARCH_OMAP4 /* TODO: OMAP4 update displays and managers */
+#define MAX_VOUT_DEV 3
+#define MAX_OVLS 4
+#else
+#define MAX_VOUT_DEV 2
+#define MAX_OVLS 3
+#endif
+#define MAX_DISPLAYS 3
+#define MAX_MANAGERS 3
+
+/* Enum for Rotation
+ * DSS understands rotation in 0, 1, 2, 3 context
+ * while V4L2 driver understands it as 0, 90, 180, 270
+ */
+enum dss_rotation {
+ dss_rotation_0_degree = 0,
+ dss_rotation_90_degree = 1,
+ dss_rotation_180_degree = 2,
+ dss_rotation_270_degree = 3,
+};
+
+/*
+ * This structure is used to store the DMA transfer parameters
+ * for VRFB hidden buffer
+ */
+struct vid_vrfb_dma {
+ int dev_id;
+ int dma_ch;
+ int req_status;
+ int tx_status;
+ wait_queue_head_t wait;
+};
+
+struct omapvideo_info {
+ int id;
+ int num_overlays;
+ struct omap_overlay *overlays[MAX_OVLS];
+};
+
+struct omap2video_device {
+ struct mutex mtx;
+
+ int state;
+
+ struct v4l2_device v4l2_dev;
+ int num_videos;
+ struct omap_vout_device *vouts[MAX_VOUT_DEV];
+
+ int num_displays;
+ struct omap_dss_device *displays[MAX_DISPLAYS];
+ int num_overlays;
+ struct omap_overlay *overlays[MAX_OVLS];
+ int num_managers;
+ struct omap_overlay_manager *managers[MAX_MANAGERS];
+};
+
+/* per-device data structure */
+struct omap_vout_device {
+
+ struct omapvideo_info vid_info;
+ struct video_device *vfd;
+ struct omap2video_device *vid_dev;
+ int vid;
+ int opened;
+
+ /* we don't allow to change image fmt/size once buffer has
+ * been allocated
+ */
+ int buffer_allocated;
+ /* allow to reuse previosuly allocated buffer which is big enough */
+ int buffer_size;
+ /* keep buffer info accross opens */
+ unsigned long buf_virt_addr[VIDEO_MAX_FRAME];
+ unsigned long buf_phy_addr[VIDEO_MAX_FRAME];
+
+/* NV12 support*/
+ unsigned long buf_phy_uv_addr[VIDEO_MAX_FRAME];
+ u8 *queued_buf_uv_addr[VIDEO_MAX_FRAME];
+
+ enum omap_color_mode dss_mode;
+
+ /* we don't allow to request new buffer when old buffers are
+ * still mmaped
+ */
+ int mmap_count;
+
+ spinlock_t vbq_lock; /* spinlock for videobuf queues */
+ unsigned long field_count; /* field counter for videobuf_buffer */
+
+ /* non-NULL means streaming is in progress. */
+ bool streaming;
+
+ struct v4l2_pix_format pix;
+ struct v4l2_rect crop;
+ struct v4l2_window win;
+ struct v4l2_framebuffer fbuf;
+
+ /* Lock to protect the shared data structures in ioctl */
+ struct mutex lock;
+
+ /* V4L2 control structure for different control id */
+ struct v4l2_control control[MAX_CID];
+ enum dss_rotation rotation;
+ bool mirror;
+ int flicker_filter;
+ /* V4L2 control structure for different control id */
+
+ int bpp; /* bytes per pixel */
+ int vrfb_bpp; /* bytes per pixel with respect to VRFB */
+ struct vid_vrfb_dma vrfb_dma_tx;
+ unsigned int smsshado_phy_addr[MAC_VRFB_CTXS];
+ unsigned int smsshado_virt_addr[MAC_VRFB_CTXS];
+ struct vrfb vrfb_context[MAC_VRFB_CTXS];
+ bool vrfb_static_allocation;
+ unsigned int smsshado_size;
+ unsigned char pos;
+
+ int ps, vr_ps, line_length, first_int, field_id;
+ enum v4l2_memory memory;
+ struct videobuf_buffer *cur_frm, *next_frm;
+ struct list_head dma_queue;
+ u8 *queued_buf_addr[VIDEO_MAX_FRAME];
+ u32 cropped_offset;
+ s32 tv_field1_offset;
+ void *isr_handle;
+
+ /* Buffer queue variabled */
+ struct omap_vout_device *vout;
+ enum v4l2_buf_type type;
+ struct videobuf_queue vbq;
+ int io_allowed;
+
+};
+#endif /* ifndef OMAP_VOUTDEF_H */
diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c
new file mode 100644
index 000000000000..37fed10107cc
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutlib.c
@@ -0,0 +1,257 @@
+/*
+ * drivers/media/video/omap/omap_voutlib.c
+ *
+ * Copyright (C) 2005-2009 Texas Instruments.
+ *
+ * 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.
+ *
+ * Based on the OMAP2 camera driver
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP24xx camera controller.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+MODULE_AUTHOR("Texas Instruments.");
+MODULE_DESCRIPTION("OMAP Video library");
+MODULE_LICENSE("GPL");
+
+/* Return the default overlay cropping rectangle in crop given the image
+ * size in pix and the video display size in fbuf. The default
+ * cropping rectangle is the largest rectangle no larger than the capture size
+ * that will fit on the display. The default cropping rectangle is centered in
+ * the image. All dimensions and offsets are rounded down to even numbers.
+ */
+void omap_vout_default_crop(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop)
+{
+ crop->width = (pix->width < fbuf->fmt.width) ?
+ pix->width : fbuf->fmt.width;
+ crop->height = (pix->height < fbuf->fmt.height) ?
+ pix->height : fbuf->fmt.height;
+ crop->width &= ~1;
+ crop->height &= ~1;
+ crop->left = ((pix->width - crop->width) >> 1) & ~1;
+ crop->top = ((pix->height - crop->height) >> 1) & ~1;
+}
+EXPORT_SYMBOL_GPL(omap_vout_default_crop);
+
+/* Given a new render window in new_win, adjust the window to the
+ * nearest supported configuration. The adjusted window parameters are
+ * returned in new_win.
+ * Returns zero if succesful, or -EINVAL if the requested window is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win)
+{
+ struct v4l2_rect try_win;
+
+ /* make a working copy of the new_win rectangle */
+ try_win = new_win->w;
+
+ /* adjust the preview window so it fits on the display by clipping any
+ * offscreen areas
+ */
+ if (try_win.left < 0) {
+ try_win.width += try_win.left;
+ try_win.left = 0;
+ }
+ if (try_win.top < 0) {
+ try_win.height += try_win.top;
+ try_win.top = 0;
+ }
+ try_win.width = (try_win.width < fbuf->fmt.width) ?
+ try_win.width : fbuf->fmt.width;
+ try_win.height = (try_win.height < fbuf->fmt.height) ?
+ try_win.height : fbuf->fmt.height;
+ if (try_win.left + try_win.width > fbuf->fmt.width)
+ try_win.width = fbuf->fmt.width - try_win.left;
+ if (try_win.top + try_win.height > fbuf->fmt.height)
+ try_win.height = fbuf->fmt.height - try_win.top;
+ try_win.width &= ~1;
+ try_win.height &= ~1;
+
+ if (try_win.width <= 0 || try_win.height <= 0)
+ return -EINVAL;
+
+ /* We now have a valid preview window, so go with it */
+ new_win->w = try_win;
+ new_win->field = V4L2_FIELD_ANY;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_try_window);
+
+/* Given a new render window in new_win, adjust the window to the
+ * nearest supported configuration. The image cropping window in crop
+ * will also be adjusted if necessary. Preference is given to keeping the
+ * the window as close to the requested configuration as possible. If
+ * successful, new_win, vout->win, and crop are updated.
+ * Returns zero if succesful, or -EINVAL if the requested preview window is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_new_window(struct v4l2_rect *crop,
+ struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win)
+{
+ int err;
+
+ err = omap_vout_try_window(fbuf, new_win);
+ if (err)
+ return err;
+
+ /* update our preview window */
+ win->w = new_win->w;
+ win->field = new_win->field;
+ win->chromakey = new_win->chromakey;
+
+ /* adjust the cropping window to allow for resizing limitations */
+ if ((crop->height/win->w.height) >= 4) {
+ /* The maximum vertical downsizing ratio is 4:1 */
+ crop->height = win->w.height * 4;
+ }
+ if ((crop->width/win->w.width) >= 4) {
+ /* The maximum horizontal downsizing ratio is 4:1 */
+ crop->width = win->w.width * 4;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_window);
+
+/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
+ * the nearest supported configuration. The image render window in win will
+ * also be adjusted if necessary. The preview window is adjusted such that the
+ * horizontal and vertical rescaling ratios stay constant. If the render
+ * window would fall outside the display boundaries, the cropping rectangle
+ * will also be adjusted to maintain the rescaling ratios. If successful, crop
+ * and win are updated.
+ * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is
+ * impossible and cannot reasonably be adjusted.
+ */
+int omap_vout_new_crop(struct v4l2_pix_format *pix,
+ struct v4l2_rect *crop, struct v4l2_window *win,
+ struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop)
+{
+ struct v4l2_rect try_crop;
+ unsigned long vresize, hresize;
+
+ /* make a working copy of the new_crop rectangle */
+ try_crop = *new_crop;
+
+ /* adjust the cropping rectangle so it fits in the image */
+ if (try_crop.left < 0) {
+ try_crop.width += try_crop.left;
+ try_crop.left = 0;
+ }
+ if (try_crop.top < 0) {
+ try_crop.height += try_crop.top;
+ try_crop.top = 0;
+ }
+ try_crop.width = (try_crop.width < pix->width) ?
+ try_crop.width : pix->width;
+ try_crop.height = (try_crop.height < pix->height) ?
+ try_crop.height : pix->height;
+ if (try_crop.left + try_crop.width > pix->width)
+ try_crop.width = pix->width - try_crop.left;
+ if (try_crop.top + try_crop.height > pix->height)
+ try_crop.height = pix->height - try_crop.top;
+ try_crop.width &= ~1;
+ try_crop.height &= ~1;
+ if (try_crop.width <= 0 || try_crop.height <= 0)
+ return -EINVAL;
+
+ if (crop->height != win->w.height) {
+ /* If we're resizing vertically, we can't support a crop width
+ * wider than 768 pixels.
+ */
+ if (try_crop.width > 768)
+ try_crop.width = 768;
+ }
+ /* vertical resizing */
+ vresize = (1024 * crop->height) / win->w.height;
+ if (vresize > 4096)
+ vresize = 4096;
+ else if (vresize == 0)
+ vresize = 1;
+ win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
+ if (win->w.height == 0)
+ win->w.height = 2;
+ if (win->w.height + win->w.top > fbuf->fmt.height) {
+ /* We made the preview window extend below the bottom of the
+ * display, so clip it to the display boundary and resize the
+ * cropping height to maintain the vertical resizing ratio.
+ */
+ win->w.height = (fbuf->fmt.height - win->w.top) & ~1;
+ if (try_crop.height == 0)
+ try_crop.height = 2;
+ }
+ /* horizontal resizing */
+ hresize = (1024 * crop->width) / win->w.width;
+ if (hresize > 4096)
+ hresize = 4096;
+ else if (hresize == 0)
+ hresize = 1;
+ win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
+ if (win->w.width == 0)
+ win->w.width = 2;
+ if (win->w.width + win->w.left > fbuf->fmt.width) {
+ /* We made the preview window extend past the right side of the
+ * display, so clip it to the display boundary and resize the
+ * cropping width to maintain the horizontal resizing ratio.
+ */
+ win->w.width = (fbuf->fmt.width - win->w.left) & ~1;
+ if (try_crop.width == 0)
+ try_crop.width = 2;
+ }
+
+ /* Check for resizing constraints */
+ if ((try_crop.height/win->w.height) >= 4) {
+ /* The maximum vertical downsizing ratio is 4:1 */
+ try_crop.height = win->w.height * 4;
+ }
+ if ((try_crop.width/win->w.width) >= 4) {
+ /* The maximum horizontal downsizing ratio is 4:1 */
+ try_crop.width = win->w.width * 4;
+ }
+
+ /* update our cropping rectangle and we're done */
+ *crop = try_crop;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_crop);
+
+/* Given a new format in pix and fbuf, crop and win
+ * structures are initialized to default values. crop
+ * is initialized to the largest window size that will fit on the display. The
+ * crop window is centered in the image. win is initialized to
+ * the same size as crop and is centered on the display.
+ * All sizes and offsets are constrained to be even numbers.
+ */
+void omap_vout_new_format(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
+ struct v4l2_window *win)
+{
+ /* crop defines the preview source window in the image capture
+ * buffer
+ */
+ omap_vout_default_crop(pix, fbuf, crop);
+
+ /* win defines the preview target window on the display */
+ win->w.width = crop->width;
+ win->w.height = crop->height;
+ win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1;
+ win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1;
+}
+EXPORT_SYMBOL_GPL(omap_vout_new_format);
diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h
new file mode 100644
index 000000000000..8ef6e25b9e62
--- /dev/null
+++ b/drivers/media/video/omap/omap_voutlib.h
@@ -0,0 +1,34 @@
+/*
+ * drivers/media/video/omap/omap_voutlib.h
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef OMAP_VOUTLIB_H
+#define OMAP_VOUTLIB_H
+
+extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
+
+extern int omap_vout_new_crop(struct v4l2_pix_format *pix,
+ struct v4l2_rect *crop, struct v4l2_window *win,
+ struct v4l2_framebuffer *fbuf,
+ const struct v4l2_rect *new_crop);
+
+extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win);
+
+extern int omap_vout_new_window(struct v4l2_rect *crop,
+ struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
+ struct v4l2_window *new_win);
+
+extern void omap_vout_new_format(struct v4l2_pix_format *pix,
+ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
+ struct v4l2_window *win);
+#endif /* #ifndef OMAP_LIB_H */
+
diff --git a/drivers/media/video/tiler/dmm_hl_drv.c b/drivers/media/video/tiler/dmm_hl_drv.c
index d2e6298e4cbb..46959e7c0624 100755
--- a/drivers/media/video/tiler/dmm_hl_drv.c
+++ b/drivers/media/video/tiler/dmm_hl_drv.c
@@ -534,6 +534,7 @@ enum errorCodeT dmm_tiler_populate_pat_page_entry_data(unsigned long numPages,
#ifndef __NEWCODE__
patAreaEntries = kmalloc(
(size_t)(numPages*4 + 16), GFP_KERNEL);
+ ((numPages*4 + 16), GFP_KERNEL);
/* Must be 16-byte aligned. */
memset(patAreaEntries, 0x0, (numPages*4 + 16));
*pageEntriesSpace = patAreaEntries;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b91d66a767d7..3579a0a887ad 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -421,6 +421,8 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_CHROMA_AGC: return "Chroma AGC";
case V4L2_CID_COLOR_KILLER: return "Color Killer";
case V4L2_CID_COLORFX: return "Color Effects";
+ case V4L2_CID_ROTATE: return "Rotate";
+ case V4L2_CID_BG_COLOR: return "Background color";
/* MPEG controls */
case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
@@ -546,6 +548,13 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
min = max = step = def = 0;
break;
+ case V4L2_CID_BG_COLOR:
+ qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ step = 1;
+ min = 0;
+ /* Max is calculated as RGB888 that is 2^12*/
+ max = 0xFFFFFF;
+ break;
default:
qctrl->type = V4L2_CTRL_TYPE_INTEGER;
break;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index f2afc4e08379..eb0e962a02a0 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -277,6 +277,10 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
[_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
+
+ [_IOC_NR(VIDIOC_S_COL_SPC_CONV)] = "VIDIOC_S_COL_SPC_CONV",
+ [_IOC_NR(VIDIOC_G_COL_SPC_CONV)] = "VIDIOC_G_COL_SPC_CONV",
+
#endif
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -1784,6 +1788,26 @@ static long __video_do_ioctl(struct file *file,
break;
}
+ /*---------------Color space conversion------------------------------*/
+ case VIDIOC_S_COL_SPC_CONV:
+ {
+ struct v4l2_color_space_conversion *p = arg;
+ if (!ops->vidioc_s_color_space_conv)
+ break;
+
+ ret = ops->vidioc_s_color_space_conv(file, fh, p);
+ break;
+ }
+
+ case VIDIOC_G_COL_SPC_CONV:
+ {
+ struct v4l2_color_space_conversion *p = arg;
+ if (!ops->vidioc_g_color_space_conv)
+ break;
+ ret = ops->vidioc_g_color_space_conv(file, fh, p);
+ break;
+ }
+
default:
{
if (!ops->vidioc_default)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 491ac0f800d2..b8f38d5cd90f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -108,6 +108,27 @@ config TWL4030_CORE
high speed USB OTG transceiver, an audio codec (on most
versions) and many other features.
+config TWL6030_CORE
+ bool "Texas Instruments TWL6030 Support"
+ depends on I2C=y && GENERIC_HARDIRQS
+ depends on !TWL4030_CORE
+ help
+ Say yes here if you have TWL6030 family chip on your board.
+ This core driver provides register access and IRQ handling
+ facilities, and registers devices for the various functions
+ so that function-specific drivers can bind to them.
+
+ These multi-function chips are meant for OMAP4 processors,
+ providing power management, RTC, a USB transciever and a GPADC.
+
+config TWL6030_GPADC
+ tristate "TWL6030 GPADC (General Purpose A/D Convertor) Support"
+ depends on TWL6030_CORE
+ default n
+ help
+ Say yes here if you want support for the TWL6030 General Purpose
+ A/D Convertor.
+
config MFD_TMIO
bool
default n
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 6f8a9a1af20b..4a3c48ca833d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -22,7 +22,9 @@ obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
-obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
+obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o
+obj-$(CONFIG_TWL6030_CORE) += twl-core.o twl6030-irq.o
+obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl-core.c
index ca54996ffd0e..8653f851e2a8 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl-core.c
@@ -36,7 +36,7 @@
#include <linux/regulator/machine.h>
#include <linux/i2c.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
#include <mach/cpu.h>
@@ -55,7 +55,7 @@
* (and associated registers).
*/
-#define DRIVER_NAME "twl4030"
+#define DRIVER_NAME "twl"
#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
@@ -76,25 +76,45 @@
#define twl_has_gpio() false
#endif
-#if defined(CONFIG_REGULATOR_TWL4030) \
- || defined(CONFIG_REGULATOR_TWL4030_MODULE)
-#define twl_has_regulator() true
+#if defined(CONFIG_REGULATOR_TWL) \
+ || defined(CONFIG_REGULATOR_TWL_MODULE)
+#ifdef CONFIG_TWL4030_CORE
+#define twl_has_4030regulator() true
+#define twl_has_6030regulator() false
+#elif CONFIG_TWL6030_CORE
+#define twl_has_6030regulator() true
+#define twl_has_4030regulator() false
+#endif
#else
-#define twl_has_regulator() false
+#define twl_has_4030regulator() false
+#define twl_has_6030regulator() false
#endif
-#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
+#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) ||\
+ defined(CONFIG_TWL6030_GPADC) || defined(CONFIG_TWL6030_GPADC_MODULE)
#define twl_has_madc() true
#else
#define twl_has_madc() false
#endif
-#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
+#if defined(CONFIG_RTC_DRV_TWL) || defined(CONFIG_RTC_DRV_TWL_MODULE)
#define twl_has_rtc() true
#else
#define twl_has_rtc() false
#endif
+#if defined(CONFIG_TWL6030_CORE) /* FIXME add MMC CONFIG*/
+#define twl_has_mmc() true
+#else
+#define twl_has_mmc() false
+#endif
+
+#if defined(CONFIG_SND_SOC_ABE_TWL6030) || defined(CONFIG_SND_SOC_TWL6030_MODULE)
+#define twl_has_codec() true
+#else
+#define twl_has_codec() false
+#endif
+
#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
#define twl_has_usb() true
#else
@@ -110,13 +130,27 @@
/* Triton Core internal information (BEGIN) */
-/* Last - for index max*/
-#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
+#define TWL_NUM_SLAVES 4
-#define TWL4030_NUM_SLAVES 4
+#define SUB_CHIP_ID0 0
+#define SUB_CHIP_ID1 1
+#define SUB_CHIP_ID2 2
+#define SUB_CHIP_ID3 3
+#ifdef CONFIG_TWL4030_CORE
+#define USB_SUB_CHIP_ID SUB_CHIP_ID0
+#define GPIO_SUB_CHIP_ID SUB_CHIP_ID1
+#define MADC_SUB_CHIP_ID SUB_CHIP_ID2
+#define KEYPAD_SUB_CHIP_ID SUB_CHIP_ID2
+#define BCI_SUB_CHIP_ID SUB_CHIP_ID3
+#define RTC_SUB_CHIP_ID SUB_CHIP_ID3
+#define REG_SUB_CHIP_ID SUB_CHIP_ID3
-/* Base Address defns for twl4030_map[] */
+/* Last - for index max*/
+#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
+#define TWL_MODULE_LAST TWL4030_MODULE_LAST
+
+/* Base Address defns for twl_map[] */
/* subchip/slave 0 - USB ID */
#define TWL4030_BASEADD_USB 0x0000
@@ -147,10 +181,53 @@
#define TWL4030_BASEADD_PM_RECEIVER 0x005B
#define TWL4030_BASEADD_RTC 0x001C
#define TWL4030_BASEADD_SECURED_REG 0x0000
-
+#endif /* CONFIG_TWL4030_CORE */
/* Triton Core internal information (END) */
+#ifdef CONFIG_TWL6030_CORE
+#define TWL6030_MODULE_LAST TWL6030_MODULE_AUDIO
+#define TWL_MODULE_LAST TWL6030_MODULE_LAST
+
+#define RTC_SUB_CHIP_ID SUB_CHIP_ID0
+#define REG_SUB_CHIP_ID SUB_CHIP_ID0
+#define MMC_SUB_CHIP_ID SUB_CHIP_ID0
+#define USB_SUB_CHIP_ID SUB_CHIP_ID1
+#define MADC_SUB_CHIP_ID SUB_CHIP_ID1
+#define BCI_SUB_CHIP_ID SUB_CHIP_ID1
+#define GPIO_SUB_CHIP_ID 0 /* NOT SUPPORTED IN TWL6030 */
+#define KEYPAD_SUB_CHIP_ID 0 /* ADDED FOR COMPILATION ONLY */
+#define CODEC_SUB_CHIP_ID SUB_CHIP_ID3
+
+/* subchip/slave 0 0x48 - POWER */
+#define TWL6030_BASEADD_RTC 0x0000
+#define TWL6030_BASEADD_MEM 0x0017
+#define TWL6030_BASEADD_PM_MASTER 0x001F
+#define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030
+#define TWL6030_BASEADD_PM_SLAVE_SMPS 0x0040
+#define TWL6030_BASEADD_PM_SLAVE_LDO 0x0080
+#define TWL6030_BASEADD_PM_SLAVE_RES 0x00AD
+#define TWL6030_BASEADD_PM_MISC 0x00E2
+#define TWL6030_BASEADD_PM_PUPD 0x00F0
+
+/* subchip/slave 1 0x49 - FEATURE */
+#define TWL6030_BASEADD_USB 0x0000
+#define TWL6030_BASEADD_GPADC_CTRL 0x0030
+#define TWL6030_BASEADD_GPADC_RT 0x0035
+#define TWL6030_BASEADD_GPADC 0x005D
+#define TWL6030_BASEADD_AUX 0x0090
+#define TWL6030_BASEADD_PWM 0x00BA
+#define TWL6030_BASEADD_GASGAUGE 0x00C0
+#define TWL6030_BASEADD_PIH 0x00D0
+#define TWL6030_BASEADD_CHARGER 0x00E0
+
+/* subchip/slave 2 0x4A - DFT */
+#define TWL6030_BASEADD_DIEID 0x00C0
+
+/* subchip/slave 3 0x4B - AUDIO */
+#define TWL6030_BASEADD_AUDIO 0x0000
+#endif /* CONFIG_TWL6030_CORE */
+
/* Few power values */
#define R_CFG_BOOT 0x05
#define R_PROTECT_KEY 0x0E
@@ -176,8 +253,8 @@
/* is driver active, bound to a chip? */
static bool inuse;
-/* Structure for each TWL4030 Slave */
-struct twl4030_client {
+/* Structure for each TWL4030/TWL6030 Slave */
+struct twl_client {
struct i2c_client *client;
u8 address;
@@ -188,16 +265,17 @@ struct twl4030_client {
struct mutex xfer_lock;
};
-static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES];
+static struct twl_client twl_modules[TWL_NUM_SLAVES];
/* mapping the module id to slave id and base address */
-struct twl4030mapping {
+struct twl_mapping {
unsigned char sid; /* Slave ID */
unsigned char base; /* base address */
};
-static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
+#ifdef CONFIG_TWL4030_CORE
+static struct twl_mapping twl_map[TWL4030_MODULE_LAST + 1] = {
/*
* NOTE: don't change this table without updating the
* <linux/i2c/twl4030.h> defines for TWL4030_MODULE_*
@@ -230,13 +308,47 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
{ 3, TWL4030_BASEADD_RTC },
{ 3, TWL4030_BASEADD_SECURED_REG },
};
+#endif
+
+#ifdef CONFIG_TWL6030_CORE
+static struct twl_mapping twl_map[TWL6030_MODULE_LAST + 1] = {
+ /*
+ * NOTE: don't change this table without updating the
+ * <linux/i2c/twl6030.h> defines for TWL6030_MODULE_*
+ * so they continue to match the order in this table.
+ */
+ { SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_SMPS },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_LDO },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_RES },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MISC },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_PM_PUPD },
+
+ { SUB_CHIP_ID1, TWL6030_BASEADD_USB },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_RT },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_AUX },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
+
+ { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
+
+ { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO },
+};
+#endif
/*----------------------------------------------------------------------*/
/* Exported Functions */
/**
- * twl4030_i2c_write - Writes a n bit register in TWL4030
+ * twl_i2c_write - Writes a n bit register in TWL4030/TWL6030
* @mod_no: module number
* @value: an array of num_bytes+1 containing data to write
* @reg: register address (just offset will do)
@@ -247,19 +359,19 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
*
* Returns the result of operation - 0 is success
*/
-int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
+int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
int sid;
- struct twl4030_client *twl;
+ struct twl_client *twl;
struct i2c_msg *msg;
- if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
+ if (unlikely(mod_no > TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
- sid = twl4030_map[mod_no].sid;
- twl = &twl4030_modules[sid];
+ sid = twl_map[mod_no].sid;
+ twl = &twl_modules[sid];
if (unlikely(!inuse)) {
pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
@@ -276,7 +388,7 @@ int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
msg->flags = 0;
msg->buf = value;
/* over write the first byte of buffer with the register address */
- *value = twl4030_map[mod_no].base + reg;
+ *value = twl_map[mod_no].base + reg;
ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
mutex_unlock(&twl->xfer_lock);
@@ -285,10 +397,10 @@ int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
ret = 0;
return ret;
}
-EXPORT_SYMBOL(twl4030_i2c_write);
+EXPORT_SYMBOL(twl_i2c_write);
/**
- * twl4030_i2c_read - Reads a n bit register in TWL4030
+ * twl_i2c_read - Reads a n bit register in TWL4030/TWL6030
* @mod_no: module number
* @value: an array of num_bytes containing data to be read
* @reg: register address (just offset will do)
@@ -296,20 +408,20 @@ EXPORT_SYMBOL(twl4030_i2c_write);
*
* Returns result of operation - num_bytes is success else failure.
*/
-int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
+int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
u8 val;
int sid;
- struct twl4030_client *twl;
+ struct twl_client *twl;
struct i2c_msg *msg;
- if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
+ if (unlikely(mod_no > TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
- sid = twl4030_map[mod_no].sid;
- twl = &twl4030_modules[sid];
+ sid = twl_map[mod_no].sid;
+ twl = &twl_modules[sid];
if (unlikely(!inuse)) {
pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
@@ -321,7 +433,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
msg->addr = twl->address;
msg->len = 1;
msg->flags = 0; /* Read the register value */
- val = twl4030_map[mod_no].base + reg;
+ val = twl_map[mod_no].base + reg;
msg->buf = &val;
/* [MSG2] fill the data rx buffer */
msg = &twl->xfer_msg[1];
@@ -337,40 +449,40 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
ret = 0;
return ret;
}
-EXPORT_SYMBOL(twl4030_i2c_read);
+EXPORT_SYMBOL(twl_i2c_read);
/**
- * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
+ * twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL6030
* @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)
+int twl_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);
+ return twl_i2c_write(mod_no, temp_buffer, reg, 1);
}
-EXPORT_SYMBOL(twl4030_i2c_write_u8);
+EXPORT_SYMBOL(twl_i2c_write_u8);
/**
- * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030
+ * twl_i2c_read_u8 - Reads a 8 bit register from TWL4030/TWL6030
* @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)
+int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
{
- return twl4030_i2c_read(mod_no, value, reg, 1);
+ return twl_i2c_read(mod_no, value, reg, 1);
}
-EXPORT_SYMBOL(twl4030_i2c_read_u8);
+EXPORT_SYMBOL(twl_i2c_read_u8);
/*----------------------------------------------------------------------*/
@@ -380,7 +492,7 @@ add_numbered_child(unsigned chip, const char *name, int num,
bool can_wakeup, int irq0, int irq1)
{
struct platform_device *pdev;
- struct twl4030_client *twl = &twl4030_modules[chip];
+ struct twl_client *twl = &twl_modules[chip];
int status;
pdev = platform_device_alloc(name, num);
@@ -448,7 +560,7 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
}
/* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
- return add_numbered_child(3, "twl4030_reg", num,
+ return add_numbered_child(REG_SUB_CHIP_ID, "twl_reg", num,
pdata, sizeof(*pdata), false, 0, 0);
}
@@ -465,41 +577,56 @@ add_regulator(int num, struct regulator_init_data *pdata)
*/
static int
-add_children(struct twl4030_platform_data *pdata, unsigned long features)
+add_children(struct twl_platform_data *pdata, unsigned long features)
{
struct device *child;
struct device *usb_transceiver = NULL;
if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) {
- child = add_child(3, "twl4030_bci",
+#if defined(CONFIG_TWL4030_CORE)
+ child = add_child(BCI_SUB_CHIP_ID, "twl_bci",
pdata->bci, sizeof(*pdata->bci),
false,
/* irq0 = CHG_PRES, irq1 = BCI */
- pdata->irq_base + 8 + 1, pdata->irq_base + 2);
+ pdata->irq_base + BCI_PRES_INTR_OFFSET,
+ pdata->irq_base + BCI_INTR_OFFSET);
+#elif defined(CONFIG_TWL6030_CORE)
+ child = add_child(BCI_SUB_CHIP_ID, "twl_charger_ctrl",
+ pdata->bci, sizeof(*pdata->bci),
+ false,
+ pdata->irq_base + CHARGER_INTR_OFFSET, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_child(BCI_SUB_CHIP_ID, "twl_charger_fault",
+ pdata->bci, sizeof(*pdata->bci),
+ false,
+ pdata->irq_base + CHARGER_INTR_OFFSET, 0);
+#endif
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_gpio() && pdata->gpio) {
- child = add_child(1, "twl4030_gpio",
+ child = add_child(GPIO_SUB_CHIP_ID, "twl4030_gpio",
pdata->gpio, sizeof(*pdata->gpio),
- false, pdata->irq_base + 0, 0);
+ false, pdata->irq_base + GPIO_INTR_OFFSET, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_keypad() && pdata->keypad) {
- child = add_child(2, "twl4030_keypad",
+ child = add_child(KEYPAD_SUB_CHIP_ID, "twl4030_keypad",
pdata->keypad, sizeof(*pdata->keypad),
- true, pdata->irq_base + 1, 0);
+ true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_madc() && pdata->madc) {
- child = add_child(2, "twl4030_madc",
+ child = add_child(MADC_SUB_CHIP_ID, "twl_madc",
pdata->madc, sizeof(*pdata->madc),
- true, pdata->irq_base + 3, 0);
+ true, pdata->irq_base + MADC_INTR_OFFSET, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
@@ -512,19 +639,38 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
* Eventually, Linux might become more aware of such
* HW security concerns, and "least privilege".
*/
- child = add_child(3, "twl4030_rtc",
+ child = add_child(RTC_SUB_CHIP_ID, "twl_rtc",
NULL, 0,
- true, pdata->irq_base + 8 + 3, 0);
+ true, pdata->irq_base + RTC_INTR_OFFSET, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
+#ifdef CONFIG_TWL6030_CORE
+ if (twl_has_mmc()) {
+ child = add_child(MMC_SUB_CHIP_ID, "twl_mmc",
+ NULL, 0, true,
+ pdata->irq_base + MMCDETECT_INTR_OFFSET, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ if (twl_has_codec()) {
+ child = add_child(CODEC_SUB_CHIP_ID, "twl6030_codec",
+ pdata->codec, sizeof(*pdata->codec), false,
+ 0, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+#endif
+
if (twl_has_usb() && pdata->usb) {
- child = add_child(0, "twl4030_usb",
+ child = add_child(USB_SUB_CHIP_ID, "twl4030_usb",
pdata->usb, sizeof(*pdata->usb),
true,
/* irq0 = USB_PRES, irq1 = USB */
- pdata->irq_base + 8 + 2, pdata->irq_base + 4);
+ pdata->irq_base + USB_PRES_INTR_OFFSET,
+ pdata->irq_base + USB_INTR_OFFSET);
if (IS_ERR(child))
return PTR_ERR(child);
@@ -538,7 +684,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
- if (twl_has_regulator()) {
+ if (twl_has_4030regulator()) {
/*
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
if (IS_ERR(child))
@@ -561,7 +707,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
- if (twl_has_regulator() && usb_transceiver) {
+ if (twl_has_4030regulator() && usb_transceiver) {
static struct regulator_consumer_supply usb1v5 = {
.supply = "usb1v5",
};
@@ -603,7 +749,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
}
/* maybe add LDOs that are omitted on cost-reduced parts */
- if (twl_has_regulator() && !(features & TPS_SUBSET)) {
+ if (twl_has_4030regulator() && !(features & TPS_SUBSET)) {
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
if (IS_ERR(child))
return PTR_ERR(child);
@@ -629,6 +775,49 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
+ /* twl6030 regulators */
+ if (twl_has_6030regulator()) {
+ child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VPP, pdata->vpp);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VANA, pdata->vana);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VDAC, pdata->vdac);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VUSB, pdata->vusb);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
return 0;
}
@@ -643,7 +832,7 @@ static inline int __init protect_pm_master(void)
{
int e = 0;
- e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
+ e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_LOCK,
R_PROTECT_KEY);
return e;
}
@@ -652,9 +841,9 @@ static inline int __init unprotect_pm_master(void)
{
int e = 0;
- e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
+ e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK1,
R_PROTECT_KEY);
- e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
+ e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK2,
R_PROTECT_KEY);
return e;
}
@@ -673,7 +862,7 @@ static void clocks_init(struct device *dev)
osc = clk_get(dev, "osc_sys_ck");
if (IS_ERR(osc)) {
- printk(KERN_WARNING "Skipping twl4030 internal clock init and "
+ printk(KERN_WARNING "Skipping twl internal clock init and "
"using bootloader value (unknown osc rate)\n");
return;
}
@@ -687,7 +876,7 @@ static void clocks_init(struct device *dev)
*/
osc = ERR_PTR(-EIO);
- printk(KERN_WARNING "Skipping twl4030 internal clock init and "
+ printk(KERN_WARNING "Skipping twl internal clock init and "
"using bootloader value (unknown osc rate)\n");
return;
@@ -708,7 +897,7 @@ static void clocks_init(struct device *dev)
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 |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
e |= protect_pm_master();
if (e < 0)
@@ -717,10 +906,7 @@ static void clocks_init(struct device *dev)
/*----------------------------------------------------------------------*/
-int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
-int twl_exit_irq(void);
-
-static int twl4030_remove(struct i2c_client *client)
+static int twl_remove(struct i2c_client *client)
{
unsigned i;
int status;
@@ -729,12 +915,12 @@ static int twl4030_remove(struct i2c_client *client)
if (status < 0)
return status;
- for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
- struct twl4030_client *twl = &twl4030_modules[i];
+ for (i = 0; i < TWL_NUM_SLAVES; i++) {
+ struct twl_client *twl = &twl_modules[i];
if (twl->client && twl->client != client)
i2c_unregister_device(twl->client);
- twl4030_modules[i].client = NULL;
+ twl_modules[i].client = NULL;
}
inuse = false;
return 0;
@@ -742,11 +928,11 @@ static int twl4030_remove(struct i2c_client *client)
/* NOTE: this driver only handles a single twl4030/tps659x0 chip */
static int
-twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
+twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int status;
unsigned i;
- struct twl4030_platform_data *pdata = client->dev.platform_data;
+ struct twl_platform_data *pdata = client->dev.platform_data;
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
@@ -763,8 +949,8 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EBUSY;
}
- for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
- struct twl4030_client *twl = &twl4030_modules[i];
+ for (i = 0; i < TWL_NUM_SLAVES; i++) {
+ struct twl_client *twl = &twl_modules[i];
twl->address = client->addr + i;
if (i == 0)
@@ -792,7 +978,8 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (client->irq
&& pdata->irq_base
&& pdata->irq_end > pdata->irq_base) {
- status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end);
+ status = twl_init_irq(client->irq, pdata->irq_base,
+ pdata->irq_end);
if (status < 0)
goto fail;
}
@@ -800,40 +987,41 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
status = add_children(pdata, id->driver_data);
fail:
if (status < 0)
- twl4030_remove(client);
+ twl_remove(client);
return status;
}
-static const struct i2c_device_id twl4030_ids[] = {
+static const struct i2c_device_id twl_ids[] = {
{ "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */
{ "twl5030", 0 }, /* T2 updated */
{ "tps65950", 0 }, /* catalog version of twl5030 */
{ "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
{ "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
+ { "twl6030", 0 }, /* "Phoenix power chip" */
{ /* end of list */ },
};
-MODULE_DEVICE_TABLE(i2c, twl4030_ids);
+MODULE_DEVICE_TABLE(i2c, twl_ids);
/* One Client Driver , 4 Clients */
-static struct i2c_driver twl4030_driver = {
+static struct i2c_driver twl_driver = {
.driver.name = DRIVER_NAME,
- .id_table = twl4030_ids,
- .probe = twl4030_probe,
- .remove = twl4030_remove,
+ .id_table = twl_ids,
+ .probe = twl_probe,
+ .remove = twl_remove,
};
-static int __init twl4030_init(void)
+static int __init twl_init(void)
{
- return i2c_add_driver(&twl4030_driver);
+ return i2c_add_driver(&twl_driver);
}
-subsys_initcall(twl4030_init);
+subsys_initcall(twl_init);
-static void __exit twl4030_exit(void)
+static void __exit twl_exit(void)
{
- i2c_del_driver(&twl4030_driver);
+ i2c_del_driver(&twl_driver);
}
-module_exit(twl4030_exit);
+module_exit(twl_exit);
MODULE_AUTHOR("Texas Instruments, Inc.");
-MODULE_DESCRIPTION("I2C Core interface for TWL4030");
+MODULE_DESCRIPTION("I2C Core interface for TWL");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 7d430835655f..2b0cdff8b101 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -32,7 +32,7 @@
#include <linux/irq.h>
#include <linux/kthread.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
/*
@@ -194,7 +194,7 @@ static int twl4030_irq_thread(void *data)
/* Wait for IRQ, then read PIH irq status (also blocking) */
wait_for_completion_interruptible(&irq_event);
- ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
+ ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
REG_PIH_ISR_P1);
if (ret) {
pr_warning("twl4030: I2C error %d reading PIH ISR\n",
@@ -290,7 +290,7 @@ static int twl4030_init_sih_modules(unsigned line)
if (!sih->bytes_ixr)
continue;
- status = twl4030_i2c_write(sih->module, buf,
+ status = twl_i2c_write(sih->module, buf,
sih->mask[line].imr_offset, sih->bytes_ixr);
if (status < 0)
pr_err("twl4030: err %d initializing %s %s\n",
@@ -304,7 +304,7 @@ static int twl4030_init_sih_modules(unsigned line)
* And for PWR_INT it's not documented...
*/
if (sih->set_cor) {
- status = twl4030_i2c_write_u8(sih->module,
+ status = twl_i2c_write_u8(sih->module,
TWL4030_SIH_CTRL_COR_MASK,
sih->control_offset);
if (status < 0)
@@ -328,14 +328,14 @@ static int twl4030_init_sih_modules(unsigned line)
* uncommon with PWR_INT.PWRON.
*/
for (j = 0; j < 2; j++) {
- status = twl4030_i2c_read(sih->module, rxbuf,
+ status = twl_i2c_read(sih->module, rxbuf,
sih->mask[line].isr_offset, sih->bytes_ixr);
if (status < 0)
pr_err("twl4030: err %d initializing %s %s\n",
status, sih->name, "ISR");
if (!sih->set_cor)
- status = twl4030_i2c_write(sih->module, buf,
+ status = twl_i2c_write(sih->module, buf,
sih->mask[line].isr_offset,
sih->bytes_ixr);
/* else COR=1 means read sufficed.
@@ -404,7 +404,7 @@ static void twl4030_sih_do_mask(struct work_struct *work)
return;
/* write the whole mask ... simpler than subsetting it */
- status = twl4030_i2c_write(sih->module, imr.bytes,
+ status = twl_i2c_write(sih->module, imr.bytes,
sih->mask[irq_line].imr_offset, sih->bytes_ixr);
if (status)
pr_err("twl4030: %s, %s --> %d\n", __func__,
@@ -435,7 +435,7 @@ static void twl4030_sih_do_edge(struct work_struct *work)
* any processor on the other IRQ line, EDR registers are
* shared.
*/
- status = twl4030_i2c_read(sih->module, bytes + 1,
+ status = twl_i2c_read(sih->module, bytes + 1,
sih->edr_offset, sih->bytes_edr);
if (status) {
pr_err("twl4030: %s, %s --> %d\n", __func__,
@@ -469,7 +469,7 @@ static void twl4030_sih_do_edge(struct work_struct *work)
}
/* Write */
- status = twl4030_i2c_write(sih->module, bytes,
+ status = twl_i2c_write(sih->module, bytes,
sih->edr_offset, sih->bytes_edr);
if (status)
pr_err("twl4030: %s, %s --> %d\n", __func__,
@@ -554,7 +554,7 @@ static inline int sih_read_isr(const struct sih *sih)
/* FIXME need retry-on-error ... */
isr.word = 0;
- status = twl4030_i2c_read(sih->module, isr.bytes,
+ status = twl_i2c_read(sih->module, isr.bytes,
sih->mask[irq_line].isr_offset, sih->bytes_ixr);
return (status < 0) ? status : le32_to_cpu(isr.word);
diff --git a/drivers/mfd/twl6030-gpadc.c b/drivers/mfd/twl6030-gpadc.c
new file mode 100644
index 000000000000..6bc169562000
--- /dev/null
+++ b/drivers/mfd/twl6030-gpadc.c
@@ -0,0 +1,444 @@
+/*
+ * drivers/i2c/chips/twl6030-gpadc.c
+ *
+ * TWL6030 GPADC module driver
+ *
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Nishant Kamat <nskamat@ti.com>
+ *
+ * Based on twl4030-madc.c
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c/twl.h>
+#include <linux/i2c/twl6030-gpadc.h>
+
+#include <linux/uaccess.h>
+
+#define TWL6030_GPADC_PFX "twl6030-gpadc: "
+
+struct twl6030_gpadc_data {
+ struct device *dev;
+ struct mutex lock;
+ struct work_struct ws;
+ struct twl6030_gpadc_request requests[TWL6030_GPADC_NUM_METHODS];
+ int irq_n;
+};
+
+static struct twl6030_gpadc_data *the_gpadc;
+
+static
+const struct twl6030_gpadc_conversion_method twl6030_conversion_methods[] = {
+ [TWL6030_GPADC_RT] = {
+ .sel = TWL6030_GPADC_RTSELECT_LSB,
+ .rbase = TWL6030_GPADC_RTCH0_LSB,
+ },
+ [TWL6030_GPADC_SW1] = {
+ .rbase = TWL6030_GPADC_GPCH0_LSB,
+ .ctrl = TWL6030_GPADC_CTRL_P1,
+ .enable = TWL6030_GPADC_CTRL_P1_SP1,
+ },
+ [TWL6030_GPADC_SW2] = {
+ .rbase = TWL6030_GPADC_GPCH0_LSB,
+ .ctrl = TWL6030_GPADC_CTRL_P2,
+ .enable = TWL6030_GPADC_CTRL_P2_SP2,
+ },
+};
+
+static int twl6030_gpadc_read(struct twl6030_gpadc_data *gpadc, u8 reg)
+{
+ int ret;
+ u8 val;
+
+ ret = twl_i2c_read_u8(TWL6030_MODULE_GPADC, &val, reg);
+ if (ret) {
+ dev_dbg(gpadc->dev, "unable to read register 0x%X\n", reg);
+ return ret;
+ }
+
+ return val;
+}
+
+static void twl6030_gpadc_write(struct twl6030_gpadc_data *gpadc,
+ u8 reg, u8 val)
+{
+ int ret;
+
+ ret = twl_i2c_write_u8(TWL6030_MODULE_GPADC, val, reg);
+ if (ret)
+ dev_err(gpadc->dev, "unable to write register 0x%X\n", reg);
+}
+
+static int twl6030_gpadc_channel_raw_read(struct twl6030_gpadc_data *gpadc,
+ u8 reg)
+{
+ u8 msb, lsb;
+
+ /* For each ADC channel, we have MSB and LSB register pair. MSB address
+ * is always LSB address+1. reg parameter is the addr of LSB register */
+ msb = twl6030_gpadc_read(gpadc, reg + 1);
+ lsb = twl6030_gpadc_read(gpadc, reg);
+
+ return (int)(((msb << 8) | lsb) >> 6);
+}
+
+static int twl6030_gpadc_read_channels(struct twl6030_gpadc_data *gpadc,
+ u8 reg_base, u16 channels, int *buf)
+{
+ int count = 0;
+ u8 reg, i;
+
+ if (unlikely(!buf))
+ return 0;
+
+ for (i = 0; i < TWL6030_GPADC_MAX_CHANNELS; i++) {
+ if (channels & (1<<i)) {
+ reg = reg_base + 2*i;
+ buf[i] = twl6030_gpadc_channel_raw_read(gpadc, reg);
+ count++;
+ }
+ }
+ return count;
+}
+
+static void twl6030_gpadc_enable_irq(struct twl6030_gpadc_data *gpadc, int id)
+{
+ twl_int_mask_reset(TWL6030_GPADC_INT_MASK, REG_INT_MSK_LINE_B);
+}
+
+static void twl6030_gpadc_disable_irq(struct twl6030_gpadc_data *gpadc, int id)
+{
+ twl_int_mask_set(TWL6030_GPADC_INT_MASK, REG_INT_MSK_LINE_B);
+}
+
+static irqreturn_t twl6030_gpadc_irq_handler(int irq, void *_gpadc)
+{
+ struct twl6030_gpadc_data *gpadc = _gpadc;
+ int i = 0;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
+
+ twl6030_gpadc_disable_irq(gpadc, i);
+
+ /* Find the cause of the interrupt and enable the pending
+ bit for the corresponding method */
+ /* gpadc->requests[i].result_pending = 1; */
+
+ schedule_work(&gpadc->ws);
+
+ return IRQ_HANDLED;
+}
+
+static void twl6030_gpadc_work(struct work_struct *ws)
+{
+ const struct twl6030_gpadc_conversion_method *method;
+ struct twl6030_gpadc_data *gpadc;
+ struct twl6030_gpadc_request *r;
+ int len, i;
+
+ gpadc = container_of(ws, struct twl6030_gpadc_data, ws);
+ mutex_lock(&gpadc->lock);
+
+ for (i = 0; i < TWL6030_GPADC_NUM_METHODS; i++) {
+
+ r = &gpadc->requests[i];
+
+ /* No pending results for this method, move to next one */
+ if (!r->result_pending)
+ continue;
+
+ method = &twl6030_conversion_methods[r->method];
+
+ /* Read results */
+ len = twl6030_gpadc_read_channels(gpadc, method->rbase,
+ r->channels, r->rbuf);
+
+ /* Return results to caller */
+ if (r->func_cb != NULL) {
+ r->func_cb(len, r->channels, r->rbuf);
+ r->func_cb = NULL;
+ }
+
+ /* Free request */
+ r->result_pending = 0;
+ r->active = 0;
+ }
+
+ mutex_unlock(&gpadc->lock);
+}
+
+static int twl6030_gpadc_set_irq(struct twl6030_gpadc_data *gpadc,
+ struct twl6030_gpadc_request *req)
+{
+ struct twl6030_gpadc_request *p;
+
+ p = &gpadc->requests[req->method];
+
+ memcpy(p, req, sizeof *req);
+
+ twl6030_gpadc_enable_irq(gpadc, req->method);
+
+ return 0;
+}
+
+static inline void
+twl6030_gpadc_start_conversion(struct twl6030_gpadc_data *gpadc,
+ int conv_method)
+{
+ const struct twl6030_gpadc_conversion_method *method;
+
+ method = &twl6030_conversion_methods[conv_method];
+
+ switch (conv_method) {
+ case TWL6030_GPADC_SW1:
+ case TWL6030_GPADC_SW2:
+ twl6030_gpadc_write(gpadc, method->ctrl, method->enable);
+ break;
+ case TWL6030_GPADC_RT:
+ default:
+ break;
+ }
+}
+
+static int twl6030_gpadc_wait_conversion_ready(
+ struct twl6030_gpadc_data *gpadc,
+ unsigned int timeout_ms, u8 status_reg)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ do {
+ u8 reg;
+
+ reg = twl6030_gpadc_read(gpadc, status_reg);
+ if (!(reg & TWL6030_GPADC_BUSY) && (reg & TWL6030_GPADC_EOC_SW))
+ return 0;
+ } while (!time_after(jiffies, timeout));
+
+ return -EAGAIN;
+}
+
+int twl6030_gpadc_conversion(struct twl6030_gpadc_request *req)
+{
+ const struct twl6030_gpadc_conversion_method *method;
+ u8 ch_msb, ch_lsb;
+ int ret = 0;
+
+ if (unlikely(!req))
+ return -EINVAL;
+
+ mutex_lock(&the_gpadc->lock);
+
+ /* Do we have a conversion request ongoing */
+ if (the_gpadc->requests[req->method].active) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (req->method == TWL6030_GPADC_RT) {
+ ch_msb = (req->channels >> 8) & 0xff;
+ ch_lsb = req->channels & 0xff;
+ twl6030_gpadc_write(the_gpadc, method->sel + 1, ch_msb);
+ twl6030_gpadc_write(the_gpadc, method->sel, ch_lsb);
+ goto out;
+ }
+
+ method = &twl6030_conversion_methods[req->method];
+
+ twl6030_gpadc_start_conversion(the_gpadc, req->method);
+ the_gpadc->requests[req->method].active = 1;
+
+ /* Wait until conversion is ready (ctrl register returns EOC) */
+ ret = twl6030_gpadc_wait_conversion_ready(the_gpadc, 5, method->ctrl);
+ if (ret) {
+ dev_dbg(the_gpadc->dev, "conversion timeout!\n");
+ the_gpadc->requests[req->method].active = 0;
+ goto out;
+ }
+
+ ret = twl6030_gpadc_read_channels(the_gpadc, method->rbase,
+ req->channels, req->rbuf);
+ the_gpadc->requests[req->method].active = 0;
+
+out:
+ mutex_unlock(&the_gpadc->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(twl6030_gpadc_conversion);
+
+
+static long twl6030_gpadc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct twl6030_gpadc_user_parms par;
+ int val, ret;
+
+ ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
+ if (ret) {
+ dev_dbg(the_gpadc->dev, "copy_from_user: %d\n", ret);
+ return -EACCES;
+ }
+
+ switch (cmd) {
+ case TWL6030_GPADC_IOCX_ADC_RAW_READ: {
+ struct twl6030_gpadc_request req;
+ if (par.channel >= TWL6030_GPADC_MAX_CHANNELS)
+ return -EINVAL;
+
+ req.channels = (1 << par.channel);
+ req.method = TWL6030_GPADC_SW1;
+ req.func_cb = NULL;
+
+ val = twl6030_gpadc_conversion(&req);
+ if (val <= 0) {
+ par.status = -1;
+ } else {
+ par.status = 0;
+ par.result = (u16)req.rbuf[par.channel];
+ }
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ ret = copy_to_user((void __user *) arg, &par, sizeof(par));
+ if (ret) {
+ dev_dbg(the_gpadc->dev, "copy_to_user: %d\n", ret);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static const struct file_operations twl6030_gpadc_fileops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = twl6030_gpadc_ioctl
+};
+
+static struct miscdevice twl6030_gpadc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "twl6030-gpadc",
+ .fops = &twl6030_gpadc_fileops
+};
+
+static int __init twl6030_gpadc_probe(struct platform_device *pdev)
+{
+ struct twl6030_gpadc_data *gpadc;
+ struct twl6030_gpadc_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ gpadc = kzalloc(sizeof *gpadc, GFP_KERNEL);
+ if (!gpadc)
+ return -ENOMEM;
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "platform_data not available\n");
+ ret = -EINVAL;
+ goto err_pdata;
+ }
+
+ ret = misc_register(&twl6030_gpadc_device);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not register misc_device\n");
+ goto err_misc;
+ }
+
+ ret = request_irq(platform_get_irq(pdev, 0), twl6030_gpadc_irq_handler,
+ 0, "twl_madc", gpadc);
+
+
+ twl_int_mask_reset(TWL6030_GPADC_INT_MASK, REG_INT_MSK_LINE_B);
+
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq\n");
+ goto err_irq;
+ }
+
+ platform_set_drvdata(pdev, gpadc);
+ mutex_init(&gpadc->lock);
+ INIT_WORK(&gpadc->ws, twl6030_gpadc_work);
+
+ the_gpadc = gpadc;
+
+ return 0;
+
+err_irq:
+ misc_deregister(&twl6030_gpadc_device);
+
+err_misc:
+err_pdata:
+ kfree(gpadc);
+
+ return ret;
+}
+
+static int __exit twl6030_gpadc_remove(struct platform_device *pdev)
+{
+ struct twl6030_gpadc_data *gpadc = platform_get_drvdata(pdev);
+
+ free_irq(platform_get_irq(pdev, 0), gpadc);
+ cancel_work_sync(&gpadc->ws);
+ misc_deregister(&twl6030_gpadc_device);
+
+ return 0;
+}
+
+static struct platform_driver twl6030_gpadc_driver = {
+ .probe = twl6030_gpadc_probe,
+ .remove = __exit_p(twl6030_gpadc_remove),
+ .driver = {
+ .name = "twl6030_gpadc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init twl6030_gpadc_init(void)
+{
+ return platform_driver_register(&twl6030_gpadc_driver);
+}
+module_init(twl6030_gpadc_init);
+
+static void __exit twl6030_gpadc_exit(void)
+{
+ platform_driver_unregister(&twl6030_gpadc_driver);
+}
+module_exit(twl6030_gpadc_exit);
+
+MODULE_ALIAS("platform:twl6030-gpadc");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("twl6030 ADC driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
new file mode 100644
index 000000000000..6738f17938b9
--- /dev/null
+++ b/drivers/mfd/twl6030-irq.c
@@ -0,0 +1,303 @@
+/*
+ * twl6030-irq.c - TWL6030 irq support
+ *
+ * Copyright (C) 2005-2009 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>
+ *
+ * TWL6030 specific code and IRQ handling changes by
+ * Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
+ * Balaji T K <balajitk@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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+#include <linux/i2c/twl.h>
+
+/*
+ * TWL6030 (unlike its predecessors, which had two level interrupt handling)
+ * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
+ * It exposes status bits saying who has raised an interrupt. There are
+ * three mask registers that corresponds to these status registers, that
+ * enables/disables these interrupts.
+ *
+ * We set up IRQs starting at a platform-specified base. An interrupt map table,
+ * specifies mapping between interrupt number and the associated module.
+ *
+ */
+
+static int twl6030_interrupt_mapping[24] = {
+ PWR_INTR_OFFSET, /* Bit 0 PWRON */
+ PWR_INTR_OFFSET, /* Bit 1 RPWRON */
+ PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */
+ PWR_INTR_OFFSET, /* Bit 3 VBAT */
+ RTC_INTR_OFFSET, /* Bit 4 RTC_ALARM */
+ RTC_INTR_OFFSET, /* Bit 5 RTC_PERIOD */
+ HOTDIE_INTR_OFFSET, /* Bit 6 HOT_DIE */
+ SMPSLDO_INTR_OFFSET, /* Bit 7 VXXX_SHORT */
+
+ SMPSLDO_INTR_OFFSET, /* Bit 8 VMMC_SHORT */
+ SMPSLDO_INTR_OFFSET, /* Bit 9 VUSIM_SHORT */
+ SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */
+ MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
+ RSV_INTR_OFFSET, /* Bit 12 Reserved */
+ GPADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */
+ GPADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */
+ GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
+
+ USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */
+ USBOTG_INTR_OFFSET, /* Bit 17 VBUS_WKUP */
+ USBOTG_INTR_OFFSET, /* Bit 18 ID */
+ USBOTG_INTR_OFFSET, /* Bit 19 VBUS */
+ CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */
+ CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */
+ CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */
+ CHARGER_INTR_OFFSET, /* Bit 23 BAT_OVT */
+};
+/*----------------------------------------------------------------------*/
+
+static unsigned twl6030_irq_base;
+
+static struct completion irq_event;
+
+/*
+ * This thread processes interrupts reported by the Primary Interrupt Handler.
+ */
+static int twl6030_irq_thread(void *data)
+{
+ long irq = (long)data;
+ static unsigned i2c_errors;
+ static const unsigned max_i2c_errors = 100;
+ int ret;
+
+ current->flags |= PF_NOFREEZE;
+
+ while (!kthread_should_stop()) {
+ int i;
+ union {
+ u8 bytes[4];
+ u32 int_sts;
+ } sts;
+
+ /* Wait for IRQ, then read PIH irq status (also blocking) */
+ wait_for_completion_interruptible(&irq_event);
+
+ /* read INT_STS_A, B and C in one shot using a burst read */
+ ret = twl_i2c_read(TWL6030_MODULE_PIH, sts.bytes,
+ REG_INT_STS_A, 3);
+ if (ret) {
+ pr_warning("twl6030: I2C error %d reading PIH ISR\n",
+ ret);
+ if (++i2c_errors >= max_i2c_errors) {
+ printk(KERN_ERR "Maximum I2C error count"
+ " exceeded. Terminating %s.\n",
+ __func__);
+ break;
+ }
+ complete(&irq_event);
+ continue;
+ }
+
+
+
+ sts.bytes[3] = 0; /* Only 24 bits are valid*/
+
+ for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
+ local_irq_disable();
+ if (sts.int_sts & 0x1) {
+ int module_irq = TWL6030_IRQ_BASE +
+ twl6030_interrupt_mapping[i];
+ struct irq_desc *d = irq_to_desc(module_irq);
+
+ if (!d) {
+ pr_err("twl6030: Invalid SIH IRQ: %d\n",
+ module_irq);
+ return -EINVAL;
+ }
+
+ /* These can't be masked ... always warn
+ * if we get any surprises.
+ */
+ if (d->status & IRQ_DISABLED)
+ note_interrupt(module_irq, d,
+ IRQ_NONE);
+ else
+ d->handle_irq(module_irq, d);
+
+ }
+ local_irq_enable();
+ }
+ ret = twl_i2c_write(TWL6030_MODULE_PIH, sts.bytes,
+ REG_INT_STS_A, 3); /* clear INT_STS_A */
+ if (ret)
+ pr_warning("twl6030: I2C error in clearing PIH ISR\n");
+
+ enable_irq(irq);
+ }
+
+ return 0;
+}
+
+/*
+ * handle_twl6030_int() is the desc->handle method for the twl6030 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 twl6030 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 irqreturn_t handle_twl6030_pih(int irq, void *devid)
+{
+ disable_irq_nosync(irq);
+ complete(devid);
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+ /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+ * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
+ */
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ /* same effect on other architectures */
+ set_irq_noprobe(irq);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+
+static unsigned twl6030_irq_next;
+
+/*----------------------------------------------------------------------*/
+int twl_int_mask_reset(u8 bit_mask, u8 offset)
+{
+ int ret;
+ u8 unmask_value;
+ ret = twl_i2c_read_u8(TWL6030_MODULE_PIH, &unmask_value,
+ REG_INT_STS_A + offset);
+ unmask_value &= (~(bit_mask));
+ ret |= twl_i2c_write_u8(TWL6030_MODULE_PIH, unmask_value,
+ REG_INT_STS_A + offset); /* unmask INT_MSK_A/B/C */
+ return ret;
+}
+
+int twl_int_mask_set(u8 bit_mask, u8 offset)
+{
+ int ret;
+ u8 mask_value;
+ ret = twl_i2c_read_u8(TWL6030_MODULE_PIH, &mask_value,
+ REG_INT_STS_A + offset);
+ mask_value |= (bit_mask);
+ ret |= twl_i2c_write_u8(TWL6030_MODULE_PIH, mask_value,
+ REG_INT_STS_A + offset); /* mask INT_MSK_A/B/C */
+ return ret;
+}
+
+int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+{
+
+ int status = 0;
+ int i;
+ struct task_struct *task;
+ int ret;
+ u8 mask[4];
+
+ static struct irq_chip twl6030_irq_chip;
+ mask[1] = 0xFF;
+ mask[2] = 0xFF;
+ mask[3] = 0xFF;
+ ret = twl_i2c_write(TWL6030_MODULE_PIH, &mask[0],
+ REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES*/
+
+ mask[1] = 0;
+ mask[2] = 0;
+ mask[3] = 0;
+ ret = twl_i2c_write(TWL6030_MODULE_PIH, &mask[0],
+ REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */
+
+ ret |= twl_int_mask_reset(TWL6030_RTC_INT_MASK, REG_INT_MSK_LINE_A);
+ ret |= twl_int_mask_reset(TWL6030_MMCDETECT_INT_MASK, \
+ REG_INT_MSK_LINE_B);
+
+ twl6030_irq_base = irq_base;
+
+ /* install an irq handler for each of the modules;
+ * clone dummy irq_chip since PIH can't *do* anything
+ */
+ twl6030_irq_chip = dummy_irq_chip;
+ twl6030_irq_chip.name = "twl6030";
+ twl6030_irq_chip.set_type = NULL;
+
+ for (i = irq_base; i < irq_end; i++) {
+ set_irq_chip_and_handler(i, &twl6030_irq_chip,
+ handle_simple_irq);
+ activate_irq(i);
+ }
+
+ twl6030_irq_next = i;
+ pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
+ irq_num, irq_base, twl6030_irq_next - 1);
+
+ /* install an irq handler to demultiplex the TWL6030 interrupt */
+ init_completion(&irq_event);
+ task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
+ if (IS_ERR(task)) {
+ pr_err("twl6030: could not create irq %d thread!\n", irq_num);
+ status = PTR_ERR(task);
+ goto fail_kthread;
+ }
+
+ status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED,
+ "TWL6030-PIH", &irq_event);
+ if (status < 0) {
+ pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
+ goto fail;
+ }
+ return status;
+fail_kthread:
+ free_irq(irq_num, &irq_event);
+
+fail:
+ for (i = irq_base; i < irq_end; i++)
+ set_irq_chip_and_handler(i, NULL, NULL);
+ return status;
+}
+
+int twl_exit_irq(void)
+{
+
+ if (twl6030_irq_base) {
+ pr_err("twl6030: can't yet clean up IRQs?\n");
+ return -ENOSYS;
+ }
+ return 0;
+}
+
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 891ef18bd77b..51831f807325 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -132,11 +132,11 @@ config MMC_OMAP
config MMC_OMAP_HS
tristate "TI OMAP High Speed Multimedia Card Interface support"
- depends on ARCH_OMAP2430 || ARCH_OMAP3
+ depends on ARCH_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
help
This selects the TI OMAP High Speed Multimedia card Interface.
- If you have an OMAP2430 or OMAP3 board with a Multimedia Card slot,
- say Y or M here.
+ If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
+ Multimedia Card slot, say Y or M here.
If unsure, say N.
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 1cf9cfb3b64f..99cc3341d410 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -32,6 +32,8 @@
#include <mach/board.h>
#include <mach/mmc.h>
#include <mach/cpu.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
/* OMAP HSMMC Host Controller Registers */
#define OMAP_HSMMC_SYSCONFIG 0x0010
@@ -101,6 +103,8 @@
#define OMAP_MMC1_DEVID 0
#define OMAP_MMC2_DEVID 1
#define OMAP_MMC3_DEVID 2
+#define OMAP_MMC4_DEVID 3
+#define OMAP_MMC5_DEVID 4
#define MMC_TIMEOUT_MS 20
#define OMAP_MMC_MASTER_CLOCK 96000000
@@ -152,6 +156,14 @@ struct mmc_omap_host {
struct omap_mmc_platform_data *pdata;
};
+#if 1
+struct mmc_omap_host *test_mmc1_omap4_host;
+struct mmc_omap_host *test_mmc2_omap4_host;
+struct mmc_omap_host *test_mmc3_omap4_host;
+struct mmc_omap_host *test_mmc4_omap4_host;
+#endif
+
+
/*
* Stop clock to the card
*/
@@ -341,6 +353,9 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
}
}
+ /* TO FIX :Hack for MMC SWITCH COMMAND which makes card go busy*/
+ if (cmd->opcode == 6)
+ host->response_busy = 0;
if ((host->data == NULL && !host->response_busy) || cmd->error) {
host->mrq = NULL;
mmc_request_done(host->mmc, cmd->mrq);
@@ -600,6 +615,88 @@ static void mmc_omap_detect(struct work_struct *work)
mmc_detect_change(host->mmc, (HZ * 50) / 1000);
}
}
+#if 1
+/* Dummy Card detect Enable/disable */
+static struct proc_dir_entry *mmc_dir, *mmc_irq_file;
+
+static int
+write_proc_entries(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int len, i;
+ char val[20];
+ struct mmc_omap_host *host ;
+ if (!buffer || (count == 0))
+ return 0;
+
+ len = (count > 3) ? 3 : count;
+ for (i = 0; i < len; i++)
+ val[i] = buffer[i];
+ val[i] = '\0';
+
+
+ if (strncmp(val, "MMC1_ON", 7) == 0) {
+ host = test_mmc1_omap4_host ;
+ host->carddetect = 0;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC1_OFF", 8) == 0) {
+ host = test_mmc1_omap4_host ;
+ host->carddetect = 1;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC2_ON", 7) == 0) {
+ host = test_mmc2_omap4_host ;
+ host->carddetect = 0;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC2_OFF", 8) == 0) {
+ host = test_mmc2_omap4_host ;
+ host->carddetect = 1;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC3_ON", 7) == 0) {
+ host = test_mmc3_omap4_host ;
+ host->carddetect = 0;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC3_OFF", 8) == 0) {
+ host = test_mmc3_omap4_host ;
+ host->carddetect = 1;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC4_ON", 7) == 0) {
+ host = test_mmc4_omap4_host ;
+ host->carddetect = 0;
+ schedule_work(&host->mmc_carddetect_work);
+ } else if (strncmp(val, "MMC4_OFF", 8) == 0) {
+ host = test_mmc4_omap4_host ;
+ host->carddetect = 1;
+ schedule_work(&host->mmc_carddetect_work);
+ } else
+ return -EINVAL;
+
+ return count;
+}
+
+/*PROC interface Implementation */
+#define MMC_DIR "driver/mmc"
+#define MMC_ROOT NULL
+static int file_type[1] = {1};
+static int
+create_proc_file_entries(void)
+{
+ mmc_dir = proc_mkdir(MMC_DIR, MMC_ROOT);
+ if (!mmc_dir)
+ return -ENOMEM;
+ mmc_irq_file = create_proc_entry("mmc_cd_irq", 0644, mmc_dir);
+ if (!mmc_irq_file)
+ goto no_mmc_irq;
+
+ mmc_irq_file->data = &file_type[0];
+ mmc_irq_file->write_proc = write_proc_entries;
+ return 0;
+
+no_mmc_irq:
+ remove_proc_entry(MMC_DIR, MMC_ROOT);
+ return -ENOMEM;
+}
+#endif
+
/*
* ISR for handling card insertion and removal
@@ -609,7 +706,6 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
schedule_work(&host->mmc_carddetect_work);
-
return IRQ_HANDLED;
}
@@ -751,6 +847,15 @@ static void set_data_timeout(struct mmc_omap_host *host,
unsigned int timeout, cycle_ns;
uint32_t reg, clkd, dto = 0;
+ /* TO FIX : Calculations needs to be done below
+ * as it is running into divide by zero.
+ * Hard coding SYSCTL register
+ */
+ if (cpu_is_omap44xx()) {
+ reg = 0xe00c7;
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
+ return;
+ }
reg = OMAP_HSMMC_READ(host->base, SYSCTL);
clkd = (reg & CLKD_MASK) >> CLKD_SHIFT;
if (clkd == 0)
@@ -1023,45 +1128,50 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
sema_init(&host->sem, 1);
- host->iclk = clk_get(&pdev->dev, "ick");
- if (IS_ERR(host->iclk)) {
- ret = PTR_ERR(host->iclk);
- host->iclk = NULL;
- goto err1;
- }
- host->fclk = clk_get(&pdev->dev, "fck");
- if (IS_ERR(host->fclk)) {
- ret = PTR_ERR(host->fclk);
- host->fclk = NULL;
- clk_put(host->iclk);
- goto err1;
- }
+ if (!cpu_is_omap44xx()) {
+ host->iclk = clk_get(&pdev->dev, "ick");
+ if (IS_ERR(host->iclk)) {
+ ret = PTR_ERR(host->iclk);
+ host->iclk = NULL;
+ goto err1;
+ }
+ host->fclk = clk_get(&pdev->dev, "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->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;
+ 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_warn(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");
+ if (!cpu_is_omap44xx()) {
+ host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+ /*
+ * MMC can still work without debounce clock.
+ */
+ if (IS_ERR(host->dbclk))
+ dev_warn(mmc_dev(host->mmc), "Failed to get"
+ "debounce clock\n");
else
- host->dbclk_enabled = 1;
+ if (clk_enable(host->dbclk) != 0)
+ dev_dbg(mmc_dev(host->mmc), "Enabling"
+ " debounce clk failed\n");
+ else
+ host->dbclk_enabled = 1;
+ }
/* Since we do only SG emulation, we can have as many segs
* as we want. */
@@ -1096,6 +1206,14 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
break;
+ case OMAP_MMC4_DEVID:
+ host->dma_line_tx = OMAP44XX_DMA_MMC4_DMA_TX;
+ host->dma_line_rx = OMAP44XX_DMA_MMC4_DMA_RX;
+ break;
+ case OMAP_MMC5_DEVID:
+ host->dma_line_tx = OMAP44XX_DMA_MMC5_DMA_TX;
+ host->dma_line_rx = OMAP44XX_DMA_MMC5_DMA_RX;
+ break;
default:
dev_err(mmc_dev(host->mmc), "Invalid MMC id\n");
goto err_irq;
@@ -1149,7 +1267,20 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_cover_switch;
}
-
+#if 1
+ if ((cpu_is_omap44xx())) {
+ if (host->id == OMAP_MMC1_DEVID)
+ create_proc_file_entries();
+ if (host->id == OMAP_MMC2_DEVID)
+ test_mmc1_omap4_host = host;
+ if (host->id == OMAP_MMC3_DEVID)
+ test_mmc2_omap4_host = host;
+ if (host->id == OMAP_MMC4_DEVID)
+ test_mmc3_omap4_host = host;
+ if (host->id == OMAP_MMC5_DEVID)
+ test_mmc4_omap4_host = host;
+ }
+#endif
return 0;
err_cover_switch:
diff --git a/drivers/power/twl6030_bci_battery.c b/drivers/power/twl6030_bci_battery.c
new file mode 100644
index 000000000000..c6384dc77051
--- /dev/null
+++ b/drivers/power/twl6030_bci_battery.c
@@ -0,0 +1,570 @@
+/*
+ * linux/drivers/power/twl6030_bci_battery.c
+ *
+ * OMAP2430/3430 BCI battery driver for Linux
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Author: 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl6030.h>
+#include <linux/power_supply.h>
+#include <linux/i2c/twl6030-madc.h>
+
+#define T2_BATTERY_VOLT 0x04
+#define T2_BATTERY_TEMP 0x06
+#define T2_BATTERY_CUR 0x08
+
+/* charger constants */
+#define NO_PW_CONN 0
+#define AC_PW_CONN 0x01
+#define USB_PW_CONN 0x02
+
+#define CONTROLLER_INT_MASK (0x0)
+#define CONTROLLER_CTRL1 (0x1)
+#define CONTROLLER_WDG (0x2)
+#define CONTROLLER_STAT1 (0x3)
+#define CHARGERUSB_INT_STATUS (0x4)
+#define CHARGERUSB_INT_MASK (0x5)
+#define CHARGERUSB_STATUS_INT1 (0x6)
+#define CHARGERUSB_STATUS_INT2 (0x7)
+#define CHARGERUSB_CTRL1 (0x8)
+#define CHARGERUSB_CTRL2 (0x9)
+#define CHARGERUSB_CTRL3 (0xA)
+#define CHARGERUSB_STAT1 (0xB)
+#define CHARGERUSB_VOREG (0xC)
+#define CHARGERUSB_VICHRG (0xD)
+#define CHARGERUSB_CINLIMIT (0xE)
+#define CHARGERUSB_CTRLLIMIT1 (0xF)
+#define CHARGERUSB_CTRLLIMIT2 (0x10)
+
+#define CONTROLLER_CTRL1_EN_CHARGER (1 << 4)
+#define CONTROLLER_CTRL1_SEL_CHARGER (1 << 3)
+
+#define CONTROLLER_STAT1_EXTCHRG_STATZ (1 << 7)
+#define CONTROLLER_STAT1_CHRG_DET_N (1 << 5)
+#define CONTROLLER_STAT1_FAULT_WDG (1 << 4)
+#define CONTROLLER_STAT1_VAC_DET (1 << 3)
+#define CONTROLLER_STAT1_VBUS_DET (1 << 2)
+#define CONTROLLER_STAT1_BAT_REMOVED (1 << 1)
+#define CONTROLLER_STAT1_BAT_TEMP_OVRANGE (1 << 0)
+
+#define CHARGERUSB_STATUS_INT1_TMREG (1 << 7)
+#define CHARGERUSB_STATUS_INT1_NO_BAT (1 << 6)
+#define CHARGERUSB_STATUS_INT1_BST_OCP (1 << 5)
+#define CHARGERUSB_STATUS_INT1_TH_SHUTD (1 << 4)
+#define CHARGERUSB_STATUS_INT1_BAT_OVP (1 << 3)
+#define CHARGERUSB_STATUS_INT1_POOR_SRC (1 << 2)
+#define CHARGERUSB_STATUS_INT1_SLP_MODE (1 << 1)
+#define CHARGERUSB_STATUS_INT1_VBUS_OVP (1 << 0)
+
+/* Ptr to thermistor table */
+int *therm_tbl;
+
+struct twl6030_bci_device_info {
+ struct device *dev;
+
+ unsigned long update_time;
+ int voltage_uV;
+ int bk_voltage_uV;
+ int current_uA;
+ int temp_C;
+ int charge_rsoc;
+ int charge_status;
+
+ struct power_supply bat;
+ struct power_supply bk_bat;
+ struct delayed_work twl6030_bci_monitor_work;
+ struct delayed_work twl6030_bk_bci_monitor_work;
+};
+
+static int usb_charger_flag;
+static int LVL_1, LVL_2, LVL_3, LVL_4;
+
+static int read_bci_val(u8 reg_1);
+static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg);
+
+/*
+ * Interrupt service routine
+ *
+ * Attends to TWL 6030 power module interruptions events, specifically
+ * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
+ *
+ */
+static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
+{
+ struct twl6030_bci_device_info *di = _di;
+ int ret; u8 chg_sts = 0;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
+
+ /* read charger controller_stat1 */
+ ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &chg_sts,
+ CONTROLLER_STAT1);
+ if (ret)
+ return IRQ_NONE;
+
+ if (chg_sts & CONTROLLER_STAT1_VBUS_DET) {
+ printk(KERN_INFO "USB charger detected\n");
+ ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
+ CONTROLLER_CTRL1_EN_CHARGER
+ CONTROLLER_CTRL1);
+ if (ret)
+ return IRQ_NONE;
+ }
+ if (chg_sts & CONTROLLER_STAT1_VAC_DET) {
+ printk(KERN_INFO "A/C charger detected\n");
+ ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
+ CONTROLLER_CTRL1_EN_CHARGER |
+ CONTROLLER_CTRL1_SEL_CHARGER ,
+ CONTROLLER_CTRL1);
+ if (ret)
+ return IRQ_NONE;
+ }
+ if (chg_sts & CONTROLLER_STAT1_FAULT_WDG) {
+ printk(KERN_INFO "Fault watchdog fired\n");
+ }
+ if (chg_sts & CONTROLLER_STAT1_BAT_REMOVED) {
+ printk(KERN_INFO "Battery removed\n");
+ }
+ if (chg_sts & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
+ printk(KERN_INFO "Battery temperature overrange\n");
+ }
+
+ power_supply_changed(&di->bat);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t twl6030charger_fault_interrupt(int irq, void *_di)
+{
+ struct twl6030_bci_device_info *di = _di;
+
+ printk(KERN_INFO "Charger fault detected\n");
+ power_supply_changed(&di->bat);
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * This function handles the twl6030 battery voltage level interrupt.
+ */
+static int twl6030battery_level_evt(void)
+{
+}
+
+
+/*
+ * Enable/Disable hardware battery level event notifications.
+ */
+static int twl6030battery_hw_level_en(int enable)
+{
+}
+
+/*
+ * Return battery temperature
+ * Or < 0 on failure.
+ */
+static int twl6030battery_temperature(void)
+{
+}
+
+/*
+ * Return battery voltage
+ * Or < 0 on failure.
+ */
+static int twl6030battery_voltage(void)
+{
+}
+
+/*
+ * Return the battery current
+ * Or < 0 on failure.
+ */
+static int twl6030battery_current(void)
+{
+}
+
+/*
+ * Return the battery backup voltage
+ * Or < 0 on failure.
+ */
+static int twl6030backupbatt_voltage(void)
+{
+}
+
+/*
+ * Returns the main charge FSM status
+ * Or < 0 on failure.
+ */
+static int twl6030bci_status(void)
+{
+}
+
+
+/*
+ * Settup the twl6030 BCI module to enable backup
+ * battery charging.
+ */
+static int twl6030backupbatt_voltage_setup(void)
+{
+}
+
+/*
+ * Settup the twl6030 BCI module to measure battery
+ * temperature
+ */
+static int twl6030battery_temp_setup(void)
+{
+}
+
+static enum power_supply_property twl6030_bci_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static enum power_supply_property twl6030_bk_bci_battery_props[] = {
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static void
+twl6030_bk_bci_battery_read_status(struct twl6030_bci_device_info *di)
+{
+ di->bk_voltage_uV = twl6030backupbatt_voltage();
+}
+
+static void twl6030_bk_bci_battery_work(struct work_struct *work)
+{
+ struct twl6030_bci_device_info *di = container_of(work,
+ struct twl6030_bci_device_info,
+ twl6030_bk_bci_monitor_work.work);
+
+ twl6030_bk_bci_battery_read_status(di);
+ schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 500);
+}
+
+static void twl6030_bci_battery_read_status(struct twl6030_bci_device_info *di)
+{
+ di->temp_C = twl6030battery_temperature();
+ di->voltage_uV = twl6030battery_voltage();
+ di->current_uA = twl6030battery_current();
+}
+
+static void
+twl6030_bci_battery_update_status(struct twl6030_bci_device_info *di)
+{
+ twl6030_bci_battery_read_status(di);
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ if (power_supply_am_i_supplied(&di->bat))
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+}
+
+static void twl6030_bci_battery_work(struct work_struct *work)
+{
+ struct twl6030_bci_device_info *di = container_of(work,
+ struct twl6030_bci_device_info, twl6030_bci_monitor_work.work);
+
+ twl6030_bci_battery_update_status(di);
+ schedule_delayed_work(&di->twl6030_bci_monitor_work, 100);
+}
+
+
+#define to_twl6030_bci_device_info(x) container_of((x), \
+ struct twl6030_bci_device_info, bat);
+
+static void twl6030_bci_battery_external_power_changed(struct power_supply *psy)
+{
+ struct twl6030_bci_device_info *di = to_twl6030_bci_device_info(psy);
+
+ cancel_delayed_work(&di->twl6030_bci_monitor_work);
+ schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+}
+
+#define to_twl6030_bk_bci_device_info(x) container_of((x), \
+ struct twl6030_bci_device_info, bk_bat);
+
+static int twl6030_bk_bci_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct twl6030_bci_device_info *di = to_twl6030_bk_bci_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->bk_voltage_uV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int twl6030_bci_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct twl6030_bci_device_info *di;
+ int status = 0;
+
+ di = to_twl6030_bci_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = di->charge_status;
+ return 0;
+ default:
+ break;
+ }
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->voltage_uV;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = di->current_uA;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = di->temp_C;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ status = twl6030bci_status();
+ if ((status & AC_STATEC) == AC_STATEC)
+ val->intval = POWER_SUPPLY_TYPE_MAINS;
+ else if (usb_charger_flag)
+ val->intval = POWER_SUPPLY_TYPE_USB;
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ /*
+ * need to get the correct percentage value per the
+ * battery characteristics. Approx values for now.
+ */
+ if (di->voltage_uV < 2894 || LVL_1) {
+ val->intval = 5;
+ LVL_1 = 0;
+ } else if ((di->voltage_uV < 3451 && di->voltage_uV > 2894)
+ || LVL_2) {
+ val->intval = 20;
+ LVL_2 = 0;
+ } else if ((di->voltage_uV < 3902 && di->voltage_uV > 3451)
+ || LVL_3) {
+ val->intval = 50;
+ LVL_3 = 0;
+ } else if ((di->voltage_uV < 3949 && di->voltage_uV > 3902)
+ || LVL_4) {
+ val->intval = 75;
+ LVL_4 = 0;
+ } else if (di->voltage_uV > 3949)
+ val->intval = 90;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static char *twl6030_bci_supplied_to[] = {
+ "twl6030_bci_battery",
+};
+
+static int __init twl6030_bci_battery_probe(struct platform_device *pdev)
+{
+ struct twl6030_bci_platform_data *pdata = pdev->dev.platform_data;
+ struct twl6030_bci_device_info *di;
+ int irq;
+ int ret;
+
+ therm_tbl = pdata->battery_tmp_tbl;
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->dev = &pdev->dev;
+ di->bat.name = "twl6030_bci_battery";
+ di->bat.supplied_to = twl6030_bci_supplied_to;
+ di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to);
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = twl6030_bci_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props);
+ di->bat.get_property = twl6030_bci_battery_get_property;
+ di->bat.external_power_changed =
+ twl6030_bci_battery_external_power_changed;
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ di->bk_bat.name = "twl6030_bci_bk_battery";
+ di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bk_bat.properties = twl6030_bk_bci_battery_props;
+ di->bk_bat.num_properties = ARRAY_SIZE(twl6030_bk_bci_battery_props);
+ di->bk_bat.get_property = twl6030_bk_bci_battery_get_property;
+ di->bk_bat.external_power_changed = NULL;
+
+ platform_set_drvdata(pdev, di);
+
+ /* settings for temperature sensing */
+ ret = twl6030battery_temp_setup();
+ if (ret)
+ goto temp_setup_fail;
+
+ /* request charger fault interruption */
+ irq = platform_get_irq(pdev, 1);
+ ret = request_irq(irq, twl6030charger_fault_interrupt,
+ 0, "twl_charger_fault", di);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ irq, ret);
+ goto batt_irq_fail;
+ }
+
+ /* request charger ctrl interruption */
+ irq = platform_get_irq(pdev, 0);
+ ret = request_irq(irq, twl6030charger_ctrl_interrupt,
+ 0, "twl_charger_ctrl", di);
+
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ irq, ret);
+ goto chg_irq_fail;
+ }
+
+ twl_int_mask_reset(TWL6030_CHARGER_CTRL_INT_MASK, REG_INT_MSK_LINE_C);
+ twl_int_mask_reset(TWL6030_CHARGER_FAULT_INT_MASK, REG_INT_MSK_LINE_C);
+
+ ret = power_supply_register(&pdev->dev, &di->bat);
+ if (ret) {
+ dev_dbg(&pdev->dev, "failed to register main battery\n");
+ goto batt_failed;
+ }
+
+ INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bci_monitor_work,
+ twl6030_bci_battery_work);
+ schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+
+ ret = power_supply_register(&pdev->dev, &di->bk_bat);
+ if (ret) {
+ dev_dbg(&pdev->dev, "failed to register backup battery\n");
+ goto bk_batt_failed;
+ }
+
+ INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bk_bci_monitor_work,
+ twl6030_bk_bci_battery_work);
+ schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 500);
+
+ return 0;
+
+bk_batt_failed:
+ power_supply_unregister(&di->bat);
+batt_failed:
+ free_irq(irq, di);
+chg_irq_fail:
+ irq = platform_get_irq(pdev, 1);
+ free_irq(irq, NULL);
+batt_irq_fail:
+voltage_setup_fail:
+temp_setup_fail:
+ kfree(di);
+
+ return ret;
+}
+
+static int __exit twl6030_bci_battery_remove(struct platform_device *pdev)
+{
+ struct twl6030_bci_device_info *di = platform_get_drvdata(pdev);
+ int irq;
+
+ irq = platform_get_irq(pdev, 0);
+ free_irq(irq, di);
+
+ irq = platform_get_irq(pdev, 1);
+ free_irq(irq, NULL);
+
+ flush_scheduled_work();
+ power_supply_unregister(&di->bat);
+ power_supply_unregister(&di->bk_bat);
+ platform_set_drvdata(pdev, NULL);
+ kfree(di);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int twl6030_bci_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct twl6030_bci_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ cancel_delayed_work(&di->twl6030_bci_monitor_work);
+ cancel_delayed_work(&di->twl6030_bk_bci_monitor_work);
+ return 0;
+}
+
+static int twl6030_bci_battery_resume(struct platform_device *pdev)
+{
+ struct twl6030_bci_device_info *di = platform_get_drvdata(pdev);
+
+ schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+ schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 50);
+ return 0;
+}
+#else
+#define twl6030_bci_battery_suspend NULL
+#define twl6030_bci_battery_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver twl6030_bci_battery_driver = {
+ .probe = twl6030_bci_battery_probe,
+ .remove = __exit_p(twl6030_bci_battery_remove),
+ .suspend = twl6030_bci_battery_suspend,
+ .resume = twl6030_bci_battery_resume,
+ .driver = {
+ .name = "twl_bci",
+ },
+};
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl6030_bci");
+MODULE_AUTHOR("Texas Instruments Inc");
+
+static int __init twl6030_battery_init(void)
+{
+ return platform_driver_register(&twl6030_bci_battery_driver);
+}
+module_init(twl6030_battery_init);
+
+static void __exit twl6030_battery_exit(void)
+{
+ platform_driver_unregister(&twl6030_bci_battery_driver);
+}
+module_exit(twl6030_battery_exit);
+
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index f4317798e47c..9e989a4d550a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -75,9 +75,9 @@ config REGULATOR_MAX1586
regulator via I2C bus. The provided regulator is suitable
for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
-config REGULATOR_TWL4030
+config REGULATOR_TWL
bool "TI TWL4030/TWL5030/TPS695x0 PMIC"
- depends on TWL4030_CORE
+ depends on TWL4030_CORE || TWL6030_CORE
help
This driver supports the voltage regulators provided by
this family of companion chips.
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 4d762c4cccfd..712f733af6b9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
-obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o
+obj-$(CONFIG_REGULATOR_TWL) += twl-regulator.o
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
diff --git a/drivers/regulator/twl4030-regulator.c b/drivers/regulator/twl-regulator.c
index e2032fb60b55..4152f2c9ae30 100644
--- a/drivers/regulator/twl4030-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1,5 +1,5 @@
/*
- * twl4030-regulator.c -- support regulators in twl4030 family chips
+ * twl-regulator.c -- support regulators in twl4030/twl6030 family chips
*
* Copyright (C) 2008 David Brownell
*
@@ -15,11 +15,11 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
/*
- * The TWL4030/TW5030/TPS659x0 family chips include power management, a
+ * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a
* USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions
* include an audio codec, battery charger, and more voltage regulators.
* These chips are often used in OMAP-based systems.
@@ -33,7 +33,7 @@ struct twlreg_info {
/* start of regulator's PM_RECEIVER control register bank */
u8 base;
- /* twl4030 resource ID, for resource control state machine */
+ /* twl resource ID, for resource control state machine */
u8 id;
/* voltage in mV = table[VSEL]; table_len must be a power-of-two */
@@ -52,27 +52,38 @@ struct twlreg_info {
* The first three registers of all power resource banks help hardware to
* manage the various resource groups.
*/
+/* Common offset in TWL4030/6030 */
#define VREG_GRP 0
+/* TWL4030 register offsets */
#define VREG_TYPE 1
#define VREG_REMAP 2
-#define VREG_DEDICATED 3 /* LDO control */
-
+#define VREG_DEDICATED 3
+/* TWL6030 register offsets */
+#define VREG_TRANS 1
+#define VREG_STATE 2
+#define VREG_VOLTAGE 3
+/* TWL6030 Misc register offsets */
+#define VREG_BC_ALL 1
+#define VREG_BC_REF 2
+#define VREG_BC_PROC 3
+#define VREG_BC_CLK_RST 4
static inline int
-twl4030reg_read(struct twlreg_info *info, unsigned offset)
+twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
{
u8 value;
int status;
- status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER,
+ status = twl_i2c_read_u8(slave_subgp,
&value, info->base + offset);
return (status < 0) ? status : value;
}
static inline int
-twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value)
+twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset,
+ u8 value)
{
- return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ return twl_i2c_write_u8(slave_subgp,
value, info->base + offset);
}
@@ -80,23 +91,29 @@ twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value)
/* generic power resource operations, which work on all regulators */
-static int twl4030reg_grp(struct regulator_dev *rdev)
+static int twlreg_grp(struct regulator_dev *rdev)
{
- return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP);
+ return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_SLAVE_LDO,
+ VREG_GRP);
}
/*
* Enable/disable regulators by joining/leaving the P1 (processor) group.
* We assume nobody else is updating the DEV_GRP registers.
*/
-
+#ifdef CONFIG_TWL4030_CORE
#define P3_GRP BIT(7) /* "peripherals" */
#define P2_GRP BIT(6) /* secondary processor, modem, etc */
#define P1_GRP BIT(5) /* CPU/Linux */
+#elif CONFIG_TWL6030_CORE
+#define P3_GRP BIT(2) /* secondary processor, modem, etc */
+#define P2_GRP BIT(1) /* "peripherals" */
+#define P1_GRP BIT(0) /* CPU/Linux */
+#endif
-static int twl4030reg_is_enabled(struct regulator_dev *rdev)
+static int twlreg_is_enabled(struct regulator_dev *rdev)
{
- int state = twl4030reg_grp(rdev);
+ int state = twlreg_grp(rdev);
if (state < 0)
return state;
@@ -104,35 +121,35 @@ static int twl4030reg_is_enabled(struct regulator_dev *rdev)
return (state & P1_GRP) != 0;
}
-static int twl4030reg_enable(struct regulator_dev *rdev)
+static int twlreg_enable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp;
- grp = twl4030reg_read(info, VREG_GRP);
+ grp = twlreg_read(info, TWL_MODULE_PM_SLAVE_LDO, VREG_GRP);
if (grp < 0)
return grp;
grp |= P1_GRP;
- return twl4030reg_write(info, VREG_GRP, grp);
+ return twlreg_write(info, TWL_MODULE_PM_SLAVE_LDO, VREG_GRP, grp);
}
-static int twl4030reg_disable(struct regulator_dev *rdev)
+static int twlreg_disable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp;
- grp = twl4030reg_read(info, VREG_GRP);
+ grp = twlreg_read(info, TWL_MODULE_PM_SLAVE_LDO, VREG_GRP);
if (grp < 0)
return grp;
grp &= ~P1_GRP;
- return twl4030reg_write(info, VREG_GRP, grp);
+ return twlreg_write(info, TWL_MODULE_PM_SLAVE_LDO, VREG_GRP, grp);
}
-static int twl4030reg_get_status(struct regulator_dev *rdev)
+static int twlreg_get_status(struct regulator_dev *rdev)
{
- int state = twl4030reg_grp(rdev);
+ int state = twlreg_grp(rdev);
if (state < 0)
return state;
@@ -146,7 +163,7 @@ static int twl4030reg_get_status(struct regulator_dev *rdev)
: REGULATOR_STATUS_STANDBY;
}
-static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
+static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
unsigned message;
@@ -165,19 +182,19 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
}
/* Ensure the resource is associated with some group */
- status = twl4030reg_grp(rdev);
+ status = twlreg_grp(rdev);
if (status < 0)
return status;
if (!(status & (P3_GRP | P2_GRP | P1_GRP)))
return -EACCES;
- status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- message >> 8, 0x15 /* PB_WORD_MSB */ );
+ status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
+ message >> 8, 0x15/* PB_WORD_MSB */);
if (status >= 0)
return status;
- return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- message, 0x16 /* PB_WORD_LSB */ );
+ return twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
+ message, 0x16/* PB_WORD_LSB */);
}
/*----------------------------------------------------------------------*/
@@ -197,7 +214,7 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
* VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported.
* TI are revising the twl5030/tps659x0 specs to support that 3.0V setting.
*/
-#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED
+#ifdef CONFIG_TWL_ALLOW_UNSUPPORTED
#define UNSUP_MASK 0x0000
#else
#define UNSUP_MASK 0x8000
@@ -260,9 +277,31 @@ static const u16 VSIM_VSEL_table[] = {
static const u16 VDAC_VSEL_table[] = {
1200, 1300, 1800, 1800,
};
+static const u16 VAUX1_6030_VSEL_table[] = {
+ 1000, 1300, 1800, 2500,
+ 2800, 2900, 3000, 3000,
+};
+static const u16 VAUX2_6030_VSEL_table[] = {
+ 1200, 1800, 2500, 2750,
+ 2800, 2800, 2800, 2800,
+};
+static const u16 VAUX3_6030_VSEL_table[] = {
+ 1000, 1200, 1300, 1800,
+ 2500, 2800, 3000, 3000,
+};
+static const u16 VMMC_VSEL_table[] = {
+ 1200, 1800, 2800, 2900,
+ 3000, 3000, 3000, 3000,
+};
+static const u16 VPP_VSEL_table[] = {
+ 1800, 1900, 2000, 2100,
+ 2200, 2300, 2400, 2500,
+};
+static const u16 VUSIM_VSEL_table[] = {
+ 1200, 1800, 2500, 2900,
+};
-
-static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
+static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int mV = info->table[index];
@@ -271,7 +310,7 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
}
static int
-twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
+twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel;
@@ -288,16 +327,18 @@ twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
/* use the first in-range value */
if (min_uV <= uV && uV <= max_uV)
- return twl4030reg_write(info, VREG_DEDICATED, vsel);
+ return twlreg_write(info, TWL_MODULE_PM_SLAVE_LDO,
+ VREG_VOLTAGE, vsel);
}
return -EDOM;
}
-static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
+static int twlldo_get_voltage(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
- int vsel = twl4030reg_read(info, VREG_DEDICATED);
+ int vsel = twlreg_read(info, TWL_MODULE_PM_SLAVE_LDO,
+ VREG_VOLTAGE);
if (vsel < 0)
return vsel;
@@ -306,19 +347,20 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
return LDO_MV(info->table[vsel]) * 1000;
}
-static struct regulator_ops twl4030ldo_ops = {
- .list_voltage = twl4030ldo_list_voltage,
+static struct regulator_ops twlldo_ops = {
+ .list_voltage = twlldo_list_voltage,
- .set_voltage = twl4030ldo_set_voltage,
- .get_voltage = twl4030ldo_get_voltage,
+ .set_voltage = twlldo_set_voltage,
+ .get_voltage = twlldo_get_voltage,
- .enable = twl4030reg_enable,
- .disable = twl4030reg_disable,
- .is_enabled = twl4030reg_is_enabled,
+ .enable = twlreg_enable,
+ .disable = twlreg_disable,
+ .is_enabled = twlreg_is_enabled,
- .set_mode = twl4030reg_set_mode,
-
- .get_status = twl4030reg_get_status,
+#ifdef CONFIG_TWL4030_CORE
+ .set_mode = twlreg_set_mode,
+ .get_status = twlreg_get_status,
+#endif
};
/*----------------------------------------------------------------------*/
@@ -326,60 +368,70 @@ static struct regulator_ops twl4030ldo_ops = {
/*
* Fixed voltage LDOs don't have a VSEL field to update.
*/
-static int twl4030fixed_list_voltage(struct regulator_dev *rdev, unsigned index)
+static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
return info->min_mV * 1000;
}
-static int twl4030fixed_get_voltage(struct regulator_dev *rdev)
+static int twlfixed_get_voltage(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
return info->min_mV * 1000;
}
-static struct regulator_ops twl4030fixed_ops = {
- .list_voltage = twl4030fixed_list_voltage,
+static struct regulator_ops twlfixed_ops = {
+ .list_voltage = twlfixed_list_voltage,
- .get_voltage = twl4030fixed_get_voltage,
+ .get_voltage = twlfixed_get_voltage,
- .enable = twl4030reg_enable,
- .disable = twl4030reg_disable,
- .is_enabled = twl4030reg_is_enabled,
+ .enable = twlreg_enable,
+ .disable = twlreg_disable,
+ .is_enabled = twlreg_is_enabled,
- .set_mode = twl4030reg_set_mode,
-
- .get_status = twl4030reg_get_status,
+#ifdef CONFIG_TWL4030_CORE
+ .set_mode = twlreg_set_mode,
+ .get_status = twlreg_get_status,
+#endif
};
/*----------------------------------------------------------------------*/
-#define TWL_ADJUSTABLE_LDO(label, offset, num) { \
+#define TWL4030_ADJUSTABLE_LDO(label, offset, num) \
+ TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030)
+#define TWL4030_FIXED_LDO(label, offset, mVolts, num) \
+ TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030)
+#define TWL6030_ADJUSTABLE_LDO(label, offset, num) \
+ TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030)
+#define TWL6030_FIXED_LDO(label, offset, mVolts, num) \
+ TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030)
+
+#define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \
.base = offset, \
.id = num, \
.table_len = ARRAY_SIZE(label##_VSEL_table), \
.table = label##_VSEL_table, \
.desc = { \
.name = #label, \
- .id = TWL4030_REG_##label, \
+ .id = family##_REG_##label, \
.n_voltages = ARRAY_SIZE(label##_VSEL_table), \
- .ops = &twl4030ldo_ops, \
+ .ops = &twlldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
-#define TWL_FIXED_LDO(label, offset, mVolts, num) { \
+#define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \
.base = offset, \
.id = num, \
.min_mV = mVolts, \
.desc = { \
.name = #label, \
- .id = TWL4030_REG_##label, \
+ .id = family##_REG_##label, \
.n_voltages = 1, \
- .ops = &twl4030fixed_ops, \
+ .ops = &twlfixed_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
@@ -389,35 +441,60 @@ static struct regulator_ops twl4030fixed_ops = {
* We list regulators here if systems need some level of
* software control over them after boot.
*/
-static struct twlreg_info twl4030_regs[] = {
- TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
- TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
- TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
- TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
- TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
- TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
- TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
+static struct twlreg_info twl_regs[] = {
+#ifdef CONFIG_TWL4030_CORE
+ TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
+ TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
+ TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
+ TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
+ TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
+ TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
+ TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
/*
- TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
+ TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
*/
- TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
- TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9),
- TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
+ TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
+ TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9),
+ TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
/*
- TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
- TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
- TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
- TWL_SMPS(VIO, 0x4b, 14),
- TWL_SMPS(VDD1, 0x55, 15),
- TWL_SMPS(VDD2, 0x63, 16),
+ TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
+ TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
+ TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
+ TWL4030_SMPS(VIO, 0x4b, 14),
+ TWL4030_SMPS(VDD1, 0x55, 15),
+ TWL4030_SMPS(VDD2, 0x63, 16),
*/
- TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
- TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
- TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
+ TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
+ TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
+ TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
/* VUSBCP is managed *only* by the USB subchip */
+#elif CONFIG_TWL6030_CORE
+ TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x84, 1),
+ TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x88, 2),
+ TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x8c, 3),
+ TWL6030_ADJUSTABLE_LDO(VMMC, 0x98, 4),
+ TWL6030_ADJUSTABLE_LDO(VPP, 0x9c, 5),
+ /*
+ TWL6030_ADJUSTABLE_LDO(VRTC, 0x00, 6),
+ */
+ TWL6030_ADJUSTABLE_LDO(VUSIM, 0xa4, 7),
+ /* SMPS
+ TWL6030_SMPS(VDD1, 0x4b, 8),
+ TWL6030_SMPS(VDD2, 0x55, 9),
+ TWL6030_SMPS(VDD3, 0x63, 10),
+ TWL6030_SMPS(VMEM, 0x00, 11),
+ TWL6030_SMPS(V1V29, 0x00, 12),
+ TWL6030_SMPS(V1V8, 0x00, 13),
+ TWL6030_SMPS(V2V1, 0x00, 14),
+ */
+ TWL6030_FIXED_LDO(VANA, 0x80, 2100, 15),
+ TWL6030_FIXED_LDO(VCXIO, 0x90, 1800, 16),
+ TWL6030_FIXED_LDO(VDAC, 0x94, 1800, 17),
+ TWL6030_FIXED_LDO(VUSB, 0xa0, 3300, 18)
+#endif
};
-static int twl4030reg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
{
int i;
struct twlreg_info *info;
@@ -425,10 +502,10 @@ static int twl4030reg_probe(struct platform_device *pdev)
struct regulation_constraints *c;
struct regulator_dev *rdev;
- for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) {
- if (twl4030_regs[i].desc.id != pdev->id)
+ for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) {
+ if (twl_regs[i].desc.id != pdev->id)
continue;
- info = twl4030_regs + i;
+ info = twl_regs + i;
break;
}
if (!info)
@@ -466,35 +543,35 @@ static int twl4030reg_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit twl4030reg_remove(struct platform_device *pdev)
+static int __devexit twlreg_remove(struct platform_device *pdev)
{
regulator_unregister(platform_get_drvdata(pdev));
return 0;
}
-MODULE_ALIAS("platform:twl4030_reg");
+MODULE_ALIAS("platform:twl_reg");
-static struct platform_driver twl4030reg_driver = {
- .probe = twl4030reg_probe,
- .remove = __devexit_p(twl4030reg_remove),
+static struct platform_driver twlreg_driver = {
+ .probe = twlreg_probe,
+ .remove = __devexit_p(twlreg_remove),
/* NOTE: short name, to work around driver model truncation of
- * "twl4030_regulator.12" (and friends) to "twl4030_regulator.1".
+ * "twl_regulator.12" (and friends) to "twl_regulator.1".
*/
- .driver.name = "twl4030_reg",
+ .driver.name = "twl_reg",
.driver.owner = THIS_MODULE,
};
-static int __init twl4030reg_init(void)
+static int __init twlreg_init(void)
{
- return platform_driver_register(&twl4030reg_driver);
+ return platform_driver_register(&twlreg_driver);
}
-subsys_initcall(twl4030reg_init);
+subsys_initcall(twlreg_init);
-static void __exit twl4030reg_exit(void)
+static void __exit twlreg_exit(void)
{
- platform_driver_unregister(&twl4030reg_driver);
+ platform_driver_unregister(&twlreg_driver);
}
-module_exit(twl4030reg_exit)
+module_exit(twlreg_exit)
-MODULE_DESCRIPTION("TWL4030 regulator driver");
+MODULE_DESCRIPTION("TWL regulator driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 81adbdbd5042..89ccc9359531 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -257,15 +257,15 @@ config RTC_DRV_TWL92330
platforms. The support is integrated with the rest of
the Menelaus driver; it's not separate module.
-config RTC_DRV_TWL4030
- tristate "TI TWL4030/TWL5030/TPS659x0"
- depends on RTC_CLASS && TWL4030_CORE
+config RTC_DRV_TWL
+ tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0"
+ depends on RTC_CLASS && (TWL4030_CORE || TWL6030_CORE)
help
If you say yes here you get support for the RTC on the
TWL4030 family chips, used mostly with OMAP3 platforms.
This driver can also be built as a module. If so, the module
- will be called rtc-twl4030.
+ will be called twl-rtc.
config RTC_DRV_S35390A
tristate "Seiko Instruments S-35390A"
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 3c0f2b2ac927..c32e21d7f66d 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
-obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o
+obj-$(CONFIG_RTC_DRV_TWL) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl.c
index 9c8c70c497dc..ff3842d9eec0 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
/*
@@ -42,6 +42,7 @@
#define REG_YEARS_REG 0x05
#define REG_WEEKS_REG 0x06
+#ifdef CONFIG_TWL4030_CORE
#define REG_ALARM_SECONDS_REG 0x07
#define REG_ALARM_MINUTES_REG 0x08
#define REG_ALARM_HOURS_REG 0x09
@@ -55,6 +56,26 @@
#define REG_RTC_COMP_LSB_REG 0x10
#define REG_RTC_COMP_MSB_REG 0x11
+#endif
+
+#ifdef CONFIG_TWL6030_CORE
+#define REG_ALARM_SECONDS_REG 0x08
+#define REG_ALARM_MINUTES_REG 0x09
+#define REG_ALARM_HOURS_REG 0x0A
+#define REG_ALARM_DAYS_REG 0x0B
+#define REG_ALARM_MONTHS_REG 0x0C
+#define REG_ALARM_YEARS_REG 0x0D
+
+#define REG_RTC_CTRL_REG 0x10
+#define REG_RTC_STATUS_REG 0x11
+#define REG_RTC_INTERRUPTS_REG 0x12
+
+#define REG_RTC_COMP_LSB_REG 0x13
+#define REG_RTC_COMP_MSB_REG 0x14
+#define REG_RTC_RESET_STATUS_REG 0x16
+
+#define TWL_MODULE_RTC TWL6030_MODULE_RTC
+#endif
/* RTC_CTRL_REG bitfields */
#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01
@@ -88,13 +109,13 @@
/*
* Supports 1 byte read from TWL4030 RTC register.
*/
-static int twl4030_rtc_read_u8(u8 *data, u8 reg)
+static int twl_rtc_read_u8(u8 *data, u8 reg)
{
int ret;
- ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg);
+ ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, reg);
if (ret < 0)
- pr_err("twl4030_rtc: Could not read TWL4030"
+ pr_err("twl_rtc: Could not read TWL4030"
"register %X - error %d\n", reg, ret);
return ret;
}
@@ -102,13 +123,13 @@ static int twl4030_rtc_read_u8(u8 *data, u8 reg)
/*
* Supports 1 byte write to TWL4030 RTC registers.
*/
-static int twl4030_rtc_write_u8(u8 data, u8 reg)
+static int twl_rtc_write_u8(u8 data, u8 reg)
{
int ret;
- ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg);
+ ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, reg);
if (ret < 0)
- pr_err("twl4030_rtc: Could not write TWL4030"
+ pr_err("twl_rtc: Could not write TWL4030"
"register %X - error %d\n", reg, ret);
return ret;
}
@@ -129,7 +150,7 @@ static int set_rtc_irq_bit(unsigned char bit)
val = rtc_irq_bits | bit;
val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
- ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+ ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
if (ret == 0)
rtc_irq_bits = val;
@@ -145,14 +166,14 @@ static int mask_rtc_irq_bit(unsigned char bit)
int ret;
val = rtc_irq_bits & ~bit;
- ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+ ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
if (ret == 0)
rtc_irq_bits = val;
return ret;
}
-static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
+static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -164,7 +185,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
return ret;
}
-static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled)
+static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -185,23 +206,23 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled)
* - Months are 1..12 vs Linux 0-11
* - Years are 0..99 vs Linux 1900..N (we assume 21st century)
*/
-static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int twl_rtc_read_time(struct device *dev, struct rtc_time *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);
+ ret = twl_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);
+ ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
if (ret < 0)
return ret;
- ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
+ ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
REG_SECONDS_REG, ALL_TIME_REGS);
if (ret < 0) {
@@ -219,7 +240,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm)
return ret;
}
-static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char save_control;
unsigned char rtc_data[ALL_TIME_REGS + 1];
@@ -233,17 +254,17 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_data[6] = bin2bcd(tm->tm_year - 100);
/* Stop RTC while updating the TC registers */
- ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
+ ret = twl_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);
+ twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
if (ret < 0)
goto out;
/* update all the time registers in one shot */
- ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data,
+ ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data,
REG_SECONDS_REG, ALL_TIME_REGS);
if (ret < 0) {
dev_err(dev, "rtc_set_time error %d\n", ret);
@@ -252,7 +273,7 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Start back RTC */
save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
- ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
out:
return ret;
@@ -261,12 +282,12 @@ out:
/*
* Gets current TWL4030 RTC alarm time.
*/
-static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
unsigned char rtc_data[ALL_TIME_REGS + 1];
int ret;
- ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data,
+ ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
if (ret < 0) {
dev_err(dev, "rtc_read_alarm error %d\n", ret);
@@ -288,12 +309,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
}
-static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
unsigned char alarm_data[ALL_TIME_REGS + 1];
int ret;
- ret = twl4030_rtc_alarm_irq_enable(dev, 0);
+ ret = twl_rtc_alarm_irq_enable(dev, 0);
if (ret)
goto out;
@@ -305,7 +326,7 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
/* update all the alarm registers in one shot */
- ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data,
+ ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
REG_ALARM_SECONDS_REG, ALL_TIME_REGS);
if (ret) {
dev_err(dev, "rtc_set_alarm error %d\n", ret);
@@ -313,12 +334,12 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
}
if (alm->enabled)
- ret = twl4030_rtc_alarm_irq_enable(dev, 1);
+ ret = twl_rtc_alarm_irq_enable(dev, 1);
out:
return ret;
}
-static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
+static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
{
unsigned long events = 0;
int ret = IRQ_NONE;
@@ -333,7 +354,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
local_irq_enable();
#endif
- res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+ res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
if (res)
goto out;
/*
@@ -347,14 +368,15 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
else
events |= RTC_IRQF | RTC_UF;
- res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
+ res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
REG_RTC_STATUS_REG);
if (res)
goto out;
+#ifdef CONFIG_TWL4030_CORE
/* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1
* needs 2 reads to clear the interrupt. One read is done in
- * do_twl4030_pwrirq(). Doing the second read, to clear
+ * do_twl_pwrirq(). Doing the second read, to clear
* the bit.
*
* FIXME the reason PWR_ISR1 needs an extra read is that
@@ -363,10 +385,11 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
* risk wrongly clearing status for some other IRQ (losing
* the interrupt). Be smarter about handling RTC_UF ...
*/
- res = twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ res = twl_i2c_read_u8(TWL_MODULE_INT,
&rd_reg, TWL4030_INT_PWR_ISR1);
if (res)
goto out;
+#endif
/* Notify RTC core on event */
rtc_update_irq(rtc, 1, events);
@@ -376,18 +399,18 @@ out:
return ret;
}
-static struct rtc_class_ops twl4030_rtc_ops = {
- .read_time = twl4030_rtc_read_time,
- .set_time = twl4030_rtc_set_time,
- .read_alarm = twl4030_rtc_read_alarm,
- .set_alarm = twl4030_rtc_set_alarm,
- .alarm_irq_enable = twl4030_rtc_alarm_irq_enable,
- .update_irq_enable = twl4030_rtc_update_irq_enable,
+static struct rtc_class_ops twl_rtc_ops = {
+ .read_time = twl_rtc_read_time,
+ .set_time = twl_rtc_set_time,
+ .read_alarm = twl_rtc_read_alarm,
+ .set_alarm = twl_rtc_set_alarm,
+ .alarm_irq_enable = twl_rtc_alarm_irq_enable,
+ .update_irq_enable = twl_rtc_update_irq_enable,
};
/*----------------------------------------------------------------------*/
-static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
+static int __devinit twl_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
int ret = 0;
@@ -398,7 +421,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
return -EINVAL;
rtc = rtc_device_register(pdev->name,
- &pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
+ &pdev->dev, &twl_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc);
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
@@ -409,7 +432,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
- ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+ ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
if (ret < 0)
goto out1;
@@ -420,11 +443,11 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
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);
+ ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
if (ret < 0)
goto out1;
- ret = request_irq(irq, twl4030_rtc_interrupt,
+ ret = request_irq(irq, twl_rtc_interrupt,
IRQF_TRIGGER_RISING,
dev_name(&rtc->dev), rtc);
if (ret < 0) {
@@ -433,20 +456,20 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
}
/* Check RTC module status, Enable if it is off */
- ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
+ ret = twl_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);
+ ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
if (ret < 0)
goto out2;
}
/* init cached IRQ enable bits */
- ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
+ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
if (ret < 0)
goto out2;
@@ -464,7 +487,7 @@ out0:
* Disable all TWL4030 RTC module interrupts.
* Sets status flag to free.
*/
-static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
+static int __devexit twl_rtc_remove(struct platform_device *pdev)
{
/* leave rtc running, but disable irqs */
struct rtc_device *rtc = platform_get_drvdata(pdev);
@@ -480,7 +503,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
return 0;
}
-static void twl4030_rtc_shutdown(struct platform_device *pdev)
+static void twl_rtc_shutdown(struct platform_device *pdev)
{
/* mask timer interrupts, but leave alarm interrupts on to enable
power-on when alarm is triggered */
@@ -491,7 +514,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev)
static unsigned char irqstat;
-static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
irqstat = rtc_irq_bits;
@@ -499,42 +522,42 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int twl4030_rtc_resume(struct platform_device *pdev)
+static int twl_rtc_resume(struct platform_device *pdev)
{
set_rtc_irq_bit(irqstat);
return 0;
}
#else
-#define twl4030_rtc_suspend NULL
-#define twl4030_rtc_resume NULL
+#define twl_rtc_suspend NULL
+#define twl_rtc_resume NULL
#endif
-MODULE_ALIAS("platform:twl4030_rtc");
+MODULE_ALIAS("platform:twl_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,
+ .probe = twl_rtc_probe,
+ .remove = __devexit_p(twl_rtc_remove),
+ .shutdown = twl_rtc_shutdown,
+ .suspend = twl_rtc_suspend,
+ .resume = twl_rtc_resume,
.driver = {
.owner = THIS_MODULE,
- .name = "twl4030_rtc",
+ .name = "twl_rtc",
},
};
-static int __init twl4030_rtc_init(void)
+static int __init twl_rtc_init(void)
{
return platform_driver_register(&twl4030rtc_driver);
}
-module_init(twl4030_rtc_init);
+module_init(twl_rtc_init);
-static void __exit twl4030_rtc_exit(void)
+static void __exit twl_rtc_exit(void)
{
platform_driver_unregister(&twl4030rtc_driver);
}
-module_exit(twl4030_rtc_exit);
+module_exit(twl_rtc_exit);
MODULE_AUTHOR("Texas Instruments, MontaVista Software");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6553833c12db..1a3b25717d6f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1359,6 +1359,123 @@ config SERIAL_OF_PLATFORM
Currently, only 8250 compatible ports are supported, but
others can easily be added.
+config SERIAL_OMAP
+ bool "OMAP serial port support"
+ depends on ARCH_OMAP3 || ARCH_OMAP4
+ select SERIAL_CORE
+ help
+ If you have a machine based on an Texas Instruments OMAP CPU you
+ can enable its onboard serial ports by enabling this option.
+
+config SERIAL_OMAP_CONSOLE
+ bool "Console on OMAP serial port"
+ depends on SERIAL_OMAP
+ select SERIAL_CORE_CONSOLE
+ help
+ If you have enabled the serial port on the Texas Instruments OMAP
+ CPU you can make it the console by answering Y to this option.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/ttyO) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttyO0". (Try "man bootparam" or see the documentation of
+ your boot loader (lilo or loadlin) about how to pass options to the
+ kernel at boot time.)
+
+config SERIAL_OMAP_DMA_UART1
+ bool "UART1 DMA support"
+ depends on SERIAL_OMAP
+ help
+ If you have enabled the serial port on the Texas Instruments OMAP
+ CPU you can enable the DMA transfer on UART 1 by answering
+ to this option.
+
+config SERIAL_OMAP_UART1_RXDMA_TIMEOUT
+ int "Timeout value for RX DMA in microseconds"
+ depends on SERIAL_OMAP_DMA_UART1
+ default "1"
+ help
+ Set the timeout value in which you want the data pulled by RX dma to
+ be passed to the tty framework.
+
+config SERIAL_OMAP_UART1_RXDMA_BUFSIZE
+ int "DMA buffer size for RX in bytes"
+ depends on SERIAL_OMAP_DMA_UART1
+ default "4096"
+ help
+ Set the dma buffer size for UART Rx
+
+config SERIAL_OMAP_DMA_UART2
+ bool "UART2 DMA support"
+ depends on SERIAL_OMAP
+ help
+ If you have enabled the serial port on the Texas Instruments OMAP
+ CPU you can enable the DMA transfer on UART 2 by answering
+ to this option.
+
+config SERIAL_OMAP_UART2_RXDMA_TIMEOUT
+ int "Timeout value for RX DMA in microseconds"
+ depends on SERIAL_OMAP_DMA_UART2
+ default "1"
+ help
+ Set the timeout value in which you want the data pulled by RX dma to
+ be passed to the tty framework.
+
+config SERIAL_OMAP_UART2_RXDMA_BUFSIZE
+ int "DMA buffer size for RX in bytes"
+ depends on SERIAL_OMAP_DMA_UART2
+ default "4096"
+ help
+ Set the dma buffer size for UART Rx
+
+config SERIAL_OMAP_DMA_UART3
+ bool "UART3 DMA support"
+ depends on SERIAL_OMAP
+ help
+ If you have enabled the serial port on the Texas Instruments OMAP
+ CPU you can enable the DMA transfer on UART 3 by answering
+ to this option.
+
+config SERIAL_OMAP_UART3_RXDMA_TIMEOUT
+ int "Timeout value for RX DMA in microseconds"
+ depends on SERIAL_OMAP_DMA_UART3
+ default "1"
+ help
+ Set the timeout value in which you want the data pulled by RX dma to
+ be passed to the tty framework.
+
+config SERIAL_OMAP_UART3_RXDMA_BUFSIZE
+ int "DMA buffer size for RX in bytes"
+ depends on SERIAL_OMAP_DMA_UART3
+ default "4096"
+ help
+ Set the dma buffer size for UART Rx
+
+config SERIAL_OMAP_DMA_UART4
+ bool "UART4 DMA support"
+ depends on ARCH_OMAP4 && SERIAL_OMAP
+ depends on SERIAL_OMAP
+ help
+ If you have enabled the serial port on the Texas Instruments OMAP
+ CPU you can enable the DMA transfer on UART 4 by answering
+ to this option.
+
+config SERIAL_OMAP_UART4_RXDMA_TIMEOUT
+ int "Timeout value for RX DMA in microseconds"
+ depends on SERIAL_OMAP_DMA_UART4
+ default "1"
+ help
+ Set the timeout value in which you want the data pulled by RX dma to
+ be passed to the tty framework.
+
+config SERIAL_OMAP_UART4_RXDMA_BUFSIZE
+ int "DMA buffer size for RX in bytes"
+ depends on SERIAL_OMAP_DMA_UART4
+ default "4096"
+ help
+ Set the dma buffer size for UART Rx
+
+
config SERIAL_OF_PLATFORM_NWPSERIAL
tristate "NWP serial port driver"
depends on PPC_OF && PPC_DCR
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d5a29981c6c4..db38f2ca1873 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -79,3 +79,4 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
new file mode 100644
index 000000000000..fe877457a17d
--- /dev/null
+++ b/drivers/serial/omap-serial.c
@@ -0,0 +1,1728 @@
+/*
+ * drivers/serial/omap-serial.c
+ *
+ * Driver for OMAP3430 UART controller.
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * Authors:
+ * Govindraj R <govindraj.raja@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * PM Framework based on arch/arm/mach-omap2/serial.c
+ * by Kevin Hilman.
+ *
+ * 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/console.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/irq.h>
+#include <mach/dma.h>
+#include <mach/dmtimer.h>
+#include <mach/omap-serial.h>
+
+static struct uart_omap_port *ui[OMAP_MAX_NR_PORTS];
+static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
+
+/* Forward declaration of functions */
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
+static void serial_omap_rx_timeout(unsigned long uart_no);
+static void serial_omap_start_rxdma(struct uart_omap_port *up);
+static int serial_omap_remove(struct platform_device *dev);
+
+static inline void omap_uart_block_sleep(int num);
+static void omap_uart_smart_idle_enable(int num, int enable);
+static inline void omap_uart_enable_clocks(int num);
+
+#ifdef DEBUG
+static void serial_omap_display_reg(struct uart_port *port);
+#endif
+
+int console_detect(char *str)
+{
+ char *next, *start = NULL;
+ int i;
+
+ i = strlen(CONSOLE_NAME);
+ next = saved_command_line;
+
+ while ((next = strchr(next, 'c')) != NULL) {
+ if (!strncmp(next, CONSOLE_NAME, i)) {
+ start = next;
+ break;
+ } else {
+ next++;
+ }
+ }
+ if (!start)
+ return -EPERM;
+ i = 0;
+ start = strchr(start, '=') + 1;
+ while (*start != ',') {
+ str[i++] = *start++;
+ if (i > 6) {
+ pr_err("%s : Invalid Console Name\n", __func__);
+ return -EPERM;
+ }
+ }
+ str[i] = '\0';
+ return 0;
+}
+
+static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
+{
+ offset <<= up->port.regshift;
+ return readw(up->port.membase + offset);
+}
+
+static inline void serial_out(struct uart_omap_port *up, int offset, int value)
+{
+ offset <<= up->port.regshift;
+ writew(value, up->port.membase + offset);
+}
+
+static inline void serial_omap_clear_fifos(struct uart_omap_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_out(up, UART_FCR, 0);
+}
+
+/*
+ * We have written our own function to get the divisor so as to support
+ * 13x mode.
+ */
+static unsigned int
+serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
+{
+ unsigned int divisor;
+ if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+ divisor = 13;
+ else
+ divisor = 16;
+ return port->uartclk/(baud * divisor);
+}
+
+static void serial_omap_stop_rxdma(struct uart_omap_port *up)
+{
+ if (up->uart_dma.rx_dma_state) {
+ del_timer_sync(&up->uart_dma.rx_timer);
+ omap_stop_dma(up->uart_dma.rx_dma_channel);
+ omap_free_dma(up->uart_dma.rx_dma_channel);
+ up->uart_dma.rx_dma_channel = 0xFF;
+ up->uart_dma.rx_dma_state = 0x0;
+ }
+}
+
+static void serial_omap_enable_ms(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static void serial_omap_stop_tx(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ if (up->use_dma) {
+ if (up->uart_dma.tx_dma_channel != 0xFF) {
+ /*
+ * Check if dma is still active . If yes do nothing,
+ * return. Else stop dma
+ */
+
+ if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
+ return;
+
+ omap_stop_dma(up->uart_dma.tx_dma_channel);
+ omap_free_dma(up->uart_dma.tx_dma_channel);
+ up->uart_dma.tx_dma_channel = 0xFF;
+ }
+ }
+
+ if (up->ier & UART_IER_THRI) {
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+}
+
+static void serial_omap_stop_rx(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ serial_omap_stop_rxdma(up);
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+
+}
+
+static inline void receive_chars(struct uart_omap_port *up, int *status)
+{
+ struct tty_struct *tty = up->port.info->port.tty;
+ unsigned int ch, flag;
+ int max_count = 256;
+
+ do {
+ ch = serial_in(up, UART_RX);
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
+ UART_LSR_FE | UART_LSR_OE))) {
+ /*
+ * For statistics only
+ */
+ if (*status & UART_LSR_BI) {
+ *status &= ~(UART_LSR_FE | UART_LSR_PE);
+ up->port.icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ goto ignore_char;
+ } else if (*status & UART_LSR_PE)
+ up->port.icount.parity++;
+ else if (*status & UART_LSR_FE)
+ up->port.icount.frame++;
+ if (*status & UART_LSR_OE)
+ up->port.icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ignored.
+ */
+ *status &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+ if (up->port.line == up->port.cons->index) {
+ /* Recover the break flag from console xmit */
+ *status |= up->lsr_break_flag;
+ up->lsr_break_flag = 0;
+ }
+#endif
+ if (*status & UART_LSR_BI)
+ flag = TTY_BREAK;
+ else if (*status & UART_LSR_PE)
+ flag = TTY_PARITY;
+ else if (*status & UART_LSR_FE)
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(&up->port, ch))
+ goto ignore_char;
+ uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
+ignore_char:
+ *status = serial_in(up, UART_LSR);
+ } while ((*status & UART_LSR_DR) && (max_count-- > 0));
+ tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct uart_omap_port *up)
+{
+ struct circ_buf *xmit = &up->port.info->xmit;
+ int count;
+
+ if (up->port.x_char) {
+ serial_out(up, UART_TX, up->port.x_char);
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ return;
+ }
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ serial_omap_stop_tx(&up->port);
+ return;
+ }
+
+ count = up->port.fifosize / 4;
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ if (uart_circ_empty(xmit))
+ serial_omap_stop_tx(&up->port);
+}
+
+static void serial_omap_start_tx(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ if (up->use_dma && !(up->port.x_char)) {
+
+ struct circ_buf *xmit = &up->port.info->xmit;
+ unsigned int start = up->uart_dma.tx_buf_dma_phys +
+ (xmit->tail & (UART_XMIT_SIZE - 1));
+ if (uart_circ_empty(xmit) || up->uart_dma.tx_dma_state)
+ return;
+ spin_lock(&(up->uart_dma.tx_lock));
+ up->uart_dma.tx_dma_state = 1;
+ spin_unlock(&(up->uart_dma.tx_lock));
+
+ up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+ /* It is a circular buffer. See if the buffer has wounded back.
+ * If yes it will have to be transferred in two separate dma
+ * transfers */
+ if (start + up->uart_dma.tx_buf_size >=
+ up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+ up->uart_dma.tx_buf_size =
+ (up->uart_dma.tx_buf_dma_phys +
+ UART_XMIT_SIZE) - start;
+
+ if (up->uart_dma.tx_dma_channel == 0xFF)
+ omap_request_dma(up->uart_dma.uart_dma_tx,
+ "UART Tx DMA",
+ (void *)uart_tx_dma_callback, up,
+ &(up->uart_dma.tx_dma_channel));
+ omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ up->uart_dma.uart_base, 0, 0);
+ omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+ OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+
+ omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+ OMAP_DMA_DATA_TYPE_S8,
+ up->uart_dma.tx_buf_size, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ up->uart_dma.uart_dma_tx, 0);
+
+ omap_start_dma(up->uart_dma.tx_dma_channel);
+
+ } else if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+}
+
+static unsigned int check_modem_status(struct uart_omap_port *up)
+{
+ int status;
+ status = serial_in(up, UART_MSR);
+
+ status |= up->msr_saved_flags;
+ up->msr_saved_flags = 0;
+
+ if ((status & UART_MSR_ANY_DELTA) == 0)
+ return status;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+ up->port.info != NULL) {
+ if (status & UART_MSR_TERI)
+ up->port.icount.rng++;
+ if (status & UART_MSR_DDSR)
+ up->port.icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change
+ (&up->port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change
+ (&up->port, status & UART_MSR_CTS);
+ wake_up_interruptible(&up->port.info->delta_msr_wait);
+ }
+
+ return status;
+}
+
+/*
+ * This handles the interrupt from one port.
+ */
+static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+{
+ struct uart_omap_port *up = dev_id;
+ unsigned int iir, lsr;
+
+ omap_uart_block_sleep(up->pdev->id - 1);
+
+ iir = serial_in(up, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ return IRQ_NONE;
+
+ lsr = serial_in(up, UART_LSR);
+ if ((iir & 0x4) && up->use_dma) {
+ up->ier &= ~UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+ serial_omap_start_rxdma(up);
+ } else if (lsr & UART_LSR_DR) {
+ receive_chars(up, &lsr);
+ }
+ check_modem_status(up);
+ if ((lsr & UART_LSR_THRE) && (iir & 0x2))
+ transmit_chars(up);
+
+ up->port_activity = jiffies;
+ return IRQ_HANDLED;
+}
+
+static unsigned int serial_omap_tx_empty(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned long flags;
+ unsigned int ret;
+
+ dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret;
+}
+
+static unsigned int serial_omap_get_mctrl(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned char status;
+ unsigned int ret;
+
+ status = check_modem_status(up);
+ dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
+
+ ret = 0;
+ if (status & UART_MSR_DCD)
+ ret |= TIOCM_CAR;
+ if (status & UART_MSR_RI)
+ ret |= TIOCM_RNG;
+ if (status & UART_MSR_DSR)
+ ret |= TIOCM_DSR;
+ if (status & UART_MSR_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned char mcr = 0;
+
+ dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ mcr |= up->mcr;
+ serial_out(up, UART_MCR, mcr);
+}
+
+static void serial_omap_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned long flags;
+
+ dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial_omap_startup(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned long flags;
+ int irq_flags = 0;
+ int retval;
+
+ omap_uart_smart_idle_enable(up->pdev->id - 1, 0);
+
+ /*
+ * Allocate the IRQ
+ */
+ retval = request_irq(up->port.irq, serial_omap_irq, irq_flags,
+ up->name, up);
+
+ if (retval)
+ return retval;
+
+ dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+
+
+ /*
+ * Clear the FIFO buffers and disable them.
+ * (they will be reenabled in set_termios())
+ */
+ serial_omap_clear_fifos(up);
+ /* For Hardware flow control */
+ serial_out(up, UART_MCR, 0x2);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ (void) serial_in(up, UART_LSR);
+ (void) serial_in(up, UART_RX);
+ (void) serial_in(up, UART_IIR);
+ (void) serial_in(up, UART_MSR);
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ if (!is_real_interrupt(up->port.irq))
+ up->port.mctrl |= TIOCM_OUT1;
+ } else {
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+ if (is_real_interrupt(up->port.irq))
+ up->port.mctrl |= TIOCM_OUT2;
+ }
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ up->msr_saved_flags = 0;
+
+ if (up->use_dma) {
+ if (!up->is_buf_dma_alloced) {
+ free_page((unsigned long)up->port.info->xmit.buf);
+ up->port.info->xmit.buf = NULL;
+ up->port.info->xmit.buf = dma_alloc_coherent(NULL,
+ UART_XMIT_SIZE,
+ (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
+ 0);
+ up->is_buf_dma_alloced = 1;
+ }
+ init_timer(&(up->uart_dma.rx_timer));
+ up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+ up->uart_dma.rx_timer.data = up->pdev->id;
+ /* Currently the buffer size is 4KB. Can increase it */
+ up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
+ up->uart_dma.rx_buf_size,
+ (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
+ serial_omap_start_rxdma(up);
+ } else {
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+ * are set via set_termios(), which will be occurring imminently
+ * anyway, so we don't enable them here.
+ */
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+ }
+
+ up->port_activity = jiffies;
+ return 0;
+}
+
+static void serial_omap_shutdown(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned long flags;
+
+ dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+ /*
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+ inb((up->port.iobase & 0xfe0) | 0x1f);
+ up->port.mctrl |= TIOCM_OUT1;
+ } else
+ up->port.mctrl &= ~TIOCM_OUT2;
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * Disable break condition and FIFOs
+ */
+ serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+ serial_omap_clear_fifos(up);
+
+ /*
+ * Read data port to reset things, and then free the irq
+ */
+ (void) serial_in(up, UART_RX);
+ if (up->use_dma) {
+ int tmp;
+ if (up->is_buf_dma_alloced) {
+ dma_free_coherent(up->port.dev,
+ UART_XMIT_SIZE,
+ up->port.info->xmit.buf,
+ up->uart_dma.tx_buf_dma_phys);
+ up->port.info->xmit.buf = NULL;
+ up->is_buf_dma_alloced = 0;
+ }
+ serial_omap_stop_rx(port);
+ dma_free_coherent(up->port.dev,
+ up->uart_dma.rx_buf_size,
+ up->uart_dma.rx_buf,
+ up->uart_dma.rx_buf_dma_phys);
+ up->uart_dma.rx_buf = NULL;
+ tmp = serial_in(up, UART_OMAP_SYSC) & 0x7;
+ serial_out(up, UART_OMAP_SYSC, tmp); /* force-idle */
+ }
+
+ free_irq(up->port.irq, up);
+}
+
+static inline void
+serial_omap_configure_xonxoff
+ (struct uart_omap_port *up, struct ktermios *termios)
+{
+ unsigned char efr = 0;
+
+ up->lcr = serial_in(up, UART_LCR);
+ serial_out(up, UART_LCR, 0xbf);
+ up->efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
+
+ serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+ serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+ /* IXON Flag:
+ * Enable XON/XOFF flow control on output.
+ * Transmit XON1, XOFF1
+ */
+ if (termios->c_iflag & IXON)
+ efr |= 0x01 << 3;
+
+ /* IXOFF Flag:
+ * Enable XON/XOFF flow control on input.
+ * Receiver compares XON1, XOFF1.
+ */
+ if (termios->c_iflag & IXOFF)
+ efr |= 0x01 << 1;
+
+ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x80);
+
+ up->mcr = serial_in(up, UART_MCR);
+
+ /* IXANY Flag:
+ * Enable any character to restart output.
+ * Operation resumes after receiving any
+ * character after recognition of the XOFF character
+ */
+ if (termios->c_iflag & IXANY)
+ up->mcr |= 1<<5;
+
+ serial_out(up, UART_MCR, up->mcr | 1<<6);
+
+ serial_out(up, UART_LCR, 0xbf);
+ serial_out(up, UART_TI752_TCR, 0x0f);
+ /* Enable special char function UARTi.EFR_REG[5] and
+ * load the new software flow control mode IXON or IXOFF
+ * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
+ */
+ serial_out(up, UART_EFR, up->efr | efr | 1<<5);
+ serial_out(up, UART_LCR, 0x80);
+
+ serial_out(up, UART_MCR, up->mcr & ~(1<<6));
+ serial_out(up, UART_LCR, up->lcr);
+}
+
+static void
+serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned char cval;
+ unsigned char efr = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ cval = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ cval = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ cval = UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ cval = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ cval |= UART_LCR_STOP;
+ if (termios->c_cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(termios->c_cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
+ quot = serial_omap_get_divisor(port, baud);
+
+ if (up->use_dma)
+ up->fcr = /* UART_FCR_ENABLE_FIFO
+ | */ 0x1 << 6 | 0x1 << 4
+ | UART_FCR_DMA_SELECT;
+ else
+ up->fcr = UART_FCR_ENABLE_FIFO
+ | 0x1 << 6 | 0x1 << 4;
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characters to ignore
+ */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * Modem status interrupts
+ */
+ up->ier &= ~UART_IER_MSI;
+ if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_LCR, cval); /* reset DLAB */
+
+ /*-----------FIFOs and DMA Settings -----------*/
+ serial_out(up, UART_LCR, UART_LCR_DLAB);
+ serial_out(up, UART_DLL, 0);
+ serial_out(up, UART_DLM, 0);
+ serial_out(up, UART_LCR, 0);
+
+ serial_out(up, UART_LCR, 0xbf);
+
+ up->efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x80); /* Access FCR */
+
+ up->mcr = serial_in(up, UART_MCR);
+ serial_out(up, UART_MCR, up->mcr | 0x40); /* Access TLR*/
+ /* FIFO ENABLE, DMA MODE */
+ serial_out(up, UART_FCR, up->fcr);
+ serial_out(up, UART_LCR, 0xbf); /* Access EFR */
+
+ if (up->use_dma) {
+ serial_out(up, UART_TI752_TLR, 0x00);
+ serial_out(up, UART_OMAP_SCR, ((1 << 6) | (1 << 7)));
+ }
+
+ serial_out(up, UART_EFR, up->efr);
+ serial_out(up, UART_LCR, 0x80);
+ serial_out(up, UART_MCR, up->mcr); /* Restore TLR */
+
+ /*-----Protocol, Baud Rate, and Interrupt Settings -- */
+
+ serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE);
+
+ serial_out(up, UART_LCR, 0xbf); /* Access EFR */
+
+ up->efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_IER, 0);
+ serial_out(up, UART_LCR, 0xbf);
+
+ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
+ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
+
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_LCR, 0xbf); /* Access EFR */
+
+ serial_out(up, UART_EFR, up->efr);
+ serial_out(up, UART_LCR, cval);
+
+ if (baud > 230400 && baud != 3000000)
+ serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X);
+ else
+ serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X);
+
+ /* Hardware Flow Control Configuration */
+
+ if (termios->c_cflag & CRTSCTS) {
+ efr |= (UART_EFR_CTS | UART_EFR_RTS);
+ serial_out(up, UART_LCR, 0x80);
+
+ up->mcr = serial_in(up, UART_MCR);
+ serial_out(up, UART_MCR, up->mcr | 0x40);
+
+ serial_out(up, UART_LCR, 0xbf); /* Access EFR */
+
+ up->efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+ serial_out(up, UART_TI752_TCR, 0x0f);
+ serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
+ serial_out(up, UART_LCR, 0x80);
+ serial_out(up, UART_MCR, up->mcr | 0x02);
+ serial_out(up, UART_LCR, cval);
+ }
+
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+ /* ----Software Flow Control Configuration----- */
+ if (termios->c_iflag & (IXON | IXOFF))
+ serial_omap_configure_xonxoff(up, termios);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
+
+#ifdef DEBUG
+ serial_omap_display_reg(port);
+#endif
+}
+
+static void
+serial_omap_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned char efr;
+ dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+ efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_LCR, 0xBF);
+ serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0);
+
+ serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
+ serial_out(up, UART_LCR, 0xBF);
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, 0);
+}
+
+static void serial_omap_release_port(struct uart_port *port)
+{
+ dev_dbg(port->dev, "serial_omap_release_port+\n");
+}
+
+static int serial_omap_request_port(struct uart_port *port)
+{
+ dev_dbg(port->dev, "serial_omap_request_port+\n");
+ return 0;
+}
+
+static void serial_omap_config_port(struct uart_port *port, int flags)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
+ up->pdev->id);
+ up->port.type = PORT_OMAP;
+}
+
+static int
+serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* we don't want the core code to modify any port params */
+ dev_dbg(port->dev, "serial_omap_verify_port+\n");
+ return -EINVAL;
+}
+
+static const char *
+serial_omap_type(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
+ return up->name;
+}
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+
+static struct uart_omap_port *serial_omap_console_ports[4];
+
+static struct uart_driver serial_omap_reg;
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_omap_port *up)
+{
+ unsigned int status, tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ do {
+ status = serial_in(up, UART_LSR);
+
+ if (status & UART_LSR_BI)
+ up->lsr_break_flag = UART_LSR_BI;
+
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ tmout = 1000000;
+ for (tmout = 1000000; tmout; tmout--) {
+ unsigned int msr = serial_in(up, UART_MSR);
+ up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+ if (msr & UART_MSR_CTS)
+ break;
+ udelay(1);
+ }
+ }
+}
+
+static void serial_omap_console_putchar(struct uart_port *port, int ch)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ wait_for_xmitr(up);
+ serial_out(up, UART_TX, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void
+serial_omap_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_omap_port *up = serial_omap_console_ports[co->index];
+ unsigned int ier;
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+
+ uart_console_write(&up->port, s, count, serial_omap_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up);
+ serial_out(up, UART_IER, ier);
+ /*
+ * The receive handling will happen properly because the
+ * receive ready bit will still be set; it is not cleared
+ * on read. However, modem control will not, we must
+ * call it if we have saved something in the saved flags
+ * while processing with interrupts off.
+ */
+ if (up->msr_saved_flags)
+ check_modem_status(up);
+}
+
+static int __init
+serial_omap_console_setup(struct console *co, char *options)
+{
+ struct uart_omap_port *up;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ int r;
+
+ if (serial_omap_console_ports[co->index] == NULL)
+ return -ENODEV;
+ up = serial_omap_console_ports[co->index];
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ r = uart_set_options(&up->port, co, baud, parity, bits, flow);
+
+ return r;
+}
+
+static struct console serial_omap_console = {
+ .name = DEVICE_NAME,
+ .write = serial_omap_console_write,
+ .device = uart_console_device,
+ .setup = serial_omap_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &serial_omap_reg,
+};
+
+static void serial_omap_add_console_port(struct uart_omap_port *up)
+{
+ serial_omap_console_ports[up->pdev->id - 1] = up;
+}
+
+#define OMAP_CONSOLE (&serial_omap_console)
+
+#else
+
+#define OMAP_CONSOLE NULL
+
+static inline void serial_omap_add_console_port(struct uart_omap_port *up) {}
+
+#endif
+
+struct uart_ops serial_omap_pops = {
+ .tx_empty = serial_omap_tx_empty,
+ .set_mctrl = serial_omap_set_mctrl,
+ .get_mctrl = serial_omap_get_mctrl,
+ .stop_tx = serial_omap_stop_tx,
+ .start_tx = serial_omap_start_tx,
+ .stop_rx = serial_omap_stop_rx,
+ .enable_ms = serial_omap_enable_ms,
+ .break_ctl = serial_omap_break_ctl,
+ .startup = serial_omap_startup,
+ .shutdown = serial_omap_shutdown,
+ .set_termios = serial_omap_set_termios,
+ .pm = serial_omap_pm,
+ .type = serial_omap_type,
+ .release_port = serial_omap_release_port,
+ .request_port = serial_omap_request_port,
+ .config_port = serial_omap_config_port,
+ .verify_port = serial_omap_verify_port,
+};
+
+static struct uart_driver serial_omap_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "OMAP-SERIAL",
+ .dev_name = DEVICE_NAME,
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = OMAP_MAX_NR_PORTS,
+ .cons = OMAP_CONSOLE,
+};
+
+static
+int serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct uart_omap_port *up = platform_get_drvdata(pdev);
+
+ if (up)
+ uart_suspend_port(&serial_omap_reg, &up->port);
+ return 0;
+}
+
+static int serial_omap_resume(struct platform_device *dev)
+{
+ struct uart_omap_port *up = platform_get_drvdata(dev);
+ if (up)
+ uart_resume_port(&serial_omap_reg, &up->port);
+ return 0;
+}
+
+static void serial_omap_rx_timeout(unsigned long uart_no)
+{
+ struct uart_omap_port *up = ui[uart_no - 1];
+ unsigned int curr_dma_pos;
+
+ curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
+
+ if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
+ (curr_dma_pos == 0)) {
+ if (jiffies_to_msecs(jiffies - up->port_activity) <
+ 10000) {
+ mod_timer(&up->uart_dma.rx_timer, jiffies +
+ usecs_to_jiffies(up->uart_dma.rx_timeout));
+ } else {
+ serial_omap_stop_rxdma(up);
+ up->ier |= UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+ }
+ return;
+ } else {
+ unsigned int curr_transmitted_size = curr_dma_pos -
+ up->uart_dma.prev_rx_dma_pos;
+ up->port.icount.rx += curr_transmitted_size;
+ tty_insert_flip_string(up->port.info->port.tty,
+ up->uart_dma.rx_buf +
+ (up->uart_dma.prev_rx_dma_pos -
+ up->uart_dma.rx_buf_dma_phys),
+ curr_transmitted_size);
+ tty_flip_buffer_push(up->port.info->port.tty);
+ up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
+ if (up->uart_dma.rx_buf_size +
+ up->uart_dma.rx_buf_dma_phys == curr_dma_pos)
+ serial_omap_start_rxdma(up);
+ else
+ mod_timer(&up->uart_dma.rx_timer, jiffies +
+ usecs_to_jiffies(up->uart_dma.rx_timeout));
+ up->port_activity = jiffies;
+ }
+}
+
+static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+ return;
+}
+
+static void serial_omap_start_rxdma(struct uart_omap_port *up)
+{
+ if (up->uart_dma.rx_dma_channel == 0xFF) {
+ omap_request_dma(up->uart_dma.uart_dma_rx, "UART Rx DMA",
+ (void *)uart_rx_dma_callback, up,
+ &(up->uart_dma.rx_dma_channel));
+
+ omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ up->uart_dma.uart_base, 0, 0);
+ omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ up->uart_dma.rx_buf_dma_phys, 0, 0);
+ omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
+ OMAP_DMA_DATA_TYPE_S8,
+ up->uart_dma.rx_buf_size, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ up->uart_dma.uart_dma_rx, 0);
+ }
+ up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
+ omap_writel(0, OMAP44XX_DMA4_BASE
+ + OMAP_DMA4_CDAC(up->uart_dma.rx_dma_channel));
+ omap_start_dma(up->uart_dma.rx_dma_channel);
+ mod_timer(&up->uart_dma.rx_timer, jiffies +
+ usecs_to_jiffies(up->uart_dma.rx_timeout));
+ up->uart_dma.rx_dma_state = 1;
+}
+
+static void serial_omap_continue_tx(struct uart_omap_port *up)
+{
+ struct circ_buf *xmit = &up->port.info->xmit;
+ int start = up->uart_dma.tx_buf_dma_phys
+ + (xmit->tail & (UART_XMIT_SIZE - 1));
+ if (uart_circ_empty(xmit))
+ return;
+
+ up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+ /* It is a circular buffer. See if the buffer has wounded back.
+ * If yes it will have to be transferred in two separate dma
+ * transfers
+ */
+ if (start + up->uart_dma.tx_buf_size >=
+ up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+ up->uart_dma.tx_buf_size =
+ (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
+ omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ up->uart_dma.uart_base, 0, 0);
+ omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+ OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+
+ omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+ OMAP_DMA_DATA_TYPE_S8,
+ up->uart_dma.tx_buf_size, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ up->uart_dma.uart_dma_tx, 0);
+
+ omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)data;
+ struct circ_buf *xmit = &up->port.info->xmit;
+ xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
+ (UART_XMIT_SIZE - 1);
+ up->port.icount.tx += up->uart_dma.tx_buf_size;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ if (uart_circ_empty(xmit)) {
+ spin_lock(&(up->uart_dma.tx_lock));
+ serial_omap_stop_tx(&up->port);
+ up->uart_dma.tx_dma_state = 0;
+ spin_unlock(&(up->uart_dma.tx_lock));
+ } else {
+ omap_stop_dma(up->uart_dma.tx_dma_channel);
+ serial_omap_continue_tx(up);
+ }
+ up->port_activity = jiffies;
+ return;
+}
+
+static int serial_omap_probe(struct platform_device *pdev)
+{
+ struct uart_omap_port *up;
+ struct resource *mem, *irq, *dma_tx, *dma_rx;
+ struct uart_dma_info *up_dma = pdev->dev.platform_data;
+ int ret = -ENOSPC;
+ char str[7];
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ return -ENODEV;
+ }
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ return -ENODEV;
+ }
+
+ ret = (int) request_mem_region(mem->start, (mem->end - mem->start) + 1,
+ pdev->dev.driver->name);
+ if (!ret) {
+ dev_err(&pdev->dev, "memory region already claimed\n");
+ return -EBUSY;
+ }
+
+ dma_tx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dma_tx) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dma_rx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!dma_rx) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ up = kzalloc(sizeof(*up), GFP_KERNEL);
+ if (up == NULL) {
+ ret = -ENOMEM;
+ goto do_release_region;
+ }
+ sprintf(up->name, "OMAP UART%d", pdev->id);
+ up->pdev = pdev;
+ up->port.dev = &pdev->dev;
+ up->port.type = PORT_OMAP;
+ up->port.iotype = UPIO_MEM;
+ up->port.mapbase = mem->start;
+ up->port.irq = irq->start;
+
+ if (cpu_is_omap44xx())
+ up->port.irq += 32;
+
+ up->uart_dma.uart_dma_tx = dma_tx->start;
+ up->uart_dma.uart_dma_rx = dma_rx->start;
+ up->uart_dma.uart_base = mem->start;
+
+ up->port.fifosize = 64;
+ up->port.ops = &serial_omap_pops;
+ up->port.line = pdev->id - 1;
+
+ up->port.membase = (void *) OMAP2_L4_IO_ADDRESS(mem->start);
+ up->port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ up->port.uartclk = UART_CLK;
+ up->port.regshift = 2;
+
+ if (up_dma->dma_enabled) {
+ up->use_dma = 1;
+ up->uart_dma.rx_buf_size = up_dma->rx_dma_bufsize;
+ up->uart_dma.rx_timeout = up_dma->rx_timeout;
+ }
+
+ if (up->use_dma) {
+ spin_lock_init(&(up->uart_dma.tx_lock));
+ spin_lock_init(&(up->uart_dma.rx_lock));
+ up->uart_dma.tx_dma_channel = 0xFF;
+ up->uart_dma.rx_dma_channel = 0xFF;
+ }
+ if (console_detect(str)) {
+ pr_err("\n %s: Invalid console paramter...\n", __func__);
+ pr_err("\n %s: UART Driver Init Failed!\n", __func__);
+ return -EPERM;
+ }
+ ui[pdev->id - 1] = up;
+ serial_omap_add_console_port(up);
+
+ ret = uart_add_one_port(&serial_omap_reg, &up->port);
+ if (ret != 0)
+ goto do_release_region;
+
+ platform_set_drvdata(pdev, up);
+ return 0;
+err:
+ dev_err(&pdev->dev, "[UART%d]: failure [%s]\n",
+ pdev->id, __func__);
+do_release_region:
+ release_mem_region(mem->start, (mem->end - mem->start) + 1);
+ return ret;
+}
+
+static int serial_omap_remove(struct platform_device *dev)
+{
+ struct uart_omap_port *up = platform_get_drvdata(dev);
+ platform_set_drvdata(dev, NULL);
+ if (up) {
+ uart_remove_one_port(&serial_omap_reg, &up->port);
+ kfree(up);
+ }
+ return 0;
+}
+
+static struct platform_driver serial_omap_driver = {
+ .probe = serial_omap_probe,
+ .remove = serial_omap_remove,
+
+ .suspend = serial_omap_suspend,
+ .resume = serial_omap_resume,
+ .driver = {
+ .name = "omap-uart",
+ },
+};
+
+int __init serial_omap_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&serial_omap_reg);
+ if (ret != 0)
+ return ret;
+ ret = platform_driver_register(&serial_omap_driver);
+ if (ret != 0)
+ uart_unregister_driver(&serial_omap_reg);
+ return ret;
+}
+
+void __exit serial_omap_exit(void)
+{
+ platform_driver_unregister(&serial_omap_driver);
+ uart_unregister_driver(&serial_omap_reg);
+}
+
+#ifdef CONFIG_PM
+static void omap_uart_save_context(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ struct uart_omap_port *up = ui[num];
+
+ u16 lcr = 0;
+ lcr = serial_in(up, UART_LCR);
+ serial_out(up, UART_LCR, 0xBF);
+ uart->dll = serial_in(up, UART_DLL);
+ uart->dlh = serial_in(up, UART_DLM);
+ serial_out(up, UART_LCR, lcr);
+ uart->ier = serial_in(up, UART_IER);
+ uart->sysc = serial_in(up, UART_OMAP_SYSC);
+ uart->scr = serial_in(up, UART_OMAP_SCR);
+ uart->wer = serial_in(up, UART_OMAP_WER);
+
+ uart->context_valid = 1;
+}
+
+static void omap_uart_restore_context(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ struct uart_omap_port *up = ui[num];
+ u16 efr = 0;
+
+ if (!uart->context_valid)
+ return;
+
+ uart->context_valid = 0;
+
+ serial_out(up, UART_OMAP_MDR1, 0x7);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ efr = serial_in(up, UART_EFR);
+ serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, 0x0);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ serial_out(up, UART_DLL, uart->dll);
+ serial_out(up, UART_DLM, uart->dlh);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, uart->ier);
+ serial_out(up, UART_FCR, up->fcr);
+ serial_out(up, UART_LCR, 0xBF); /* Config B mode */
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+ serial_out(up, UART_OMAP_SCR, uart->scr);
+ serial_out(up, UART_OMAP_WER, uart->wer);
+ serial_out(up, UART_OMAP_SYSC, uart->sysc | (0x2 << 3));
+ serial_out(up, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+}
+
+/* Remove this during /mach-omap2/serial.c cleanup for 8250 support */
+void omap_uart_enable_irqs(int enable) {}
+
+static inline void omap_uart_disable_clocks(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ if (!uart->clocked)
+ return;
+
+ omap_uart_save_context(num);
+ uart->clocked = 0;
+ clk_disable(uart->ick);
+ clk_disable(uart->fck);
+}
+
+void omap_uart_enable_wakeup(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ /* Set wake-enable bit */
+ if (uart->wk_en && uart->wk_mask) {
+ u32 v = __raw_readl(uart->wk_en);
+ v |= uart->wk_mask;
+ __raw_writel(v, uart->wk_en);
+ }
+
+ /* Ensure IOPAD wake-enables are set */
+ if (cpu_is_omap34xx() && uart->padconf) {
+ u16 v = omap_ctrl_readw(uart->padconf);
+ v |= OMAP3_PADCONF_WAKEUPENABLE0;
+ omap_ctrl_writew(v, uart->padconf);
+ }
+}
+
+static void omap_uart_smart_idle_enable(int num, int enable)
+{
+ struct uart_omap_port *up = ui[num];
+ u16 sysc;
+
+ sysc = serial_in(up, UART_OMAP_SYSC) & 0x7;
+
+ if (enable)
+ /* Errata 2.15: Force idle if in DMA mode */
+ sysc |= up->use_dma ? 0x0 : (0x2 << 3);
+ else
+ sysc |= 0x1 << 3;
+
+ serial_out(up, UART_OMAP_SYSC, sysc);
+}
+
+static void omap_uart_block_sleep(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+
+ omap_uart_enable_clocks(num);
+
+ omap_uart_smart_idle_enable(num, 0);
+ uart->can_sleep = 0;
+ if (uart->timeout)
+ mod_timer(&uart->timer, jiffies + uart->timeout);
+}
+
+static void omap_uart_allow_sleep(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ if (!uart->clocked)
+ return;
+
+ if (uart->padconf)
+ omap_uart_enable_wakeup(num);
+
+ omap_uart_smart_idle_enable(num, 1);
+ uart->can_sleep = 1;
+
+ if (uart->timeout)
+ del_timer_sync(&uart->timer);
+}
+
+void omap_uart_prepare_idle(int num)
+{
+ omap_uart_disable_clocks(num);
+}
+
+void omap_uart_resume_idle(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+
+ omap_uart_enable_clocks(num);
+
+ /* Check for IO pad wakeup */
+ if (cpu_is_omap34xx() && uart->padconf) {
+ u16 p = omap_ctrl_readw(uart->padconf);
+
+ if (p & OMAP3_PADCONF_WAKEUPEVENT0)
+ omap_uart_block_sleep(num);
+ }
+
+ /* Check for normal UART wakeup */
+ if (__raw_readl(uart->wk_st) & uart->wk_mask)
+ omap_uart_block_sleep(num);
+}
+
+void omap_uart_prepare_suspend(void)
+{
+ int j;
+ for (j = 0; j < OMAP_MAX_NR_PORTS; j++)
+ omap_uart_allow_sleep(j);
+}
+
+int omap_uart_can_sleep(void)
+{
+ int can_sleep = 1;
+ int j;
+
+ for (j = 0; j < OMAP_MAX_NR_PORTS; j++) {
+ struct omap_uart_state *uart = &omap_uart[j];
+
+ if (!uart->clocked)
+ continue;
+
+ if (!uart->can_sleep) {
+ can_sleep = 0;
+ continue;
+ }
+
+ omap_uart_allow_sleep(j);
+ }
+ return can_sleep;
+}
+
+static void omap_uart_init_wakeup_source(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+
+ if (cpu_is_omap34xx()) {
+ u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+ u32 wk_mask = 0;
+ u32 padconf = 0;
+
+ uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
+ uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
+ switch (uart->num) {
+ case 0:
+ wk_mask = OMAP3430_ST_UART1_MASK;
+ padconf = 0x182;
+ break;
+ case 1:
+ wk_mask = OMAP3430_ST_UART2_MASK;
+ padconf = 0x17a;
+ break;
+ case 2:
+ wk_mask = OMAP3430_ST_UART3_MASK;
+ padconf = 0x19e;
+ break;
+ }
+ uart->wk_mask = wk_mask;
+ uart->padconf = padconf;
+ } else if (cpu_is_omap24xx()) {
+ u32 wk_mask = 0;
+
+ if (cpu_is_omap2430()) {
+ uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+ uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
+ } else if (cpu_is_omap2420()) {
+ uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+ uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
+ }
+ switch (uart->num) {
+ case 0:
+ wk_mask = OMAP24XX_ST_UART1_MASK;
+ break;
+ case 1:
+ wk_mask = OMAP24XX_ST_UART2_MASK;
+ break;
+ case 2:
+ wk_mask = OMAP24XX_ST_UART3_MASK;
+ break;
+ }
+ uart->wk_mask = wk_mask;
+ } else {
+ uart->wk_en = 0;
+ uart->wk_st = 0;
+ uart->wk_mask = 0;
+ uart->padconf = 0;
+ }
+}
+
+static void omap_uart_idle_timer(unsigned long data)
+{
+
+ struct omap_uart_state *uart = (struct omap_uart_state *)data;
+ struct uart_omap_port *up = ui[uart->num];
+
+ if (up->use_dma && (up->uart_dma.tx_dma_channel != 0xFF
+ || up->uart_dma.rx_dma_channel != 0xFF)) {
+ omap_uart_block_sleep(uart->num);
+ return;
+ }
+
+ omap_uart_allow_sleep(uart->num);
+}
+
+void omap_uart_idle_init(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+
+ uart->can_sleep = 0;
+ uart->timeout = SLEEP_TIMEOUT;
+ setup_timer(&uart->timer, omap_uart_idle_timer,
+ (unsigned long) uart);
+
+ mod_timer(&uart->timer, jiffies + uart->timeout);
+
+ omap_uart_init_wakeup_source(num);
+}
+
+#else
+static inline void omap_uart_restore_context(int num) {}
+static inline void omap_uart_block_sleep(int num) {}
+static void omap_uart_smart_idle_enable(int num, int enable) {}
+void omap_uart_idle_init(int num) {}
+#endif /* CONFIG_PM */
+
+static inline void omap_uart_enable_clocks(int num)
+{
+ struct omap_uart_state *uart = &omap_uart[num];
+ if (uart->clocked)
+ return;
+
+ clk_enable(uart->ick);
+ clk_enable(uart->fck);
+ uart->clocked = 1;
+ omap_uart_restore_context(num);
+}
+
+void omap_serial_early_init()
+{
+ int i;
+ char name[16];
+
+ for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+ struct omap_uart_state *uart = &omap_uart[i];
+ sprintf(name, "uart%d_ick", i+1);
+ uart->ick = clk_get(NULL, name);
+
+ if (IS_ERR(uart->ick)) {
+ printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
+ uart->ick = NULL;
+ }
+
+ sprintf(name, "uart%d_fck", i+1);
+ uart->fck = clk_get(NULL, name);
+
+ if (IS_ERR(uart->fck)) {
+ printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
+ uart->fck = NULL;
+ }
+
+ uart->num = i;
+ omap_uart_enable_clocks(i);
+ }
+}
+
+#ifdef DEBUG
+#define UART_OMAP_SPR 0x07 /* Scratchpad register */
+static void serial_omap_display_reg(struct uart_port *port)
+{
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned int lcr, efr, mcr, dll, dlh, xon1, xon2, xoff1, xoff2;
+ unsigned int tcr, tlr, uasr;
+ pr_debug("Register dump for UART%d\n", up->pdev->id);
+ pr_debug("IER_REG = 0x%x\n", serial_in(up, UART_IER));
+ pr_debug("IIR_REG = 0x%x\n", serial_in(up, UART_IIR));
+ lcr = serial_in(up, UART_LCR);
+ pr_debug("LCR_REG = 0x%x\n", lcr);
+ mcr = serial_in(up, UART_MCR);
+ pr_debug("MCR_REG = 0x%x\n", mcr);
+ pr_debug("LSR_REG = 0x%x\n", serial_in(up, UART_LSR));
+ pr_debug("MSR_REG = 0x%x\n", serial_in(up, UART_MSR));
+ pr_debug("SPR_REG = 0x%x\n", serial_in(up, UART_OMAP_SPR));
+ pr_debug("MDR1_REG = 0x%x\n", serial_in(up, UART_OMAP_MDR1));
+ pr_debug("MDR2_REG = 0x%x\n", serial_in(up, UART_OMAP_MDR2));
+ pr_debug("SCR_REG = 0x%x\n", serial_in(up, UART_OMAP_SCR));
+ pr_debug("SSR_REG = 0x%x\n", serial_in(up, UART_OMAP_SSR));
+ pr_debug("MVR_REG = 0x%x\n", serial_in(up, UART_OMAP_MVER));
+ pr_debug("SYSC_REG = 0x%x\n", serial_in(up, UART_OMAP_SYSC));
+ pr_debug("SYSS_REG = 0x%x\n", serial_in(up, UART_OMAP_SYSS));
+ pr_debug("WER_REG = 0x%x\n", serial_in(up, UART_OMAP_WER));
+
+ serial_out(up, UART_LCR, 0xBF);
+ dll = serial_in(up, UART_DLL);
+ dlh = serial_in(up, UART_DLM);
+ efr = serial_in(up, UART_EFR);
+ xon1 = serial_in(up, UART_XON1);
+ xon2 = serial_in(up, UART_XON2);
+
+ serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, lcr);
+ serial_out(up, UART_MCR, mcr | UART_MCR_TCRTLR);
+ serial_out(up, UART_LCR, 0xBF);
+
+ tcr = serial_in(up, UART_TI752_TCR);
+ tlr = serial_in(up, UART_TI752_TLR);
+
+ serial_out(up, UART_LCR, lcr);
+ serial_out(up, UART_MCR, mcr);
+ serial_out(up, UART_LCR, 0xBF);
+
+ xoff1 = serial_in(up, UART_XOFF1);
+ xoff2 = serial_in(up, UART_XOFF2);
+ uasr = serial_in(up, UART_OMAP_UASR);
+
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, lcr);
+
+ pr_debug("DLL_REG = 0x%x\n", dll);
+ pr_debug("DLH_REG = 0x%x\n", dlh);
+ pr_debug("EFR_REG = 0x%x\n", efr);
+
+ pr_debug("XON1_ADDR_REG = 0x%x\n", xon1);
+ pr_debug("XON2_ADDR_REG = 0x%x\n", xon2);
+ pr_debug("TCR_REG = 0x%x\n", tcr);
+ pr_debug("TLR_REG = 0x%x\n", tlr);
+
+ pr_debug("XOFF1_REG = 0x%x\n", xoff1);
+ pr_debug("XOFF2_REG = 0x%x\n", xoff2);
+ pr_debug("UASR_REG = 0x%x\n", uasr);
+}
+#endif /* DEBUG */
+
+subsys_initcall(serial_omap_init);
+module_exit(serial_omap_exit);
+
+MODULE_DESCRIPTION("OMAP High Speed UART driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2c733c27db2f..c2564689acd2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -157,10 +157,10 @@ config SPI_OMAP_UWIRE
This hooks up to the MicroWire controller on OMAP1 chips.
config SPI_OMAP24XX
- tristate "McSPI driver for OMAP24xx/OMAP34xx"
- depends on ARCH_OMAP24XX || ARCH_OMAP34XX
+ tristate "McSPI driver for OMAP24xx/OMAP34xx/OMAP4"
+ depends on ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4
help
- SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
+ SPI master controller for OMAP24xx/OMAP34xx/OMAP4 Multichannel SPI
(McSPI) modules.
config SPI_ORION
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 9b80ad36dbba..3c6454a38624 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -37,26 +37,47 @@
#include <mach/dma.h>
#include <mach/clock.h>
+#include <mach/mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
+#define OMAP2_MCSPI_MAX_FIFODEPTH 64
#define OMAP2_MCSPI_REVISION 0x00
-#define OMAP2_MCSPI_SYSCONFIG 0x10
-#define OMAP2_MCSPI_SYSSTATUS 0x14
-#define OMAP2_MCSPI_IRQSTATUS 0x18
-#define OMAP2_MCSPI_IRQENABLE 0x1c
-#define OMAP2_MCSPI_WAKEUPENABLE 0x20
-#define OMAP2_MCSPI_SYST 0x24
-#define OMAP2_MCSPI_MODULCTRL 0x28
+#ifdef CONFIG_ARCH_OMAP4
+#define OMAP2_MCSPI_SYSCONFIG 0x110
+#define OMAP2_MCSPI_SYSSTATUS 0x114
+#define OMAP2_MCSPI_IRQSTATUS 0x118
+#define OMAP2_MCSPI_IRQENABLE 0x11c
+#define OMAP2_MCSPI_WAKEUPENABLE 0x120
+#define OMAP2_MCSPI_SYST 0x124
+#define OMAP2_MCSPI_MODULCTRL 0x128
+#define OMAP2_MCSPI_XFERLEVEL 0x17c
/* per-channel banks, 0x14 bytes each, first is: */
-#define OMAP2_MCSPI_CHCONF0 0x2c
-#define OMAP2_MCSPI_CHSTAT0 0x30
-#define OMAP2_MCSPI_CHCTRL0 0x34
-#define OMAP2_MCSPI_TX0 0x38
-#define OMAP2_MCSPI_RX0 0x3c
+#define OMAP2_MCSPI_CHCONF0 0x12c
+#define OMAP2_MCSPI_CHSTAT0 0x130
+#define OMAP2_MCSPI_CHCTRL0 0x134
+#define OMAP2_MCSPI_TX0 0x138
+#define OMAP2_MCSPI_RX0 0x13c
+#else
+#define OMAP2_MCSPI_REVISION 0x00
+#define OMAP2_MCSPI_SYSCONFIG 0x10
+#define OMAP2_MCSPI_SYSSTATUS 0x14
+#define OMAP2_MCSPI_IRQSTATUS 0x18
+#define OMAP2_MCSPI_IRQENABLE 0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE 0x20
+#define OMAP2_MCSPI_SYST 0x24
+#define OMAP2_MCSPI_MODULCTRL 0x28
+#define OMAP2_MCSPI_XFERLEVEL 0x7c
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0 0x2c
+#define OMAP2_MCSPI_CHSTAT0 0x30
+#define OMAP2_MCSPI_CHCTRL0 0x34
+#define OMAP2_MCSPI_TX0 0x38
+#define OMAP2_MCSPI_RX0 0x3c
+#endif
/* per-register bitmasks: */
#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
@@ -85,10 +106,13 @@
#define OMAP2_MCSPI_CHCONF_IS (1 << 18)
#define OMAP2_MCSPI_CHCONF_TURBO (1 << 19)
#define OMAP2_MCSPI_CHCONF_FORCE (1 << 20)
+#define OMAP2_MCSPI_CHCONF_FFET (1 << 27)
+#define OMAP2_MCSPI_CHCONF_FFER (1 << 28)
#define OMAP2_MCSPI_CHSTAT_RXS (1 << 0)
#define OMAP2_MCSPI_CHSTAT_TXS (1 << 1)
#define OMAP2_MCSPI_CHSTAT_EOT (1 << 2)
+#define OMAP2_MCSPI_IRQ_EOW (1 << 17)
#define OMAP2_MCSPI_CHCTRL_EN (1 << 0)
@@ -125,6 +149,10 @@ struct omap2_mcspi {
unsigned long phys;
/* SPI1 has 4 channels, while SPI2 has 2 */
struct omap2_mcspi_dma *dma_channels;
+ unsigned short mcspi_mode;
+ unsigned short dma_mode;
+ unsigned short force_cs_mode;
+ unsigned short fifo_depth;
};
struct omap2_mcspi_cs {
@@ -133,6 +161,37 @@ struct omap2_mcspi_cs {
int word_len;
};
+#ifdef CONFIG_SPI_DEBUG
+struct reg_type {
+ char name[40];
+ int offset;
+};
+
+static struct reg_type reg_map[] = {
+ {"MCSPI_REV", 0x0},
+ {"MCSPI_SYSCONFIG", 0x10},
+ {"MCSPI_SYSSTATUS", 0x14},
+ {"MCSPI_IRQSTATUS", 0x18},
+ {"MCSPI_IRQENABLE", 0x1C},
+ {"MCSPI_WAKEUPENABLE", 0x20},
+ {"MCSPI_SYST", 0x24},
+ {"MCSPI_MODULCTRL", 0x28},
+ {"MCSPI_XFERLEVEL", 0x7c},
+ {"CH0", 0x2C},
+ {"CH1", 0x40},
+ {"CH2", 0x54},
+ {"CH3", 0x68}
+};
+
+static struct reg_type ch_reg_type[] = {
+ {"CONF", 0x00},
+ {"STAT", 0x04},
+ {"CTRL", 0x08},
+ {"TX", 0x0C},
+ {"RX", 0x10},
+};
+#endif
+
static struct workqueue_struct *omap2_mcspi_wq;
#define MOD_REG_BIT(val, mask, set) do { \
@@ -188,6 +247,39 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
}
+#ifdef CONFIG_SPI_DEBUG
+static int
+omap2_mcspi_dump_regs(struct spi_master *master)
+{
+ u32 spi_base;
+ u32 reg;
+ u32 channel;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ spi_base = (u32)mcspi->base;
+
+ for (reg = 0; (reg < ARRAY_SIZE(reg_map)); reg++) {
+ struct reg_type *reg_d = &reg_map[reg];
+ u32 base1 = spi_base + reg_d->offset;
+ if (reg_d->name[0] == 'C') {
+ for (channel = 0; (channel < (ARRAY_SIZE(ch_reg_type)));
+ channel++) {
+ struct reg_type *reg_c = &ch_reg_type[channel];
+ u32 base2 = base1 + reg_c->offset;
+ pr_debug("MCSPI_%s%s [0x%08X] = 0x%08X\n",
+ reg_d->name, reg_c->name, base2,
+ __raw_readl(base2));
+ }
+ } else {
+ pr_debug("%s : [0x%08X] = 0x%08X\n",
+ reg_d->name, base1, __raw_readl(base1));
+ }
+
+ }
+ return 0;
+}
+#endif
+
static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
{
u32 l;
@@ -205,34 +297,160 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
}
+static int omap2_mcspi_set_txfifo(const struct spi_device *spi, int buf_size,
+ int enable)
+{
+ u32 l, rw, s;
+ unsigned short revert = 0;
+ struct spi_master *master = spi->master;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ s = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
+
+ if (enable == 1) {
+
+ /* FIFO cannot be enabled for both TX and RX
+ * simultaneously
+ */
+ if (l & OMAP2_MCSPI_CHCONF_FFER)
+ return -EPERM;
+
+ /* Channel needs to be disabled and enabled
+ * for FIFO setting to take affect
+ */
+ if (s & OMAP2_MCSPI_CHCTRL_EN) {
+ omap2_mcspi_set_enable(spi, 0);
+ revert = 1;
+ }
+
+ if (buf_size < mcspi->fifo_depth)
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (buf_size - 1) << 0));
+ else
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (mcspi->fifo_depth - 1) << 0));
+ }
+
+ rw = OMAP2_MCSPI_CHCONF_FFET;
+ MOD_REG_BIT(l, rw, enable);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+ if (revert)
+ omap2_mcspi_set_enable(spi, 1);
+
+ return 0;
+
+}
+
+static int omap2_mcspi_set_rxfifo(const struct spi_device *spi, int buf_size,
+ int enable)
+{
+ u32 l, rw, s;
+ unsigned short revert = 0;
+ struct spi_master *master = spi->master;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ s = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
+
+ if (enable == 1) {
+
+ /* FIFO cannot be enabled for both TX and RX
+ * simultaneously
+ */
+ if (l & OMAP2_MCSPI_CHCONF_FFET)
+ return -EPERM;
+
+ /* Channel needs to be disabled and enabled
+ * for FIFO setting to take affect
+ */
+ if (s & OMAP2_MCSPI_CHCTRL_EN) {
+ omap2_mcspi_set_enable(spi, 0);
+ revert = 1;
+ }
+
+ if (buf_size < mcspi->fifo_depth)
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (buf_size - 1) << 8));
+ else
+ mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL,
+ ((buf_size << 16) |
+ (mcspi->fifo_depth - 1) << 8));
+ }
+
+ rw = OMAP2_MCSPI_CHCONF_FFER;
+ MOD_REG_BIT(l, rw, enable);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+ if (revert)
+ omap2_mcspi_set_enable(spi, 1);
+
+ return 0;
+
+}
+
static void omap2_mcspi_set_master_mode(struct spi_master *master)
{
u32 l;
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
/* setup when switching from (reset default) slave mode
- * to single-channel master mode
+ * to single-channel master mode based on config value
*/
l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
- MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+
+ if (mcspi->force_cs_mode)
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
}
+static void omap2_mcspi_set_slave_mode(struct spi_master *master)
+{
+ u32 l;
+
+ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 1);
+ mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+}
+
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (!(__raw_readl(reg) & bit)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ cpu_relax();
+ }
+ return 0;
+}
+
static unsigned
omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
{
struct omap2_mcspi *mcspi;
struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi_dma *mcspi_dma;
- unsigned int count, c;
+ unsigned int count, c, bytes_per_transfer;
unsigned long base, tx_reg, rx_reg;
- int word_len, data_type, element_count;
- u8 * rx;
- const u8 * tx;
+ int word_len, data_type, element_count, frame_count,
+ sync_type;
+ u8 *rx;
+ const u8 *tx;
+ void __iomem *irqstat_reg;
mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+ irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
count = xfer->len;
c = count;
@@ -247,19 +465,34 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
if (word_len <= 8) {
data_type = OMAP_DMA_DATA_TYPE_S8;
element_count = count;
+ bytes_per_transfer = 1;
} else if (word_len <= 16) {
data_type = OMAP_DMA_DATA_TYPE_S16;
element_count = count >> 1;
+ bytes_per_transfer = 2;
} else /* word_len <= 32 */ {
data_type = OMAP_DMA_DATA_TYPE_S32;
element_count = count >> 2;
+ bytes_per_transfer = 4;
+ }
+
+ if ((mcspi->fifo_depth != 0) && (count > mcspi->fifo_depth)) {
+ sync_type = OMAP_DMA_SYNC_FRAME;
+ element_count = mcspi->fifo_depth/bytes_per_transfer;
+ frame_count = count/mcspi->fifo_depth;
+ } else if ((mcspi->fifo_depth != 0) && (count <= mcspi->fifo_depth)) {
+ sync_type = OMAP_DMA_SYNC_FRAME;
+ frame_count = 1;
+ } else {
+ sync_type = OMAP_DMA_SYNC_ELEMENT;
+ frame_count = 1;
}
if (tx != NULL) {
+
omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
- data_type, element_count, 1,
- OMAP_DMA_SYNC_ELEMENT,
- mcspi_dma->dma_tx_sync_dev, 0);
+ data_type, element_count, frame_count,
+ sync_type, mcspi_dma->dma_tx_sync_dev, 0);
omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
OMAP_DMA_AMODE_CONSTANT,
@@ -268,13 +501,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
OMAP_DMA_AMODE_POST_INC,
xfer->tx_dma, 0, 0);
+
+ if (mcspi->fifo_depth != 0)
+ omap2_mcspi_set_txfifo(spi, count, 1);
+
}
if (rx != NULL) {
omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
- data_type, element_count - 1, 1,
- OMAP_DMA_SYNC_ELEMENT,
- mcspi_dma->dma_rx_sync_dev, 1);
+ data_type, element_count, frame_count,
+ sync_type, mcspi_dma->dma_rx_sync_dev, 1);
omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
OMAP_DMA_AMODE_CONSTANT,
@@ -283,6 +519,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
OMAP_DMA_AMODE_POST_INC,
xfer->rx_dma, 0, 0);
+
+ if (mcspi->fifo_depth != 0) {
+ omap2_mcspi_set_rxfifo(spi, count, 1);
+
+ /* Dummy write required for RX only mode */
+ if (tx == NULL)
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_TX0, 0);
+ }
}
if (tx != NULL) {
@@ -297,12 +541,31 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
if (tx != NULL) {
wait_for_completion(&mcspi_dma->dma_tx_completion);
+
+ if (mcspi->fifo_depth != 0) {
+ if (mcspi_wait_for_reg_bit(irqstat_reg,
+ OMAP2_MCSPI_IRQ_EOW) < 0)
+ dev_err(&spi->dev, "TXS timed out\n");
+
+ mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
+ OMAP2_MCSPI_IRQ_EOW);
+
+ omap2_mcspi_set_txfifo(spi, count, 0);
+ }
dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
}
if (rx != NULL) {
wait_for_completion(&mcspi_dma->dma_rx_completion);
+
+ if (mcspi->fifo_depth != 0) {
+ omap2_mcspi_set_rxfifo(spi, count, 0);
+
+ mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
+ OMAP2_MCSPI_IRQ_EOW);
+ }
dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+
omap2_mcspi_set_enable(spi, 0);
if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
& OMAP2_MCSPI_CHSTAT_RXS)) {
@@ -326,19 +589,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
return count;
}
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(1000);
- while (!(__raw_readl(reg) & bit)) {
- if (time_after(jiffies, timeout))
- return -1;
- cpu_relax();
- }
- return 0;
-}
-
static unsigned
omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
{
@@ -527,8 +777,14 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
/* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
* REVISIT: this controller could support SPI_3WIRE mode.
*/
- l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
- l |= OMAP2_MCSPI_CHCONF_DPE0;
+ if (mcspi->mcspi_mode == OMAP2_MCSPI_MASTER) {
+ l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
+ l |= OMAP2_MCSPI_CHCONF_DPE0;
+ } else {
+ l |= OMAP2_MCSPI_CHCONF_IS;
+ l |= OMAP2_MCSPI_CHCONF_DPE1;
+ l &= ~OMAP2_MCSPI_CHCONF_DPE0;
+ }
/* wordlength */
l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
@@ -540,9 +796,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
else
l &= ~OMAP2_MCSPI_CHCONF_EPOL;
- /* set clock divisor */
- l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
- l |= div << 2;
+ if (mcspi->mcspi_mode == OMAP2_MCSPI_MASTER) {
+ /* set clock divisor */
+ l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+ l |= div << 2;
+ }
/* set SPI mode 0..3 */
if (spi->mode & SPI_CPOL)
@@ -736,7 +994,10 @@ static void omap2_mcspi_work(struct work_struct *work)
par_override = 0;
}
- if (!cs_active) {
+ if ((!cs_active) && (mcspi->force_cs_mode) &&
+ (mcspi->mcspi_mode ==
+ OMAP2_MCSPI_MASTER)) {
+
omap2_mcspi_force_cs(spi, 1);
cs_active = 1;
}
@@ -757,10 +1018,14 @@ static void omap2_mcspi_work(struct work_struct *work)
__raw_writel(0, cs->base
+ OMAP2_MCSPI_TX0);
- if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
+ if (m->is_dma_mapped ||
+ t->len >= DMA_MIN_BYTES ||
+ mcspi->dma_mode)
+
count = omap2_mcspi_txrx_dma(spi, t);
else
count = omap2_mcspi_txrx_pio(spi, t);
+
m->actual_length += count;
if (count != t->len) {
@@ -773,7 +1038,10 @@ static void omap2_mcspi_work(struct work_struct *work)
udelay(t->delay_usecs);
/* ignore the "leave it on after last xfer" hint */
- if (t->cs_change) {
+ if ((t->cs_change) && (mcspi->force_cs_mode) &&
+ (mcspi->mcspi_mode ==
+ OMAP2_MCSPI_MASTER)) {
+
omap2_mcspi_force_cs(spi, 0);
cs_active = 0;
}
@@ -785,8 +1053,9 @@ static void omap2_mcspi_work(struct work_struct *work)
status = omap2_mcspi_setup_transfer(spi, NULL);
}
- if (cs_active)
- omap2_mcspi_force_cs(spi, 0);
+ if ((cs_active) && (mcspi->force_cs_mode) &&
+ (mcspi->mcspi_mode == OMAP2_MCSPI_MASTER))
+ omap2_mcspi_force_cs(spi, 0);
omap2_mcspi_set_enable(spi, 0);
@@ -811,6 +1080,8 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
m->actual_length = 0;
m->status = 0;
+ mcspi = spi_master_get_devdata(spi->master);
+
/* reject invalid messages and transfers */
if (list_empty(&m->transfers) || !m->complete)
return -EINVAL;
@@ -839,7 +1110,14 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
return -EINVAL;
}
- if (m->is_dma_mapped || len < DMA_MIN_BYTES)
+ if (mcspi->fifo_depth != 0) {
+ if ((len % mcspi->fifo_depth) != 0)
+ return -EINVAL;
+ }
+
+ /* Ignore DMA_MIN_BYTES check if dma only mode is set */
+ if (m->is_dma_mapped || ((len < DMA_MIN_BYTES) &&
+ (!mcspi->dma_mode)))
continue;
/* Do DMA mapping "early" for better error reporting and
@@ -870,8 +1148,6 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
}
}
- mcspi = spi_master_get_devdata(spi->master);
-
spin_lock_irqsave(&mcspi->lock, flags);
list_add_tail(&m->queue, &mcspi->msg_queue);
queue_work(omap2_mcspi_wq, &mcspi->work);
@@ -902,7 +1178,10 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
OMAP2_MCSPI_WAKEUPENABLE_WKEN);
- omap2_mcspi_set_master_mode(master);
+ if (mcspi->mcspi_mode == OMAP2_MCSPI_MASTER)
+ omap2_mcspi_set_master_mode(master);
+ else
+ omap2_mcspi_set_slave_mode(master);
clk_disable(mcspi->fck);
clk_disable(mcspi->ick);
@@ -933,7 +1212,8 @@ static u8 __initdata spi2_txdma_id[] = {
OMAP24XX_DMA_SPI2_TX1,
};
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) ||\
+defined(CONFIG_ARCH_OMAP4)
static u8 __initdata spi3_rxdma_id[] = {
OMAP24XX_DMA_SPI3_RX0,
OMAP24XX_DMA_SPI3_RX1,
@@ -945,7 +1225,7 @@ static u8 __initdata spi3_txdma_id[] = {
};
#endif
-#ifdef CONFIG_ARCH_OMAP3
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
static u8 __initdata spi4_rxdma_id[] = {
OMAP34XX_DMA_SPI4_RX0,
};
@@ -958,6 +1238,8 @@ static u8 __initdata spi4_txdma_id[] = {
static int __init omap2_mcspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
+ struct omap2_mcspi_platform_config *pdata =
+ (struct omap2_mcspi_platform_config *)pdev->dev.platform_data;
struct omap2_mcspi *mcspi;
struct resource *r;
int status = 0, i;
@@ -975,14 +1257,15 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
txdma_id = spi2_txdma_id;
num_chipselect = 2;
break;
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) ||\
+defined(CONFIG_ARCH_OMAP4)
case 3:
rxdma_id = spi3_rxdma_id;
txdma_id = spi3_txdma_id;
num_chipselect = 2;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP3
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
case 4:
rxdma_id = spi4_rxdma_id;
txdma_id = spi4_txdma_id;
@@ -1014,6 +1297,16 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
mcspi = spi_master_get_devdata(master);
mcspi->master = master;
+ mcspi->mcspi_mode = pdata->mode;
+ mcspi->dma_mode = pdata->dma_mode;
+ mcspi->force_cs_mode = pdata->force_cs_mode;
+
+ if (pdata->fifo_depth <= OMAP2_MCSPI_MAX_FIFODEPTH)
+ mcspi->fifo_depth = pdata->fifo_depth;
+ else {
+ mcspi->fifo_depth = 0;
+ dev_dbg(&pdev->dev, "Invalid fifo depth specified\n");
+ }
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
@@ -1038,20 +1331,24 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
spin_lock_init(&mcspi->lock);
INIT_LIST_HEAD(&mcspi->msg_queue);
-
- mcspi->ick = clk_get(&pdev->dev, "ick");
- if (IS_ERR(mcspi->ick)) {
- dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
- status = PTR_ERR(mcspi->ick);
- goto err1a;
- }
- mcspi->fck = clk_get(&pdev->dev, "fck");
- if (IS_ERR(mcspi->fck)) {
- dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
- status = PTR_ERR(mcspi->fck);
- goto err2;
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx()) {
+ mcspi->ick = clk_get(&pdev->dev, "ick");
+ if (IS_ERR(mcspi->ick)) {
+ dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
+ status = PTR_ERR(mcspi->ick);
+ goto err1a;
+ }
+ mcspi->fck = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(mcspi->fck)) {
+ dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
+ status = PTR_ERR(mcspi->fck);
+ goto err2;
+ }
}
-
mcspi->dma_channels = kcalloc(master->num_chipselect,
sizeof(struct omap2_mcspi_dma),
GFP_KERNEL);
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 9e3e7a5c258b..60fbf469eb39 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -33,7 +33,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
@@ -258,7 +258,7 @@ struct twl4030_usb {
spinlock_t lock;
/* pin configuration */
- enum twl4030_usb_mode usb_mode;
+ enum twl_usb_mode usb_mode;
int irq;
u8 linkstat;
@@ -276,16 +276,16 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
{
u8 check;
- if ((twl4030_i2c_write_u8(module, data, address) >= 0) &&
- (twl4030_i2c_read_u8(module, &check, address) >= 0) &&
+ if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+ (twl_i2c_read_u8(module, &check, address) >= 0) &&
(check == data))
return 0;
dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
1, module, address, check, data);
/* Failed once: Try again */
- if ((twl4030_i2c_write_u8(module, data, address) >= 0) &&
- (twl4030_i2c_read_u8(module, &check, address) >= 0) &&
+ if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+ (twl_i2c_read_u8(module, &check, address) >= 0) &&
(check == data))
return 0;
dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
@@ -303,7 +303,7 @@ static inline int twl4030_usb_write(struct twl4030_usb *twl,
{
int ret = 0;
- ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address);
+ ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
if (ret < 0)
dev_dbg(twl->dev,
"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
@@ -315,7 +315,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
u8 data;
int ret = 0;
- ret = twl4030_i2c_read_u8(module, &data, address);
+ ret = twl_i2c_read_u8(module, &data, address);
if (ret >= 0)
ret = data;
else
@@ -462,7 +462,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
* SLEEP. We work around this by clearing the bit after usv3v1
* is re-activated. This ensures that VUSB3V1 is really active.
*/
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
VUSB_DEDICATED2);
regulator_enable(twl->usb1v5);
pwr &= ~PHY_PWR_PHYPWD;
@@ -505,44 +505,44 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
static int 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);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
+ twl_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);
+ twl_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);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
/* Initialize 3.1V regulator */
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
if (IS_ERR(twl->usb3v1))
return -ENODEV;
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
/* Initialize 1.5V regulator */
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
if (IS_ERR(twl->usb1v5))
goto fail1;
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
/* Initialize 1.8V regulator */
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
if (IS_ERR(twl->usb1v8))
goto fail2;
- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+ twl_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);
+ twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
return 0;
@@ -655,7 +655,7 @@ static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host)
static int __devinit twl4030_usb_probe(struct platform_device *pdev)
{
- struct twl4030_usb_data *pdata = pdev->dev.platform_data;
+ struct twl_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
int status, err;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3b54b3940178..e09367a60446 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2149,6 +2149,7 @@ config FB_BROADSHEET
a bridge adapter.
source "drivers/video/omap/Kconfig"
+source "drivers/video/omap2/Kconfig"
source "drivers/video/backlight/Kconfig"
source "drivers/video/display/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 01a819f47371..01bf7a50ec12 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
+obj-$(CONFIG_OMAP2_DSS) += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 44408850e2eb..0c8f3a52865e 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,6 +1,7 @@
config FB_OMAP
tristate "OMAP frame buffer support (EXPERIMENTAL)"
- depends on FB && ARCH_OMAP
+ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
+
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -9,7 +10,7 @@ config FB_OMAP
config FB_OMAP_BOOTLOADER_INIT
bool "Check bootloader initialization"
- depends on FB_OMAP
+ depends on FB_OMAP || FB_OMAP2
help
Say Y here if you want to enable checking if the bootloader has
already initialized the display controller. In this case the
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 9dfcf39d3367..782b48843a7d 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -25,9 +25,9 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/omapfb.h>
#include <mach/dma.h>
-#include <mach/omapfb.h>
#include <mach/blizzard.h>
#include "dispc.h"
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 148cbcc39602..8bd6b03898e2 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -24,9 +24,9 @@
#include <linux/vmalloc.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/sram.h>
-#include <mach/omapfb.h>
#include <mach/board.h>
#include "dispc.h"
@@ -35,6 +35,17 @@
#define DSS_BASE 0x48050000
#define DSS_SYSCONFIG 0x0010
+#ifndef CONFIG_ARCH_OMAP4
+ /* DSS */
+ #define DSS_BASE 0x48050000
+ /* DISPLAY CONTROLLER */
+ #define DISPC_BASE 0x48050400
+#else
+ /* DSS */
+ #define DSS_BASE 0x48042000
+ /* DISPLAY CONTROLLER */
+ #define DISPC_BASE 0x48043000
+#endif
#define DISPC_BASE 0x48050400
@@ -856,6 +867,7 @@ void omap_dispc_free_irq(void)
}
EXPORT_SYMBOL(omap_dispc_free_irq);
+#ifndef CONFIG_ARCH_OMAP4
static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
{
u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
@@ -877,30 +889,32 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
return IRQ_HANDLED;
}
+#endif
static int get_dss_clocks(void)
{
- dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
- if (IS_ERR(dispc.dss_ick)) {
- dev_err(dispc.fbdev->dev, "can't get ick\n");
- return PTR_ERR(dispc.dss_ick);
- }
+ if (!cpu_is_omap44xx()) {
+ dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
+ if (IS_ERR(dispc.dss_ick)) {
+ dev_err(dispc.fbdev->dev, "can't get ick\n");
+ return PTR_ERR(dispc.dss_ick);
+ }
- dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
- if (IS_ERR(dispc.dss1_fck)) {
- dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
- clk_put(dispc.dss_ick);
- return PTR_ERR(dispc.dss1_fck);
- }
+ dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
+ if (IS_ERR(dispc.dss1_fck)) {
+ dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
+ clk_put(dispc.dss_ick);
+ return PTR_ERR(dispc.dss1_fck);
+ }
- dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
- if (IS_ERR(dispc.dss_54m_fck)) {
- dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
- clk_put(dispc.dss_ick);
- clk_put(dispc.dss1_fck);
- return PTR_ERR(dispc.dss_54m_fck);
+ dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
+ if (IS_ERR(dispc.dss_54m_fck)) {
+ dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
+ clk_put(dispc.dss_ick);
+ clk_put(dispc.dss1_fck);
+ return PTR_ERR(dispc.dss_54m_fck);
+ }
}
-
return 0;
}
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 5d4f34887a22..d865b55b8269 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -25,9 +25,9 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/omapfb.h>
#include <mach/dma.h>
-#include <mach/omapfb.h>
#include <mach/hwa742.h>
#define HWA742_REV_CODE_REG 0x0
diff --git a/drivers/video/omap/lcd_4430sdp.c b/drivers/video/omap/lcd_4430sdp.c
new file mode 100644
index 000000000000..1065d2acfbef
--- /dev/null
+++ b/drivers/video/omap/lcd_4430sdp.c
@@ -0,0 +1,128 @@
+/*
+ * LCD panel support for the TI 4430SDP 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/omapfb.h>
+
+#include <mach/mux.h>
+#include <asm/mach-types.h>
+
+#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */
+
+static int sdp4430_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void sdp4430_panel_cleanup(struct lcd_panel *panel)
+{
+ return;
+}
+
+static int sdp4430_panel_enable(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+static void sdp4430_panel_disable(struct lcd_panel *panel)
+{
+ return;
+}
+
+static unsigned long sdp4430_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel sdp4430_panel = {
+ .name = "sdp4430",
+ .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 = sdp4430_panel_init,
+ .cleanup = sdp4430_panel_cleanup,
+ .enable = sdp4430_panel_enable,
+ .disable = sdp4430_panel_disable,
+ .get_caps = sdp4430_panel_get_caps,
+};
+
+static int sdp4430_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&sdp4430_panel);
+ return 0;
+}
+
+static int sdp4430_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+static int sdp4430_panel_suspend(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ return 0;
+}
+
+static int sdp4430_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver sdp4430_panel_driver = {
+ .probe = sdp4430_panel_probe,
+ .remove = sdp4430_panel_remove,
+ .suspend = sdp4430_panel_suspend,
+ .resume = sdp4430_panel_resume,
+
+ .driver = {
+ .name = "sdp4430_lcd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sdp4430_panel_drv_init(void)
+{
+ return platform_driver_register(&sdp4430_panel_driver);
+}
+
+static void __exit sdp4430_panel_drv_exit(void)
+{
+ platform_driver_unregister(&sdp4430_panel_driver);
+ return;
+}
+
+module_init(sdp4430_panel_drv_init);
+module_exit(sdp4430_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 2486237ebba5..f7264ea35d35 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -22,9 +22,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c/tps65010.h>
+#include <linux/omapfb.h>
#include <mach/gpio.h>
-#include <mach/omapfb.h>
#define MODULE_NAME "omapfb-lcd_h3"
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
index 6ff56430341b..d72df0c16d79 100644
--- a/drivers/video/omap/lcd_h4.c
+++ b/drivers/video/omap/lcd_h4.c
@@ -21,8 +21,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-
-#include <mach/omapfb.h>
+#include <linux/omapfb.h>
static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index 6953ed4b5820..f6e05d7f080b 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -22,9 +22,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/fpga.h>
-#include <mach/omapfb.h>
static int innovator1510_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 4c4f7ee6d733..c599e41f9a42 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -21,9 +21,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/omapfb.h>
#include <mach/gpio.h>
-#include <mach/omapfb.h>
#define MODULE_NAME "omapfb-lcd_h3"
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index 379c96d36da5..d6b193ec6a82 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -22,10 +22,10 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/omapfb.h>
#include <mach/gpio.h>
#include <mach/mux.h>
-#include <mach/omapfb.h>
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 218317366e6e..dcb456c39959 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -22,9 +22,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/fpga.h>
-#include <mach/omapfb.h>
static int palmte_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index 57b0f6cf6a5a..e8adab8a76fa 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -28,9 +28,9 @@ GPIO13 - screen blanking
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/gpio.h>
-#include <mach/omapfb.h>
static int palmtt_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index d33d78b11723..d5b3f82b26a2 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -23,8 +23,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-
-#include <mach/omapfb.h>
+#include <linux/omapfb.h>
static int palmz71_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index ab3949256677..633e33ce54a6 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -28,9 +28,9 @@
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
#include <linux/clk.h>
+#include <linux/omapfb.h>
#include <mach/dma.h>
-#include <mach/omapfb.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 8862233d57b6..f67c3c61eb42 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -27,9 +27,9 @@
#include <linux/platform_device.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
+#include <linux/omapfb.h>
#include <mach/dma.h>
-#include <mach/omapfb.h>
#include "lcdc.h"
#include "dispc.h"
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 9332d6ca6456..690a48bbc6de 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -26,8 +26,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
-
-#include <mach/omapfb.h>
+#include <linux/omapfb.h>
#include "dispc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index a76946220249..cab398f81ecc 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -23,9 +23,9 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/omapfb.h>
#include <mach/dma.h>
-#include <mach/omapfb.h>
#include "lcdc.h"
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
new file mode 100644
index 000000000000..89bf2107bb2a
--- /dev/null
+++ b/drivers/video/omap2/Kconfig
@@ -0,0 +1,3 @@
+source "drivers/video/omap2/dss/Kconfig"
+source "drivers/video/omap2/displays/Kconfig"
+source "drivers/video/omap2/omapfb/Kconfig"
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
new file mode 100644
index 000000000000..72134dbcb165
--- /dev/null
+++ b/drivers/video/omap2/Makefile
@@ -0,0 +1,4 @@
+# OMAP2/3 Display Subsystem
+obj-y += dss/
+obj-y += displays/
+obj-y += omapfb/
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
new file mode 100644
index 000000000000..1c582bdacdc0
--- /dev/null
+++ b/drivers/video/omap2/displays/Kconfig
@@ -0,0 +1,49 @@
+menu "OMAP2/3 Display Device Drivers"
+ depends on OMAP2_DSS
+
+config PANEL_GENERIC
+ tristate "Generic Panel"
+ help
+ Generic panel driver.
+ Used for DVI output for Beagle and OMAP3 SDP.
+
+config PANEL_SAMSUNG_LTE430WQ_F0C
+ tristate "Samsung LTE430WQ-F0C LCD Panel"
+ depends on OMAP2_DSS
+ help
+ LCD Panel used on Overo Palo43
+
+config PANEL_SHARP_LS037V7DW01
+ tristate "Sharp LS037V7DW01 LCD Panel"
+ depends on OMAP2_DSS
+ help
+ LCD Panel used in TI's SDP3430 and EVM boards
+
+config PANEL_N800
+ tristate "Panel N8x0"
+ help
+ N8x0 LCD (hack)
+
+config CTRL_BLIZZARD
+ tristate "Blizzard Controller"
+ help
+ Blizzard Controller (hack)
+
+config PANEL_ACX565AKM
+ tristate "ACX565AKM LCD Panel"
+ depends on OMAP2_DSS_SDI
+ select BACKLIGHT_CLASS_DEVICE
+ help
+ LCD Panel used in RX51
+
+config LCD_4430SDP
+ tristate "OMAP4 LCD Panel"
+ help
+ LCD Panel used in OMAP4
+
+config PANEL_4430SDP_TAAL
+ tristate "OMAP4 LCD TAAL Panel"
+ help
+ DSI LCD Panel used in OMAP4
+
+endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
new file mode 100644
index 000000000000..bab01e1dbc20
--- /dev/null
+++ b/drivers/video/omap2/displays/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
+obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
+obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+
+obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
+obj-$(CONFIG_PANEL_N800) += panel-n800.o
+
+obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+
+obj-$(CONFIG_LCD_4430SDP) += lcd_4430sdp.o
+obj-$(CONFIG_PANEL_4430SDP_TAAL) += panel-taal.o
diff --git a/drivers/video/omap2/displays/ctrl-blizzard.c b/drivers/video/omap2/displays/ctrl-blizzard.c
new file mode 100644
index 000000000000..6698e4df8368
--- /dev/null
+++ b/drivers/video/omap2/displays/ctrl-blizzard.c
@@ -0,0 +1,279 @@
+
+//#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define BLIZZARD_REV_CODE 0x00
+#define BLIZZARD_CONFIG 0x02
+#define BLIZZARD_PLL_DIV 0x04
+#define BLIZZARD_PLL_LOCK_RANGE 0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
+#define BLIZZARD_PLL_MODE 0x0c
+#define BLIZZARD_CLK_SRC 0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
+#define BLIZZARD_MEM_BANK0_STATUS 0x14
+#define BLIZZARD_PANEL_CONFIGURATION 0x28
+#define BLIZZARD_HDISP 0x2a
+#define BLIZZARD_HNDP 0x2c
+#define BLIZZARD_VDISP0 0x2e
+#define BLIZZARD_VDISP1 0x30
+#define BLIZZARD_VNDP 0x32
+#define BLIZZARD_HSW 0x34
+#define BLIZZARD_VSW 0x38
+#define BLIZZARD_DISPLAY_MODE 0x68
+#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
+#define BLIZZARD_POWER_SAVE 0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD 0x00
+#define BLIZZARD_SRC_BLT_LCD 0x06
+
+#define BLIZZARD_COLOR_RGB565 0x01
+#define BLIZZARD_COLOR_YUV420 0x09
+
+#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
+
+
+
+static struct {
+ int version;
+} blizzard;
+
+
+static inline void blizzard_cmd(u8 cmd)
+{
+ omap_rfbi_write_command(&cmd, 1);
+}
+
+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
+{
+ omap_rfbi_write_command(&cmd, 1);
+ omap_rfbi_write_data(buf, len);
+}
+
+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
+{
+ omap_rfbi_write_command(&cmd, 1);
+ omap_rfbi_read_data(buf, len);
+}
+
+static u8 blizzard_read_reg(u8 cmd)
+{
+ u8 data;
+ blizzard_read(cmd, &data, 1);
+ return data;
+}
+
+static int blizzard_ctrl_init(struct omap_display *display)
+{
+ DBG("blizzard_ctrl_init\n");
+
+ return 0;
+}
+
+
+static int blizzard_ctrl_enable(struct omap_display *display)
+{
+ int r = 0;
+ u8 rev, conf;
+
+ DBG("blizzard_ctrl_enable\n");
+
+ if (display->hw_config.ctrl_enable) {
+ r = display->hw_config.ctrl_enable(display);
+ if (r)
+ return r;
+ }
+
+ msleep(100);
+
+ rev = blizzard_read_reg(BLIZZARD_CLK_SRC);
+ printk("CLK_SRC %x\n", rev);
+
+ rev = blizzard_read_reg(BLIZZARD_PLL_DIV);
+ printk("PLLDIV %x\n", rev);
+
+ rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+ conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+ printk("rev %x, conf %x\n", rev, conf);
+
+ switch (rev & 0xfc) {
+ case 0x9c:
+ blizzard.version = BLIZZARD_VERSION_S1D13744;
+ pr_info("omapfb: s1d13744 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ case 0xa4:
+ blizzard.version = BLIZZARD_VERSION_S1D13745;
+ pr_info("omapfb: s1d13745 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ default:
+ printk("invalid s1d1374x revision %02x\n",
+ rev);
+ r = -ENODEV;
+ }
+
+ return r;
+}
+
+static void blizzard_ctrl_disable(struct omap_display *display)
+{
+ DBG("blizzard_ctrl_disable\n");
+
+ if (display->hw_config.ctrl_disable)
+ display->hw_config.ctrl_disable(display);
+}
+
+int rfbi_configure(int rfbi_module, int bpp, int lines);
+
+static void blizzard_ctrl_setup_update(struct omap_display *display,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ u8 tmp[18];
+ int x_end, y_end;
+
+ DBG("blizzard_ctrl_setup_update\n");
+
+ x_end = x + w - 1;
+ y_end = y + h - 1;
+
+ tmp[0] = x;
+ tmp[1] = x >> 8;
+ tmp[2] = y;
+ tmp[3] = y >> 8;
+ tmp[4] = x_end;
+ tmp[5] = x_end >> 8;
+ tmp[6] = y_end;
+ tmp[7] = y_end >> 8;
+
+ /* scaling? */
+ tmp[8] = x;
+ tmp[9] = x >> 8;
+ tmp[10] = y;
+ tmp[11] = y >> 8;
+ tmp[12] = x_end;
+ tmp[13] = x_end >> 8;
+ tmp[14] = y_end;
+ tmp[15] = y_end >> 8;
+
+ tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode;
+
+ if (blizzard.version == BLIZZARD_VERSION_S1D13745)
+ tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+ else
+ tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+ BLIZZARD_SRC_WRITE_LCD :
+ BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+ rfbi_configure(display->hw_config.u.rfbi.channel,
+ 16,
+ 8);
+
+ blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
+
+ rfbi_configure(display->hw_config.u.rfbi.channel,
+ 16,
+ 16);
+}
+
+static int blizzard_ctrl_enable_te(struct omap_display *display, bool enable)
+{
+ return 0;
+}
+
+static int blizzard_ctrl_rotate(struct omap_display *display, u8 rotate)
+{
+ return 0;
+}
+
+static int blizzard_ctrl_mirror(struct omap_display *display, bool enable)
+{
+ return 0;
+}
+
+static int blizzard_run_test(struct omap_display *display, int test_num)
+{
+ return 0;
+}
+
+static struct omap_ctrl blizzard_ctrl = {
+ .owner = THIS_MODULE,
+ .name = "ctrl-blizzard",
+ .init = blizzard_ctrl_init,
+ .enable = blizzard_ctrl_enable,
+ .disable = blizzard_ctrl_disable,
+ .setup_update = blizzard_ctrl_setup_update,
+ .enable_te = blizzard_ctrl_enable_te,
+ .set_rotate = blizzard_ctrl_rotate,
+ .set_mirror = blizzard_ctrl_mirror,
+ .run_test = blizzard_run_test,
+ .pixel_size = 16,
+
+ .timings = {
+ .cs_on_time = 0,
+
+ .we_on_time = 9000,
+ .we_off_time = 18000,
+ .we_cycle_time = 36000,
+
+ .re_on_time = 9000,
+ .re_off_time = 27000,
+ .re_cycle_time = 36000,
+
+ .access_time = 27000,
+ .cs_off_time = 36000,
+
+ .cs_pulse_width = 0,
+ },
+};
+
+
+static int __init blizzard_init(void)
+{
+ DBG("blizzard_init\n");
+ omap_dss_register_ctrl(&blizzard_ctrl);
+ return 0;
+}
+
+static void __exit blizzard_exit(void)
+{
+ DBG("blizzard_exit\n");
+
+ omap_dss_unregister_ctrl(&blizzard_ctrl);
+}
+
+module_init(blizzard_init);
+module_exit(blizzard_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("Blizzard Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/lcd_4430sdp.c b/drivers/video/omap2/displays/lcd_4430sdp.c
new file mode 100644
index 000000000000..6840333a1f26
--- /dev/null
+++ b/drivers/video/omap2/displays/lcd_4430sdp.c
@@ -0,0 +1,126 @@
+/*
+ * lcd4430_sdp panel support
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Author: Mayuresh Janorkar <mayur@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <linux/spi/spi.h>
+
+#include <mach/gpio.h>
+#include <mach/gpio.h>
+#include <mach/mux.h>
+#include <asm/mach-types.h>
+#include <mach/control.h>
+
+#include <mach/display.h>
+
+#define LCD_XRES 800
+#define LCD_YRES 480
+#define LCD_PIXCLOCK_MAX 21625
+
+/*NEC NL8048HL11-01B Manual
+* defines HFB, HSW, HBP, VFP, VSW, VBP as shown below
+*/
+
+static struct omap_video_timings lcd_4430_sdp_panel_timings = {
+ /* 800 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
+ .x_res = LCD_XRES,
+ .y_res = LCD_YRES,
+ .pixel_clock = LCD_PIXCLOCK_MAX,
+ .hfp = 6,
+ .hsw = 1,
+ .hbp = 4,
+ .vfp = 3,
+ .vsw = 1,
+ .vbp = 4,
+};
+
+static int lcd_4430_sdp_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.timings = lcd_4430_sdp_panel_timings;
+
+ return 0;
+}
+
+static void lcd_4430_sdp_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int lcd_4430_sdp_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+ mdelay(4);
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+ /* Enable LCD-Enable bit in DISPC_CONTROL */
+ omap_writel((omap_readl(0x48043040) | 0x1), 0x48043040);
+ return r;
+}
+
+static void lcd_4430_sdp_panel_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+ mdelay(4);
+}
+
+static int lcd_4430_sdp_panel_suspend(struct omap_dss_device *dssdev)
+{
+ lcd_4430_sdp_panel_disable(dssdev);
+ return 0;
+}
+
+static int lcd_4430_sdp_panel_resume(struct omap_dss_device *dssdev)
+{
+ return lcd_4430_sdp_panel_enable(dssdev);
+}
+
+static struct omap_dss_driver lcd_4430_sdp_driver = {
+ .probe = lcd_4430_sdp_panel_probe,
+ .remove = lcd_4430_sdp_panel_remove,
+
+ .enable = lcd_4430_sdp_panel_enable,
+ .disable = lcd_4430_sdp_panel_disable,
+ .suspend = lcd_4430_sdp_panel_suspend,
+ .resume = lcd_4430_sdp_panel_resume,
+
+ .driver = {
+ .name = "sdp4430_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init lcd_4430_sdp_lcd_init(void)
+{
+
+ return omap_dss_register_driver(&lcd_4430_sdp_driver);
+}
+
+static void __exit lcd_4430_sdp_lcd_exit(void)
+{
+ return omap_dss_unregister_driver(&lcd_4430_sdp_driver);
+}
+
+module_init(lcd_4430_sdp_lcd_init);
+module_exit(lcd_4430_sdp_lcd_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
new file mode 100644
index 000000000000..2679d6c2a6dc
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -0,0 +1,712 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#include "panel-acx565akm.h"
+
+#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_CMD_WRITE_DISP_BRIGHTNESS 0x51
+#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
+#define MIPID_CMD_WRITE_CTRL_DISP 0x53
+
+#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
+#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
+#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
+#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
+
+#define MIPID_CMD_READ_CTRL_DISP 0x54
+#define MIPID_CMD_WRITE_CABC 0x55
+#define MIPID_CMD_READ_CABC 0x56
+
+#define MIPID_VER_LPH8923 3
+#define MIPID_VER_LS041Y3 4
+#define MIPID_VER_L4F00311 8
+#define MIPID_VER_ACX565AKM 9
+
+struct acx565akm_device {
+ struct backlight_device *bl_dev;
+ int enabled;
+ int model;
+ int revision;
+ u8 display_id[3];
+ int has_bc:1;
+ int has_cabc:1;
+ 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 spi_device *spi;
+ struct mutex mutex;
+ struct omap_panel panel;
+ struct omap_display *display;
+};
+
+static int acx565akm_bl_update_status(struct backlight_device *dev);
+
+static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
+ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+ struct spi_message m;
+ struct spi_transfer *x, xfer[5];
+ 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;
+
+ if (rlen > 1 && wlen == 0) {
+ /*
+ * Between the command and the response data there is a
+ * dummy clock cycle. Add an extra bit after the command
+ * word to account for this.
+ */
+ x->bits_per_word = 10;
+ cmd <<= 1;
+ }
+ 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 = rbuf;
+ x->len = rlen;
+ 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);
+}
+
+static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
+{
+ acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void acx565akm_write(struct acx565akm_device *md,
+ int reg, const u8 *buf, int len)
+{
+ acx565akm_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void acx565akm_read(struct acx565akm_device *md,
+ int reg, u8 *buf, int len)
+{
+ acx565akm_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void hw_guard_start(struct acx565akm_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 acx565akm_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 acx565akm_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);
+ acx565akm_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 acx565akm_device *md, int enabled)
+{
+ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+ acx565akm_cmd(md, cmd);
+}
+
+static int panel_enabled(struct acx565akm_device *md)
+{
+ u32 disp_status;
+ int enabled;
+
+ acx565akm_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 void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
+{
+ u16 ctrl;
+
+ acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
+ if (enable) {
+ ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
+ CTRL_DISP_BACKLIGHT_ON;
+ } else {
+ ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
+ CTRL_DISP_BACKLIGHT_ON);
+ }
+
+ ctrl |= 1 << 8;
+ acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
+}
+
+static void set_cabc_mode(struct acx565akm_device *md, int mode)
+{
+ u16 cabc_ctrl;
+
+ cabc_ctrl = 0;
+ acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
+ cabc_ctrl &= ~3;
+ cabc_ctrl |= (1 << 8) | (mode & 3);
+ acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
+}
+
+static int get_cabc_mode(struct acx565akm_device *md)
+{
+ u8 cabc_ctrl;
+
+ acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
+ return cabc_ctrl & 3;
+}
+
+static int panel_detect(struct acx565akm_device *md)
+{
+ acx565akm_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 0x10:
+ md->model = MIPID_VER_ACX565AKM;
+ md->panel.name = "acx565akm";
+ md->has_bc = 1;
+ md->has_cabc = 1;
+ break;
+ case 0x29:
+ md->model = MIPID_VER_L4F00311;
+ md->panel.name = "l4f00311";
+ break;
+ case 0x45:
+ md->model = MIPID_VER_LPH8923;
+ md->panel.name = "lph8923";
+ break;
+ case 0x83:
+ md->model = MIPID_VER_LS041Y3;
+ md->panel.name = "ls041y3";
+ break;
+ default:
+ md->panel.name = "unknown";
+ dev_err(&md->spi->dev, "invalid display ID\n");
+ return -ENODEV;
+ }
+
+ md->revision = md->display_id[1];
+
+ pr_info("omapfb: %s rev %02x LCD detected\n",
+ md->panel.name, md->revision);
+
+ return 0;
+}
+
+static int acx565akm_panel_enable(struct omap_display *display)
+{
+ struct acx565akm_device *md =
+ (struct acx565akm_device *)display->panel->priv;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ mutex_lock(&md->mutex);
+
+ if (display->hw_config.panel_enable)
+ display->hw_config.panel_enable(display);
+
+ md->enabled = panel_enabled(md);
+
+ if (md->enabled) {
+ dev_dbg(&md->spi->dev, "panel already enabled\n");
+ mutex_unlock(&md->mutex);
+ return 0;
+ }
+
+ set_sleep_mode(md, 0);
+ md->enabled = 1;
+ set_display_state(md, 1);
+
+ mutex_unlock(&md->mutex);
+
+ return acx565akm_bl_update_status(md->bl_dev);
+}
+
+static void acx565akm_panel_disable(struct omap_display *display)
+{
+ struct acx565akm_device *md =
+ (struct acx565akm_device *)display->panel->priv;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ mutex_lock(&md->mutex);
+
+ if (!md->enabled) {
+ mutex_unlock(&md->mutex);
+ return;
+ }
+ set_display_state(md, 0);
+ set_sleep_mode(md, 1);
+ md->enabled = 0;
+
+ if (display->hw_config.panel_disable)
+ display->hw_config.panel_disable(display);
+
+ mutex_unlock(&md->mutex);
+}
+
+#if 0
+static void acx565akm_set_mode(struct omap_display *display,
+ int x_res, int y_res, int bpp)
+{
+ struct acx565akm_device *md =
+ (struct acx565akm_device *)display->panel->priv;
+ u16 par;
+
+ switch (bpp) {
+ case 16:
+ par = 0x150;
+ break;
+ case 18:
+ par = 0x160;
+ break;
+ case 24:
+ par = 0x170;
+ break;
+ }
+
+ acx565akm_write(md, 0x3a, (u8 *)&par, 2);
+}
+#endif
+
+static int acx565akm_panel_suspend(struct omap_display *display)
+{
+ acx565akm_panel_disable(display);
+ return 0;
+}
+
+static int acx565akm_panel_resume(struct omap_display *display)
+{
+ return acx565akm_panel_enable(display);
+}
+
+static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
+{
+ int bv;
+
+ bv = level | (1 << 8);
+ acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
+
+ if (level)
+ enable_backlight_ctrl(md, 1);
+ else
+ enable_backlight_ctrl(md, 0);
+}
+
+static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
+{
+ u8 bv;
+
+ acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
+
+ return bv;
+}
+
+static int acx565akm_bl_update_status(struct backlight_device *dev)
+{
+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
+ struct omap_display *display = md->display;
+ int r;
+ int level;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ if (display->hw_config.set_backlight == NULL)
+ return -ENODEV;
+
+ mutex_lock(&md->mutex);
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ level = dev->props.brightness;
+ else
+ level = 0;
+
+ r = 0;
+ if (md->has_bc)
+ acx565akm_set_brightness(md, level);
+ else
+ if (display->hw_config.set_backlight != NULL)
+ r = display->hw_config.set_backlight(display, level);
+ else
+ r = -ENODEV;
+
+ mutex_unlock(&md->mutex);
+
+ return r;
+}
+
+static int acx565akm_bl_get_intensity(struct backlight_device *dev)
+{
+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
+ struct omap_display *display = md->display;
+
+ dev_dbg(&dev->dev, "%s\n", __func__);
+
+ if (md->has_bc && display->hw_config.set_backlight == NULL)
+ return -ENODEV;
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK) {
+ if (md->has_bc)
+ return acx565akm_get_actual_brightness(md);
+ else
+ return dev->props.brightness;
+ }
+
+ return 0;
+}
+
+static struct backlight_ops acx565akm_bl_ops = {
+ .get_brightness = acx565akm_bl_get_intensity,
+ .update_status = acx565akm_bl_update_status,
+};
+
+static const char *cabc_modes[] = {
+ "off", /* used also always when CABC is not supported */
+ "ui",
+ "still-image",
+ "moving-image",
+};
+
+static ssize_t show_cabc_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct acx565akm_device *md = dev_get_drvdata(dev);
+ const char *mode_str;
+ int mode;
+ int len;
+
+ if (!md->has_cabc)
+ mode = 0;
+ else
+ mode = get_cabc_mode(md);
+ mode_str = "unknown";
+ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
+ mode_str = cabc_modes[mode];
+ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
+
+ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
+}
+
+static ssize_t store_cabc_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct acx565akm_device *md = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
+ const char *mode_str = cabc_modes[i];
+ int cmp_len = strlen(mode_str);
+
+ if (count > 0 && buf[count - 1] == '\n')
+ count--;
+ if (count != cmp_len)
+ continue;
+
+ if (strncmp(buf, mode_str, cmp_len) == 0)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cabc_modes))
+ return -EINVAL;
+
+ if (!md->has_cabc && i != 0)
+ return -EINVAL;
+
+ mutex_lock(&md->mutex);
+ set_cabc_mode(md, i);
+ mutex_unlock(&md->mutex);
+
+ return count;
+}
+
+static ssize_t show_cabc_available_modes(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct acx565akm_device *md = dev_get_drvdata(dev);
+ int len;
+ int i;
+
+ if (!md->has_cabc)
+ return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
+
+ for (i = 0, len = 0;
+ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
+ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
+ i ? " " : "", cabc_modes[i],
+ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
+
+ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
+}
+
+static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
+ show_cabc_mode, store_cabc_mode);
+static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
+ show_cabc_available_modes, NULL);
+
+static struct attribute *bldev_attrs[] = {
+ &dev_attr_cabc_mode.attr,
+ &dev_attr_cabc_available_modes.attr,
+ NULL,
+};
+
+static struct attribute_group bldev_attr_group = {
+ .attrs = bldev_attrs,
+};
+
+static int acx565akm_panel_init(struct omap_display *display)
+{
+ struct omap_panel *panel = display->panel;
+ struct acx565akm_panel_data *panel_data = display->hw_config.panel_data;
+ struct acx565akm_device *md = (struct acx565akm_device *)panel->priv;
+
+ struct backlight_device *bldev;
+ int brightness;
+ int max_brightness;
+ int r;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ if (!panel_data) {
+ dev_err(&md->spi->dev, "no panel data\n");
+ return -ENODEV;
+ }
+
+ mutex_init(&md->mutex);
+ md->display = display;
+
+ if (display->hw_config.panel_enable)
+ display->hw_config.panel_enable(display);
+
+ md->enabled = panel_enabled(md);
+
+ r = panel_detect(md);
+ if (r) {
+ if (!md->enabled && display->hw_config.panel_disable)
+ display->hw_config.panel_disable(display);
+ mutex_unlock(&md->mutex);
+ return r;
+ }
+
+ if (!panel_data->bc_connected) {
+ md->has_bc = 0;
+ md->has_cabc = 0;
+ }
+
+#if 0
+ acx565akm_set_mode(display, panel->timings.x_res, panel->timings.y_res,
+ panel->bpp);
+#endif
+
+ if (!md->enabled)
+ display->hw_config.panel_disable(display);
+
+ bldev = backlight_device_register("acx565akm", &md->spi->dev,
+ md, &acx565akm_bl_ops);
+ md->bl_dev = bldev;
+
+ if (md->has_cabc) {
+ r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
+ if (r) {
+ dev_err(&bldev->dev, "failed to create sysfs files\n");
+ backlight_device_unregister(bldev);
+ return r;
+ }
+ }
+
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
+
+ if (md->has_bc)
+ max_brightness = 255;
+ else
+ max_brightness = display->hw_config.max_backlight_level;
+
+ if (md->has_bc)
+ brightness = acx565akm_get_actual_brightness(md);
+ else {
+ if (display->hw_config.get_backlight != NULL)
+ brightness = display->hw_config.get_backlight(display);
+ else
+ brightness = 0;
+ }
+
+ bldev->props.max_brightness = max_brightness;
+ bldev->props.brightness = brightness;
+ acx565akm_bl_update_status(bldev);
+
+ return 0;
+}
+
+static struct omap_panel acx565akm_panel = {
+ .name = "panel-acx565akm",
+ .init = acx565akm_panel_init,
+ .suspend = acx565akm_panel_suspend,
+ .resume = acx565akm_panel_resume,
+ .enable = acx565akm_panel_enable,
+ .disable = acx565akm_panel_disable,
+
+ .timings = {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 24000,
+
+ .hsw = 4,
+ .hfp = 16,
+ .hbp = 12,
+
+ .vsw = 3,
+ .vfp = 3,
+ .vbp = 3,
+ },
+
+ .config = OMAP_DSS_LCD_TFT,
+
+ .recommended_bpp = 16,
+
+ /*
+ * supported modes: 12bpp(444), 16bpp(565), 18bpp(666), 24bpp(888)
+ * resolutions.
+ */
+};
+
+static int acx565akm_spi_probe(struct spi_device *spi)
+{
+ struct acx565akm_device *md;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ md = kzalloc(sizeof(*md), GFP_KERNEL);
+ if (md == NULL) {
+ dev_err(&spi->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ spi->mode = SPI_MODE_3;
+ md->spi = spi;
+ dev_set_drvdata(&spi->dev, md);
+ md->panel = acx565akm_panel;
+ acx565akm_panel.priv = md;
+
+ omap_dss_register_panel(&acx565akm_panel);
+
+ return 0;
+}
+
+static int acx565akm_spi_remove(struct spi_device *spi)
+{
+ struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
+ backlight_device_unregister(md->bl_dev);
+ omap_dss_unregister_panel(&acx565akm_panel);
+
+ kfree(md);
+
+ return 0;
+}
+
+static struct spi_driver acx565akm_spi_driver = {
+ .driver = {
+ .name = "acx565akm",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = acx565akm_spi_probe,
+ .remove = __devexit_p(acx565akm_spi_remove),
+};
+
+static int __init acx565akm_init(void)
+{
+ return spi_register_driver(&acx565akm_spi_driver);
+}
+
+static void __exit acx565akm_exit(void)
+{
+ spi_unregister_driver(&acx565akm_spi_driver);
+}
+
+module_init(acx565akm_init);
+module_exit(acx565akm_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("acx565akm LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-acx565akm.h b/drivers/video/omap2/displays/panel-acx565akm.h
new file mode 100644
index 000000000000..6d3727b4c7af
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-acx565akm.h
@@ -0,0 +1,9 @@
+#ifndef __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
+#define __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
+
+struct acx565akm_panel_data {
+ unsigned bc_connected:1;
+};
+
+#endif
+
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
new file mode 100644
index 000000000000..738147eee49c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-generic.c
@@ -0,0 +1,104 @@
+/*
+ * Generic panel support
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+
+static struct omap_video_timings generic_panel_timings = {
+ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
+ .x_res = 640,
+ .y_res = 480,
+ .pixel_clock = 23500,
+ .hfp = 48,
+ .hsw = 32,
+ .hbp = 80,
+ .vfp = 3,
+ .vsw = 4,
+ .vbp = 7,
+};
+
+static int generic_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
+ dssdev->panel.timings = generic_panel_timings;
+
+ return 0;
+}
+
+static void generic_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int generic_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+
+ return r;
+}
+
+static void generic_panel_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+}
+
+static int generic_panel_suspend(struct omap_dss_device *dssdev)
+{
+ generic_panel_disable(dssdev);
+ return 0;
+}
+
+static int generic_panel_resume(struct omap_dss_device *dssdev)
+{
+ return generic_panel_enable(dssdev);
+}
+
+static struct omap_dss_driver generic_driver = {
+ .probe = generic_panel_probe,
+ .remove = generic_panel_remove,
+
+ .enable = generic_panel_enable,
+ .disable = generic_panel_disable,
+ .suspend = generic_panel_suspend,
+ .resume = generic_panel_resume,
+
+ .driver = {
+ .name = "generic_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init generic_panel_drv_init(void)
+{
+ return omap_dss_register_driver(&generic_driver);
+}
+
+static void __exit generic_panel_drv_exit(void)
+{
+ omap_dss_unregister_driver(&generic_driver);
+}
+
+module_init(generic_panel_drv_init);
+module_exit(generic_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-n800.c b/drivers/video/omap2/displays/panel-n800.c
new file mode 100644
index 000000000000..91d3e37d6d4c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n800.c
@@ -0,0 +1,435 @@
+
+/*#define DEBUG*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#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)
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+struct pn800_device {
+ struct backlight_device *bl_dev;
+ 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 spi_device *spi;
+ struct mutex mutex;
+ struct omap_panel panel;
+ struct omap_display *display;
+};
+
+
+static void pn800_transfer(struct pn800_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 pn800_cmd(struct pn800_device *md, int cmd)
+{
+ pn800_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void pn800_write(struct pn800_device *md,
+ int reg, const u8 *buf, int len)
+{
+ pn800_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void pn800_read(struct pn800_device *md,
+ int reg, u8 *buf, int len)
+{
+ pn800_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct pn800_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;
+ }
+ pn800_write(md, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct pn800_device *md)
+{
+ u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+ int data_lines;
+
+ pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
+
+ data_lines = (int)md->display->hw_config.panel_data; // XXX
+
+ set_data_lines(md, data_lines);
+}
+
+static void hw_guard_start(struct pn800_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 pn800_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 pn800_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);
+ pn800_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 pn800_device *md, int enabled)
+{
+ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+ pn800_cmd(md, cmd);
+}
+
+static int panel_enabled(struct pn800_device *md)
+{
+ u32 disp_status;
+ int enabled;
+
+ pn800_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 %s enabled by bootloader (status 0x%04x)\n",
+ enabled ? "" : "not ", disp_status);
+ DBG("status %#08x\n", disp_status);
+ return enabled;
+}
+
+static int panel_detect(struct pn800_device *md)
+{
+ pn800_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];
+ pr_info("omapfb: %s rev %02x LCD detected\n",
+ md->panel.name, md->revision);
+
+ return 0;
+}
+
+
+
+static int pn800_panel_enable(struct omap_display *display)
+{
+ int r;
+ struct pn800_device *md =
+ (struct pn800_device *)display->panel->priv;
+
+ DBG("pn800_panel_enable\n");
+
+ mutex_lock(&md->mutex);
+
+ if (display->hw_config.panel_enable)
+ display->hw_config.panel_enable(display);
+
+ msleep(50); // wait for power up
+
+ r = panel_detect(md);
+ if (r) {
+ mutex_unlock(&md->mutex);
+ return r;
+ }
+
+ md->enabled = panel_enabled(md);
+
+ if (md->enabled) {
+ DBG("panel already enabled\n");
+ ; /*pn800_esd_start_check(md);*/
+ } else {
+ ; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+ }
+
+
+ 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 pn800_panel_disable(struct omap_display *display)
+{
+ struct pn800_device *md =
+ (struct pn800_device *)display->panel->priv;
+
+ DBG("pn800_panel_disable\n");
+
+ mutex_lock(&md->mutex);
+
+ if (!md->enabled) {
+ mutex_unlock(&md->mutex);
+ return;
+ }
+ /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+ /*pn800_set_bklight_level(panel, 0);*/
+
+ set_display_state(md, 0);
+ set_sleep_mode(md, 1);
+ md->enabled = 0;
+
+
+ if (display->hw_config.panel_disable)
+ display->hw_config.panel_disable(display);
+
+ mutex_unlock(&md->mutex);
+}
+
+static int pn800_panel_init(struct omap_display *display)
+{
+ struct pn800_device *md =
+ (struct pn800_device *)display->panel->priv;
+
+ DBG("pn800_panel_init\n");
+
+ mutex_init(&md->mutex);
+ md->display = display;
+
+ return 0;
+}
+
+static int pn800_run_test(struct omap_display *display, int test_num)
+{
+ return 0;
+}
+
+static struct omap_panel pn800_panel = {
+ .owner = THIS_MODULE,
+ .name = "panel-pn800",
+ .init = pn800_panel_init,
+ /*.remove = pn800_cleanup,*/
+ .enable = pn800_panel_enable,
+ .disable = pn800_panel_disable,
+ //.set_mode = pn800_set_mode,
+ .run_test = pn800_run_test,
+
+ .timings = {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 21940,
+ .hsw = 50,
+ .hfp = 20,
+ .hbp = 15,
+
+ .vsw = 2,
+ .vfp = 1,
+ .vbp = 3,
+ },
+ .config = OMAP_DSS_LCD_TFT,
+};
+
+static int pn800_spi_probe(struct spi_device *spi)
+{
+ struct pn800_device *md;
+
+ DBG("pn800_spi_probe\n");
+
+ 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 = pn800_panel;
+ pn800_panel.priv = md;
+
+ omap_dss_register_panel(&pn800_panel);
+
+ return 0;
+}
+
+static int pn800_spi_remove(struct spi_device *spi)
+{
+ struct pn800_device *md = dev_get_drvdata(&spi->dev);
+
+ DBG("pn800_spi_remove\n");
+
+ omap_dss_unregister_panel(&pn800_panel);
+
+ /*pn800_disable(&md->panel);*/
+ kfree(md);
+
+ return 0;
+}
+
+static struct spi_driver pn800_spi_driver = {
+ .driver = {
+ .name = "panel-n800",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = pn800_spi_probe,
+ .remove = __devexit_p(pn800_spi_remove),
+};
+
+static int __init pn800_init(void)
+{
+ DBG("pn800_init\n");
+ return spi_register_driver(&pn800_spi_driver);
+}
+
+static void __exit pn800_exit(void)
+{
+ DBG("pn800_exit\n");
+ spi_unregister_driver(&pn800_spi_driver);
+}
+
+module_init(pn800_init);
+module_exit(pn800_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("N800 LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
new file mode 100644
index 000000000000..eafe581b36ff
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
@@ -0,0 +1,113 @@
+/*
+ * LCD panel driver for Samsung LTE430WQ-F0C
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+
+static struct omap_video_timings samsung_lte_timings = {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 9200,
+
+ .hsw = 41,
+ .hfp = 8,
+ .hbp = 45-41,
+
+ .vsw = 10,
+ .vfp = 4,
+ .vbp = 12-10,
+};
+
+static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.timings = samsung_lte_timings;
+
+ return 0;
+}
+
+static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+
+ return r;
+}
+
+static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ /* wait at least 5 vsyncs after disabling the LCD */
+
+ msleep(100);
+}
+
+static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
+{
+ samsung_lte_panel_disable(dssdev);
+ return 0;
+}
+
+static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
+{
+ return samsung_lte_panel_enable(dssdev);
+}
+
+static struct omap_dss_driver samsung_lte_driver = {
+ .probe = samsung_lte_panel_probe,
+ .remove = samsung_lte_panel_remove,
+
+ .enable = samsung_lte_panel_enable,
+ .disable = samsung_lte_panel_disable,
+ .suspend = samsung_lte_panel_suspend,
+ .resume = samsung_lte_panel_resume,
+
+ .driver = {
+ .name = "samsung_lte_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init samsung_lte_panel_drv_init(void)
+{
+ return omap_dss_register_driver(&samsung_lte_driver);
+}
+
+static void __exit samsung_lte_panel_drv_exit(void)
+{
+ omap_dss_unregister_driver(&samsung_lte_driver);
+}
+
+module_init(samsung_lte_panel_drv_init);
+module_exit(samsung_lte_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
new file mode 100644
index 000000000000..2b6d8899441a
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -0,0 +1,153 @@
+/*
+ * LCD panel driver for Sharp LS037V7DW01
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+
+#include <mach/display.h>
+
+struct sharp_data {
+ /* XXX This regulator should actually be in SDP board file, not here,
+ * as it doesn't actually power the LCD, but something else that
+ * affects the output to LCD (I think. Somebody clarify). It doesn't do
+ * harm here, as SDP is the only board using this currently */
+ struct regulator *vdvi_reg;
+};
+
+static struct omap_video_timings sharp_ls_timings = {
+ .x_res = 480,
+ .y_res = 640,
+
+ .pixel_clock = 19200,
+
+ .hsw = 2,
+ .hfp = 1,
+ .hbp = 28,
+
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 1,
+};
+
+static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
+{
+ struct sharp_data *sd;
+
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.acb = 0x28;
+ dssdev->panel.timings = sharp_ls_timings;
+
+ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+
+ dev_set_drvdata(&dssdev->dev, sd);
+
+ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
+ if (IS_ERR(sd->vdvi_reg)) {
+ kfree(sd);
+ printk(KERN_INFO "failed to get VDVI regulator\n");
+ return PTR_ERR(sd->vdvi_reg);
+ }
+
+ return 0;
+}
+
+static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
+{
+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
+
+ regulator_put(sd->vdvi_reg);
+
+ kfree(sd);
+}
+
+static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+{
+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
+ regulator_enable(sd->vdvi_reg);
+
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+
+ return r;
+}
+
+static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
+{
+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ regulator_disable(sd->vdvi_reg);
+
+ /* wait at least 5 vsyncs after disabling the LCD */
+
+ msleep(100);
+}
+
+static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
+{
+ sharp_ls_panel_disable(dssdev);
+ return 0;
+}
+
+static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
+{
+ return sharp_ls_panel_enable(dssdev);
+}
+
+static struct omap_dss_driver sharp_ls_driver = {
+ .probe = sharp_ls_panel_probe,
+ .remove = sharp_ls_panel_remove,
+
+ .enable = sharp_ls_panel_enable,
+ .disable = sharp_ls_panel_disable,
+ .suspend = sharp_ls_panel_suspend,
+ .resume = sharp_ls_panel_resume,
+
+ .driver = {
+ .name = "sharp_ls_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sharp_ls_panel_drv_init(void)
+{
+ return omap_dss_register_driver(&sharp_ls_driver);
+}
+
+static void __exit sharp_ls_panel_drv_exit(void)
+{
+ omap_dss_unregister_driver(&sharp_ls_driver);
+}
+
+module_init(sharp_ls_panel_drv_init);
+module_exit(sharp_ls_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
new file mode 100644
index 000000000000..54b27316d638
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -0,0 +1,905 @@
+/*
+ * Taal DSI command mode panel
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*#define DEBUG*/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/completion.h>
+
+#include <mach/display.h>
+
+/* DSI Virtual channel. Hardcoded for now. */
+#define TCH 0
+
+#define DCS_READ_NUM_ERRORS 0x05
+#define DCS_READ_POWER_MODE 0x0a
+#define DCS_READ_MADCTL 0x0b
+#define DCS_READ_PIXEL_FORMAT 0x0c
+#define DCS_SLEEP_IN 0x10
+#define DCS_SLEEP_OUT 0x11
+#define DCS_DISPLAY_OFF 0x28
+#define DCS_DISPLAY_ON 0x29
+#define DCS_COLUMN_ADDR 0x2a
+#define DCS_PAGE_ADDR 0x2b
+#define DCS_MEMORY_WRITE 0x2c
+#define DCS_TEAR_OFF 0x34
+#define DCS_TEAR_ON 0x35
+#define DCS_MEM_ACC_CTRL 0x36
+#define DCS_PIXEL_FORMAT 0x3a
+#define DCS_BRIGHTNESS 0x51
+#define DCS_CTRL_DISPLAY 0x53
+#define DCS_WRITE_CABC 0x55
+#define DCS_READ_CABC 0x56
+#define DCS_GET_ID1 0xda
+#define DCS_GET_ID2 0xdb
+#define DCS_GET_ID3 0xdc
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "Taal: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+struct taal_data {
+ struct backlight_device *bldev;
+
+ 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 omap_dss_device *dssdev;
+
+ bool enabled;
+ u8 rotate;
+ bool mirror;
+
+ bool te_enabled;
+ bool use_ext_te;
+ struct completion te_completion;
+
+ bool use_dsi_bl;
+
+ bool cabc_broken;
+ unsigned cabc_mode;
+ bool intro_printed;
+};
+
+static void hw_guard_start(struct taal_data *td, int guard_msec)
+{
+ td->hw_guard_wait = msecs_to_jiffies(guard_msec);
+ td->hw_guard_end = jiffies + td->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct taal_data *td)
+{
+ unsigned long wait = td->hw_guard_end - jiffies;
+
+ if ((long)wait > 0 && wait <= td->hw_guard_wait) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(wait);
+ }
+}
+
+static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
+{
+ int r;
+ u8 buf[1];
+
+ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
+
+ if (r < 0) {
+ printk(KERN_ERR "Taal read error\n");
+ return r;
+ }
+
+ *data = buf[0];
+
+ return 0;
+}
+
+static int taal_dcs_write_0(u8 dcs_cmd)
+{
+ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
+}
+
+static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
+{
+ u8 buf[2];
+ buf[0] = dcs_cmd;
+ buf[1] = param;
+ return dsi_vc_dcs_write(TCH, buf, 2);
+}
+
+static int taal_sleep_in(struct taal_data *td)
+{
+ u8 cmd;
+ int r;
+
+ hw_guard_wait(td);
+
+ cmd = DCS_SLEEP_IN;
+ r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
+ if (r)
+ return r;
+
+ hw_guard_start(td, 120);
+
+ msleep(5);
+
+ return 0;
+}
+
+static int taal_sleep_out(struct taal_data *td)
+{
+ int r;
+
+ hw_guard_wait(td);
+
+ r = taal_dcs_write_0(DCS_SLEEP_OUT);
+ if (r)
+ return r;
+
+ hw_guard_start(td, 120);
+
+ msleep(5);
+
+ return 0;
+}
+
+static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
+{
+ int r;
+
+ r = taal_dcs_read_1(DCS_GET_ID1, id1);
+ if (r)
+ return r;
+ r = taal_dcs_read_1(DCS_GET_ID2, id2);
+ if (r)
+ return r;
+ r = taal_dcs_read_1(DCS_GET_ID3, id3);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int taal_set_addr_mode(u8 rotate, bool mirror)
+{
+ int r;
+ u8 mode;
+ int b5, b6, b7;
+
+ r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
+ if (r)
+ return r;
+
+ switch (rotate) {
+ default:
+ case 0:
+ b7 = 0;
+ b6 = 0;
+ b5 = 0;
+ break;
+ case 1:
+ b7 = 0;
+ b6 = 1;
+ b5 = 1;
+ break;
+ case 2:
+ b7 = 1;
+ b6 = 1;
+ b5 = 0;
+ break;
+ case 3:
+ b7 = 1;
+ b6 = 0;
+ b5 = 1;
+ break;
+ }
+
+ if (mirror)
+ b6 = !b6;
+
+ mode &= ~((1<<7) | (1<<6) | (1<<5));
+ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
+
+ return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
+}
+
+static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
+{
+ int r;
+ u16 x1 = x;
+ u16 x2 = x + w - 1;
+ u16 y1 = y;
+ u16 y2 = y + h - 1;
+
+ u8 buf[5];
+ buf[0] = DCS_COLUMN_ADDR;
+ buf[1] = (x1 >> 8) & 0xff;
+ buf[2] = (x1 >> 0) & 0xff;
+ buf[3] = (x2 >> 8) & 0xff;
+ buf[4] = (x2 >> 0) & 0xff;
+
+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+ if (r)
+ return r;
+
+ buf[0] = DCS_PAGE_ADDR;
+ buf[1] = (y1 >> 8) & 0xff;
+ buf[2] = (y1 >> 0) & 0xff;
+ buf[3] = (y2 >> 8) & 0xff;
+ buf[4] = (y2 >> 0) & 0xff;
+
+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+ if (r)
+ return r;
+
+ dsi_vc_send_bta_sync(TCH);
+
+ return r;
+}
+
+static int taal_bl_update_status(struct backlight_device *dev)
+{
+ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ int r;
+ int level;
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ level = dev->props.brightness;
+ else
+ level = 0;
+
+ DBG("update brightness to %d\n", level);
+
+ if (td->use_dsi_bl) {
+ if (td->enabled) {
+ dsi_bus_lock();
+ r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
+ dsi_bus_unlock();
+ if (r)
+ return r;
+ }
+ } else {
+ if (!dssdev->set_backlight)
+ return -EINVAL;
+
+ r = dssdev->set_backlight(dssdev, level);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int taal_bl_get_intensity(struct backlight_device *dev)
+{
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ return dev->props.brightness;
+
+ return 0;
+}
+
+static struct backlight_ops taal_bl_ops = {
+ .get_brightness = taal_bl_get_intensity,
+ .update_status = taal_bl_update_status,
+};
+
+static void taal_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ *timings = dssdev->panel.timings;
+}
+
+static void taal_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ if (td->rotate == 0 || td->rotate == 2) {
+ *xres = dssdev->panel.timings.x_res;
+ *yres = dssdev->panel.timings.y_res;
+ } else {
+ *yres = dssdev->panel.timings.x_res;
+ *xres = dssdev->panel.timings.y_res;
+ }
+}
+
+static irqreturn_t taal_te_isr(int irq, void *data)
+{
+ struct omap_dss_device *dssdev = data;
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ complete_all(&td->te_completion);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t taal_num_errors_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ u8 errors;
+ int r;
+
+ if (td->enabled) {
+ dsi_bus_lock();
+ r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
+ dsi_bus_unlock();
+ } else {
+ r = -ENODEV;
+ }
+
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", errors);
+}
+
+static ssize_t taal_hw_revision_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ u8 id1, id2, id3;
+ int r;
+
+ if (td->enabled) {
+ dsi_bus_lock();
+ r = taal_get_id(&id1, &id2, &id3);
+ dsi_bus_unlock();
+ } else {
+ r = -ENODEV;
+ }
+
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
+}
+
+static const char *cabc_modes[] = {
+ "off", /* used also always when CABC is not supported */
+ "ui",
+ "still-image",
+ "moving-image",
+};
+
+static ssize_t show_cabc_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ const char *mode_str;
+ int mode;
+ int len;
+
+ mode = td->cabc_mode;
+
+ mode_str = "unknown";
+ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
+ mode_str = cabc_modes[mode];
+ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
+
+ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
+}
+
+static ssize_t store_cabc_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
+ if (sysfs_streq(cabc_modes[i], buf))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cabc_modes))
+ return -EINVAL;
+
+ if (td->enabled) {
+ dsi_bus_lock();
+ if (!td->cabc_broken)
+ taal_dcs_write_1(DCS_WRITE_CABC, i);
+ dsi_bus_unlock();
+ }
+
+ td->cabc_mode = i;
+
+ return count;
+}
+
+static ssize_t show_cabc_available_modes(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int len;
+ int i;
+
+ for (i = 0, len = 0;
+ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
+ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
+ i ? " " : "", cabc_modes[i],
+ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
+
+ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
+}
+
+static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
+static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
+static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
+ show_cabc_mode, store_cabc_mode);
+static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
+ show_cabc_available_modes, NULL);
+
+static struct attribute *taal_attrs[] = {
+ &dev_attr_num_dsi_errors.attr,
+ &dev_attr_hw_revision.attr,
+ &dev_attr_cabc_mode.attr,
+ &dev_attr_cabc_available_modes.attr,
+ NULL,
+};
+
+static struct attribute_group taal_attr_group = {
+ .attrs = taal_attrs,
+};
+
+static int taal_probe(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td;
+ struct backlight_device *bldev;
+ int r;
+
+ const struct omap_video_timings taal_panel_timings = {
+ .x_res = 864,
+ .y_res = 480,
+ };
+
+ DBG("probe\n");
+
+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
+ dssdev->panel.timings = taal_panel_timings;
+ dssdev->ctrl.pixel_size = 24;
+
+ td = kzalloc(sizeof(*td), GFP_KERNEL);
+ if (!td) {
+ r = -ENOMEM;
+ goto err0;
+ }
+
+ dev_set_drvdata(&dssdev->dev, td);
+
+ dssdev->get_timings = taal_get_timings;
+ dssdev->get_resolution = taal_get_resolution;
+
+ /* if no platform set_backlight() defined, presume DSI backlight
+ * control */
+ if (!dssdev->set_backlight)
+ td->use_dsi_bl = true;
+
+ bldev = backlight_device_register("panel-taal", &dssdev->dev, dssdev,
+ &taal_bl_ops);
+
+ if (IS_ERR(bldev)) {
+ r = PTR_ERR(bldev);
+ goto err1;
+ }
+
+ td->bldev = bldev;
+
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
+ if (td->use_dsi_bl) {
+ bldev->props.max_brightness = 255;
+ bldev->props.brightness = 255;
+ } else {
+ bldev->props.max_brightness = 127;
+ bldev->props.brightness = 127;
+ }
+
+ taal_bl_update_status(bldev);
+
+ if (dssdev->phy.dsi.ext_te) {
+ int gpio = dssdev->phy.dsi.ext_te_gpio;
+ r = gpio_request(gpio, "taal irq");
+ if (r)
+ goto err2;
+
+ gpio_direction_input(gpio);
+
+ r = request_irq(gpio_to_irq(gpio), taal_te_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "taal vsync", dssdev);
+
+ if (r) {
+ gpio_free(gpio);
+ goto err2;
+ }
+
+ init_completion(&td->te_completion);
+
+ td->use_ext_te = true;
+ }
+
+ r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to create sysfs files\n");
+ goto err3;
+ }
+
+ return 0;
+err3:
+ if (td->use_ext_te) {
+ int gpio = dssdev->phy.dsi.ext_te_gpio;
+ free_irq(gpio_to_irq(gpio), dssdev);
+ gpio_free(gpio);
+ }
+err2:
+ backlight_device_unregister(bldev);
+err1:
+ kfree(td);
+err0:
+ return r;
+}
+
+static void taal_remove(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct backlight_device *bldev;
+
+ DBG("remove\n");
+
+ sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
+
+ if (td->use_ext_te) {
+ int gpio = dssdev->phy.dsi.ext_te_gpio;
+ free_irq(gpio_to_irq(gpio), dssdev);
+ gpio_free(gpio);
+ }
+
+ bldev = td->bldev;
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ taal_bl_update_status(bldev);
+ backlight_device_unregister(bldev);
+
+ kfree(td);
+}
+
+static int taal_enable(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ u8 id1, id2, id3;
+ int r;
+
+ DBG("enable\n");
+ if (dssdev->platform_enable) {
+ r = dssdev->platform_enable(dssdev);
+ if (r)
+ return r;
+ }
+
+ /* it seems we have to wait a bit until taal is ready */
+ msleep(5);
+
+#if 1
+ r = taal_sleep_out(td);
+ if (r)
+ return r;
+
+ r = taal_get_id(&id1, &id2, &id3);
+ if (r)
+ return r;
+
+ /* on early revisions CABC is broken */
+ if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
+ td->cabc_broken = true;
+ taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
+ taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
+
+ taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+
+ taal_set_addr_mode(td->rotate, td->mirror);
+ if (!td->cabc_broken)
+ taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
+
+ taal_dcs_write_0(DCS_DISPLAY_ON);
+
+ td->enabled = 1;
+
+ if (!td->intro_printed) {
+ dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
+ id1, id2, id3);
+ if (td->cabc_broken)
+ dev_info(&dssdev->dev,
+ "old Taal version, CABC disabled\n");
+ td->intro_printed = true;
+ }
+#endif
+ return 0;
+}
+
+static void taal_disable(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+ DBG("disable\n");
+
+ taal_dcs_write_0(DCS_DISPLAY_OFF);
+ taal_sleep_in(td);
+
+ /* wait a bit so that the message goes through */
+ msleep(10);
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ td->enabled = 0;
+}
+
+static int taal_suspend(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct backlight_device *bldev = td->bldev;
+
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ taal_bl_update_status(bldev);
+
+ return 0;
+}
+
+static int taal_resume(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ struct backlight_device *bldev = td->bldev;
+
+ bldev->props.power = FB_BLANK_UNBLANK;
+ taal_bl_update_status(bldev);
+
+ return 0;
+}
+
+static void taal_setup_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ taal_set_update_window(x, y, w, h);
+}
+
+static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ td->te_enabled = enable;
+ if (enable)
+ r = taal_dcs_write_1(DCS_TEAR_ON, 0);
+ else
+ r = taal_dcs_write_0(DCS_TEAR_OFF);
+ return r;
+}
+
+static int taal_wait_te(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ long wait = msecs_to_jiffies(500);
+
+ if (!td->use_ext_te || !td->te_enabled)
+ return 0;
+
+ INIT_COMPLETION(td->te_completion);
+ wait = wait_for_completion_timeout(&td->te_completion, wait);
+ if (wait == 0) {
+ printk(KERN_ERR "Taal: timeout waiting TE\n");
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ DBG("taal_rotate %d\n", rotate);
+
+ if (td->enabled) {
+ r = taal_set_addr_mode(rotate, td->mirror);
+
+ if (r)
+ return r;
+ }
+
+ td->rotate = rotate;
+
+ return 0;
+}
+
+static u8 taal_get_rotate(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ return td->rotate;
+}
+
+static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ DBG("taal_mirror %d\n", enable);
+
+ if (td->enabled) {
+ r = taal_set_addr_mode(td->rotate, enable);
+
+ if (r)
+ return r;
+ }
+
+ td->mirror = enable;
+
+ return 0;
+}
+
+static bool taal_get_mirror(struct omap_dss_device *dssdev)
+{
+ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+ return td->mirror;
+}
+
+static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
+{
+ u8 id1, id2, id3;
+ int r;
+
+ r = taal_dcs_read_1(DCS_GET_ID1, &id1);
+ if (r)
+ return r;
+ r = taal_dcs_read_1(DCS_GET_ID2, &id2);
+ if (r)
+ return r;
+ r = taal_dcs_read_1(DCS_GET_ID3, &id3);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int taal_memory_read(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int r;
+ int first = 1;
+ int plen;
+ unsigned buf_used = 0;
+
+ if (size < w * h * 3)
+ return -ENOMEM;
+
+ size = min(w * h * 3,
+ dssdev->panel.timings.x_res *
+ dssdev->panel.timings.y_res * 3);
+
+ /* plen 1 or 2 goes into short packet. until checksum error is fixed,
+ * use short packets. plen 32 works, but bigger packets seem to
+ * cause an error.
+ */
+ if (size % 2)
+ plen = 1;
+ else
+ plen = 2;
+
+ taal_setup_update(dssdev, x, y, w, h);
+
+ r = dsi_vc_set_max_rx_packet_size(TCH, plen);
+ if (r)
+ return r;
+
+ while (buf_used < size) {
+ u8 dcs_cmd = first ? 0x2e : 0x3e;
+ first = 0;
+
+ r = dsi_vc_dcs_read(TCH, dcs_cmd,
+ buf + buf_used, size - buf_used);
+
+ if (r < 0) {
+ printk(KERN_ERR "Taal read error\n");
+ goto err;
+ }
+
+ buf_used += r;
+
+ if (r < plen) {
+ printk(KERN_INFO "short read\n");
+ break;
+ }
+ }
+
+ r = buf_used;
+
+err:
+ dsi_vc_set_max_rx_packet_size(TCH, 1);
+
+ return r;
+}
+
+static struct omap_dss_driver taal_driver = {
+ .probe = taal_probe,
+ .remove = taal_remove,
+
+ .enable = taal_enable,
+ .disable = taal_disable,
+ .suspend = taal_suspend,
+ .resume = taal_resume,
+
+ .setup_update = taal_setup_update,
+ .enable_te = taal_enable_te,
+ .wait_for_te = taal_wait_te,
+ .set_rotate = taal_rotate,
+ .get_rotate = taal_get_rotate,
+ .set_mirror = taal_mirror,
+ .get_mirror = taal_get_mirror,
+ .run_test = taal_run_test,
+ .memory_read = taal_memory_read,
+
+ .driver = {
+ .name = "panel-taal",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init taal_init(void)
+{
+ DBG("\n taal_init\n");
+
+ omap_dss_register_driver(&taal_driver);
+ printk(KERN_INFO "\n omap_dss_register_driver DONE ");
+ return 0;
+}
+
+static void __exit taal_exit(void)
+{
+ DBG("exit\n");
+
+ omap_dss_unregister_driver(&taal_driver);
+}
+
+module_init(taal_init);
+module_exit(taal_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("Taal Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
new file mode 100644
index 000000000000..9ac8f5a45901
--- /dev/null
+++ b/drivers/video/omap2/dss/Kconfig
@@ -0,0 +1,90 @@
+menuconfig OMAP2_DSS
+ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
+ depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
+ default y
+ help
+ OMAP2/3/4 Display Subsystem support.
+
+if OMAP2_DSS
+
+config OMAP2_DSS_VRAM_SIZE
+ int "VRAM size (MB)"
+ range 0 32
+ default 4
+ help
+ The amount of SDRAM to reserve at boot time for video RAM use.
+ This VRAM will be used by omapfb and other drivers that need
+ large continuous RAM area for video use.
+
+ You can also set this with "vram=<bytes>" kernel argument, or
+ in the board file.
+
+config OMAP2_DSS_DEBUG_SUPPORT
+ bool "Debug support"
+ default y
+ help
+ This enables debug messages. You need to enable printing
+ with 'debug' module parameter.
+
+config OMAP2_DSS_RFBI
+ bool "RFBI support"
+ default n
+ help
+ MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
+
+config OMAP2_DSS_VENC
+ bool "VENC support"
+ default y
+ help
+ OMAP Video Encoder support.
+
+config OMAP2_DSS_SDI
+ bool "SDI support"
+ depends on ARCH_OMAP3
+ default n
+ help
+ SDI (Serial Display Interface) support.
+
+config OMAP2_DSS_DSI
+ bool "DSI support"
+ depends on ARCH_OMAP3 || ARCH_OMAP4
+ default n
+ help
+ MIPI DSI support.
+
+config OMAP2_DSS_USE_DSI_PLL
+ bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
+ default n
+ depends on OMAP2_DSS_DSI
+ help
+ Use DSI PLL to generate pixel clock. Currently only for DPI output.
+ DSI PLL can be used to generate higher and more precise pixel clocks.
+
+config OMAP2_DSS_FAKE_VSYNC
+ bool "Fake VSYNC irq from manual update displays"
+ default n
+ help
+ If this is selected, DSI will generate a fake DISPC VSYNC interrupt
+ when DSI has sent a frame. This is only needed with DSI or RFBI
+ displays using manual mode, and you want VSYNC to, for example,
+ time animation.
+
+config OMAP2_DSS_MIN_FCK_PER_PCK
+ int "Minimum FCK/PCK ratio (for scaling)"
+ range 0 32
+ default 0
+ help
+ This can be used to adjust the minimum FCK/PCK ratio.
+
+ With this you can make sure that DISPC FCK is at least
+ n x PCK. Video plane scaling requires higher FCK than
+ normally.
+
+ If this is set to 0, there's no extra constraint on the
+ DISPC FCK. However, the FCK will at minimum be
+ 2xPCK (if active matrix) or 3xPCK (if passive matrix).
+
+ Max FCK is 173MHz, so this doesn't work if your PCK
+ is very high.
+
+endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
new file mode 100644
index 000000000000..980c72c2db98
--- /dev/null
+++ b/drivers/video/omap2/dss/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_OMAP2_DSS) += omapdss.o
+omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
+omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
+omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
new file mode 100644
index 000000000000..89170ac8d251
--- /dev/null
+++ b/drivers/video/omap2/dss/core.c
@@ -0,0 +1,925 @@
+/*
+ * linux/drivers/video/omap2/dss/core.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "CORE"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/device.h>
+
+#include <mach/display.h>
+#include <mach/clock.h>
+
+#include "dss.h"
+
+static struct {
+ struct platform_device *pdev;
+ int ctx_id;
+
+ struct clk *dss_ick;
+ struct clk *dss1_fck;
+ struct clk *dss2_fck;
+ struct clk *dss_54m_fck;
+ struct clk *dss_96m_fck;
+ unsigned num_clks_enabled;
+} core;
+
+static void dss_clk_enable_all_no_ctx(void);
+static void dss_clk_disable_all_no_ctx(void);
+static void dss_clk_enable_no_ctx(enum dss_clock clks);
+static void dss_clk_disable_no_ctx(enum dss_clock clks);
+
+static char *def_disp_name;
+module_param_named(def_disp, def_disp_name, charp, 0);
+MODULE_PARM_DESC(def_disp_name, "default display name");
+
+#ifdef DEBUG
+unsigned int dss_debug;
+module_param_named(debug, dss_debug, bool, 0644);
+#endif
+
+/* CONTEXT */
+static int dss_get_ctx_id(void)
+{
+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+ int r;
+
+ if (!pdata->get_last_off_on_transaction_id)
+ return 0;
+ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
+ if (r < 0) {
+ dev_err(&core.pdev->dev, "getting transaction ID failed, "
+ "will force context restore\n");
+ r = -1;
+ }
+ return r;
+}
+
+int dss_need_ctx_restore(void)
+{
+ int id = dss_get_ctx_id();
+
+ if (id < 0 || id != core.ctx_id) {
+ DSSDBG("ctx id %d -> id %d\n",
+ core.ctx_id, id);
+ core.ctx_id = id;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void save_all_ctx(void)
+{
+ DSSDBG("save context\n");
+
+ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dss_save_context();
+ dispc_save_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_save_context();
+#endif
+
+ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+static void restore_all_ctx(void)
+{
+ DSSDBG("restore context\n");
+
+ dss_clk_enable_all_no_ctx();
+
+ dss_restore_context();
+ dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_restore_context();
+#endif
+
+ dss_clk_disable_all_no_ctx();
+}
+
+/* CLOCKS */
+void dss_dump_clocks(struct seq_file *s)
+{
+ int i;
+ struct clk *clocks[5] = {
+ core.dss_ick,
+ core.dss1_fck,
+ core.dss2_fck,
+ core.dss_54m_fck,
+ core.dss_96m_fck
+ };
+
+ seq_printf(s, "- dss -\n");
+
+ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
+
+ for (i = 0; i < 5; i++) {
+ if (!clocks[i])
+ continue;
+ seq_printf(s, "%-15s\t%lu\t%d\n",
+ clocks[i]->name,
+ clk_get_rate(clocks[i]),
+ clocks[i]->usecount);
+ }
+}
+
+static int dss_get_clock(struct clk **clock, const char *clk_name)
+{
+ struct clk *clk;
+
+ clk = clk_get(&core.pdev->dev, clk_name);
+
+ if (IS_ERR(clk)) {
+ DSSERR("can't get clock %s", clk_name);
+ return PTR_ERR(clk);
+ }
+
+ *clock = clk;
+
+ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
+
+ return 0;
+}
+
+static int dss_get_clocks(void)
+{
+ int r;
+
+ core.dss_ick = NULL;
+ core.dss1_fck = NULL;
+ core.dss2_fck = NULL;
+ core.dss_54m_fck = NULL;
+ core.dss_96m_fck = NULL;
+
+ r = dss_get_clock(&core.dss_ick, "ick");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&core.dss1_fck, "dss1_fck");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&core.dss2_fck, "dss2_fck");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&core.dss_96m_fck, "video_fck");
+ if (r)
+ goto err;
+
+ return 0;
+
+err:
+ if (core.dss_ick)
+ clk_put(core.dss_ick);
+ if (core.dss1_fck)
+ clk_put(core.dss1_fck);
+ if (core.dss2_fck)
+ clk_put(core.dss2_fck);
+ if (core.dss_54m_fck)
+ clk_put(core.dss_54m_fck);
+ if (core.dss_96m_fck)
+ clk_put(core.dss_96m_fck);
+
+ return r;
+}
+
+static void dss_put_clocks(void)
+{
+ if (core.dss_96m_fck)
+ clk_put(core.dss_96m_fck);
+ clk_put(core.dss_54m_fck);
+ clk_put(core.dss1_fck);
+ clk_put(core.dss2_fck);
+ clk_put(core.dss_ick);
+}
+
+unsigned long dss_clk_get_rate(enum dss_clock clk)
+{
+ switch (clk) {
+ case DSS_CLK_ICK:
+ return clk_get_rate(core.dss_ick);
+ case DSS_CLK_FCK1:
+ return clk_get_rate(core.dss1_fck);
+ case DSS_CLK_FCK2:
+ return clk_get_rate(core.dss2_fck);
+ case DSS_CLK_54M:
+ return clk_get_rate(core.dss_54m_fck);
+ case DSS_CLK_96M:
+ return clk_get_rate(core.dss_96m_fck);
+ }
+
+ BUG();
+ return 0;
+}
+
+static unsigned count_clk_bits(enum dss_clock clks)
+{
+ unsigned num_clks = 0;
+
+ if (clks & DSS_CLK_ICK)
+ ++num_clks;
+ if (clks & DSS_CLK_FCK1)
+ ++num_clks;
+ if (clks & DSS_CLK_FCK2)
+ ++num_clks;
+ if (clks & DSS_CLK_54M)
+ ++num_clks;
+ if (clks & DSS_CLK_96M)
+ ++num_clks;
+
+ return num_clks;
+}
+
+static void dss_clk_enable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_enable(core.dss_ick);
+ if (clks & DSS_CLK_FCK1)
+ clk_enable(core.dss1_fck);
+ if (clks & DSS_CLK_FCK2)
+ clk_enable(core.dss2_fck);
+ if (clks & DSS_CLK_54M)
+ clk_enable(core.dss_54m_fck);
+ if (clks & DSS_CLK_96M)
+ clk_enable(core.dss_96m_fck);
+
+ core.num_clks_enabled += num_clks;
+}
+
+void dss_clk_enable(enum dss_clock clks)
+{
+ dss_clk_enable_no_ctx(clks);
+
+ if (cpu_is_omap34xx() && dss_need_ctx_restore())
+ restore_all_ctx();
+ else if (cpu_is_omap44xx() && dss_need_ctx_restore())
+ restore_all_ctx();
+}
+
+static void dss_clk_disable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_disable(core.dss_ick);
+ if (clks & DSS_CLK_FCK1)
+ clk_disable(core.dss1_fck);
+ if (clks & DSS_CLK_FCK2)
+ clk_disable(core.dss2_fck);
+ if (clks & DSS_CLK_54M)
+ clk_disable(core.dss_54m_fck);
+ if (clks & DSS_CLK_96M)
+ clk_disable(core.dss_96m_fck);
+
+ core.num_clks_enabled -= num_clks;
+}
+
+void dss_clk_disable(enum dss_clock clks)
+{
+ if (cpu_is_omap34xx()) {
+ unsigned num_clks = count_clk_bits(clks);
+
+ BUG_ON(core.num_clks_enabled < num_clks);
+
+ if (core.num_clks_enabled == num_clks)
+ save_all_ctx();
+ }
+
+ dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_enable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ clks |= DSS_CLK_96M;
+ dss_clk_enable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ clks |= DSS_CLK_96M;
+ dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ clks |= DSS_CLK_96M;
+ dss_clk_disable(clks);
+}
+
+/* DEBUGFS */
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+static void dss_debug_dump_clocks(struct seq_file *s)
+{
+ dss_dump_clocks(s);
+ dispc_dump_clocks(s);
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_dump_clocks(s);
+#endif
+}
+
+static int dss_debug_show(struct seq_file *s, void *unused)
+{
+ void (*func)(struct seq_file *) = s->private;
+ func(s);
+ return 0;
+}
+
+static int dss_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dss_debug_show, inode->i_private);
+}
+
+static const struct file_operations dss_debug_fops = {
+ .open = dss_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *dss_debugfs_dir;
+
+static int dss_initialize_debugfs(void)
+{
+ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
+ if (IS_ERR(dss_debugfs_dir)) {
+ int err = PTR_ERR(dss_debugfs_dir);
+ dss_debugfs_dir = NULL;
+ return err;
+ }
+
+ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
+ &dss_debug_dump_clocks, &dss_debug_fops);
+
+ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
+ &dss_dump_regs, &dss_debug_fops);
+ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
+ &dispc_dump_regs, &dss_debug_fops);
+#ifdef CONFIG_OMAP2_DSS_RFBI
+ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
+ &rfbi_dump_regs, &dss_debug_fops);
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
+ &dsi_dump_regs, &dss_debug_fops);
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
+ &venc_dump_regs, &dss_debug_fops);
+#endif
+ return 0;
+}
+
+static void dss_uninitialize_debugfs(void)
+{
+ if (dss_debugfs_dir)
+ debugfs_remove_recursive(dss_debugfs_dir);
+}
+#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+
+/* PLATFORM DEVICE */
+static int omap_dss_probe(struct platform_device *pdev)
+{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+ int skip_init = 0;
+ int r;
+ int i;
+
+ core.pdev = pdev;
+
+ dss_init_overlay_managers(pdev);
+ dss_init_overlays(pdev);
+
+ /*
+ * FIX-ME: Replace with correct clk node when clk
+ * framework is available
+ */
+ if (!cpu_is_omap44xx()) {
+ r = dss_get_clocks();
+ if (r)
+ goto fail0;
+ }
+
+ dss_clk_enable_all_no_ctx();
+
+ core.ctx_id = dss_get_ctx_id();
+ DSSDBG("initial ctx id %u\n", core.ctx_id);
+
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ /* DISPC_CONTROL */
+ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
+ skip_init = 1;
+#endif
+
+ r = dss_init(skip_init);
+ if (r) {
+ DSSERR("Failed to initialize DSS\n");
+ goto fail0;
+ }
+
+#ifdef CONFIG_OMAP2_DSS_RFBI
+ r = rfbi_init();
+ if (r) {
+ DSSERR("Failed to initialize rfbi\n");
+ goto fail0;
+ }
+#endif
+
+ r = dpi_init();
+ if (r) {
+ DSSERR("Failed to initialize dpi\n");
+ goto fail0;
+ }
+
+ r = dispc_init();
+ if (r) {
+ DSSERR("Failed to initialize dispc\n");
+ goto fail0;
+ }
+#ifdef CONFIG_OMAP2_DSS_VENC
+ r = venc_init(pdev);
+ if (r) {
+ DSSERR("Failed to initialize venc\n");
+ goto fail0;
+ }
+#endif
+ if (cpu_is_omap34xx()) {
+#ifdef CONFIG_OMAP2_DSS_SDI
+ r = sdi_init(skip_init);
+ if (r) {
+ DSSERR("Failed to initialize SDI\n");
+ goto fail0;
+ }
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+ r = dsi_init(pdev);
+ if (r) {
+ DSSERR("Failed to initialize DSI\n");
+ goto fail0;
+ }
+#endif
+ }
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+ r = dss_initialize_debugfs();
+ if (r)
+ goto fail0;
+#endif
+
+ for (i = 0; i < pdata->num_devices; ++i) {
+ struct omap_dss_device *dssdev = pdata->devices[i];
+
+ r = omap_dss_register_device(dssdev);
+ if (r)
+ DSSERR("device reg failed %d\n", i);
+
+ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
+ pdata->default_device = dssdev;
+ }
+
+ dss_clk_disable_all();
+
+ return 0;
+
+ /* XXX fail correctly */
+fail0:
+ return r;
+}
+
+static int omap_dss_remove(struct platform_device *pdev)
+{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+ int i;
+ int c;
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+ dss_uninitialize_debugfs();
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+ venc_exit();
+#endif
+ dispc_exit();
+ dpi_exit();
+#ifdef CONFIG_OMAP2_DSS_RFBI
+ rfbi_exit();
+#endif
+ if (cpu_is_omap34xx()) {
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_exit();
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+ sdi_exit();
+#endif
+ }
+
+ dss_exit();
+
+ /* these should be removed at some point */
+ c = core.dss_ick->usecount;
+ if (c > 0) {
+ DSSERR("warning: dss_ick usecount %d, disabling\n", c);
+ while (c-- > 0)
+ clk_disable(core.dss_ick);
+ }
+
+ c = core.dss1_fck->usecount;
+ if (c > 0) {
+ DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
+ while (c-- > 0)
+ clk_disable(core.dss1_fck);
+ }
+
+ c = core.dss2_fck->usecount;
+ if (c > 0) {
+ DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
+ while (c-- > 0)
+ clk_disable(core.dss2_fck);
+ }
+
+ c = core.dss_54m_fck->usecount;
+ if (c > 0) {
+ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
+ while (c-- > 0)
+ clk_disable(core.dss_54m_fck);
+ }
+
+ if (core.dss_96m_fck) {
+ c = core.dss_96m_fck->usecount;
+ if (c > 0) {
+ DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
+ c);
+ while (c-- > 0)
+ clk_disable(core.dss_96m_fck);
+ }
+ }
+
+ dss_put_clocks();
+
+ dss_uninit_overlays(pdev);
+ dss_uninit_overlay_managers(pdev);
+
+ for (i = 0; i < pdata->num_devices; ++i)
+ omap_dss_unregister_device(pdata->devices[i]);
+
+ return 0;
+}
+
+static void omap_dss_shutdown(struct platform_device *pdev)
+{
+ DSSDBG("shutdown\n");
+}
+
+static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ DSSDBG("suspend %d\n", state.event);
+
+ return dss_suspend_all_devices();
+}
+
+static int omap_dss_resume(struct platform_device *pdev)
+{
+ DSSDBG("resume\n");
+
+ return dss_resume_all_devices();
+}
+
+static struct platform_driver omap_dss_driver = {
+ .probe = omap_dss_probe,
+ .remove = omap_dss_remove,
+ .shutdown = omap_dss_shutdown,
+ .suspend = omap_dss_suspend,
+ .resume = omap_dss_resume,
+ .driver = {
+ .name = "omapdss",
+ .owner = THIS_MODULE,
+ },
+};
+
+/* BUS */
+static int dss_bus_match(struct device *dev, struct device_driver *driver)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+ DSSDBG("bus_match. dev %s/%s, drv %s\n",
+ dev_name(dev), dssdev->driver_name, driver->name);
+
+ return strcmp(dssdev->driver_name, driver->name) == 0;
+}
+
+static ssize_t device_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ dssdev->name ?
+ dssdev->name : "");
+}
+
+static struct device_attribute default_dev_attrs[] = {
+ __ATTR(name, S_IRUGO, device_name_show, NULL),
+ __ATTR_NULL,
+};
+
+static ssize_t driver_name_show(struct device_driver *drv, char *buf)
+{
+ struct omap_dss_driver *dssdrv = to_dss_driver(drv);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ dssdrv->driver.name ?
+ dssdrv->driver.name : "");
+}
+static struct driver_attribute default_drv_attrs[] = {
+ __ATTR(name, S_IRUGO, driver_name_show, NULL),
+ __ATTR_NULL,
+};
+
+static struct bus_type dss_bus_type = {
+ .name = "omapdss",
+ .match = dss_bus_match,
+ .dev_attrs = default_dev_attrs,
+ .drv_attrs = default_drv_attrs,
+};
+
+static void dss_bus_release(struct device *dev)
+{
+ DSSDBG("bus_release\n");
+}
+
+static struct device dss_bus = {
+ .release = dss_bus_release,
+};
+
+struct bus_type *dss_get_bus(void)
+{
+ return &dss_bus_type;
+}
+
+/* DRIVER */
+static int dss_driver_probe(struct device *dev)
+{
+ int r;
+ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+ bool force;
+
+ DSSDBG("driver_probe: dev %s/%s, drv %s\n",
+ dev_name(dev), dssdev->driver_name,
+ dssdrv->driver.name);
+
+ dss_init_device(core.pdev, dssdev);
+
+ /* skip this if the device is behind a ctrl */
+ if (!dssdev->panel.ctrl) {
+ force = pdata->default_device == dssdev;
+ dss_recheck_connections(dssdev, force);
+ }
+
+ r = dssdrv->probe(dssdev);
+
+ if (r) {
+ DSSERR("driver probe failed: %d\n", r);
+ return r;
+ }
+
+ DSSDBG("probe done for device %s\n", dev_name(dev));
+
+ dssdev->driver = dssdrv;
+
+ return 0;
+}
+
+static int dss_driver_remove(struct device *dev)
+{
+ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
+ dssdev->driver_name);
+
+ dssdrv->remove(dssdev);
+
+ dss_uninit_device(core.pdev, dssdev);
+
+ dssdev->driver = NULL;
+
+ return 0;
+}
+
+int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
+{
+ dssdriver->driver.bus = &dss_bus_type;
+ dssdriver->driver.probe = dss_driver_probe;
+ dssdriver->driver.remove = dss_driver_remove;
+ return driver_register(&dssdriver->driver);
+}
+EXPORT_SYMBOL(omap_dss_register_driver);
+
+void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
+{
+ driver_unregister(&dssdriver->driver);
+}
+EXPORT_SYMBOL(omap_dss_unregister_driver);
+
+/* DEVICE */
+static void reset_device(struct device *dev, int check)
+{
+ u8 *dev_p = (u8 *)dev;
+ u8 *dev_end = dev_p + sizeof(*dev);
+ void *saved_pdata;
+
+ saved_pdata = dev->platform_data;
+ if (check) {
+ /*
+ * Check if there is any other setting than platform_data
+ * in struct device; warn that these will be reset by our
+ * init.
+ */
+ dev->platform_data = NULL;
+ while (dev_p < dev_end) {
+ if (*dev_p) {
+ WARN("%s: struct device fields will be "
+ "discarded\n",
+ __func__);
+ break;
+ }
+ dev_p++;
+ }
+ }
+ memset(dev, 0, sizeof(*dev));
+ dev->platform_data = saved_pdata;
+}
+
+
+static void omap_dss_dev_release(struct device *dev)
+{
+ reset_device(dev, 0);
+}
+
+int omap_dss_register_device(struct omap_dss_device *dssdev)
+{
+ static int dev_num;
+ static int panel_num;
+ int r;
+
+ WARN_ON(!dssdev->driver_name);
+
+ reset_device(&dssdev->dev, 1);
+ dssdev->dev.bus = &dss_bus_type;
+ dssdev->dev.parent = &dss_bus;
+ dssdev->dev.release = omap_dss_dev_release;
+ dev_set_name(&dssdev->dev, "display%d", dev_num++);
+ r = device_register(&dssdev->dev);
+ if (r)
+ return r;
+
+ if (dssdev->ctrl.panel) {
+ struct omap_dss_device *panel = dssdev->ctrl.panel;
+
+ panel->panel.ctrl = dssdev;
+
+ reset_device(&panel->dev, 1);
+ panel->dev.bus = &dss_bus_type;
+ panel->dev.parent = &dssdev->dev;
+ panel->dev.release = omap_dss_dev_release;
+ dev_set_name(&panel->dev, "panel%d", panel_num++);
+ r = device_register(&panel->dev);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+void omap_dss_unregister_device(struct omap_dss_device *dssdev)
+{
+ device_unregister(&dssdev->dev);
+
+ if (dssdev->ctrl.panel) {
+ struct omap_dss_device *panel = dssdev->ctrl.panel;
+ device_unregister(&panel->dev);
+ }
+}
+
+/* BUS */
+static int omap_dss_bus_register(void)
+{
+ int r;
+
+ r = bus_register(&dss_bus_type);
+ if (r) {
+ DSSERR("bus register failed\n");
+ return r;
+ }
+
+ dev_set_name(&dss_bus, "omapdss");
+ r = device_register(&dss_bus);
+ if (r) {
+ DSSERR("bus driver register failed\n");
+ bus_unregister(&dss_bus_type);
+ return r;
+ }
+
+ return 0;
+}
+
+/* INIT */
+
+#ifdef CONFIG_OMAP2_DSS_MODULE
+static void omap_dss_bus_unregister(void)
+{
+ device_unregister(&dss_bus);
+
+ bus_unregister(&dss_bus_type);
+}
+
+static int __init omap_dss_init(void)
+{
+ int r;
+
+ r = omap_dss_bus_register();
+ if (r)
+ return r;
+
+ r = platform_driver_register(&omap_dss_driver);
+ if (r) {
+ omap_dss_bus_unregister();
+ return r;
+ }
+
+ return 0;
+}
+
+static void __exit omap_dss_exit(void)
+{
+ platform_driver_unregister(&omap_dss_driver);
+
+ omap_dss_bus_unregister();
+}
+
+module_init(omap_dss_init);
+module_exit(omap_dss_exit);
+#else
+static int __init omap_dss_init(void)
+{
+ return omap_dss_bus_register();
+}
+
+static int __init omap_dss_init2(void)
+{
+ return platform_driver_register(&omap_dss_driver);
+}
+
+core_initcall(omap_dss_init);
+device_initcall(omap_dss_init2);
+#endif
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
new file mode 100644
index 000000000000..25aa9eac2040
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc.c
@@ -0,0 +1,4131 @@
+/*
+ * linux/drivers/video/omap2/dss/dispc.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPC"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+
+#include <mach/sram.h>
+#include <mach/board.h>
+#include <mach/clock.h>
+
+#include <mach/display.h>
+
+#include "dss.h"
+#include "../../../media/video/tiler/tiler.h"
+
+#ifndef CONFIG_ARCH_OMAP4
+ /* DSS */
+ #define DSS_BASE 0x48050000
+ /* DISPLAY CONTROLLER */
+ #define DISPC_BASE 0x48050400
+#else
+ /* DSS */
+ #define DSS_BASE 0x48042000
+ /* DISPLAY CONTROLLER */
+ #define DISPC_BASE 0x48043000
+#endif
+
+#define DISPC_SZ_REGS SZ_1K
+
+struct dispc_reg { u16 idx; };
+
+#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
+
+/* DISPC common */
+#define DISPC_REVISION DISPC_REG(0x0000)
+#define DISPC_SYSCONFIG DISPC_REG(0x0010)
+#define DISPC_SYSSTATUS DISPC_REG(0x0014)
+#define DISPC_IRQSTATUS DISPC_REG(0x0018)
+#define DISPC_IRQENABLE DISPC_REG(0x001C)
+#define DISPC_CONTROL DISPC_REG(0x0040)
+ /* DISPC_CONTROL1 in OMAP4 */
+#define DISPC_CONFIG DISPC_REG(0x0044)
+ /* DISPC_CONFIG1 in OMAP4 */
+#define DISPC_CAPABLE DISPC_REG(0x0048)
+#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
+#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
+#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
+#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
+#define DISPC_LINE_STATUS DISPC_REG(0x005C)
+#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
+#define DISPC_TIMING_H DISPC_REG(0x0064)
+ /* DISPC_TIMING_H1 in OMAP4 */
+#define DISPC_TIMING_V DISPC_REG(0x0068)
+ /* DISPC_TIMING_V1 in OMAP4 */
+#define DISPC_POL_FREQ DISPC_REG(0x006C)
+ /* DISPC_POL_FREQ1 in OMAP4 */
+
+#ifndef CONFIG_ARCH_OMAP4
+#define DISPC_DIVISOR DISPC_REG(0x0070)
+#else
+#define DISPC_DIVISOR DISPC_REG(0x0804)
+#define DISPC_DIVISOR1 DISPC_REG(0x0070)
+#endif
+
+#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
+#define DISPC_SIZE_DIG DISPC_REG(0x0078)
+ /* DISPC_SIZE_TV in OMAP4 */
+#define DISPC_SIZE_LCD DISPC_REG(0x007C)
+ /* DISPC_SIZE_LCD1 in OMAP4 */
+
+#ifdef CONFIG_ARCH_OMAP4
+#define DISPC_GLOBAL_BUFFER DISPC_REG(0x0800)
+#endif
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0 DISPC_REG(0x0080)
+#define DISPC_GFX_BA1 DISPC_REG(0x0084)
+#define DISPC_GFX_POSITION DISPC_REG(0x0088)
+#define DISPC_GFX_SIZE DISPC_REG(0x008C)
+#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
+#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
+ /* DISPC_GFX_BUF_THRESHOLD in OMAP4 */
+#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
+ /* DISPC_GFX_BUF_SIZE_STATUS in OMAP4 */
+#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
+#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
+#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
+#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
+
+#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
+ /* DISPC_DATA1_CYCLE1 in OMAP4 */
+#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
+ /* DISPC_DATA1_CYCLE2 in OMAP4 */
+#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
+ /* DISPC_DATA1_CYCLE3 in OMAP4 */
+
+#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
+ /* DISPC_CPR1_COEFF_R in OMAP4 */
+#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
+ /* DISPC_CPR1_COEFF_G in OMAP4 */
+#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
+ /* DISPC_CPR1_COEFF_B in OMAP4 */
+
+#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
+
+/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
+#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
+
+#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
+#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
+
+#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
+#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
+#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
+#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
+#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
+#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
+#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
+#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
+#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
+#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
+#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4} */
+#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
+
+#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
+
+#ifdef CONFIG_ARCH_OMAP4
+
+#define DISPC_CONTROL2 DISPC_REG(0x0238)
+
+/******** registers related to VID3 and WB pipelines ****/
+/* DISPC Video plane, n = 0 for VID3, n = 1 for WB _VID_V3_WB_ */
+#define DISPC_VID_V3_WB_REG(n, idx) DISPC_REG(0x0300 + (n)*0x200 + idx)
+
+#define DISPC_VID_V3_WB_ACCU0(n) DISPC_VID_V3_WB_REG(n, 0x0000)
+#define DISPC_VID_V3_WB_ACCU1(n) DISPC_VID_V3_WB_REG(n, 0x0004)
+
+#define DISPC_VID_V3_WB_BA0(n) DISPC_VID_V3_WB_REG(n, 0x0008)
+#define DISPC_VID_V3_WB_BA1(n) DISPC_VID_V3_WB_REG(n, 0x000C)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_V3_WB_FIR_COEF_H(n, i) DISPC_REG(0x0310+(n)*0x200+(i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_V3_WB_FIR_COEF_HV(n, i) DISPC_REG(0x0314+(n)*0x200+(i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_V3_WB_FIR_COEF_V(n, i) DISPC_REG(0x0350+(n)*0x200+(i)*0x4)
+
+#define DISPC_VID_V3_WB_ATTRIBUTES(n) DISPC_VID_V3_WB_REG(n, 0x0070)
+
+/* coef index i = {0, 1, 2, 3, 4} */
+#define DISPC_VID_V3_WB_CONV_COEF(n, i) DISPC_REG(0x0374 + (n)*0x200 + (i)*0x4)
+
+#define DISPC_VID_V3_WB_BUF_SIZE_STATUS(n) DISPC_VID_V3_WB_REG(n, 0x0088)
+#define DISPC_VID_V3_WB_BUF_THRESHOLD(n) DISPC_VID_V3_WB_REG(n, 0x008C)
+#define DISPC_VID_V3_WB_FIR(n) DISPC_VID_V3_WB_REG(n, 0x0090)
+#define DISPC_VID_V3_WB_PICTURE_SIZE(n) DISPC_VID_V3_WB_REG(n, 0x0094)
+#define DISPC_VID_V3_WB_PIXEL_INC(n) DISPC_VID_V3_WB_REG(n, 0x0098)
+
+#define DISPC_VID_VID3_POSITION DISPC_REG(0x039C)
+#define DISPC_VID_VID3_PRELOAD DISPC_REG(0x03A0)
+
+#define DISPC_VID_V3_WB_ROW_INC(n) DISPC_VID_V3_WB_REG(n, 0x00A4)
+#define DISPC_VID_V3_WB_SIZE(n) DISPC_VID_V3_WB_REG(n, 0x00A8)
+
+#define DISPC_VID_V3_WB_FIR2(n) DISPC_REG(0x0724 + (n)*0x6C)
+ /* n=0: VID3, n=1: WB*/
+
+#define DISPC_VID_V3_WB_ACCU2_0(n) DISPC_REG(0x0728 + (n)*0x6C)
+ /* n=0: VID3, n=1: WB*/
+#define DISPC_VID_V3_WB_ACCU2_1(n) DISPC_REG(0x072C + (n)*0x6C)
+ /* n=0: VID3, n=1: WB*/
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} n=0: VID3, n=1: WB */
+#define DISPC_VID_V3_WB_FIR_COEF_H2(n, i) DISPC_REG(0x0730+(n)*0x6C+(i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_V3_WB_FIR_COEF_HV2(n, i) DISPC_REG(0x0734+(n)*0x6C+(i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_V3_WB_FIR_COEF_V2(n, i) DISPC_REG(0x0770+(n)*0x6C+(i)*0x4)
+
+
+/*********End Vid3 and WB Registers ***************/
+
+/********** OMAP4 new global registers **/
+#define DISPC_DEFAULT_COLOR2 DISPC_REG(0x03AC)
+#define DISPC_TRANS_COLOR2 DISPC_REG(0x03B0)
+#define DISPC_CPR2_COEF_B DISPC_REG(0x03B4)
+#define DISPC_CPR2_COEF_G DISPC_REG(0x03B8)
+#define DISPC_CPR2_COEF_R DISPC_REG(0x03BC)
+#define DISPC_DATA2_CYCLE1 DISPC_REG(0x03C0)
+#define DISPC_DATA2_CYCLE2 DISPC_REG(0x03C4)
+#define DISPC_DATA2_CYCLE3 DISPC_REG(0x03C8)
+#define DISPC_SIZE_LCD2 DISPC_REG(0x03CC)
+#define DISPC_TIMING_H2 DISPC_REG(0x0400)
+#define DISPC_TIMING_V2 DISPC_REG(0x0404)
+#define DISPC_POL_FREQ2 DISPC_REG(0x0408)
+#define DISPC_DIVISOR2 DISPC_REG(0x040C)
+
+
+
+/* DISPC Video plane,
+ n = 0 for VID1
+ n = 1 for VID2
+ and n = 2 for VID3,
+ n = 3 for WB*/
+
+#define DISPC_VID_OMAP4_REG(n, idx) DISPC_REG(0x0600 + (n)*0x04 + idx)
+
+#define DISPC_VID_BA_UV0(n) DISPC_VID_OMAP4_REG((n)*2, 0x0000)
+#define DISPC_VID_BA_UV1(n) DISPC_VID_OMAP4_REG((n)*2, 0x0004)
+
+#define DISPC_CONFIG2 DISPC_REG(0x0620)
+
+#define DISPC_VID_ATTRIBUTES2(n) DISPC_VID_OMAP4_REG(n, 0x0024)
+ /* n = {0,1,2,3} */
+#define DISPC_GAMMA_TABLE(n) DISPC_VID_OMAP4_REG(n, 0x0030)
+ /* n = {0,1,2,3} */
+
+/* VID1/VID2 specific new registers */
+#define DISPC_VID_FIR2(n) DISPC_REG(0x063C + (n)*0x6C)
+ /* n=0: VID1, n=1: VID2*/
+
+#define DISPC_VID_ACCU2_0(n) DISPC_REG(0x0640 + (n)*0x6C)
+ /* n=0: VID1, n=1: VID2*/
+#define DISPC_VID_ACCU2_1(n) DISPC_REG(0x0644 + (n)*0x6C)
+ /* n=0: VID1, n=1: VID2*/
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} n=0: VID1, n=1: VID2 */
+#define DISPC_VID_FIR_COEF_H2(n, i) DISPC_REG(0x0648 + (n)*0x6C + (i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_HV2(n, i) DISPC_REG(0x064C + (n)*0x6C + (i)*0x8)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_V2(n, i) DISPC_REG(0x0688 + (n)*0x6C + (i)*0x4)
+
+/*end of VID1/VID2 specific new registers*/
+
+
+#endif
+
+
+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+ DISPC_IRQ_OCP_ERR | \
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+ DISPC_IRQ_SYNC_LOST | \
+ DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS 8
+
+struct omap_dispc_isr_data {
+ omap_dispc_isr_t isr;
+ void *arg;
+ u32 mask;
+};
+
+#define REG_GET(idx, start, end) \
+ FLD_GET(dispc_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
+
+static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
+ DISPC_VID_ATTRIBUTES(0),
+ DISPC_VID_ATTRIBUTES(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_ATTRIBUTES(0)/* VID 3 pipeline */
+#endif
+
+};
+
+static struct {
+ void __iomem *base;
+
+ struct clk *dpll4_m4_ck;
+
+ unsigned long cache_req_pck;
+ unsigned long cache_prate;
+ struct dispc_clock_info cache_cinfo;
+
+ u32 fifo_size[3];
+
+ spinlock_t irq_lock;
+ u32 irq_error_mask;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+ u32 error_irqs;
+ struct work_struct error_work;
+
+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+} dispc;
+
+static void _omap_dispc_set_irqs(void);
+
+static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
+{
+ __raw_writel(val, dispc.base + idx.idx);
+}
+
+static inline u32 dispc_read_reg(const struct dispc_reg idx)
+{
+ return __raw_readl(dispc.base + idx.idx);
+}
+
+static inline u8 calc_tiler_orientation(u8 rotation, u8 mir)
+{
+ static u8 orientation;
+ switch (rotation) {
+ case 0:
+ orientation = (mir ? 0x2 : 0x0);
+ break;
+ case 1:
+ orientation = (mir ? 0x7 : 0x6);
+ break;
+ case 2:
+ orientation = (mir ? 0x1 : 0x3);
+ break;
+ case 3:
+ orientation = (mir ? 0x4 : 0x5);
+ break;
+ }
+ return orientation;
+}
+
+#define SR(reg) \
+ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
+#define RR(reg) \
+ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
+
+void dispc_save_context(void)
+{
+ if (cpu_is_omap24xx())
+ return;
+
+ SR(SYSCONFIG);
+ SR(IRQENABLE);
+ SR(CONTROL);
+ SR(CONFIG);
+ SR(DEFAULT_COLOR0);
+ SR(DEFAULT_COLOR1);
+ SR(TRANS_COLOR0);
+ SR(TRANS_COLOR1);
+ SR(LINE_NUMBER);
+ SR(TIMING_H);
+ SR(TIMING_V);
+ SR(POL_FREQ);
+ SR(DIVISOR);
+ SR(GLOBAL_ALPHA);
+ SR(SIZE_DIG);
+ SR(SIZE_LCD);
+
+ SR(GFX_BA0);
+ SR(GFX_BA1);
+ SR(GFX_POSITION);
+ SR(GFX_SIZE);
+ SR(GFX_ATTRIBUTES);
+ SR(GFX_FIFO_THRESHOLD);
+ SR(GFX_ROW_INC);
+ SR(GFX_PIXEL_INC);
+ SR(GFX_WINDOW_SKIP);
+ SR(GFX_TABLE_BA);
+
+ SR(DATA_CYCLE1);
+ SR(DATA_CYCLE2);
+ SR(DATA_CYCLE3);
+
+ SR(CPR_COEF_R);
+ SR(CPR_COEF_G);
+ SR(CPR_COEF_B);
+
+ SR(GFX_PRELOAD);
+
+#ifdef CONFIG_ARCH_OMAP4
+/* TODO: find out what needs to be saved */
+#endif
+
+ /* VID1 */
+ SR(VID_BA0(0));
+ SR(VID_BA1(0));
+ SR(VID_POSITION(0));
+ SR(VID_SIZE(0));
+ SR(VID_ATTRIBUTES(0));
+ SR(VID_FIFO_THRESHOLD(0));
+ SR(VID_ROW_INC(0));
+ SR(VID_PIXEL_INC(0));
+ SR(VID_FIR(0));
+ SR(VID_PICTURE_SIZE(0));
+ SR(VID_ACCU0(0));
+ SR(VID_ACCU1(0));
+
+ SR(VID_FIR_COEF_H(0, 0));
+ SR(VID_FIR_COEF_H(0, 1));
+ SR(VID_FIR_COEF_H(0, 2));
+ SR(VID_FIR_COEF_H(0, 3));
+ SR(VID_FIR_COEF_H(0, 4));
+ SR(VID_FIR_COEF_H(0, 5));
+ SR(VID_FIR_COEF_H(0, 6));
+ SR(VID_FIR_COEF_H(0, 7));
+
+ SR(VID_FIR_COEF_HV(0, 0));
+ SR(VID_FIR_COEF_HV(0, 1));
+ SR(VID_FIR_COEF_HV(0, 2));
+ SR(VID_FIR_COEF_HV(0, 3));
+ SR(VID_FIR_COEF_HV(0, 4));
+ SR(VID_FIR_COEF_HV(0, 5));
+ SR(VID_FIR_COEF_HV(0, 6));
+ SR(VID_FIR_COEF_HV(0, 7));
+
+ SR(VID_CONV_COEF(0, 0));
+ SR(VID_CONV_COEF(0, 1));
+ SR(VID_CONV_COEF(0, 2));
+ SR(VID_CONV_COEF(0, 3));
+ SR(VID_CONV_COEF(0, 4));
+
+ SR(VID_FIR_COEF_V(0, 0));
+ SR(VID_FIR_COEF_V(0, 1));
+ SR(VID_FIR_COEF_V(0, 2));
+ SR(VID_FIR_COEF_V(0, 3));
+ SR(VID_FIR_COEF_V(0, 4));
+ SR(VID_FIR_COEF_V(0, 5));
+ SR(VID_FIR_COEF_V(0, 6));
+ SR(VID_FIR_COEF_V(0, 7));
+
+ SR(VID_PRELOAD(0));
+
+ /* VID2 */
+ SR(VID_BA0(1));
+ SR(VID_BA1(1));
+ SR(VID_POSITION(1));
+ SR(VID_SIZE(1));
+ SR(VID_ATTRIBUTES(1));
+ SR(VID_FIFO_THRESHOLD(1));
+ SR(VID_ROW_INC(1));
+ SR(VID_PIXEL_INC(1));
+ SR(VID_FIR(1));
+ SR(VID_PICTURE_SIZE(1));
+ SR(VID_ACCU0(1));
+ SR(VID_ACCU1(1));
+
+ SR(VID_FIR_COEF_H(1, 0));
+ SR(VID_FIR_COEF_H(1, 1));
+ SR(VID_FIR_COEF_H(1, 2));
+ SR(VID_FIR_COEF_H(1, 3));
+ SR(VID_FIR_COEF_H(1, 4));
+ SR(VID_FIR_COEF_H(1, 5));
+ SR(VID_FIR_COEF_H(1, 6));
+ SR(VID_FIR_COEF_H(1, 7));
+
+ SR(VID_FIR_COEF_HV(1, 0));
+ SR(VID_FIR_COEF_HV(1, 1));
+ SR(VID_FIR_COEF_HV(1, 2));
+ SR(VID_FIR_COEF_HV(1, 3));
+ SR(VID_FIR_COEF_HV(1, 4));
+ SR(VID_FIR_COEF_HV(1, 5));
+ SR(VID_FIR_COEF_HV(1, 6));
+ SR(VID_FIR_COEF_HV(1, 7));
+
+ SR(VID_CONV_COEF(1, 0));
+ SR(VID_CONV_COEF(1, 1));
+ SR(VID_CONV_COEF(1, 2));
+ SR(VID_CONV_COEF(1, 3));
+ SR(VID_CONV_COEF(1, 4));
+
+ SR(VID_FIR_COEF_V(1, 0));
+ SR(VID_FIR_COEF_V(1, 1));
+ SR(VID_FIR_COEF_V(1, 2));
+ SR(VID_FIR_COEF_V(1, 3));
+ SR(VID_FIR_COEF_V(1, 4));
+ SR(VID_FIR_COEF_V(1, 5));
+ SR(VID_FIR_COEF_V(1, 6));
+ SR(VID_FIR_COEF_V(1, 7));
+
+ SR(VID_PRELOAD(1));
+}
+
+void dispc_restore_context(void)
+{
+ RR(SYSCONFIG);
+ RR(IRQENABLE);
+ /*RR(CONTROL);*/
+ RR(CONFIG);
+ RR(DEFAULT_COLOR0);
+ RR(DEFAULT_COLOR1);
+ RR(TRANS_COLOR0);
+ RR(TRANS_COLOR1);
+ RR(LINE_NUMBER);
+ RR(TIMING_H);
+ RR(TIMING_V);
+ RR(POL_FREQ);
+ RR(DIVISOR);
+ RR(GLOBAL_ALPHA);
+ RR(SIZE_DIG);
+ RR(SIZE_LCD);
+
+#ifdef CONFIG_ARCH_OMAP4
+ /* TODO: find out what needs to be saved/restored */
+#endif
+
+ RR(GFX_BA0);
+ RR(GFX_BA1);
+ RR(GFX_POSITION);
+ RR(GFX_SIZE);
+ RR(GFX_ATTRIBUTES);
+ RR(GFX_FIFO_THRESHOLD);
+ RR(GFX_ROW_INC);
+ RR(GFX_PIXEL_INC);
+ RR(GFX_WINDOW_SKIP);
+ RR(GFX_TABLE_BA);
+
+ RR(DATA_CYCLE1);
+ RR(DATA_CYCLE2);
+ RR(DATA_CYCLE3);
+
+ RR(CPR_COEF_R);
+ RR(CPR_COEF_G);
+ RR(CPR_COEF_B);
+
+ RR(GFX_PRELOAD);
+
+ /* VID1 */
+ RR(VID_BA0(0));
+ RR(VID_BA1(0));
+ RR(VID_POSITION(0));
+ RR(VID_SIZE(0));
+ RR(VID_ATTRIBUTES(0));
+ RR(VID_FIFO_THRESHOLD(0));
+ RR(VID_ROW_INC(0));
+ RR(VID_PIXEL_INC(0));
+ RR(VID_FIR(0));
+ RR(VID_PICTURE_SIZE(0));
+ RR(VID_ACCU0(0));
+ RR(VID_ACCU1(0));
+
+ RR(VID_FIR_COEF_H(0, 0));
+ RR(VID_FIR_COEF_H(0, 1));
+ RR(VID_FIR_COEF_H(0, 2));
+ RR(VID_FIR_COEF_H(0, 3));
+ RR(VID_FIR_COEF_H(0, 4));
+ RR(VID_FIR_COEF_H(0, 5));
+ RR(VID_FIR_COEF_H(0, 6));
+ RR(VID_FIR_COEF_H(0, 7));
+
+ RR(VID_FIR_COEF_HV(0, 0));
+ RR(VID_FIR_COEF_HV(0, 1));
+ RR(VID_FIR_COEF_HV(0, 2));
+ RR(VID_FIR_COEF_HV(0, 3));
+ RR(VID_FIR_COEF_HV(0, 4));
+ RR(VID_FIR_COEF_HV(0, 5));
+ RR(VID_FIR_COEF_HV(0, 6));
+ RR(VID_FIR_COEF_HV(0, 7));
+
+ RR(VID_CONV_COEF(0, 0));
+ RR(VID_CONV_COEF(0, 1));
+ RR(VID_CONV_COEF(0, 2));
+ RR(VID_CONV_COEF(0, 3));
+ RR(VID_CONV_COEF(0, 4));
+
+ RR(VID_FIR_COEF_V(0, 0));
+ RR(VID_FIR_COEF_V(0, 1));
+ RR(VID_FIR_COEF_V(0, 2));
+ RR(VID_FIR_COEF_V(0, 3));
+ RR(VID_FIR_COEF_V(0, 4));
+ RR(VID_FIR_COEF_V(0, 5));
+ RR(VID_FIR_COEF_V(0, 6));
+ RR(VID_FIR_COEF_V(0, 7));
+
+ RR(VID_PRELOAD(0));
+
+ /* VID2 */
+ RR(VID_BA0(1));
+ RR(VID_BA1(1));
+ RR(VID_POSITION(1));
+ RR(VID_SIZE(1));
+ RR(VID_ATTRIBUTES(1));
+ RR(VID_FIFO_THRESHOLD(1));
+ RR(VID_ROW_INC(1));
+ RR(VID_PIXEL_INC(1));
+ RR(VID_FIR(1));
+ RR(VID_PICTURE_SIZE(1));
+ RR(VID_ACCU0(1));
+ RR(VID_ACCU1(1));
+
+ RR(VID_FIR_COEF_H(1, 0));
+ RR(VID_FIR_COEF_H(1, 1));
+ RR(VID_FIR_COEF_H(1, 2));
+ RR(VID_FIR_COEF_H(1, 3));
+ RR(VID_FIR_COEF_H(1, 4));
+ RR(VID_FIR_COEF_H(1, 5));
+ RR(VID_FIR_COEF_H(1, 6));
+ RR(VID_FIR_COEF_H(1, 7));
+
+ RR(VID_FIR_COEF_HV(1, 0));
+ RR(VID_FIR_COEF_HV(1, 1));
+ RR(VID_FIR_COEF_HV(1, 2));
+ RR(VID_FIR_COEF_HV(1, 3));
+ RR(VID_FIR_COEF_HV(1, 4));
+ RR(VID_FIR_COEF_HV(1, 5));
+ RR(VID_FIR_COEF_HV(1, 6));
+ RR(VID_FIR_COEF_HV(1, 7));
+
+ RR(VID_CONV_COEF(1, 0));
+ RR(VID_CONV_COEF(1, 1));
+ RR(VID_CONV_COEF(1, 2));
+ RR(VID_CONV_COEF(1, 3));
+ RR(VID_CONV_COEF(1, 4));
+
+ RR(VID_FIR_COEF_V(1, 0));
+ RR(VID_FIR_COEF_V(1, 1));
+ RR(VID_FIR_COEF_V(1, 2));
+ RR(VID_FIR_COEF_V(1, 3));
+ RR(VID_FIR_COEF_V(1, 4));
+ RR(VID_FIR_COEF_V(1, 5));
+ RR(VID_FIR_COEF_V(1, 6));
+ RR(VID_FIR_COEF_V(1, 7));
+
+ RR(VID_PRELOAD(1));
+
+ /* enable last, because LCD & DIGIT enable are here */
+ RR(CONTROL);
+}
+
+#undef SR
+#undef RR
+
+static inline void enable_clocks(bool enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+bool dispc_go_busy(enum omap_channel channel)
+{
+ int bit;
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel != OMAP_DSS_CHANNEL_DIGIT)
+#else
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+#endif
+ bit = 5; /* GOLCD */
+ else
+ bit = 6; /* GODIGIT */
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
+ return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
+ else
+#endif
+ return REG_GET(DISPC_CONTROL, bit, bit) == 1;
+}
+
+void dispc_go(enum omap_channel channel)
+{
+ int bit;
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel != OMAP_DSS_CHANNEL_DIGIT)
+#else
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+#endif
+ bit = 0; /* LCDENABLE */
+ else
+ bit = 1; /* DIGITALENABLE */
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
+ REG_FLD_MOD(DISPC_CONTROL2, 1, 0, 0);
+ else
+ REG_FLD_MOD(DISPC_CONTROL, 1, 0, 0);
+
+ /* if the channel is not enabled, we don't need GO
+ //CLEAN UP: REMOVE THIS IF NOT NEEDED
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
+ goto end;
+ */
+#endif
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
+ goto end;
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel != OMAP_DSS_CHANNEL_DIGIT)
+#else
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+#endif
+ bit = 5; /* GOLCD */
+ else
+ bit = 6; /* GODIGIT */
+
+#ifndef CONFIG_ARCH_OMAP4
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+ DSSERR("GO bit not down for channel %d\n", channel);
+ goto end;
+ }
+
+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
+
+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+#else
+ if (channel == OMAP_DSS_CHANNEL_LCD2) {
+ if (REG_GET(DISPC_CONTROL2, bit, bit) == 1) {
+ DSSERR("GO bit not down for channel %d\n", channel);
+ goto end;
+ }
+ DSSDBG("GO LCD2\n");
+ REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
+ } else {
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+ DSSERR("GO bit not down for channel %d\n", channel);
+ goto end;
+ }
+
+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ?
+ "LCD" : "DIGIT");
+
+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+ }
+#endif
+
+end:
+ enable_clocks(0);
+}
+
+static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+#ifdef CONFIG_ARCH_OMAP4
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+#endif
+ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
+#ifdef CONFIG_ARCH_OMAP4
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_H(0, reg), value);
+#endif
+
+}
+
+static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+#ifdef CONFIG_ARCH_OMAP4
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+#endif
+ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
+#ifdef CONFIG_ARCH_OMAP4
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_HV(0, reg), value);
+#endif
+}
+
+static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+#ifdef CONFIG_ARCH_OMAP4
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+#endif
+
+ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
+#ifdef CONFIG_ARCH_OMAP4
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_V(0, reg), value);
+#endif
+}
+
+#ifdef CONFIG_ARCH_OMAP4
+static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+ dispc_write_reg(DISPC_VID_FIR_COEF_H2(plane-1, reg), value);
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_H2(0, reg), value);
+
+}
+
+static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+ dispc_write_reg(DISPC_VID_FIR_COEF_HV2(plane-1, reg), value);
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_HV2(0, reg), value);
+}
+
+static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ if ((OMAP_DSS_VIDEO1 == plane) || (OMAP_DSS_VIDEO2 == plane))
+ dispc_write_reg(DISPC_VID_FIR_COEF_V2(plane-1, reg), value);
+ else if (OMAP_DSS_VIDEO3 == plane)
+ dispc_write_reg(DISPC_VID_V3_WB_FIR_COEF_V2(0, reg), value);
+}
+#endif
+
+
+static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
+ int vscaleup, int five_taps)
+{
+ /* Coefficients for horizontal up-sampling */
+ static const u32 coef_hup[8] = {
+ 0x00800000,
+ 0x0D7CF800,
+ 0x1E70F5FF,
+ 0x335FF5FE,
+ 0xF74949F7,
+ 0xF55F33FB,
+ 0xF5701EFE,
+ 0xF87C0DFF,
+ };
+
+ /* Coefficients for horizontal down-sampling */
+ static const u32 coef_hdown[8] = {
+ 0x24382400,
+ 0x28371FFE,
+ 0x2C361BFB,
+ 0x303516F9,
+ 0x11343311,
+ 0x1635300C,
+ 0x1B362C08,
+ 0x1F372804,
+ };
+
+ /* Coefficients for horizontal and vertical up-sampling */
+ static const u32 coef_hvup[2][8] = {
+ {
+ 0x00800000,
+ 0x037B02FF,
+ 0x0C6F05FE,
+ 0x205907FB,
+ 0x00404000,
+ 0x075920FE,
+ 0x056F0CFF,
+ 0x027B0300,
+ },
+ {
+ 0x00800000,
+ 0x0D7CF8FF,
+ 0x1E70F5FE,
+ 0x335FF5FB,
+ 0xF7404000,
+ 0xF55F33FE,
+ 0xF5701EFF,
+ 0xF87C0D00,
+ },
+ };
+
+ /* Coefficients for horizontal and vertical down-sampling */
+ static const u32 coef_hvdown[2][8] = {
+ {
+ 0x24382400,
+ 0x28391F04,
+ 0x2D381B08,
+ 0x3237170C,
+ 0x123737F7,
+ 0x173732F9,
+ 0x1B382DFB,
+ 0x1F3928FE,
+ },
+ {
+ 0x24382400,
+ 0x28371F04,
+ 0x2C361B08,
+ 0x3035160C,
+ 0x113433F7,
+ 0x163530F9,
+ 0x1B362CFB,
+ 0x1F3728FE,
+ },
+ };
+
+ /* Coefficients for vertical up-sampling */
+ static const u32 coef_vup[8] = {
+ 0x00000000,
+ 0x0000FF00,
+ 0x0000FEFF,
+ 0x0000FBFE,
+ 0x000000F7,
+ 0x0000FEFB,
+ 0x0000FFFE,
+ 0x000000FF,
+ };
+
+
+ /* Coefficients for vertical down-sampling */
+ static const u32 coef_vdown[8] = {
+ 0x00000000,
+ 0x000004FE,
+ 0x000008FB,
+ 0x00000CF9,
+ 0x0000F711,
+ 0x0000F90C,
+ 0x0000FB08,
+ 0x0000FE04,
+ };
+
+ const u32 *h_coef;
+ const u32 *hv_coef;
+ const u32 *hv_coef_mod;
+ const u32 *v_coef;
+ int i;
+
+ if (hscaleup)
+ h_coef = coef_hup;
+ else
+ h_coef = coef_hdown;
+
+ if (vscaleup) {
+ hv_coef = coef_hvup[five_taps];
+ v_coef = coef_vup;
+
+ if (hscaleup)
+ hv_coef_mod = NULL;
+ else
+ hv_coef_mod = coef_hvdown[five_taps];
+ } else {
+ hv_coef = coef_hvdown[five_taps];
+ v_coef = coef_vdown;
+
+ if (hscaleup)
+ hv_coef_mod = coef_hvup[five_taps];
+ else
+ hv_coef_mod = NULL;
+ }
+
+ for (i = 0; i < 8; i++) {
+ u32 h, hv;
+
+ h = h_coef[i];
+
+ hv = hv_coef[i];
+
+ if (hv_coef_mod) {
+ hv &= 0xffffff00;
+ hv |= (hv_coef_mod[i] & 0xff);
+ }
+
+ _dispc_write_firh_reg(plane, i, h);
+ _dispc_write_firhv_reg(plane, i, hv);
+ }
+
+ if (!five_taps)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ u32 v;
+ v = v_coef[i];
+ _dispc_write_firv_reg(plane, i, v);
+ }
+}
+
+static void _dispc_setup_color_conv_coef(void)
+{
+ const struct color_conv_coef {
+ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
+ int full_range;
+ } ctbl_bt601_5 = {
+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+ };
+
+ const struct color_conv_coef *ct;
+
+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
+
+ ct = &ctbl_bt601_5;
+
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
+
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
+
+#ifdef CONFIG_ARCH_OMAP4
+ dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 0),
+ CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 1),
+ CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 2),
+ CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 3),
+ CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 4),
+ CVAL(0, ct->bcb));
+
+ REG_FLD_MOD(DISPC_VID_V3_WB_ATTRIBUTES(0), ct->full_range, 11, 11);
+#endif
+
+#undef CVAL
+
+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
+}
+
+
+static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
+ DISPC_VID_BA0(0),
+ DISPC_VID_BA0(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_BA0(0) /* VID 3 pipeline*/
+#endif
+ };
+
+ dispc_write_reg(ba0_reg[plane], paddr);
+}
+
+static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
+ DISPC_VID_BA1(0),
+ DISPC_VID_BA1(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_BA1(0) /* VID 3 pipeline*/
+#endif
+
+ };
+
+ dispc_write_reg(ba1_reg[plane], paddr);
+}
+
+#ifdef CONFIG_ARCH_OMAP4
+static void _dispc_set_plane_ba_uv0(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba_uv0_reg[] = { DISPC_VID_BA_UV0(0),
+ DISPC_VID_BA_UV0(1),
+ DISPC_VID_BA_UV0(2) /* VID 3 pipeline*/
+ };
+
+ u32 val = 0;
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ dispc_write_reg(ba_uv0_reg[plane - 1], paddr);
+ /* plane - 1 => no UV_BA for GFX*/
+
+}
+
+static void _dispc_set_plane_ba_uv1(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba_uv1_reg[] = { DISPC_VID_BA_UV1(0),
+ DISPC_VID_BA_UV1(1),
+ DISPC_VID_BA_UV1(2)
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ dispc_write_reg(ba_uv1_reg[plane - 1], paddr);
+ /* plane - 1 => no UV_BA for GFX*/
+}
+
+#endif
+
+static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
+{
+ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
+ DISPC_VID_POSITION(0),
+ DISPC_VID_POSITION(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_VID3_POSITION /* VID 3 pipeline*/
+#endif
+
+ };
+
+ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+ dispc_write_reg(pos_reg[plane], val);
+}
+
+static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
+{
+ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
+ DISPC_VID_PICTURE_SIZE(0),
+ DISPC_VID_PICTURE_SIZE(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_PICTURE_SIZE(0) /* VID 3 pipeline*/
+#endif
+
+ };
+ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dispc_write_reg(siz_reg[plane], val);
+}
+
+static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+{
+ u32 val;
+ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
+ DISPC_VID_SIZE(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_SIZE(0) /* VID 3 pipeline*/
+#endif
+
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dispc_write_reg(vsi_reg[plane-1], val);
+}
+
+static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+{
+#ifndef CONFIG_ARCH_OMAP4 /* all pipelines have alpha coeff in OMAP4 */
+ BUG_ON(plane == OMAP_DSS_VIDEO1);
+#endif
+ if (plane == OMAP_DSS_GFX)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
+ else if (plane == OMAP_DSS_VIDEO2)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
+#ifdef CONFIG_ARCH_OMAP4
+ else if (plane == OMAP_DSS_VIDEO1)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 15, 8);
+ else if (plane == OMAP_DSS_VIDEO3)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 31, 24);
+#endif
+
+}
+
+static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+{
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
+ DISPC_VID_PIXEL_INC(0),
+ DISPC_VID_PIXEL_INC(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_PIXEL_INC(0) /* VID 3 pipeline*/
+#endif
+
+ };
+
+ dispc_write_reg(ri_reg[plane], inc);
+}
+
+static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
+{
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
+ DISPC_VID_ROW_INC(0),
+ DISPC_VID_ROW_INC(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_ROW_INC(0) /* VID 3 pipeline*/
+#endif
+
+ };
+
+ dispc_write_reg(ri_reg[plane], inc);
+}
+
+static void _dispc_set_color_mode(enum omap_plane plane,
+ enum omap_color_mode color_mode)
+{
+ u32 m = 0;
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_GFX == plane) {
+#endif
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_CLUT1:
+ m = 0x0; break;
+ case OMAP_DSS_COLOR_CLUT2:
+ m = 0x1; break;
+ case OMAP_DSS_COLOR_CLUT4:
+ m = 0x2; break;
+ case OMAP_DSS_COLOR_CLUT8:
+ m = 0x3; break;
+ case OMAP_DSS_COLOR_RGB12U:
+ m = 0x4; break;
+ case OMAP_DSS_COLOR_ARGB16:
+ m = 0x5; break;
+ case OMAP_DSS_COLOR_RGB16:
+ m = 0x6; break;
+ case OMAP_DSS_COLOR_RGB24U:
+ m = 0x8; break;
+ case OMAP_DSS_COLOR_RGB24P:
+ m = 0x9; break;
+ case OMAP_DSS_COLOR_YUV2:
+ m = 0xa; break;
+ case OMAP_DSS_COLOR_UYVY:
+ m = 0xb; break;
+ case OMAP_DSS_COLOR_ARGB32:
+ m = 0xc; break;
+ case OMAP_DSS_COLOR_RGBA32:
+ m = 0xd; break;
+ case OMAP_DSS_COLOR_RGBX32:
+ m = 0xe; break;
+
+ default:
+ BUG(); break;
+ }
+#ifdef CONFIG_ARCH_OMAP4
+ } else {
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_NV12:
+ m = 0x0; break;
+ case OMAP_DSS_COLOR_RGB12U:
+ m = 0x1; break;
+ case OMAP_DSS_COLOR_RGBA12:
+ m = 0x2; break;
+ case OMAP_DSS_COLOR_XRGB12:
+ m = 0x4; break;
+ case OMAP_DSS_COLOR_ARGB16:
+ m = 0x5; break;
+ case OMAP_DSS_COLOR_RGB16:
+ m = 0x6; break;
+ case OMAP_DSS_COLOR_ARGB16_1555:
+ m = 0x7; break;
+ case OMAP_DSS_COLOR_RGB24U:
+ m = 0x8; break;
+ case OMAP_DSS_COLOR_RGB24P:
+ m = 0x9; break;
+ case OMAP_DSS_COLOR_YUV2:
+ m = 0xA; break;
+ case OMAP_DSS_COLOR_UYVY:
+ m = 0xB; break;
+ case OMAP_DSS_COLOR_ARGB32:
+ m = 0xC; break;
+ case OMAP_DSS_COLOR_RGBA32:
+ m = 0xD; break;
+ case OMAP_DSS_COLOR_RGBX24_32_ALGN:
+ m = 0xE; break;
+ case OMAP_DSS_COLOR_XRGB15:
+ m = 0xF; break;
+ default:
+ BUG(); break;
+ }
+ }
+#endif
+ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
+}
+
+static void _dispc_set_channel_out(enum omap_plane plane,
+ enum omap_channel channel)
+{
+ int shift;
+ u32 val;
+
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ shift = 8;
+ break;
+ case OMAP_DSS_VIDEO1:
+ case OMAP_DSS_VIDEO2:
+#ifdef CONFIG_ARCH_OMAP4
+ case OMAP_DSS_VIDEO3: /* VID 3 pipeline*/
+#endif
+ shift = 16;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, channel, shift, shift);
+ dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_set_burst_size(enum omap_plane plane,
+ enum omap_burst_size burst_size)
+{
+ int shift;
+ u32 val;
+
+ enable_clocks(1);
+
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ shift = 6;
+ break;
+ case OMAP_DSS_VIDEO1:
+ case OMAP_DSS_VIDEO2:
+#ifdef CONFIG_ARCH_OMAP4
+ case OMAP_DSS_VIDEO3: /* VID 3 pipeline*/
+#endif
+ shift = 14;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, burst_size, shift+1, shift);
+ dispc_write_reg(dispc_reg_att[plane], val);
+
+ enable_clocks(0);
+}
+
+#ifdef CONFIG_ARCH_OMAP4
+void dispc_set_zorder(enum omap_plane plane,
+ enum omap_overlay_zorder zorder)
+{
+ u32 val;
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, zorder, 27, 26);
+ dispc_write_reg(dispc_reg_att[plane], val);
+
+}
+void dispc_enable_zorder(enum omap_plane plane, bool enable)
+{
+ u32 val;
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, enable, 25, 25);
+ dispc_write_reg(dispc_reg_att[plane], val);
+
+}
+
+#endif
+
+static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
+{
+ u32 val;
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, enable, 9, 9);
+ dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_enable_replication(enum omap_plane plane, bool enable)
+{
+ int bit;
+
+ if (plane == OMAP_DSS_GFX)
+ bit = 5;
+ else
+ bit = 10;
+
+ enable_clocks(1);
+ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
+ enable_clocks(0);
+}
+
+void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
+{
+ u32 val;
+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ dispc_write_reg(DISPC_SIZE_LCD2, val);
+ else
+#endif
+ dispc_write_reg(DISPC_SIZE_LCD, val);
+ enable_clocks(0);
+}
+
+void dispc_set_digit_size(u16 width, u16 height)
+{
+ u32 val;
+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
+ dispc_write_reg(DISPC_SIZE_DIG, val);
+ enable_clocks(0);
+}
+
+
+static void dispc_read_plane_fifo_sizes(void)
+{
+ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+ DISPC_VID_FIFO_SIZE_STATUS(0),
+ DISPC_VID_FIFO_SIZE_STATUS(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_BUF_SIZE_STATUS(0)
+ /* VID 3 pipeline*/
+#endif
+
+ };
+ u32 size;
+ int plane;
+
+ enable_clocks(1);
+
+ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+ if (cpu_is_omap24xx())
+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
+ else if (cpu_is_omap34xx())
+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
+ else if (cpu_is_omap44xx())
+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 15, 0);
+ else
+ BUG();
+ dispc.fifo_size[plane] = size;
+ }
+
+ enable_clocks(0);
+}
+
+u32 dispc_get_plane_fifo_size(enum omap_plane plane)
+{
+ return dispc.fifo_size[plane];
+}
+
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+{
+ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+ DISPC_VID_FIFO_THRESHOLD(0),
+ DISPC_VID_FIFO_THRESHOLD(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_BUF_THRESHOLD(0)
+ /* VID 3 pipeline*/
+#endif
+
+ };
+ enable_clocks(1);
+
+ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
+ plane,
+ REG_GET(ftrs_reg[plane], 11, 0),
+ REG_GET(ftrs_reg[plane], 27, 16),
+ low, high);
+
+ if (cpu_is_omap24xx())
+ dispc_write_reg(ftrs_reg[plane],
+ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
+ else if (cpu_is_omap34xx())
+ dispc_write_reg(ftrs_reg[plane],
+ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
+ else /* cpu is omap44xx */
+ dispc_write_reg(ftrs_reg[plane],
+ FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
+
+ enable_clocks(0);
+}
+
+void dispc_enable_fifomerge(bool enable)
+{
+ enable_clocks(1);
+
+ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
+
+ enable_clocks(0);
+}
+
+static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
+{
+ u32 val;
+ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
+ DISPC_VID_FIR(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_FIR(0)
+ /* VID 3 pipeline*/
+#endif
+
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ if (cpu_is_omap24xx())
+ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
+ else
+ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+ dispc_write_reg(fir_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
+ DISPC_VID_ACCU0(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_ACCU0(0)
+ /* VID 3 pipeline*/
+#endif
+
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+ if (cpu_is_omap44xx())
+ val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+ else
+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+ dispc_write_reg(ac0_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
+ DISPC_VID_ACCU1(1)
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_VID_V3_WB_ACCU1(0) /* VID 3 pipeline*/
+#endif
+
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+ if (cpu_is_omap44xx())
+ val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+ else
+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+ dispc_write_reg(ac1_reg[plane-1], val);
+}
+
+#ifdef CONFIG_ARCH_OMAP4
+static void _dispc_set_fir2(enum omap_plane plane, int hinc, int vinc)
+{
+ u32 val;
+ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR2(0),
+ DISPC_VID_FIR2(1),
+ DISPC_VID_V3_WB_FIR2(0)
+ /* VID 3 pipeline*/
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+
+ dispc_write_reg(fir_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU2_0(0),
+ DISPC_VID_ACCU2_0(1),
+ DISPC_VID_V3_WB_ACCU2_0(0)
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+ dispc_write_reg(ac0_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU2_1(0),
+ DISPC_VID_ACCU2_1(1),
+ DISPC_VID_V3_WB_ACCU2_1(0)
+ };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+ dispc_write_reg(ac1_reg[plane-1], val);
+}
+
+#endif
+
+static void _dispc_set_scaling(enum omap_plane plane,
+ u16 orig_width, u16 orig_height,
+ u16 out_width, u16 out_height,
+ bool ilace, bool five_taps,
+ bool fieldmode)
+{
+ int fir_hinc;
+ int fir_vinc;
+ int hscaleup, vscaleup;
+ int accu0 = 0;
+ int accu1 = 0;
+ u32 l;
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ hscaleup = orig_width <= out_width;
+ vscaleup = orig_height <= out_height;
+
+ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
+
+ if (!orig_width || orig_width == out_width)
+ fir_hinc = 0;
+ else
+ fir_hinc = 1024 * orig_width / out_width;
+
+ if (!orig_height || orig_height == out_height)
+ fir_vinc = 0;
+ else
+ fir_vinc = 1024 * orig_height / out_height;
+
+ _dispc_set_fir(plane, fir_hinc, fir_vinc);
+
+ l = dispc_read_reg(dispc_reg_att[plane]);
+ l &= ~((0x0f << 5) | (0x1 << 21));
+
+ l |= fir_hinc ? (1 << 5) : 0;
+ l |= fir_vinc ? (1 << 6) : 0;
+
+ l |= hscaleup ? 0 : (1 << 7);
+ l |= vscaleup ? 0 : (1 << 8);
+
+ l |= five_taps ? (1 << 21) : 0;
+
+ dispc_write_reg(dispc_reg_att[plane], l);
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ if (ilace && !fieldmode) {
+ accu1 = 0;
+ accu0 = (fir_vinc / 2) & 0x3ff;
+ if (accu0 >= 1024/2) {
+ accu1 = 1024/2;
+ accu0 -= accu1;
+ }
+ }
+
+ _dispc_set_vid_accu0(plane, 0, accu0);
+ _dispc_set_vid_accu1(plane, 0, accu1);
+}
+
+static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ bool mirroring, enum omap_color_mode color_mode)
+{
+#ifndef CONFIG_ARCH_OMAP4
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY) {
+ int vidrot = 0;
+
+ if (mirroring) {
+ switch (rotation) {
+ case 0:
+ vidrot = 2;
+ break;
+ case 1:
+ vidrot = 1;
+ break;
+ case 2:
+ vidrot = 0;
+ break;
+ case 3:
+ vidrot = 3;
+ break;
+ }
+ } else {
+ switch (rotation) {
+ case 0:
+ vidrot = 0;
+ break;
+ case 1:
+ vidrot = 1;
+ break;
+ case 2:
+ vidrot = 2;
+ break;
+ case 3:
+ vidrot = 3;
+ break;
+ }
+ }
+
+ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
+
+ if (rotation == 1 || rotation == 3)
+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
+ else
+ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
+ } else {
+ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
+ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
+ }
+#else
+ if (plane != OMAP_DSS_GFX) {
+ if (color_mode == OMAP_DSS_COLOR_NV12) {
+ /* DOUBLESTRIDE : 0 for 90-, 270-; 1 for 0- and 180- */
+ if (rotation == 1 || rotation == 3)
+ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 22, 22);
+ else
+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 22, 22);
+ }
+ }
+
+ /* Set the rotation value for pipeline */
+/* REG_FLD_MOD(dispc_reg_att[plane], rotation, 13, 12); */
+#endif
+}
+
+static s32 pixinc(int pixels, u8 ps)
+{
+ if (pixels == 1)
+ return 1;
+ else if (pixels > 1)
+ return 1 + (pixels - 1) * ps;
+ else if (pixels < 0)
+ return 1 - (-pixels + 1) * ps;
+ else
+ BUG();
+}
+
+static void calc_tiler_row_rotation(u8 rotation,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode,
+ s32 *row_inc)
+{
+ u8 ps = 1;
+ DSSDBG("calc_tiler_rot(%d): %dx%d\n", rotation, width, height);
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ ps = 4;
+ break;
+
+ case OMAP_DSS_COLOR_NV12:
+ ps = 1;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ switch (rotation) {
+ case 0:
+ case 2:
+ if (1 == ps)
+ *row_inc = 16384 + 1 - (width);
+ else
+ *row_inc = 32768 + 1 - (width * ps);
+ break;
+
+ case 1:
+ case 3:
+ if (4 == ps)
+ *row_inc = 16384 + 1 - (width * ps);
+ else
+ *row_inc = 8192 + 1 - (width * ps);
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ printk(KERN_INFO
+ " colormode: %d, rotation: %d, ps: %d, width: %d,"
+ " height: %d, row_inc:%d\n",
+ color_mode, rotation, ps, width, height, *row_inc);
+
+ return;
+}
+
+static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+{
+ u8 ps;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ ps = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ ps = 3;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 4;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+ width, height);
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ case 2:
+ /*
+ * If the pixel format is YUV or UYVY divide the width
+ * of the image by 2 for 0 and 180 degree rotation.
+ */
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width = width >> 1;
+ case 1:
+ case 3:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+
+ *row_inc = pixinc(1 + (screen_width - width) +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ case 4:
+ case 6:
+ /* If the pixel format is YUV or UYVY divide the width
+ * of the image by 2 for 0 degree and 180 degree
+ */
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width = width >> 1;
+ case 5:
+ case 7:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+ *row_inc = pixinc(1 - (screen_width + width) -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+{
+ u8 ps;
+ u16 fbw, fbh;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ ps = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ ps = 3;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ ps = 4;
+ break;
+
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 2;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+ width, height);
+
+ /* width & height are overlay sizes, convert to fb sizes */
+
+ if (rotation == 0 || rotation == 2) {
+ fbw = width;
+ fbh = height;
+ } else {
+ fbw = height;
+ fbh = width;
+ }
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(1 + (screen_width - fbw) +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+ case 1:
+ *offset1 = screen_width * (fbh - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(-screen_width, ps);
+ break;
+ case 2:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-1 -
+ (screen_width - fbw) -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(-1, ps);
+ break;
+ case 3:
+ *offset1 = (fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(screen_width, ps);
+ break;
+
+ /* mirroring */
+ case 0 + 4:
+ *offset1 = (fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * 2 - 1 +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(-1, ps);
+ break;
+
+ case 1 + 4:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0),
+ ps);
+ *pix_inc = pixinc(screen_width, ps);
+ break;
+
+ case 2 + 4:
+ *offset1 = screen_width * (fbh - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(1 - screen_width * 2 -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ case 3 + 4:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0),
+ ps);
+ *pix_inc = pixinc(-screen_width, ps);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static unsigned long calc_fclk_five_taps(enum omap_channel channel,
+ u16 width, u16 height, u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode)
+{
+ u32 fclk = 0;
+ /* FIXME venc pclk? */
+ u64 tmp, pclk = dispc_pclk_rate(channel);
+
+ if (height > out_height) {
+ /* FIXME get real display PPL */
+ unsigned int ppl = 800;
+
+ tmp = pclk * height * out_width;
+ do_div(tmp, 2 * out_height * ppl);
+ fclk = tmp;
+
+ if (height > 2 * out_height && ppl != out_width) {
+ tmp = pclk * (height - 2 * out_height) * out_width;
+ do_div(tmp, 2 * out_height * (ppl - out_width));
+ fclk = max(fclk, (u32) tmp);
+ }
+ }
+
+ if (width > out_width) {
+ tmp = pclk * width;
+ do_div(tmp, out_width);
+ fclk = max(fclk, (u32) tmp);
+
+ if (color_mode == OMAP_DSS_COLOR_RGB24U)
+ fclk <<= 1;
+ }
+
+ return fclk;
+}
+
+static unsigned long calc_fclk(enum omap_channel channel, u16 width,
+ u16 height, u16 out_width, u16 out_height)
+{
+ unsigned int hf, vf;
+
+ /*
+ * FIXME how to determine the 'A' factor
+ * for the no downscaling case ?
+ */
+
+ if (width > 3 * out_width)
+ hf = 4;
+ else if (width > 2 * out_width)
+ hf = 3;
+ else if (width > out_width)
+ hf = 2;
+ else
+ hf = 1;
+
+ if (height > out_height)
+ vf = 2;
+ else
+ vf = 1;
+
+ /* FIXME venc pclk? */
+ return dispc_pclk_rate(channel) * vf * hf;
+}
+
+void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
+{
+ enable_clocks(1);
+ _dispc_set_channel_out(plane, channel_out);
+ enable_clocks(0);
+}
+
+
+
+static int _dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, int mirror,
+ u8 global_alpha, enum omap_channel channel
+#ifdef CONFIG_ARCH_OMAP4
+ , u32 puv_addr
+#endif
+ )
+{
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+ bool five_taps = 0;
+ bool fieldmode = 0;
+ int cconv = 0;
+ unsigned offset0, offset1;
+ s32 row_inc;
+ s32 pix_inc;
+ u16 frame_height = height;
+ unsigned int field_offset = 0;
+
+ u8 orientation = 0;
+ struct dmmViewOrientT orient;
+
+ if (paddr == 0)
+ return -EINVAL;
+
+ if (ilace && height == out_height)
+ fieldmode = 1;
+
+ if (ilace) {
+ if (fieldmode)
+ height /= 2;
+ pos_y /= 2;
+ out_height /= 2;
+
+ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
+ "out_height %d\n",
+ height, pos_y, out_height);
+ }
+
+ if (plane == OMAP_DSS_GFX) {
+ if (width != out_width || height != out_height)
+ return -EINVAL;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ } else {
+ /* video plane */
+
+ unsigned long fclk = 0;
+
+ if (out_width < width / maxdownscale ||
+ out_width > width * 8)
+ return -EINVAL;
+
+ if (out_height < height / maxdownscale ||
+ out_height > height * 8)
+ return -EINVAL;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_RGB24U:
+#ifndef CONFIG_ARCH_OMAP4
+ case OMAP_DSS_COLOR_RGBX32:
+#endif
+ break;
+
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+#ifdef CONFIG_ARCH_OMAP4
+ case OMAP_DSS_COLOR_RGBA12:
+ case OMAP_DSS_COLOR_XRGB12:
+ case OMAP_DSS_COLOR_ARGB16_1555:
+ case OMAP_DSS_COLOR_RGBX24_32_ALGN:
+ case OMAP_DSS_COLOR_XRGB15:
+#else
+ if (plane == OMAP_DSS_VIDEO1)
+ return -EINVAL;
+#endif
+ break;
+
+#ifdef CONFIG_ARCH_OMAP4
+ case OMAP_DSS_COLOR_NV12:
+#endif
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ cconv = 1;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Must use 5-tap filter? */
+ five_taps = height > out_height * 2;
+
+ if (!five_taps) {
+ fclk = calc_fclk(channel, width, height,
+ out_width, out_height);
+
+ /* Try 5-tap filter if 3-tap fclk is too high */
+ if (cpu_is_omap34xx() && height > out_height &&
+ fclk > dispc_fclk_rate())
+ five_taps = true;
+ }
+
+ if (width > (2048 >> five_taps))
+ return -EINVAL;
+
+ if (five_taps)
+ fclk = calc_fclk_five_taps(channel, width, height,
+ out_width, out_height, color_mode);
+
+ DSSDBG("required fclk rate = %lu Hz\n", fclk);
+ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+
+ if (fclk > dispc_fclk_rate())
+ return -EINVAL;
+ }
+
+ if (ilace && !fieldmode) {
+ /*
+ * when downscaling the bottom field may have to start several
+ * source lines below the top field. Unfortunately ACCUI
+ * registers will only hold the fractional part of the offset
+ * so the integer part must be added to the base address of the
+ * bottom field.
+ */
+ if (!height || height == out_height)
+ field_offset = 0;
+ else
+ field_offset = height / out_height / 2;
+ }
+
+ /* Fields are independent but interleaved in memory. */
+ if (fieldmode)
+ field_offset = 1;
+#ifdef CONFIG_ARCH_OMAP4 /*TODO: OMAP4: check ?! */
+ pix_inc = 0x1;
+ offset0 = 0x0;
+ offset1 = 0x0;
+ /* check if tiler address; else set row_inc = 1*/
+ if ((paddr >= 0x60000000) && (paddr <= 0x7fffffff)) {
+ calc_tiler_row_rotation(rotation, width, frame_height,
+ color_mode, &row_inc);
+
+ orientation = calc_tiler_orientation(rotation, (u8)mirror);
+#if 1
+ paddr &= ~(0x7 << 29);
+ paddr |= (orientation << 29);
+ if (puv_addr) {
+ puv_addr &= ~(0x7 << 29);
+ puv_addr |= (orientation << 29);
+ }
+#else
+ orient.dmm90Rotate = ((orientation & 0x04) ? 1 : 0);
+ orient.dmmYInvert = ((orientation & 0x02) ? 1 : 0);
+ orient.dmmXInvert = ((orientation & 0x01) ? 1 : 0);
+
+ paddr = tiler_get_tiler_address(paddr, orient, width,
+ frame_height, 0, 0);
+
+ if (puv_addr)
+ puv_addr = tiler_get_tiler_address(puv_addr,
+ orient, width, frame_height,
+ 1, 0);
+#endif
+
+
+ printk(KERN_INFO
+ "rotated addresses: 0x%0x, 0x%0x\n",
+ paddr, puv_addr);
+ /* set BURSTTYPE if rotation is non-zero */
+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 29, 29);
+
+ } else
+ row_inc = 0x1;
+
+#else
+ if (rotation_type == OMAP_DSS_ROT_DMA)
+ calc_dma_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+ else
+ calc_vrfb_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+#endif
+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+ offset0, offset1, row_inc, pix_inc);
+
+ _dispc_set_color_mode(plane, color_mode);
+
+ _dispc_set_plane_ba0(plane, paddr + offset0);
+ _dispc_set_plane_ba1(plane, paddr + offset1);
+#ifdef CONFIG_ARCH_OMAP4
+ /* TODO: check the offset calculations? */
+ if (OMAP_DSS_COLOR_NV12 == color_mode) {
+ _dispc_set_plane_ba_uv0(plane, puv_addr + offset0);
+ _dispc_set_plane_ba_uv1(plane, puv_addr + offset1);
+ }
+#endif
+ _dispc_set_row_inc(plane, row_inc);
+ _dispc_set_pix_inc(plane, pix_inc);
+
+ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
+ out_width, out_height);
+
+ _dispc_set_plane_pos(plane, pos_x, pos_y);
+
+ _dispc_set_pic_size(plane, width, height);
+
+ if (plane != OMAP_DSS_GFX) {
+ _dispc_set_scaling(plane, width, height,
+ out_width, out_height,
+ ilace, five_taps, fieldmode);
+ _dispc_set_vid_size(plane, out_width, out_height);
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+
+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+
+#ifndef CONFIG_ARCH_OMAP4
+ if (plane != OMAP_DSS_VIDEO1)
+#endif
+ _dispc_setup_global_alpha(plane, global_alpha);
+
+ pix_inc = dispc_read_reg(dispc_reg_att[plane]);
+ DSSDBG("vid[%d] attributes = %x\n", plane, pix_inc);
+
+ return 0;
+}
+
+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
+}
+
+static void dispc_disable_isr(void *data, u32 mask)
+{
+ struct completion *compl = data;
+ complete(compl);
+}
+
+static void _enable_lcd_out(enum omap_channel channel, bool enable)
+{
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
+ else
+#endif
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
+}
+
+void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
+{
+ struct completion frame_done_completion;
+ bool is_on;
+ int r;
+ int irq;
+
+ enable_clocks(1);
+
+ /* When we disable LCD output, we need to wait until frame is done.
+ * Otherwise the DSS is still working, and turning off the clocks
+ * prevents DSS from going to OFF mode */
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel) {
+ is_on = REG_GET(DISPC_CONTROL2, 0, 0);
+ irq = DISPC_IRQ_FRAMEDONE2;
+ } else
+#endif
+ {
+ is_on = REG_GET(DISPC_CONTROL, 0, 0);
+ irq = DISPC_IRQ_FRAMEDONE;
+ }
+
+ if (!enable && is_on) {
+ init_completion(&frame_done_completion);
+
+ r = omap_dispc_register_isr(dispc_disable_isr,
+ &frame_done_completion,
+ irq);
+
+ if (r)
+ DSSERR("failed to register FRAMEDONE isr\n");
+ }
+
+ _enable_lcd_out(channel, enable);
+
+ if (!enable && is_on) {
+ if (!wait_for_completion_timeout(&frame_done_completion,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for FRAME DONE\n");
+
+ r = omap_dispc_unregister_isr(dispc_disable_isr,
+ &frame_done_completion,
+ irq);
+
+ if (r)
+ DSSERR("failed to unregister FRAMEDONE isr\n");
+ }
+
+ enable_clocks(0);
+}
+
+static void _enable_digit_out(bool enable)
+{
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
+}
+
+void dispc_enable_digit_out(bool enable)
+{
+ struct completion frame_done_completion;
+ int r;
+
+ enable_clocks(1);
+
+ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
+ enable_clocks(0);
+ return;
+ }
+
+ if (enable) {
+ unsigned long flags;
+ /* When we enable digit output, we'll get an extra digit
+ * sync lost interrupt, that we need to ignore */
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
+ _omap_dispc_set_irqs();
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ /* When we disable digit output, we need to wait until fields are done.
+ * Otherwise the DSS is still working, and turning off the clocks
+ * prevents DSS from going to OFF mode. And when enabling, we need to
+ * wait for the extra sync losts */
+ init_completion(&frame_done_completion);
+
+ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+ if (r)
+ DSSERR("failed to register EVSYNC isr\n");
+
+ _enable_digit_out(enable);
+
+ /* XXX I understand from TRM that we should only wait for the
+ * current field to complete. But it seems we have to wait
+ * for both fields */
+ if (!wait_for_completion_timeout(&frame_done_completion,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for EVSYNC\n");
+
+ if (!wait_for_completion_timeout(&frame_done_completion,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for EVSYNC\n");
+
+ r = omap_dispc_unregister_isr(dispc_disable_isr,
+ &frame_done_completion,
+ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+ if (r)
+ DSSERR("failed to unregister EVSYNC isr\n");
+
+ if (enable) {
+ unsigned long flags;
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+ _omap_dispc_set_irqs();
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ enable_clocks(0);
+}
+
+void dispc_lcd_enable_signal_polarity(bool act_high)
+{
+ enable_clocks(1);
+ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+ enable_clocks(0);
+}
+
+void dispc_lcd_enable_signal(bool enable)
+{
+ enable_clocks(1);
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+ enable_clocks(0);
+}
+
+void dispc_pck_free_enable(bool enable)
+{
+ enable_clocks(1);
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+ enable_clocks(0);
+}
+
+void dispc_enable_fifohandcheck(bool enable)
+{
+ enable_clocks(1);
+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
+ enable_clocks(0);
+}
+
+
+void dispc_set_lcd_display_type(enum omap_channel channel,
+ enum omap_lcd_display_type type)
+{
+ int mode;
+
+ switch (type) {
+ case OMAP_DSS_LCD_DISPLAY_STN:
+ mode = 0;
+ break;
+
+ case OMAP_DSS_LCD_DISPLAY_TFT:
+ mode = 1;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
+ else
+#endif
+ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
+ enable_clocks(0);
+}
+
+void dispc_set_loadmode(enum omap_dss_load_mode mode)
+{
+ enable_clocks(1);
+ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+ enable_clocks(0);
+}
+
+
+void dispc_set_default_color(enum omap_channel channel, u32 color)
+{
+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
+ DISPC_DEFAULT_COLOR1
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_DEFAULT_COLOR2
+#endif
+ };
+
+ enable_clocks(1);
+ dispc_write_reg(def_reg[channel], color);
+ enable_clocks(0);
+}
+
+u32 dispc_get_default_color(enum omap_channel channel)
+{
+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
+ DISPC_DEFAULT_COLOR1
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_DEFAULT_COLOR2
+#endif
+};
+
+ u32 l;
+
+#ifndef CONFIG_ARCH_OMAP4
+ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
+ channel != OMAP_DSS_CHANNEL_LCD);
+#endif
+
+ enable_clocks(1);
+ l = dispc_read_reg(def_reg[channel]);
+ enable_clocks(0);
+
+ return l;
+}
+
+void dispc_set_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type type,
+ u32 trans_key)
+{
+ const struct dispc_reg tr_reg[] = {
+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_TRANS_COLOR2
+#endif
+
+ };
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (ch == OMAP_DSS_CHANNEL_LCD2)
+ REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
+ else
+#endif
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
+
+ dispc_write_reg(tr_reg[ch], trans_key);
+ enable_clocks(0);
+}
+
+void dispc_get_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type *type,
+ u32 *trans_key)
+{
+ const struct dispc_reg tr_reg[] = {
+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1
+#ifdef CONFIG_ARCH_OMAP4
+ , DISPC_TRANS_COLOR2
+#endif
+
+ };
+
+ enable_clocks(1);
+ if (type) {
+#ifdef CONFIG_ARCH_OMAP4
+ if (ch == OMAP_DSS_CHANNEL_LCD2)
+ *type = REG_GET(DISPC_CONFIG2, 11, 11);
+ else
+#endif
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ *type = REG_GET(DISPC_CONFIG, 11, 11);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ *type = REG_GET(DISPC_CONFIG, 13, 13);
+ else
+ BUG();
+ }
+
+ if (trans_key)
+ *trans_key = dispc_read_reg(tr_reg[ch]);
+ enable_clocks(0);
+}
+
+void dispc_enable_trans_key(enum omap_channel ch, bool enable)
+{
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (ch == OMAP_DSS_CHANNEL_LCD2)
+ REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
+ else
+#endif
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
+ enable_clocks(0);
+}
+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
+{
+ enable_clocks(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
+ enable_clocks(0);
+}
+bool dispc_alpha_blending_enabled(enum omap_channel ch)
+{
+ bool enabled;
+#ifdef CONFIG_ARCH_OMAP4
+ BUG_ON(ch == OMAP_DSS_CHANNEL_LCD2);
+#endif
+ enable_clocks(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else
+ BUG();
+ enable_clocks(0);
+
+ return enabled;
+
+}
+
+
+bool dispc_trans_key_enabled(enum omap_channel ch)
+{
+ bool enabled;
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (ch == OMAP_DSS_CHANNEL_LCD2)
+ enabled = REG_GET(DISPC_CONFIG2, 10, 10);
+ else
+#endif
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ enabled = REG_GET(DISPC_CONFIG, 10, 10);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 12, 12);
+ else
+ BUG();
+ enable_clocks(0);
+
+ return enabled;
+}
+
+
+void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+{
+ int code;
+
+ switch (data_lines) {
+ case 12:
+ code = 0;
+ break;
+ case 16:
+ code = 1;
+ break;
+ case 18:
+ code = 2;
+ break;
+ case 24:
+ code = 3;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
+ REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
+ else
+#endif
+ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
+ enable_clocks(0);
+}
+
+void dispc_set_parallel_interface_mode(enum omap_channel channel,
+ enum omap_parallel_interface_mode mode)
+{
+ u32 l;
+ int stallmode;
+ int gpout0 = 1;
+ int gpout1;
+
+ switch (mode) {
+ case OMAP_DSS_PARALLELMODE_BYPASS:
+ stallmode = 0;
+ gpout1 = 1;
+ break;
+
+ case OMAP_DSS_PARALLELMODE_RFBI:
+ stallmode = 1;
+ gpout1 = 0;
+ break;
+
+ case OMAP_DSS_PARALLELMODE_DSI:
+ stallmode = 1;
+ gpout1 = 1;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel) {
+ l = dispc_read_reg(DISPC_CONTROL2);
+
+ printk(KERN_INFO "OMAP DISPCONTROL read (stallmode)%d\n",
+ FLD_GET(l, 11, 11));
+
+ l = FLD_MOD(l, stallmode, 11, 11);
+
+ dispc_write_reg(DISPC_CONTROL2, l);
+
+ } else
+#endif
+ {
+ l = dispc_read_reg(DISPC_CONTROL);
+
+ printk(KERN_INFO "OMAP DISPCONTROL read (stallmode)%d\n",
+ FLD_GET(l, 11, 11));
+ printk(KERN_INFO "OMAP DISPCONTROL read (gpout)%d\n",
+ FLD_GET(l, 15, 15));
+ printk(KERN_INFO "OMAP DISPCONTROL read (stallmode)%d\n",
+ FLD_GET(l, 16, 16));
+
+
+ l = FLD_MOD(l, stallmode, 11, 11);
+ l = FLD_MOD(l, gpout0, 15, 15);
+ l = FLD_MOD(l, gpout1, 16, 16);
+
+ dispc_write_reg(DISPC_CONTROL, l);
+ }
+ enable_clocks(0);
+}
+
+static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
+ int vsw, int vfp, int vbp)
+{
+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+ if (hsw < 1 || hsw > 64 ||
+ hfp < 1 || hfp > 256 ||
+ hbp < 1 || hbp > 256 ||
+ vsw < 1 || vsw > 64 ||
+ vfp < 0 || vfp > 255 ||
+ vbp < 0 || vbp > 255)
+ return false;
+ } else {
+ if (hsw < 1 || hsw > 256 ||
+ hfp < 1 || hfp > 4096 ||
+ hbp < 1 || hbp > 4096 ||
+ vsw < 1 || vsw > 256 ||
+ vfp < 0 || vfp > 4095 ||
+ vbp < 0 || vbp > 4095)
+ return false;
+ }
+
+ return true;
+}
+
+bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
+{
+
+ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
+ timings->hbp, timings->vsw,
+ timings->vfp, timings->vbp);
+}
+
+static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
+ int hfp, int hbp, int vsw, int vfp, int vbp)
+{
+ u32 timing_h, timing_v;
+
+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
+ FLD_VAL(hbp-1, 27, 20);
+
+ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
+ FLD_VAL(vbp, 27, 20);
+ } else {
+
+ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
+ FLD_VAL(hbp-1, 31, 20);
+
+ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
+ FLD_VAL(vbp, 31, 20);
+ }
+ enable_clocks(1);
+
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel) {
+ dispc_write_reg(DISPC_TIMING_H2, timing_h);
+ dispc_write_reg(DISPC_TIMING_V2, timing_v);
+ } else
+#endif
+ {
+ dispc_write_reg(DISPC_TIMING_H, timing_h);
+ dispc_write_reg(DISPC_TIMING_V, timing_v);
+ }
+ enable_clocks(0);
+}
+
+
+void dispc_set_lcd_timings(enum omap_channel channel,
+ struct omap_video_timings *timings)
+{
+ unsigned xtot, ytot;
+ unsigned long ht, vt;
+
+ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
+ timings->hbp, timings->vsw,
+ timings->vfp, timings->vbp))
+ BUG();
+
+ _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
+ timings->hbp, timings->vsw, timings->vfp,
+ timings->vbp);
+
+ dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
+
+ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
+ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
+
+ ht = (timings->pixel_clock * 1000) / xtot;
+ vt = (timings->pixel_clock * 1000) / xtot / ytot;
+
+ DSSDBG("channel %u xres %u yres %u\n", channel, timings->x_res,
+ timings->y_res);
+ DSSDBG("pck %u\n", timings->pixel_clock);
+ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
+ timings->hsw, timings->hfp, timings->hbp,
+ timings->vsw, timings->vfp, timings->vbp);
+
+ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
+}
+
+void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
+ u16 pck_div)
+{
+ BUG_ON(lck_div < 1);
+ BUG_ON(pck_div < 2);
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ dispc_write_reg(DISPC_DIVISOR2,
+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+ else
+ dispc_write_reg(DISPC_DIVISOR1,
+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+#else
+ dispc_write_reg(DISPC_DIVISOR,
+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+#endif
+ enable_clocks(0);
+}
+
+static void dispc_get_lcd_divisor(enum omap_channel channel,
+ int *lck_div, int *pck_div)
+{
+ u32 l;
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ l = dispc_read_reg(DISPC_DIVISOR2);
+ else
+ l = dispc_read_reg(DISPC_DIVISOR1);
+#else
+ l = dispc_read_reg(DISPC_DIVISOR);
+#endif
+ *lck_div = FLD_GET(l, 23, 16);
+ *pck_div = FLD_GET(l, 7, 0);
+}
+
+/* TODO: Check with Senthil on handling of clocks */
+unsigned long dispc_fclk_rate(void)
+{
+ unsigned long r = 0;
+
+ if (dss_get_dispc_clk_source() == 0)
+ r = dss_clk_get_rate(DSS_CLK_FCK1);
+ else
+#ifdef CONFIG_OMAP2_DSS_DSI
+ r = dsi_get_dsi1_pll_rate();
+#else
+ BUG();
+#endif
+ return r;
+}
+
+unsigned long dispc_lclk_rate(enum omap_channel channel)
+{
+ int lcd;
+ unsigned long r;
+ u32 l;
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ l = dispc_read_reg(DISPC_DIVISOR2);
+ else
+ l = dispc_read_reg(DISPC_DIVISOR1);
+#else
+ l = dispc_read_reg(DISPC_DIVISOR);
+#endif
+ lcd = FLD_GET(l, 23, 16);
+
+ r = dispc_fclk_rate();
+
+ return r / lcd;
+}
+
+unsigned long dispc_pclk_rate(enum omap_channel channel)
+{
+ int lcd, pcd;
+ unsigned long r;
+ u32 l;
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2 == channel)
+ l = dispc_read_reg(DISPC_DIVISOR2);
+ else
+ l = dispc_read_reg(DISPC_DIVISOR1);
+#else
+ l = dispc_read_reg(DISPC_DIVISOR);
+#endif
+ lcd = FLD_GET(l, 23, 16);
+ pcd = FLD_GET(l, 7, 0);
+
+ r = dispc_fclk_rate();
+
+ return r / lcd / pcd;
+}
+
+void dispc_dump_clocks(struct seq_file *s)
+{
+ int lcd, pcd;
+
+ enable_clocks(1);
+
+ dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
+
+ seq_printf(s, "- dispc -\n");
+
+ seq_printf(s, "dispc fclk source = %s\n",
+ dss_get_dispc_clk_source() == 0 ?
+ "dss1_alwon_fclk" : "dsi1_pll_fclk");
+
+ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
+ dispc_fclk_rate(),
+ lcd, pcd,
+ dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD));
+
+#ifdef CONFIG_ARCH_OMAP4
+ dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
+
+ seq_printf(s, "- dispc -\n");
+
+ seq_printf(s, "dispc fclk source = %s\n",
+ dss_get_dispc_clk_source() == 0 ?
+ "dss1_alwon_fclk" : "dsi1_pll_fclk");
+
+ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
+ dispc_fclk_rate(),
+ lcd, pcd,
+ dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2));
+
+#endif
+
+ enable_clocks(0);
+}
+
+void dispc_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ DUMPREG(DISPC_REVISION);
+ DUMPREG(DISPC_SYSCONFIG);
+ DUMPREG(DISPC_SYSSTATUS);
+ DUMPREG(DISPC_IRQSTATUS);
+ DUMPREG(DISPC_IRQENABLE);
+ DUMPREG(DISPC_CONTROL);
+ DUMPREG(DISPC_CONFIG);
+ DUMPREG(DISPC_CAPABLE);
+ DUMPREG(DISPC_DEFAULT_COLOR0);
+ DUMPREG(DISPC_DEFAULT_COLOR1);
+ DUMPREG(DISPC_TRANS_COLOR0);
+ DUMPREG(DISPC_TRANS_COLOR1);
+ DUMPREG(DISPC_LINE_STATUS);
+ DUMPREG(DISPC_LINE_NUMBER);
+ DUMPREG(DISPC_TIMING_H);
+ DUMPREG(DISPC_TIMING_V);
+ DUMPREG(DISPC_POL_FREQ);
+#ifdef CONFIG_ARCH_OMAP4
+ DUMPREG(DISPC_DIVISOR1);
+#else
+ DUMPREG(DISPC_DIVISOR);
+#endif
+ DUMPREG(DISPC_GLOBAL_ALPHA);
+ DUMPREG(DISPC_SIZE_DIG);
+ DUMPREG(DISPC_SIZE_LCD);
+
+ DUMPREG(DISPC_GFX_BA0);
+ DUMPREG(DISPC_GFX_BA1);
+ DUMPREG(DISPC_GFX_POSITION);
+ DUMPREG(DISPC_GFX_SIZE);
+ DUMPREG(DISPC_GFX_ATTRIBUTES);
+ DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
+ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
+ DUMPREG(DISPC_GFX_ROW_INC);
+ DUMPREG(DISPC_GFX_PIXEL_INC);
+ DUMPREG(DISPC_GFX_WINDOW_SKIP);
+ DUMPREG(DISPC_GFX_TABLE_BA);
+
+ DUMPREG(DISPC_DATA_CYCLE1);
+ DUMPREG(DISPC_DATA_CYCLE2);
+ DUMPREG(DISPC_DATA_CYCLE3);
+
+ DUMPREG(DISPC_CPR_COEF_R);
+ DUMPREG(DISPC_CPR_COEF_G);
+ DUMPREG(DISPC_CPR_COEF_B);
+
+ DUMPREG(DISPC_GFX_PRELOAD);
+
+ DUMPREG(DISPC_VID_BA0(0));
+ DUMPREG(DISPC_VID_BA1(0));
+ DUMPREG(DISPC_VID_POSITION(0));
+ DUMPREG(DISPC_VID_SIZE(0));
+ DUMPREG(DISPC_VID_ATTRIBUTES(0));
+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
+ DUMPREG(DISPC_VID_ROW_INC(0));
+ DUMPREG(DISPC_VID_PIXEL_INC(0));
+ DUMPREG(DISPC_VID_FIR(0));
+ DUMPREG(DISPC_VID_PICTURE_SIZE(0));
+ DUMPREG(DISPC_VID_ACCU0(0));
+ DUMPREG(DISPC_VID_ACCU1(0));
+
+ DUMPREG(DISPC_VID_BA0(1));
+ DUMPREG(DISPC_VID_BA1(1));
+ DUMPREG(DISPC_VID_POSITION(1));
+ DUMPREG(DISPC_VID_SIZE(1));
+ DUMPREG(DISPC_VID_ATTRIBUTES(1));
+ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
+ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
+ DUMPREG(DISPC_VID_ROW_INC(1));
+ DUMPREG(DISPC_VID_PIXEL_INC(1));
+ DUMPREG(DISPC_VID_FIR(1));
+ DUMPREG(DISPC_VID_PICTURE_SIZE(1));
+ DUMPREG(DISPC_VID_ACCU0(1));
+ DUMPREG(DISPC_VID_ACCU1(1));
+
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
+ DUMPREG(DISPC_VID_CONV_COEF(0, 0));
+ DUMPREG(DISPC_VID_CONV_COEF(0, 1));
+ DUMPREG(DISPC_VID_CONV_COEF(0, 2));
+ DUMPREG(DISPC_VID_CONV_COEF(0, 3));
+ DUMPREG(DISPC_VID_CONV_COEF(0, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
+
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
+ DUMPREG(DISPC_VID_CONV_COEF(1, 0));
+ DUMPREG(DISPC_VID_CONV_COEF(1, 1));
+ DUMPREG(DISPC_VID_CONV_COEF(1, 2));
+ DUMPREG(DISPC_VID_CONV_COEF(1, 3));
+ DUMPREG(DISPC_VID_CONV_COEF(1, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
+ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
+
+ DUMPREG(DISPC_VID_PRELOAD(0));
+ DUMPREG(DISPC_VID_PRELOAD(1));
+/* TODO: OMAP4: add new registers here */
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+#undef DUMPREG
+}
+
+static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff,
+ bool rf, bool ieo, bool ipc, bool ihs,
+ bool ivs, u8 acbi, u8 acb)
+{
+ u32 l = 0;
+
+ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
+ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
+
+ l |= FLD_VAL(onoff, 17, 17);
+ l |= FLD_VAL(rf, 16, 16);
+ l |= FLD_VAL(ieo, 15, 15);
+ l |= FLD_VAL(ipc, 14, 14);
+ l |= FLD_VAL(ihs, 13, 13);
+ l |= FLD_VAL(ivs, 12, 12);
+ l |= FLD_VAL(acbi, 11, 8);
+ l |= FLD_VAL(acb, 7, 0);
+
+ enable_clocks(1);
+#ifdef CONFIG_ARCH_OMAP4
+ if (OMAP_DSS_CHANNEL_LCD2)
+ dispc_write_reg(DISPC_POL_FREQ2, l);
+ else
+#endif
+ dispc_write_reg(DISPC_POL_FREQ, l);
+ enable_clocks(0);
+}
+
+void dispc_set_pol_freq(enum omap_channel ch, enum omap_panel_config config,
+ u8 acbi, u8 acb)
+{
+ _dispc_set_pol_freq(ch, (config & OMAP_DSS_LCD_ONOFF) != 0,
+ (config & OMAP_DSS_LCD_RF) != 0,
+ (config & OMAP_DSS_LCD_IEO) != 0,
+ (config & OMAP_DSS_LCD_IPC) != 0,
+ (config & OMAP_DSS_LCD_IHS) != 0,
+ (config & OMAP_DSS_LCD_IVS) != 0,
+ acbi, acb);
+}
+
+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+ u16 *lck_div, u16 *pck_div)
+{
+ u16 pcd_min = is_tft ? 2 : 3;
+ unsigned long best_pck;
+ u16 best_ld, cur_ld;
+ u16 best_pd, cur_pd;
+
+ best_pck = 0;
+ best_ld = 0;
+ best_pd = 0;
+
+ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
+ unsigned long lck = fck / cur_ld;
+
+ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
+ unsigned long pck = lck / cur_pd;
+ long old_delta = abs(best_pck - req_pck);
+ long new_delta = abs(pck - req_pck);
+
+ if (best_pck == 0 || new_delta < old_delta) {
+ best_pck = pck;
+ best_ld = cur_ld;
+ best_pd = cur_pd;
+
+ if (pck == req_pck)
+ goto found;
+ }
+
+ if (pck < req_pck)
+ break;
+ }
+
+ if (lck / pcd_min < req_pck)
+ break;
+ }
+
+found:
+ *lck_div = best_ld;
+ *pck_div = best_pd;
+}
+
+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
+ struct dispc_clock_info *cinfo)
+{
+ unsigned long prate;
+ struct dispc_clock_info cur, best;
+ int match = 0;
+ int min_fck_per_pck;
+ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
+
+ if (cpu_is_omap34xx())
+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
+ else
+ prate = 0;
+
+ if (req_pck == dispc.cache_req_pck &&
+ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
+ dispc.cache_cinfo.fck == fck_rate)) {
+ DSSDBG("dispc clock info found from cache.\n");
+ *cinfo = dispc.cache_cinfo;
+ return 0;
+ }
+
+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+ if (min_fck_per_pck &&
+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+ DSSERR("Requested pixel clock not possible with the current "
+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+ "the constraint off.\n");
+ min_fck_per_pck = 0;
+ }
+
+retry:
+ memset(&cur, 0, sizeof(cur));
+ memset(&best, 0, sizeof(best));
+
+ if (cpu_is_omap24xx()) {
+ /* XXX can we change the clock on omap2? */
+ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
+ cur.fck_div = 1;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
+ &cur.lck_div, &cur.pck_div);
+
+ cur.lck = cur.fck / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ best = cur;
+
+ goto found;
+ } else if (cpu_is_omap34xx()) {
+ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
+ cur.fck = prate / cur.fck_div * 2;
+
+ if (cur.fck > DISPC_MAX_FCK)
+ continue;
+
+ if (min_fck_per_pck &&
+ cur.fck < req_pck * min_fck_per_pck)
+ continue;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
+ &cur.lck_div, &cur.pck_div);
+
+ cur.lck = cur.fck / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
+ best = cur;
+
+ if (cur.pck == req_pck)
+ goto found;
+ }
+ }
+ } else if (cpu_is_omap44xx()) {
+ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
+ cur.fck = prate / cur.fck_div * 2;
+
+ if (cur.fck > DISPC_MAX_FCK)
+ continue;
+
+ if (min_fck_per_pck &&
+ cur.fck < req_pck * min_fck_per_pck)
+ continue;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
+ &cur.lck_div, &cur.pck_div);
+
+ cur.lck = cur.fck / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
+ best = cur;
+
+ if (cur.pck == req_pck)
+ goto found;
+ }
+ }
+ } else {
+ BUG();
+ }
+
+found:
+ if (!match) {
+ if (min_fck_per_pck) {
+ DSSERR("Could not find suitable clock settings.\n"
+ "Turning FCK/PCK constraint off and"
+ "trying again.\n");
+ min_fck_per_pck = 0;
+ goto retry;
+ }
+
+ DSSERR("Could not find suitable clock settings.\n");
+
+ return -EINVAL;
+ }
+
+ if (cinfo)
+ *cinfo = best;
+
+ dispc.cache_req_pck = req_pck;
+ dispc.cache_prate = prate;
+ dispc.cache_cinfo = best;
+
+ return 0;
+}
+
+int dispc_set_clock_div(struct dispc_clock_info *cinfo)
+{
+ unsigned long prate;
+ int r;
+
+ if (cpu_is_omap34xx()) {
+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
+ DSSDBG("dpll4_m4 = %ld\n", prate);
+ }
+
+ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
+ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
+ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
+
+ if (cpu_is_omap34xx()) {
+ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
+ if (r)
+ return r;
+ }
+
+ /* TODO: update here for LCD2 support */
+ dispc_set_lcd_divisor(OMAP_DSS_CHANNEL_LCD, cinfo->lck_div,
+ cinfo->pck_div);
+
+ return 0;
+}
+
+int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+{
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
+
+ if (cpu_is_omap34xx()) {
+ unsigned long prate;
+ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
+ cinfo->fck_div = prate / (cinfo->fck / 2);
+ } else {
+ cinfo->fck_div = 0;
+ }
+#ifdef CONFIG_ARCH_OMAP4
+ cinfo->lck_div = REG_GET(DISPC_DIVISOR1, 23, 16);
+ cinfo->pck_div = REG_GET(DISPC_DIVISOR1, 7, 0);
+#else
+ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
+ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
+#endif
+ cinfo->lck = cinfo->fck / cinfo->lck_div;
+ cinfo->pck = cinfo->lck / cinfo->pck_div;
+
+ return 0;
+}
+
+/* dispc.irq_lock has to be locked by the caller */
+static void _omap_dispc_set_irqs(void)
+{
+ u32 mask;
+ u32 old_mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+ mask = dispc.irq_error_mask;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+
+ if (isr_data->isr == NULL)
+ continue;
+
+ mask |= isr_data->mask;
+ }
+
+ enable_clocks(1);
+
+ old_mask = dispc_read_reg(DISPC_IRQENABLE);
+ /* clear the irqstatus for newly enabled irqs */
+ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
+
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+
+ enable_clocks(0);
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+ int i;
+ int ret;
+ unsigned long flags;
+ struct omap_dispc_isr_data *isr_data;
+
+ if (isr == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+
+ /* check for duplicate entry */
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+ if (isr_data->isr == isr && isr_data->arg == arg &&
+ isr_data->mask == mask) {
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ isr_data = NULL;
+ ret = -EBUSY;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+
+ if (isr_data->isr != NULL)
+ continue;
+
+ isr_data->isr = isr;
+ isr_data->arg = arg;
+ isr_data->mask = mask;
+ ret = 0;
+
+ break;
+ }
+
+ _omap_dispc_set_irqs();
+
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return 0;
+err:
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+ int i;
+ unsigned long flags;
+ int ret = -EINVAL;
+ struct omap_dispc_isr_data *isr_data;
+
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+ if (isr_data->isr != isr || isr_data->arg != arg ||
+ isr_data->mask != mask)
+ continue;
+
+ /* found the correct isr */
+
+ isr_data->isr = NULL;
+ isr_data->arg = NULL;
+ isr_data->mask = 0;
+
+ ret = 0;
+ break;
+ }
+
+ if (ret == 0)
+ _omap_dispc_set_irqs();
+
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+#ifdef DEBUG
+static void print_irq_status(u32 status)
+{
+ if ((status & dispc.irq_error_mask) == 0)
+ return;
+
+ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
+
+#define PIS(x) \
+ if (status & DISPC_IRQ_##x) \
+ printk(#x " ");
+ PIS(GFX_FIFO_UNDERFLOW);
+ PIS(OCP_ERR);
+ PIS(VID1_FIFO_UNDERFLOW);
+ PIS(VID2_FIFO_UNDERFLOW);
+ PIS(SYNC_LOST);
+ PIS(SYNC_LOST_DIGIT);
+#undef PIS
+
+ printk("\n");
+}
+#endif
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+void dispc_irq_handler(void)
+{
+ int i;
+ u32 irqstatus;
+ u32 handledirqs = 0;
+ u32 unhandled_errors;
+ struct omap_dispc_isr_data *isr_data;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+ spin_lock(&dispc.irq_lock);
+
+ irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
+
+#ifdef DEBUG
+ if (dss_debug)
+ print_irq_status(irqstatus);
+#endif
+ /* Ack the interrupt. Do it here before clocks are possibly turned
+ * off */
+ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
+
+ /* make a copy and unlock, so that isrs can unregister
+ * themselves */
+ memcpy(registered_isr, dispc.registered_isr,
+ sizeof(registered_isr));
+
+ spin_unlock(&dispc.irq_lock);
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &registered_isr[i];
+
+ if (!isr_data->isr)
+ continue;
+
+ if (isr_data->mask & irqstatus) {
+ isr_data->isr(isr_data->arg, irqstatus);
+ handledirqs |= isr_data->mask;
+ }
+ }
+
+ spin_lock(&dispc.irq_lock);
+
+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
+
+ if (unhandled_errors) {
+ dispc.error_irqs |= unhandled_errors;
+
+ dispc.irq_error_mask &= ~unhandled_errors;
+ _omap_dispc_set_irqs();
+
+ schedule_work(&dispc.error_work);
+ }
+
+ spin_unlock(&dispc.irq_lock);
+}
+
+static void dispc_error_worker(struct work_struct *work)
+{
+ int i;
+ u32 errors;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+ errors = dispc.error_irqs;
+ dispc.error_irqs = 0;
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
+ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id == 0) {
+ dispc_enable_plane(ovl->id, 0);
+ dispc_go(ovl->manager->id);
+ mdelay(50);
+ break;
+ }
+ }
+ }
+
+ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
+ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id == 1) {
+ dispc_enable_plane(ovl->id, 0);
+ dispc_go(ovl->manager->id);
+ mdelay(50);
+ break;
+ }
+ }
+ }
+
+ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
+ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id == 2) {
+ dispc_enable_plane(ovl->id, 0);
+ dispc_go(ovl->manager->id);
+ mdelay(50);
+ break;
+ }
+ }
+ }
+#ifdef CONFIG_ARCH_OMAP4
+ if (errors & DISPC_IRQ_VID3_FIFO_UNDERFLOW) {
+ DSSERR("VID3_FIFO_UNDERFLOW, disabling VID2\n");
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id == 3) {
+ dispc_enable_plane(ovl->id, 0);
+ dispc_go(ovl->manager->id);
+ mdelay(50);
+ break;
+ }
+ }
+ }
+
+ if (errors & DISPC_IRQ_SYNC_LOST_2) {
+ struct omap_overlay_manager *manager = NULL;
+ bool enable = false;
+
+ DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+#ifdef CONFIG_ARCH_OMAP4
+ if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
+ manager = mgr;
+ enable = mgr->device->state ==
+ OMAP_DSS_DISPLAY_ACTIVE;
+ mgr->device->disable(mgr->device);
+ break;
+ }
+#endif
+ }
+
+ if (manager) {
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id != 0 && ovl->manager == manager)
+ dispc_enable_plane(ovl->id, 0);
+ }
+
+ dispc_go(manager->id);
+ mdelay(50);
+ if (enable)
+ manager->device->enable(manager->device);
+ }
+ }
+
+#endif
+
+ if (errors & DISPC_IRQ_SYNC_LOST) {
+ struct omap_overlay_manager *manager = NULL;
+ bool enable = false;
+
+ DSSERR("SYNC_LOST, disabling LCD\n");
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
+ manager = mgr;
+ enable = mgr->device->state ==
+ OMAP_DSS_DISPLAY_ACTIVE;
+ mgr->device->disable(mgr->device);
+ break;
+ }
+ }
+
+ if (manager) {
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id != 0 && ovl->manager == manager)
+ dispc_enable_plane(ovl->id, 0);
+ }
+
+ dispc_go(manager->id);
+ mdelay(50);
+ if (enable)
+ manager->device->enable(manager->device);
+ }
+ }
+
+ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
+ struct omap_overlay_manager *manager = NULL;
+ bool enable = false;
+
+ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
+ manager = mgr;
+ enable = mgr->device->state ==
+ OMAP_DSS_DISPLAY_ACTIVE;
+ mgr->device->disable(mgr->device);
+ break;
+ }
+ }
+
+ if (manager) {
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ if (ovl->id != 0 && ovl->manager == manager)
+ dispc_enable_plane(ovl->id, 0);
+ }
+
+ dispc_go(manager->id);
+ mdelay(50);
+ if (enable)
+ manager->device->enable(manager->device);
+ }
+ }
+
+ if (errors & DISPC_IRQ_OCP_ERR) {
+ DSSERR("OCP_ERR\n");
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
+ mgr->device->disable(mgr->device);
+ }
+ }
+
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask |= errors;
+ _omap_dispc_set_irqs();
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+}
+
+int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
+{
+ void dispc_irq_wait_handler(void *data, u32 mask)
+ {
+ complete((struct completion *)data);
+ }
+
+ int r;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+ irqmask);
+
+ if (r)
+ return r;
+
+ timeout = wait_for_completion_timeout(&completion, timeout);
+
+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+ if (timeout == 0)
+ return -ETIMEDOUT;
+
+ if (timeout == -ERESTARTSYS)
+ return -ERESTARTSYS;
+
+ return 0;
+}
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout)
+{
+ void dispc_irq_wait_handler(void *data, u32 mask)
+ {
+ complete((struct completion *)data);
+ }
+
+ int r;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+ irqmask);
+
+ if (r)
+ return r;
+
+ timeout = wait_for_completion_interruptible_timeout(&completion,
+ timeout);
+
+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+ if (timeout == 0)
+ return -ETIMEDOUT;
+
+ if (timeout == -ERESTARTSYS)
+ return -ERESTARTSYS;
+
+ return 0;
+}
+
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+void dispc_fake_vsync_irq(void)
+{
+ u32 irqstatus = DISPC_IRQ_VSYNC;
+ int i;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ struct omap_dispc_isr_data *isr_data;
+ isr_data = &dispc.registered_isr[i];
+
+ if (!isr_data->isr)
+ continue;
+
+ if (isr_data->mask & irqstatus)
+ isr_data->isr(isr_data->arg, irqstatus);
+ }
+}
+#endif
+
+static void _omap_dispc_initialize_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dispc.irq_lock, flags);
+
+ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
+
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+
+ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+ * so clear it */
+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+
+ _omap_dispc_set_irqs();
+
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+}
+
+void dispc_enable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
+}
+
+void dispc_disable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
+}
+
+static void _omap_dispc_initial_config(void)
+{
+ u32 l;
+
+ l = dispc_read_reg(DISPC_SYSCONFIG);
+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
+ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
+ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
+ dispc_write_reg(DISPC_SYSCONFIG, l);
+
+ /* FUNCGATED */
+ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
+
+ /* L3 firewall setting: enable access to OCM RAM */
+ if (cpu_is_omap24xx())
+ __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
+
+ _dispc_setup_color_conv_coef();
+
+ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
+
+ dispc_read_plane_fifo_sizes();
+}
+
+int dispc_init(void)
+{
+ u32 rev;
+
+ spin_lock_init(&dispc.irq_lock);
+
+ INIT_WORK(&dispc.error_work, dispc_error_worker);
+
+ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
+ if (!dispc.base) {
+ DSSERR("can't ioremap DISPC\n");
+ return -ENOMEM;
+ }
+
+ if (cpu_is_omap34xx()) {
+ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+ if (IS_ERR(dispc.dpll4_m4_ck)) {
+ DSSERR("Failed to get dpll4_m4_ck\n");
+ return -ENODEV;
+ }
+ }
+
+
+
+ enable_clocks(1);
+
+ _omap_dispc_initial_config();
+
+ _omap_dispc_initialize_irq();
+
+ dispc_save_context();
+
+ rev = dispc_read_reg(DISPC_REVISION);
+ printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ enable_clocks(0);
+
+ return 0;
+}
+
+void dispc_exit(void)
+{
+ if (cpu_is_omap34xx())
+ clk_put(dispc.dpll4_m4_ck);
+ iounmap(dispc.base);
+}
+
+int dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
+ enable_clocks(1);
+ _dispc_enable_plane(plane, enable);
+ enable_clocks(0);
+
+ return 0;
+}
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror, u8 global_alpha,
+ enum omap_channel channel
+#ifdef CONFIG_ARCH_OMAP4
+ , u32 puv_addr
+#endif
+ )
+{
+ int r = 0;
+
+ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
+ plane, paddr, screen_width, pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ ilace, color_mode,
+ rotation, mirror);
+
+ enable_clocks(1);
+
+ r = _dispc_setup_plane(plane,
+ paddr, screen_width,
+ pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+ rotation, mirror,
+ global_alpha, channel
+#ifdef CONFIG_ARCH_OMAP4
+ , puv_addr
+#endif
+ );
+
+ enable_clocks(0);
+
+ return r;
+}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
new file mode 100644
index 000000000000..850239989402
--- /dev/null
+++ b/drivers/video/omap2/dss/display.c
@@ -0,0 +1,668 @@
+/*
+ * linux/drivers/video/omap2/dss/display.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+
+#include <mach/display.h>
+#include "dss.h"
+
+static LIST_HEAD(display_list);
+
+static ssize_t display_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ bool enabled, r;
+
+ enabled = simple_strtoul(buf, NULL, 10);
+
+ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
+ if (enabled) {
+ r = dssdev->enable(dssdev);
+ if (r)
+ return r;
+ } else {
+ dssdev->disable(dssdev);
+ }
+ }
+
+ return size;
+}
+
+static ssize_t display_upd_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
+ if (dssdev->get_update_mode)
+ mode = dssdev->get_update_mode(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+}
+
+static ssize_t display_upd_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int val, r;
+ enum omap_dss_update_mode mode;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ switch (val) {
+ case OMAP_DSS_UPDATE_DISABLED:
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ mode = (enum omap_dss_update_mode)val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ r = dssdev->set_update_mode(dssdev, mode);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_tear_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ dssdev->get_te ? dssdev->get_te(dssdev) : 0);
+}
+
+static ssize_t display_tear_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long te;
+ int r;
+
+ if (!dssdev->enable_te || !dssdev->get_te)
+ return -ENOENT;
+
+ te = simple_strtoul(buf, NULL, 0);
+
+ r = dssdev->enable_te(dssdev, te);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t;
+
+ if (!dssdev->get_timings)
+ return -ENOENT;
+
+ dssdev->get_timings(dssdev, &t);
+
+ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+ t.pixel_clock,
+ t.x_res, t.hfp, t.hbp, t.hsw,
+ t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t;
+ int r, found;
+
+ if (!dssdev->set_timings || !dssdev->check_timings)
+ return -ENOENT;
+
+ found = 0;
+#ifdef CONFIG_OMAP2_DSS_VENC
+ if (strncmp("pal", buf, 3) == 0) {
+ t = omap_dss_pal_timings;
+ found = 1;
+ } else if (strncmp("ntsc", buf, 4) == 0) {
+ t = omap_dss_ntsc_timings;
+ found = 1;
+ }
+#endif
+ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+ &t.pixel_clock,
+ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+ return -EINVAL;
+
+ r = dssdev->check_timings(dssdev, &t);
+ if (r)
+ return r;
+
+ dssdev->set_timings(dssdev, &t);
+
+ return size;
+}
+
+static ssize_t display_rotate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int rotate;
+ if (!dssdev->get_rotate)
+ return -ENOENT;
+ rotate = dssdev->get_rotate(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+}
+
+static ssize_t display_rotate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long rot;
+ int r;
+
+ if (!dssdev->set_rotate || !dssdev->get_rotate)
+ return -ENOENT;
+
+ rot = simple_strtoul(buf, NULL, 0);
+
+ r = dssdev->set_rotate(dssdev, rot);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_mirror_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int mirror;
+ if (!dssdev->get_mirror)
+ return -ENOENT;
+ mirror = dssdev->get_mirror(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+}
+
+static ssize_t display_mirror_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long mirror;
+ int r;
+
+ if (!dssdev->set_mirror || !dssdev->get_mirror)
+ return -ENOENT;
+
+ mirror = simple_strtoul(buf, NULL, 0);
+
+ r = dssdev->set_mirror(dssdev, mirror);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_wss_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned int wss;
+
+ if (!dssdev->get_wss)
+ return -ENOENT;
+
+ wss = dssdev->get_wss(dssdev);
+
+ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+}
+
+static ssize_t display_wss_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long wss;
+ int r;
+
+ if (!dssdev->get_wss || !dssdev->set_wss)
+ return -ENOENT;
+
+ if (strict_strtoul(buf, 0, &wss))
+ return -EINVAL;
+
+ if (wss > 0xfffff)
+ return -EINVAL;
+
+ r = dssdev->set_wss(dssdev, wss);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+ display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
+ display_upd_mode_show, display_upd_mode_store);
+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+ display_tear_show, display_tear_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+ display_timings_show, display_timings_store);
+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+ display_rotate_show, display_rotate_store);
+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+ display_mirror_show, display_mirror_store);
+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+ display_wss_show, display_wss_store);
+
+static struct device_attribute *display_sysfs_attrs[] = {
+ &dev_attr_enabled,
+ &dev_attr_update_mode,
+ &dev_attr_tear_elim,
+ &dev_attr_timings,
+ &dev_attr_rotate,
+ &dev_attr_mirror,
+ &dev_attr_wss,
+ NULL
+};
+
+static void default_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres)
+{
+ *xres = dssdev->panel.timings.x_res;
+ *yres = dssdev->panel.timings.y_res;
+}
+
+void default_get_overlay_fifo_thresholds(enum omap_plane plane,
+ u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 *fifo_low, u32 *fifo_high)
+{
+ unsigned low, high, size;
+ unsigned burst_size_bytes;
+
+#if 0
+ *burst_size = OMAP_DSS_BURST_16x32; /* OMAP4: same as 8x128*/
+#ifndef CONFIG_ARCH_OMAP4
+ burst_size_bytes = 16 * 32 / 8;
+#else
+ burst_size_bytes = 8 * 128 / 8; /* OMAP4: highest burst size is 8x128*/
+#endif
+#else
+ *burst_size = OMAP_DSS_BURST_4x32; /* OMAP4: same as 2x128*/
+ burst_size_bytes = 2 * 128 / 8; /* OMAP4: highest burst size is 8x128*/
+
+#endif
+ *fifo_high = fifo_size - 1;
+ *fifo_low = fifo_size - burst_size_bytes;
+}
+
+static int default_wait_vsync(struct omap_dss_device *dssdev)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ u32 irq;
+
+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+ irq = DISPC_IRQ_EVSYNC_ODD;
+ else
+ irq = DISPC_IRQ_VSYNC;
+
+ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+}
+
+static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
+{
+ if (dssdev->panel.recommended_bpp)
+ return dssdev->panel.recommended_bpp;
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ if (dssdev->phy.dpi.data_lines == 24)
+ return 24;
+ else
+ return 16;
+
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_DSI:
+ if (dssdev->ctrl.pixel_size == 24)
+ return 24;
+ else
+ return 16;
+ case OMAP_DISPLAY_TYPE_VENC:
+ case OMAP_DISPLAY_TYPE_SDI:
+ return 24;
+ return 24;
+ default:
+ BUG();
+ }
+}
+
+/* Checks if replication logic should be used. Only use for active matrix,
+ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
+ * 18bpp or 24bpp */
+bool dss_use_replication(struct omap_dss_device *dssdev,
+ enum omap_color_mode mode)
+{
+ int bpp;
+
+ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
+ return false;
+
+ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
+ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
+ return false;
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ bpp = dssdev->phy.dpi.data_lines;
+ break;
+ case OMAP_DISPLAY_TYPE_VENC:
+ case OMAP_DISPLAY_TYPE_SDI:
+ bpp = 24;
+ break;
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_DSI:
+ bpp = dssdev->ctrl.pixel_size;
+ break;
+ default:
+ BUG();
+ }
+
+ return bpp > 16;
+}
+
+void dss_init_device(struct platform_device *pdev,
+ struct omap_dss_device *dssdev)
+{
+ struct device_attribute *attr;
+ int i;
+ int r;
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+#ifdef CONFIG_OMAP2_DSS_RFBI
+ case OMAP_DISPLAY_TYPE_DBI:
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+ case OMAP_DISPLAY_TYPE_SDI:
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+ case OMAP_DISPLAY_TYPE_DSI:
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+ case OMAP_DISPLAY_TYPE_VENC:
+#endif
+ break;
+ default:
+ DSSERR("Support for display '%s' not compiled in.\n",
+ dssdev->name);
+ return;
+ }
+
+ dssdev->get_resolution = default_get_resolution;
+ dssdev->get_recommended_bpp = default_get_recommended_bpp;
+ dssdev->wait_vsync = default_wait_vsync;
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ r = dpi_init_display(dssdev);
+ break;
+#ifdef CONFIG_OMAP2_DSS_RFBI
+ case OMAP_DISPLAY_TYPE_DBI:
+ r = rfbi_init_display(dssdev);
+ break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+ case OMAP_DISPLAY_TYPE_VENC:
+ r = venc_init_display(dssdev);
+ break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+ case OMAP_DISPLAY_TYPE_SDI:
+ r = sdi_init_display(dssdev);
+ break;
+#endif
+#ifdef CONFIG_OMAP2_DSS_DSI
+ case OMAP_DISPLAY_TYPE_DSI:
+ r = dsi_init_display(dssdev);
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ if (r) {
+ DSSERR("failed to init display %s\n", dssdev->name);
+ return;
+ }
+
+ /* create device sysfs files */
+ i = 0;
+ while ((attr = display_sysfs_attrs[i++]) != NULL) {
+ r = device_create_file(&dssdev->dev, attr);
+ if (r)
+ DSSERR("failed to create sysfs file\n");
+ }
+
+ /* create display? sysfs links */
+ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
+ dev_name(&dssdev->dev));
+ if (r)
+ DSSERR("failed to create sysfs display link\n");
+}
+
+void dss_uninit_device(struct platform_device *pdev,
+ struct omap_dss_device *dssdev)
+{
+ struct device_attribute *attr;
+ int i = 0;
+
+ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
+
+ while ((attr = display_sysfs_attrs[i++]) != NULL)
+ device_remove_file(&dssdev->dev, attr);
+
+ if (dssdev->manager)
+ dssdev->manager->unset_device(dssdev->manager);
+}
+
+static int dss_suspend_device(struct device *dev, void *data)
+{
+ int r;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ dssdev->activate_after_resume = false;
+ return 0;
+ }
+
+ if (!dssdev->suspend) {
+ DSSERR("display '%s' doesn't implement suspend\n",
+ dssdev->name);
+ return -ENOSYS;
+ }
+
+ r = dssdev->suspend(dssdev);
+ if (r)
+ return r;
+
+ dssdev->activate_after_resume = true;
+
+ return 0;
+}
+
+int dss_suspend_all_devices(void)
+{
+ int r;
+ struct bus_type *bus = dss_get_bus();
+
+ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
+ if (r) {
+ /* resume all displays that were suspended */
+ dss_resume_all_devices();
+ return r;
+ }
+
+ return 0;
+}
+
+static int dss_resume_device(struct device *dev, void *data)
+{
+ int r;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+ if (dssdev->activate_after_resume && dssdev->resume) {
+ r = dssdev->resume(dssdev);
+ if (r)
+ return r;
+ }
+
+ dssdev->activate_after_resume = false;
+
+ return 0;
+}
+
+int dss_resume_all_devices(void)
+{
+ struct bus_type *bus = dss_get_bus();
+
+ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
+}
+
+
+void omap_dss_get_device(struct omap_dss_device *dssdev)
+{
+ get_device(&dssdev->dev);
+}
+EXPORT_SYMBOL(omap_dss_get_device);
+
+void omap_dss_put_device(struct omap_dss_device *dssdev)
+{
+ put_device(&dssdev->dev);
+}
+EXPORT_SYMBOL(omap_dss_put_device);
+
+/* ref count of the found device is incremented. ref count
+ * of from-device is decremented. */
+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
+{
+ struct device *dev;
+ struct device *dev_start = NULL;
+ struct omap_dss_device *dssdev = NULL;
+
+ int match(struct device *dev, void *data)
+ {
+ /* skip panels connected to controllers */
+ if (to_dss_device(dev)->panel.ctrl)
+ return 0;
+
+ return 1;
+ }
+
+ if (from)
+ dev_start = &from->dev;
+ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
+ if (dev)
+ dssdev = to_dss_device(dev);
+ if (from)
+ put_device(&from->dev);
+
+ return dssdev;
+}
+EXPORT_SYMBOL(omap_dss_get_next_device);
+
+struct omap_dss_device *omap_dss_find_device(void *data,
+ int (*match)(struct omap_dss_device *dssdev, void *data))
+{
+ struct omap_dss_device *dssdev = NULL;
+
+ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
+ if (match(dssdev, data))
+ return dssdev;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(omap_dss_find_device);
+
+int omap_dss_start_device(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ if (!dssdev->driver) {
+ DSSDBG("no driver\n");
+ r = -ENODEV;
+ goto err0;
+ }
+
+ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
+ DSSDBG("no panel driver\n");
+ r = -ENODEV;
+ goto err0;
+ }
+
+ if (!try_module_get(dssdev->dev.driver->owner)) {
+ r = -ENODEV;
+ goto err0;
+ }
+
+ if (dssdev->ctrl.panel) {
+ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
+ r = -ENODEV;
+ goto err1;
+ }
+ }
+
+ return 0;
+err1:
+ module_put(dssdev->dev.driver->owner);
+err0:
+ return r;
+}
+EXPORT_SYMBOL(omap_dss_start_device);
+
+void omap_dss_stop_device(struct omap_dss_device *dssdev)
+{
+ if (dssdev->ctrl.panel)
+ module_put(dssdev->ctrl.panel->dev.driver->owner);
+
+ module_put(dssdev->dev.driver->owner);
+}
+EXPORT_SYMBOL(omap_dss_stop_device);
+
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
new file mode 100644
index 000000000000..cf85741dd121
--- /dev/null
+++ b/drivers/video/omap2/dss/dpi.c
@@ -0,0 +1,407 @@
+/*
+ * linux/drivers/video/omap2/dss/dpi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DPI"
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include <mach/cpu.h>
+
+#include "dss.h"
+
+static struct {
+ int update_enabled;
+} dpi;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
+ unsigned long *fck, int *lck_div, int *pck_div)
+{
+ struct dsi_clock_info cinfo;
+ int r;
+
+ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
+ if (r)
+ return r;
+
+ r = dsi_pll_program(&cinfo);
+ if (r)
+ return r;
+
+ dss_select_clk_source(0, 1);
+
+ /* TODO: update here for LCD 2 support */
+ dispc_set_lcd_divisor(OMAP_DSS_CHANNEL_LCD, cinfo.lck_div,
+ cinfo.pck_div);
+
+ *fck = cinfo.dsi1_pll_fclk;
+ *lck_div = cinfo.lck_div;
+ *pck_div = cinfo.pck_div;
+
+ return 0;
+}
+#else
+static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
+ unsigned long *fck, int *lck_div, int *pck_div)
+{
+ struct dispc_clock_info cinfo;
+ int r = 0;
+
+ return 0;
+ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
+ if (r)
+ return r;
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r)
+ return r;
+
+ *fck = cinfo.fck;
+ *lck_div = cinfo.lck_div;
+ *pck_div = cinfo.pck_div;
+
+ return 0;
+}
+#endif
+
+static int dpi_set_mode(struct omap_dss_device *dssdev)
+{
+ struct omap_video_timings *t = &dssdev->panel.timings;
+ int lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+ bool is_tft;
+ int r = 0;
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ /* TODO: add LCD2 support here*/
+ dispc_set_pol_freq(OMAP_DSS_CHANNEL_LCD, dssdev->panel.config,
+ dssdev->panel.acbi, dssdev->panel.acb);
+
+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
+ &fck, &lck_div, &pck_div);
+#else
+ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
+ &fck, &lck_div, &pck_div);
+#endif
+ if (r)
+ goto err0;
+
+#ifndef CONFIG_ARCH_OMAP4
+ pck = fck / lck_div / pck_div / 1000;
+#else
+ pck = 0;
+#endif
+
+ if (pck != t->pixel_clock) {
+ DSSWARN("Could not find exact pixel clock. "
+ "Requested %d kHz, got %lu kHz\n",
+ t->pixel_clock, pck);
+
+ t->pixel_clock = pck;
+ }
+
+ /* TODO: OMAP4: add LCD 2 support here*/
+ dispc_set_lcd_timings(OMAP_DSS_CHANNEL_LCD, t);
+
+err0:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ return r;
+}
+
+static int dpi_basic_init(struct omap_dss_device *dssdev)
+{
+ bool is_tft;
+
+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_PARALLELMODE_BYPASS);
+
+ /*TODO: change here for LCD 2 support */
+ dispc_set_lcd_display_type(OMAP_DSS_CHANNEL_LCD,
+ is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
+ dispc_set_tft_data_lines(OMAP_DSS_CHANNEL_LCD,
+ dssdev->phy.dpi.data_lines);
+
+ return 0;
+}
+
+static int dpi_display_enable(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = omap_dss_start_device(dssdev);
+ if (r) {
+ DSSERR("failed to start device\n");
+ goto err0;
+ }
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ DSSERR("display already enabled\n");
+ r = -EINVAL;
+ goto err1;
+ }
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ r = dpi_basic_init(dssdev);
+ if (r)
+ goto err2;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ dss_clk_enable(DSS_CLK_FCK2);
+ r = dsi_pll_init(0, 1);
+ if (r)
+ goto err3;
+#endif
+ r = dpi_set_mode(dssdev);
+ if (r)
+ goto err4;
+
+ mdelay(2);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err5;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+
+err5:
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+err4:
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ dsi_pll_uninit();
+err3:
+ dss_clk_disable(DSS_CLK_FCK2);
+#endif
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+err1:
+ omap_dss_stop_device(dssdev);
+err0:
+ return r;
+}
+
+static int dpi_display_resume(struct omap_dss_device *dssdev);
+
+static void dpi_display_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ return;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ dpi_display_resume(dssdev);
+
+ dssdev->driver->disable(dssdev);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ dss_select_clk_source(0, 0);
+ dsi_pll_uninit();
+ dss_clk_disable(DSS_CLK_FCK2);
+#endif
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ omap_dss_stop_device(dssdev);
+}
+
+static int dpi_display_suspend(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EINVAL;
+
+ DSSDBG("dpi_display_suspend\n");
+
+ if (dssdev->driver->suspend)
+ dssdev->driver->suspend(dssdev);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ return 0;
+}
+
+static int dpi_display_resume(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
+ DSSDBG("dpi_display_resume\n");
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+
+ if (dssdev->driver->resume)
+ dssdev->driver->resume(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static void dpi_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ DSSDBG("dpi_set_timings\n");
+ dssdev->panel.timings = *timings;
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ dpi_set_mode(dssdev);
+ dispc_go(OMAP_DSS_CHANNEL_LCD);
+ }
+}
+
+static int dpi_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ bool is_tft;
+ int r = 0;
+ int lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+
+ if (!dispc_lcd_timings_ok(timings))
+ return -EINVAL;
+
+ if (timings->pixel_clock == 0)
+ return -EINVAL;
+
+ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ {
+ struct dsi_clock_info cinfo;
+ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
+ &cinfo);
+
+ if (r)
+ return r;
+
+ fck = cinfo.dsi1_pll_fclk;
+ lck_div = cinfo.lck_div;
+ pck_div = cinfo.pck_div;
+ }
+#else
+ {
+ struct dispc_clock_info cinfo;
+ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
+ &cinfo);
+
+ if (r)
+ return r;
+
+ fck = cinfo.fck;
+ lck_div = cinfo.lck_div;
+ pck_div = cinfo.pck_div;
+ }
+#endif
+
+ pck = fck / lck_div / pck_div / 1000;
+
+ timings->pixel_clock = pck;
+
+ return 0;
+}
+
+static void dpi_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ *timings = dssdev->panel.timings;
+}
+
+static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ if (mode == OMAP_DSS_UPDATE_MANUAL)
+ return -EINVAL;
+
+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+ dpi.update_enabled = 0;
+ } else {
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+ dpi.update_enabled = 1;
+ }
+
+ return 0;
+}
+
+static enum omap_dss_update_mode dpi_display_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+ OMAP_DSS_UPDATE_DISABLED;
+}
+
+int dpi_init_display(struct omap_dss_device *dssdev)
+{
+ DSSDBG("init_display\n");
+
+ dssdev->enable = dpi_display_enable;
+ dssdev->disable = dpi_display_disable;
+ dssdev->suspend = dpi_display_suspend;
+ dssdev->resume = dpi_display_resume;
+ dssdev->set_timings = dpi_set_timings;
+ dssdev->check_timings = dpi_check_timings;
+ dssdev->get_timings = dpi_get_timings;
+ dssdev->set_update_mode = dpi_display_set_update_mode;
+ dssdev->get_update_mode = dpi_display_get_update_mode;
+
+ return 0;
+}
+
+int dpi_init(void)
+{
+ return 0;
+}
+
+void dpi_exit(void)
+{
+}
+
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
new file mode 100644
index 000000000000..011d0acd973d
--- /dev/null
+++ b/drivers/video/omap2/dss/dsi.c
@@ -0,0 +1,3517 @@
+/*
+ * linux/drivers/video/omap2/dss/dsi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSI"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include <mach/clock.h>
+
+#include "dss.h"
+
+/*#define VERBOSE_IRQ*/
+
+#define DSI_BASE 0x4804FC00
+
+struct dsi_reg { u16 idx; };
+
+#define DSI_REG(idx) ((const struct dsi_reg) { idx })
+
+#define DSI_SZ_REGS SZ_1K
+/* DSI Protocol Engine */
+
+#define DSI_REVISION DSI_REG(0x0000)
+#define DSI_SYSCONFIG DSI_REG(0x0010)
+#define DSI_SYSSTATUS DSI_REG(0x0014)
+#define DSI_IRQSTATUS DSI_REG(0x0018)
+#define DSI_IRQENABLE DSI_REG(0x001C)
+#define DSI_CTRL DSI_REG(0x0040)
+#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
+#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
+#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
+#define DSI_CLK_CTRL DSI_REG(0x0054)
+#define DSI_TIMING1 DSI_REG(0x0058)
+#define DSI_TIMING2 DSI_REG(0x005C)
+#define DSI_VM_TIMING1 DSI_REG(0x0060)
+#define DSI_VM_TIMING2 DSI_REG(0x0064)
+#define DSI_VM_TIMING3 DSI_REG(0x0068)
+#define DSI_CLK_TIMING DSI_REG(0x006C)
+#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
+#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
+#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
+#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
+#define DSI_VM_TIMING4 DSI_REG(0x0080)
+#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
+#define DSI_VM_TIMING5 DSI_REG(0x0088)
+#define DSI_VM_TIMING6 DSI_REG(0x008C)
+#define DSI_VM_TIMING7 DSI_REG(0x0090)
+#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
+#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
+#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
+#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
+#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
+#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
+
+/* DSIPHY_SCP */
+
+#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
+#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
+#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
+#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
+
+/* DSI_PLL_CTRL_SCP */
+
+#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
+#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
+#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
+#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
+#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
+
+#define REG_GET(idx, start, end) \
+ FLD_GET(dsi_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
+
+/* Global interrupts */
+#define DSI_IRQ_VC0 (1 << 0)
+#define DSI_IRQ_VC1 (1 << 1)
+#define DSI_IRQ_VC2 (1 << 2)
+#define DSI_IRQ_VC3 (1 << 3)
+#define DSI_IRQ_WAKEUP (1 << 4)
+#define DSI_IRQ_RESYNC (1 << 5)
+#define DSI_IRQ_PLL_LOCK (1 << 7)
+#define DSI_IRQ_PLL_UNLOCK (1 << 8)
+#define DSI_IRQ_PLL_RECALL (1 << 9)
+#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
+#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
+#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
+#define DSI_IRQ_TE_TRIGGER (1 << 16)
+#define DSI_IRQ_ACK_TRIGGER (1 << 17)
+#define DSI_IRQ_SYNC_LOST (1 << 18)
+#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
+#define DSI_IRQ_TA_TIMEOUT (1 << 20)
+#define DSI_IRQ_ERROR_MASK \
+ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
+ DSI_IRQ_TA_TIMEOUT)
+#define DSI_IRQ_CHANNEL_MASK 0xf
+
+/* Virtual channel interrupts */
+#define DSI_VC_IRQ_CS (1 << 0)
+#define DSI_VC_IRQ_ECC_CORR (1 << 1)
+#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
+#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
+#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
+#define DSI_VC_IRQ_BTA (1 << 5)
+#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
+#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
+#define DSI_VC_IRQ_ERROR_MASK \
+ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
+ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
+ DSI_VC_IRQ_FIFO_TX_UDF)
+
+/* ComplexIO interrupts */
+#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
+#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
+#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
+#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
+#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
+#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
+#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
+#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
+#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
+#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
+#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
+#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
+
+#define DSI_DT_DCS_SHORT_WRITE_0 0x05
+#define DSI_DT_DCS_SHORT_WRITE_1 0x15
+#define DSI_DT_DCS_READ 0x06
+#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
+#define DSI_DT_NULL_PACKET 0x09
+#define DSI_DT_DCS_LONG_WRITE 0x39
+
+#define DSI_DT_RX_ACK_WITH_ERR 0x02
+#define DSI_DT_RX_DCS_LONG_READ 0x1c
+#define DSI_DT_RX_SHORT_READ_1 0x21
+#define DSI_DT_RX_SHORT_READ_2 0x22
+
+#define FINT_MAX 2100000
+#define FINT_MIN 750000
+#define REGN_MAX (1 << 7)
+#define REGM_MAX ((1 << 11) - 1)
+#define REGM3_MAX (1 << 4)
+#define REGM4_MAX (1 << 4)
+
+enum fifo_size {
+ DSI_FIFO_SIZE_0 = 0,
+ DSI_FIFO_SIZE_32 = 1,
+ DSI_FIFO_SIZE_64 = 2,
+ DSI_FIFO_SIZE_96 = 3,
+ DSI_FIFO_SIZE_128 = 4,
+};
+
+enum dsi_vc_mode {
+ DSI_VC_MODE_L4 = 0,
+ DSI_VC_MODE_VP,
+};
+
+struct dsi_update_region {
+ bool dirty;
+ u16 x, y, w, h;
+ struct omap_dss_device *device;
+};
+
+static struct
+{
+ void __iomem *base;
+
+ unsigned long dsi1_pll_fclk; /* Hz */
+ unsigned long dsi2_pll_fclk; /* Hz */
+ unsigned long dsiphy; /* Hz */
+ unsigned long ddr_clk; /* Hz */
+
+ struct regulator *vdds_dsi_reg;
+
+ struct {
+ enum dsi_vc_mode mode;
+ struct omap_dss_device *dssdev;
+ enum fifo_size fifo_size;
+ int dest_per; /* destination peripheral 0-3 */
+ } vc[4];
+
+ struct mutex lock;
+ struct mutex bus_lock;
+
+ unsigned pll_locked;
+
+ struct completion bta_completion;
+
+ struct task_struct *thread;
+ wait_queue_head_t waitqueue;
+
+ spinlock_t update_lock;
+ bool framedone_received;
+ struct dsi_update_region update_region;
+ struct dsi_update_region active_update_region;
+ struct completion update_completion;
+
+ enum omap_dss_update_mode user_update_mode;
+ enum omap_dss_update_mode update_mode;
+ bool te_enabled;
+ bool use_ext_te;
+
+ unsigned long cache_req_pck;
+ unsigned long cache_clk_freq;
+ struct dsi_clock_info cache_cinfo;
+
+ u32 errors;
+ spinlock_t errors_lock;
+#ifdef DEBUG
+ ktime_t perf_setup_time;
+ ktime_t perf_start_time;
+ ktime_t perf_start_time_auto;
+ int perf_measure_frames;
+#endif
+ int debug_read;
+ int debug_write;
+} dsi;
+
+#ifdef DEBUG
+static unsigned int dsi_perf;
+module_param_named(dsi_perf, dsi_perf, bool, 0644);
+#endif
+
+static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
+{
+ __raw_writel(val, dsi.base + idx.idx);
+}
+
+static inline u32 dsi_read_reg(const struct dsi_reg idx)
+{
+ return __raw_readl(dsi.base + idx.idx);
+}
+
+
+void dsi_save_context(void)
+{
+}
+
+void dsi_restore_context(void)
+{
+}
+
+void dsi_bus_lock(void)
+{
+ mutex_lock(&dsi.bus_lock);
+}
+EXPORT_SYMBOL(dsi_bus_lock);
+
+void dsi_bus_unlock(void)
+{
+ mutex_unlock(&dsi.bus_lock);
+}
+EXPORT_SYMBOL(dsi_bus_unlock);
+
+static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
+ int value)
+{
+ int t = 100000;
+
+ while (REG_GET(idx, bitnum, bitnum) != value) {
+ if (--t == 0)
+ return !value;
+ }
+
+ return value;
+}
+
+#ifdef DEBUG
+static void dsi_perf_mark_setup(void)
+{
+ dsi.perf_setup_time = ktime_get();
+}
+
+static void dsi_perf_mark_start(void)
+{
+ dsi.perf_start_time = ktime_get();
+}
+
+static void dsi_perf_mark_start_auto(void)
+{
+ dsi.perf_measure_frames = 0;
+ dsi.perf_start_time_auto = ktime_get();
+}
+
+static void dsi_perf_show(const char *name)
+{
+ ktime_t t, setup_time, trans_time;
+ u32 total_bytes;
+ u32 setup_us, trans_us, total_us;
+
+ if (!dsi_perf)
+ return;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+ return;
+
+ t = ktime_get();
+
+ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
+ setup_us = (u32)ktime_to_us(setup_time);
+ if (setup_us == 0)
+ setup_us = 1;
+
+ trans_time = ktime_sub(t, dsi.perf_start_time);
+ trans_us = (u32)ktime_to_us(trans_time);
+ if (trans_us == 0)
+ trans_us = 1;
+
+ total_us = setup_us + trans_us;
+
+ total_bytes = dsi.active_update_region.w *
+ dsi.active_update_region.h *
+ dsi.active_update_region.device->ctrl.pixel_size / 8;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
+ static u32 s_total_trans_us, s_total_setup_us;
+ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
+ static u32 s_max_trans_us, s_max_setup_us;
+ const int numframes = 100;
+ ktime_t total_time_auto;
+ u32 total_time_auto_us;
+
+ dsi.perf_measure_frames++;
+
+ if (setup_us < s_min_setup_us)
+ s_min_setup_us = setup_us;
+
+ if (setup_us > s_max_setup_us)
+ s_max_setup_us = setup_us;
+
+ s_total_setup_us += setup_us;
+
+ if (trans_us < s_min_trans_us)
+ s_min_trans_us = trans_us;
+
+ if (trans_us > s_max_trans_us)
+ s_max_trans_us = trans_us;
+
+ s_total_trans_us += trans_us;
+
+ if (dsi.perf_measure_frames < numframes)
+ return;
+
+ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
+ total_time_auto_us = (u32)ktime_to_us(total_time_auto);
+
+ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
+ "trans %u/%u/%u\n",
+ name,
+ 1000 * 1000 * numframes / total_time_auto_us,
+ s_min_setup_us,
+ s_max_setup_us,
+ s_total_setup_us / numframes,
+ s_min_trans_us,
+ s_max_trans_us,
+ s_total_trans_us / numframes);
+
+ s_total_setup_us = 0;
+ s_min_setup_us = 0xffffffff;
+ s_max_setup_us = 0;
+ s_total_trans_us = 0;
+ s_min_trans_us = 0xffffffff;
+ s_max_trans_us = 0;
+ dsi_perf_mark_start_auto();
+ } else {
+ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
+ "%u bytes, %u kbytes/sec\n",
+ name,
+ setup_us,
+ trans_us,
+ total_us,
+ 1000*1000 / total_us,
+ total_bytes,
+ total_bytes * 1000 / total_us);
+ }
+}
+#else
+#define dsi_perf_mark_setup()
+#define dsi_perf_mark_start()
+#define dsi_perf_mark_start_auto()
+#define dsi_perf_show(x)
+#endif
+
+static void print_irq_status(u32 status)
+{
+#ifndef VERBOSE_IRQ
+ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+ return;
+#endif
+ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
+
+#define PIS(x) \
+ if (status & DSI_IRQ_##x) \
+ printk(#x " ");
+#ifdef VERBOSE_IRQ
+ PIS(VC0);
+ PIS(VC1);
+ PIS(VC2);
+ PIS(VC3);
+#endif
+ PIS(WAKEUP);
+ PIS(RESYNC);
+ PIS(PLL_LOCK);
+ PIS(PLL_UNLOCK);
+ PIS(PLL_RECALL);
+ PIS(COMPLEXIO_ERR);
+ PIS(HS_TX_TIMEOUT);
+ PIS(LP_RX_TIMEOUT);
+ PIS(TE_TRIGGER);
+ PIS(ACK_TRIGGER);
+ PIS(SYNC_LOST);
+ PIS(LDO_POWER_GOOD);
+ PIS(TA_TIMEOUT);
+#undef PIS
+
+ printk("\n");
+}
+
+static void print_irq_status_vc(int channel, u32 status)
+{
+#ifndef VERBOSE_IRQ
+ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+ return;
+#endif
+ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
+
+#define PIS(x) \
+ if (status & DSI_VC_IRQ_##x) \
+ printk(#x " ");
+ PIS(CS);
+ PIS(ECC_CORR);
+#ifdef VERBOSE_IRQ
+ PIS(PACKET_SENT);
+#endif
+ PIS(FIFO_TX_OVF);
+ PIS(FIFO_RX_OVF);
+ PIS(BTA);
+ PIS(ECC_NO_CORR);
+ PIS(FIFO_TX_UDF);
+ PIS(PP_BUSY_CHANGE);
+#undef PIS
+ printk("\n");
+}
+
+static void print_irq_status_cio(u32 status)
+{
+ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
+
+#define PIS(x) \
+ if (status & DSI_CIO_IRQ_##x) \
+ printk(#x " ");
+ PIS(ERRSYNCESC1);
+ PIS(ERRSYNCESC2);
+ PIS(ERRSYNCESC3);
+ PIS(ERRESC1);
+ PIS(ERRESC2);
+ PIS(ERRESC3);
+ PIS(ERRCONTROL1);
+ PIS(ERRCONTROL2);
+ PIS(ERRCONTROL3);
+ PIS(STATEULPS1);
+ PIS(STATEULPS2);
+ PIS(STATEULPS3);
+ PIS(ERRCONTENTIONLP0_1);
+ PIS(ERRCONTENTIONLP1_1);
+ PIS(ERRCONTENTIONLP0_2);
+ PIS(ERRCONTENTIONLP1_2);
+ PIS(ERRCONTENTIONLP0_3);
+ PIS(ERRCONTENTIONLP1_3);
+ PIS(ULPSACTIVENOT_ALL0);
+ PIS(ULPSACTIVENOT_ALL1);
+#undef PIS
+
+ printk("\n");
+}
+
+static int debug_irq;
+
+/* called from dss */
+void dsi_irq_handler(void)
+{
+ u32 irqstatus, vcstatus, ciostatus;
+ int i;
+
+ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
+
+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
+ DSSERR("DSI error, irqstatus %x\n", irqstatus);
+ print_irq_status(irqstatus);
+ spin_lock(&dsi.errors_lock);
+ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
+ spin_unlock(&dsi.errors_lock);
+ } else if (debug_irq) {
+ print_irq_status(irqstatus);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ if ((irqstatus & (1<<i)) == 0)
+ continue;
+
+ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+ if (vcstatus & DSI_VC_IRQ_BTA)
+ complete(&dsi.bta_completion);
+
+ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
+ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
+ i, vcstatus);
+ print_irq_status_vc(i, vcstatus);
+ } else if (debug_irq) {
+ print_irq_status_vc(i, vcstatus);
+ }
+
+ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
+ }
+
+ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
+ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
+
+ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+ print_irq_status_cio(ciostatus);
+ }
+
+ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+}
+
+
+static void _dsi_initialize_irq(void)
+{
+ u32 l;
+ int i;
+
+ /* disable all interrupts */
+ dsi_write_reg(DSI_IRQENABLE, 0);
+ for (i = 0; i < 4; ++i)
+ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
+
+ /* clear interrupt status */
+ l = dsi_read_reg(DSI_IRQSTATUS);
+ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
+
+ for (i = 0; i < 4; ++i) {
+ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
+ }
+
+ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
+
+ /* enable error irqs */
+ l = DSI_IRQ_ERROR_MASK;
+ dsi_write_reg(DSI_IRQENABLE, l);
+
+ l = DSI_VC_IRQ_ERROR_MASK;
+ for (i = 0; i < 4; ++i)
+ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
+
+ /* XXX zonda responds incorrectly, causing control error:
+ Exit from LP-ESC mode to LP11 uses wrong transition states on the
+ data lines LP0 and LN0. */
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
+}
+
+static u32 dsi_get_errors(void)
+{
+ unsigned long flags;
+ u32 e;
+ spin_lock_irqsave(&dsi.errors_lock, flags);
+ e = dsi.errors;
+ dsi.errors = 0;
+ spin_unlock_irqrestore(&dsi.errors_lock, flags);
+ return e;
+}
+
+static void dsi_vc_enable_bta_irq(int channel)
+{
+ u32 l;
+
+ dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
+
+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+ l |= DSI_VC_IRQ_BTA;
+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+static void dsi_vc_disable_bta_irq(int channel)
+{
+ u32 l;
+
+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+ l &= ~DSI_VC_IRQ_BTA;
+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+/* DSI func clock. this could also be DSI2_PLL_FCLK */
+static inline void enable_clocks(bool enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+/* source clock for DSI PLL. this could also be PCLKFREE */
+static inline void dsi_enable_pll_clock(bool enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_FCK2);
+ else
+ dss_clk_disable(DSS_CLK_FCK2);
+
+ if (enable && dsi.pll_locked) {
+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
+ DSSERR("cannot lock PLL when enabling clocks\n");
+ }
+}
+
+#ifdef DEBUG
+static void _dsi_print_reset_status(void)
+{
+ u32 l;
+
+ if (!dss_debug)
+ return;
+
+ /* A dummy read using the SCP interface to any DSIPHY register is
+ * required after DSIPHY reset to complete the reset of the DSI complex
+ * I/O. */
+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
+
+ printk(KERN_DEBUG "DSI resets: ");
+
+ l = dsi_read_reg(DSI_PLL_STATUS);
+ printk("PLL (%d) ", FLD_GET(l, 0, 0));
+
+ l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+ printk("CIO (%d) ", FLD_GET(l, 29, 29));
+
+ l = dsi_read_reg(DSI_DSIPHY_CFG5);
+ printk("PHY (%x, %d, %d, %d)\n",
+ FLD_GET(l, 28, 26),
+ FLD_GET(l, 29, 29),
+ FLD_GET(l, 30, 30),
+ FLD_GET(l, 31, 31));
+}
+#else
+#define _dsi_print_reset_status()
+#endif
+
+static inline int dsi_if_enable(bool enable)
+{
+ DSSDBG("dsi_if_enable(%d)\n", enable);
+
+ enable = enable ? 1 : 0;
+ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
+
+ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
+ DSSERR("Failed to set dsi_if_enable to %d\n", enable);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static unsigned long dsi_fclk_rate(void)
+{
+ unsigned long r;
+
+ if (dss_get_dsi_clk_source() == 0) {
+ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
+ r = dss_clk_get_rate(DSS_CLK_FCK1);
+ } else {
+ /* DSI FCLK source is DSI2_PLL_FCLK */
+ r = dsi.dsi2_pll_fclk;
+ }
+
+ return r;
+}
+
+static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
+{
+ unsigned n;
+ unsigned long dsi_fclk;
+ unsigned long lp_clk, lp_clk_req;
+
+ dsi_fclk = dsi_fclk_rate();
+
+ lp_clk_req = dssdev->phy.dsi.lp_clk_hz;
+
+ for (n = 1; n < (1 << 13) - 1; ++n) {
+ lp_clk = dsi_fclk / 2 / n;
+ if (lp_clk <= lp_clk_req)
+ break;
+ }
+
+ if (n == (1 << 13) - 1) {
+ DSSERR("Failed to find LP_CLK_DIVISOR\n");
+ return -EINVAL;
+ }
+
+ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
+
+ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
+ if (dsi_fclk > 30*1000*1000)
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
+
+ return 0;
+}
+
+
+enum dsi_pll_power_state {
+ DSI_PLL_POWER_OFF = 0x0,
+ DSI_PLL_POWER_ON_HSCLK = 0x1,
+ DSI_PLL_POWER_ON_ALL = 0x2,
+ DSI_PLL_POWER_ON_DIV = 0x3,
+};
+
+static int dsi_pll_power(enum dsi_pll_power_state state)
+{
+ int t = 0;
+
+ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
+
+ /* PLL_PWR_STATUS */
+ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
+ udelay(1);
+ if (t++ > 1000) {
+ DSSERR("Failed to set DSI PLL power mode to %d\n",
+ state);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ struct dsi_clock_info *cinfo)
+{
+ struct dsi_clock_info cur, best;
+ int min_fck_per_pck;
+ int match = 0;
+ unsigned long dss_clk_fck2;
+
+ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
+
+ if (req_pck == dsi.cache_req_pck &&
+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ DSSDBG("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+ }
+
+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+ if (min_fck_per_pck &&
+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+ DSSERR("Requested pixel clock not possible with the current "
+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+ "the constraint off.\n");
+ min_fck_per_pck = 0;
+ }
+
+ DSSDBG("dsi_pll_calc\n");
+
+retry:
+ memset(&best, 0, sizeof(best));
+
+ memset(&cur, 0, sizeof(cur));
+ cur.clkin = dss_clk_fck2;
+ cur.use_dss2_fck = 1;
+ cur.highfreq = 0;
+
+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+ if (cur.highfreq == 0)
+ cur.fint = cur.clkin / cur.regn;
+ else
+ cur.fint = cur.clkin / (2 * cur.regn);
+
+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+ continue;
+
+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+ unsigned long a, b;
+
+ a = 2 * cur.regm * (cur.clkin/1000);
+ b = cur.regn * (cur.highfreq + 1);
+ cur.dsiphy = a / b * 1000;
+
+ if (cur.dsiphy > 1800 * 1000 * 1000)
+ break;
+
+ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
+ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
+ ++cur.regm3) {
+ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
+
+ /* this will narrow down the search a bit,
+ * but still give pixclocks below what was
+ * requested */
+ if (cur.dsi1_pll_fclk < req_pck)
+ break;
+
+ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
+ continue;
+
+ if (min_fck_per_pck &&
+ cur.dsi1_pll_fclk <
+ req_pck * min_fck_per_pck)
+ continue;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck,
+ cur.dsi1_pll_fclk,
+ &cur.lck_div,
+ &cur.pck_div);
+
+ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ if (abs(cur.pck - req_pck) <
+ abs(best.pck - req_pck)) {
+ best = cur;
+
+ if (cur.pck == req_pck)
+ goto found;
+ }
+ }
+ }
+ }
+found:
+ if (!match) {
+ if (min_fck_per_pck) {
+ DSSERR("Could not find suitable clock settings.\n"
+ "Turning FCK/PCK constraint off and"
+ "trying again.\n");
+ min_fck_per_pck = 0;
+ goto retry;
+ }
+
+ DSSERR("Could not find suitable clock settings.\n");
+
+ return -EINVAL;
+ }
+
+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
+ best.regm4 = best.dsiphy / 48000000;
+ if (best.regm4 > REGM4_MAX)
+ best.regm4 = REGM4_MAX;
+ else if (best.regm4 == 0)
+ best.regm4 = 1;
+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
+
+ if (cinfo)
+ *cinfo = best;
+
+ dsi.cache_req_pck = req_pck;
+ dsi.cache_clk_freq = 0;
+ dsi.cache_cinfo = best;
+
+ return 0;
+}
+
+static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
+ struct dsi_clock_info *cinfo)
+{
+ struct dsi_clock_info cur, best;
+ const bool use_dss2_fck = 1;
+ unsigned long datafreq;
+ unsigned long dss_clk_fck2;
+
+ DSSDBG("dsi_pll_calc_ddrfreq\n");
+
+ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
+
+ if (clk_freq == dsi.cache_clk_freq &&
+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ DSSDBG("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+ }
+
+ datafreq = clk_freq * 4;
+
+ memset(&best, 0, sizeof(best));
+
+ memset(&cur, 0, sizeof(cur));
+ cur.use_dss2_fck = use_dss2_fck;
+ if (use_dss2_fck) {
+ cur.clkin = dss_clk_fck2;
+ cur.highfreq = 0;
+ } else {
+ /* TODO: Add support for LCD2 */
+ cur.clkin = dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD);
+ if (cur.clkin < 32000000)
+ cur.highfreq = 0;
+ else
+ cur.highfreq = 1;
+ }
+
+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+ if (cur.highfreq == 0)
+ cur.fint = cur.clkin / cur.regn;
+ else
+ cur.fint = cur.clkin / (2 * cur.regn);
+
+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+ continue;
+
+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+ unsigned long a, b;
+
+ a = 2 * cur.regm * (cur.clkin/1000);
+ b = cur.regn * (cur.highfreq + 1);
+ cur.dsiphy = a / b * 1000;
+
+ if (cur.dsiphy > 1800 * 1000 * 1000)
+ break;
+
+ if (abs(cur.dsiphy - datafreq) <
+ abs(best.dsiphy - datafreq)) {
+ best = cur;
+ /* DSSDBG("best %ld\n", best.dsiphy); */
+ }
+
+ if (cur.dsiphy == datafreq)
+ goto found;
+ }
+ }
+found:
+ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
+ best.regm3 = best.dsiphy / 48000000;
+ if (best.regm3 > REGM3_MAX)
+ best.regm3 = REGM3_MAX;
+ else if (best.regm3 == 0)
+ best.regm3 = 1;
+ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
+
+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
+ best.regm4 = best.dsiphy / 48000000;
+ if (best.regm4 > REGM4_MAX)
+ best.regm4 = REGM4_MAX;
+ else if (best.regm4 == 0)
+ best.regm4 = 1;
+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
+
+ if (cinfo)
+ *cinfo = best;
+
+ dsi.cache_clk_freq = clk_freq;
+ dsi.cache_req_pck = 0;
+ dsi.cache_cinfo = best;
+
+ return 0;
+}
+
+int dsi_pll_program(struct dsi_clock_info *cinfo)
+{
+ int r = 0;
+ u32 l;
+
+ DSSDBG("dsi_pll_program\n");
+
+ dsi.dsiphy = cinfo->dsiphy;
+ dsi.ddr_clk = dsi.dsiphy / 4;
+ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
+ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+
+ DSSDBG("DSI Fint %ld\n", cinfo->fint);
+
+ DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
+ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
+ cinfo->clkin,
+ cinfo->highfreq);
+
+ /* DSIPHY == CLKIN4DDR */
+ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
+ cinfo->regm,
+ cinfo->regn,
+ cinfo->clkin,
+ cinfo->highfreq + 1,
+ cinfo->dsiphy);
+
+ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
+ dsi.dsiphy / 1000 / 1000 / 2);
+
+ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
+
+ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
+ cinfo->regm3, cinfo->dsi1_pll_fclk);
+ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
+ cinfo->regm4, cinfo->dsi2_pll_fclk);
+
+ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
+ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
+ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
+ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
+ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
+ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
+ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
+ /* DSI_PLL_CLKSEL */
+ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
+ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
+
+ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
+ DSSERR("dsi pll go bit not going down.\n");
+ r = -EIO;
+ goto err;
+ }
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
+ DSSERR("cannot lock PLL\n");
+ r = -EIO;
+ goto err;
+ }
+
+ dsi.pll_locked = 1;
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
+ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
+ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
+ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
+ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
+ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
+ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
+ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
+ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
+ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
+ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ DSSDBG("PLL config done\n");
+err:
+ return r;
+}
+
+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+{
+ int r = 0;
+ enum dsi_pll_power_state pwstate;
+ struct dispc_clock_info cinfo;
+
+ DSSDBG("PLL init\n");
+
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ /* XXX this should be calculated depending on the screen size,
+ * required framerate and DSI speed.
+ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
+ * with two lanes */
+ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
+ if (r)
+ goto err0;
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r) {
+ DSSERR("Failed to set basic clocks\n");
+ goto err0;
+ }
+
+ r = regulator_enable(dsi.vdds_dsi_reg);
+ if (r)
+ goto err0;
+
+ /* XXX PLL does not come out of reset without this... */
+ dispc_pck_free_enable(1);
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
+ DSSERR("PLL not coming out of reset.\n");
+ r = -ENODEV;
+ goto err1;
+ }
+
+ /* XXX ... but if left on, we get problems when planes do not
+ * fill the whole display. No idea about this */
+ dispc_pck_free_enable(0);
+
+ if (enable_hsclk && enable_hsdiv)
+ pwstate = DSI_PLL_POWER_ON_ALL;
+ else if (enable_hsclk)
+ pwstate = DSI_PLL_POWER_ON_HSCLK;
+ else if (enable_hsdiv)
+ pwstate = DSI_PLL_POWER_ON_DIV;
+ else
+ pwstate = DSI_PLL_POWER_OFF;
+
+ r = dsi_pll_power(pwstate);
+
+ if (r)
+ goto err1;
+
+ DSSDBG("PLL init done\n");
+
+ return 0;
+err1:
+ regulator_disable(dsi.vdds_dsi_reg);
+err0:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+ return r;
+}
+
+void dsi_pll_uninit(void)
+{
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+
+ dsi.pll_locked = 0;
+ dsi_pll_power(DSI_PLL_POWER_OFF);
+ regulator_disable(dsi.vdds_dsi_reg);
+ DSSDBG("PLL uninit done\n");
+}
+
+unsigned long dsi_get_dsi1_pll_rate(void)
+{
+ return dsi.dsi1_pll_fclk;
+}
+
+unsigned long dsi_get_dsi2_pll_rate(void)
+{
+ return dsi.dsi2_pll_fclk;
+}
+
+void dsi_dump_clocks(struct seq_file *s)
+{
+ int clksel;
+
+ enable_clocks(1);
+
+ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
+
+ seq_printf(s, "- dsi -\n");
+
+ seq_printf(s, "dsi fclk source = %s\n",
+ dss_get_dsi_clk_source() == 0 ?
+ "dss1_alwon_fclk" : "dsi2_pll_fclk");
+
+ seq_printf(s, "dsi pll source = %s\n",
+ clksel == 0 ?
+ "dss2_alwon_fclk" : "pclkfree");
+
+ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
+ dsi.dsiphy, dsi.ddr_clk);
+
+ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n"
+ "dsi2_pll_fck\t%lu (%s)\n",
+ dsi.dsi1_pll_fclk,
+ dss_get_dispc_clk_source() == 0 ? "off" : "on",
+ dsi.dsi2_pll_fclk,
+ dss_get_dsi_clk_source() == 0 ? "off" : "on");
+
+ enable_clocks(0);
+}
+
+void dsi_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ DUMPREG(DSI_REVISION);
+ DUMPREG(DSI_SYSCONFIG);
+ DUMPREG(DSI_SYSSTATUS);
+ DUMPREG(DSI_IRQSTATUS);
+ DUMPREG(DSI_IRQENABLE);
+ DUMPREG(DSI_CTRL);
+ DUMPREG(DSI_COMPLEXIO_CFG1);
+ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
+ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
+ DUMPREG(DSI_CLK_CTRL);
+ DUMPREG(DSI_TIMING1);
+ DUMPREG(DSI_TIMING2);
+ DUMPREG(DSI_VM_TIMING1);
+ DUMPREG(DSI_VM_TIMING2);
+ DUMPREG(DSI_VM_TIMING3);
+ DUMPREG(DSI_CLK_TIMING);
+ DUMPREG(DSI_TX_FIFO_VC_SIZE);
+ DUMPREG(DSI_RX_FIFO_VC_SIZE);
+ DUMPREG(DSI_COMPLEXIO_CFG2);
+ DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
+ DUMPREG(DSI_VM_TIMING4);
+ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
+ DUMPREG(DSI_VM_TIMING5);
+ DUMPREG(DSI_VM_TIMING6);
+ DUMPREG(DSI_VM_TIMING7);
+ DUMPREG(DSI_STOPCLK_TIMING);
+
+ DUMPREG(DSI_VC_CTRL(0));
+ DUMPREG(DSI_VC_TE(0));
+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
+ DUMPREG(DSI_VC_IRQSTATUS(0));
+ DUMPREG(DSI_VC_IRQENABLE(0));
+
+ DUMPREG(DSI_VC_CTRL(1));
+ DUMPREG(DSI_VC_TE(1));
+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
+ DUMPREG(DSI_VC_IRQSTATUS(1));
+ DUMPREG(DSI_VC_IRQENABLE(1));
+
+ DUMPREG(DSI_VC_CTRL(2));
+ DUMPREG(DSI_VC_TE(2));
+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
+ DUMPREG(DSI_VC_IRQSTATUS(2));
+ DUMPREG(DSI_VC_IRQENABLE(2));
+
+ DUMPREG(DSI_VC_CTRL(3));
+ DUMPREG(DSI_VC_TE(3));
+ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
+ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
+ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
+ DUMPREG(DSI_VC_IRQSTATUS(3));
+ DUMPREG(DSI_VC_IRQENABLE(3));
+
+ DUMPREG(DSI_DSIPHY_CFG0);
+ DUMPREG(DSI_DSIPHY_CFG1);
+ DUMPREG(DSI_DSIPHY_CFG2);
+ DUMPREG(DSI_DSIPHY_CFG5);
+
+ DUMPREG(DSI_PLL_CONTROL);
+ DUMPREG(DSI_PLL_STATUS);
+ DUMPREG(DSI_PLL_GO);
+ DUMPREG(DSI_PLL_CONFIGURATION1);
+ DUMPREG(DSI_PLL_CONFIGURATION2);
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+#undef DUMPREG
+}
+
+enum dsi_complexio_power_state {
+ DSI_COMPLEXIO_POWER_OFF = 0x0,
+ DSI_COMPLEXIO_POWER_ON = 0x1,
+ DSI_COMPLEXIO_POWER_ULPS = 0x2,
+};
+
+static int dsi_complexio_power(enum dsi_complexio_power_state state)
+{
+ int t = 0;
+
+ /* PWR_CMD */
+ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
+
+ /* PWR_STATUS */
+ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
+ udelay(1);
+ if (t++ > 1000) {
+ DSSERR("failed to set complexio power state to "
+ "%d\n", state);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static void dsi_complexio_config(struct omap_dss_device *dssdev)
+{
+ u32 r;
+
+ int clk_lane = dssdev->phy.dsi.clk_lane;
+ int data1_lane = dssdev->phy.dsi.data1_lane;
+ int data2_lane = dssdev->phy.dsi.data2_lane;
+ int clk_pol = dssdev->phy.dsi.clk_pol;
+ int data1_pol = dssdev->phy.dsi.data1_pol;
+ int data2_pol = dssdev->phy.dsi.data2_pol;
+
+ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+ r = FLD_MOD(r, clk_lane, 2, 0);
+ r = FLD_MOD(r, clk_pol, 3, 3);
+ r = FLD_MOD(r, data1_lane, 6, 4);
+ r = FLD_MOD(r, data1_pol, 7, 7);
+ r = FLD_MOD(r, data2_lane, 10, 8);
+ r = FLD_MOD(r, data2_pol, 11, 11);
+ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
+
+ /* The configuration of the DSI complex I/O (number of data lanes,
+ position, differential order) should not be changed while
+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
+ the hardware to take into account a new configuration of the complex
+ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
+ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
+ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
+ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
+ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
+ DSI complex I/O configuration is unknown. */
+
+ /*
+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+ */
+}
+
+static inline unsigned ns2ddr(unsigned ns)
+{
+ /* convert time in ns to ddr ticks, rounding up */
+ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
+}
+
+static inline unsigned ddr2ns(unsigned ddr)
+{
+ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
+}
+
+static void dsi_complexio_timings(void)
+{
+ u32 r;
+ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
+ u32 tlpx_half, tclk_trail, tclk_zero;
+ u32 tclk_prepare;
+
+ /* calculate timings */
+
+ /* 1 * DDR_CLK = 2 * UI */
+
+ /* min 40ns + 4*UI max 85ns + 6*UI */
+ ths_prepare = ns2ddr(70) + 2;
+
+ /* min 145ns + 10*UI */
+ ths_prepare_ths_zero = ns2ddr(175) + 2;
+
+ /* min max(8*UI, 60ns+4*UI) */
+ ths_trail = ns2ddr(60) + 5;
+
+ /* min 100ns */
+ ths_exit = ns2ddr(145);
+
+ /* tlpx min 50n */
+ tlpx_half = ns2ddr(25);
+
+ /* min 60ns */
+ tclk_trail = ns2ddr(60) + 2;
+
+ /* min 38ns, max 95ns */
+ tclk_prepare = ns2ddr(65);
+
+ /* min tclk-prepare + tclk-zero = 300ns */
+ tclk_zero = ns2ddr(260);
+
+ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
+ ths_prepare, ddr2ns(ths_prepare),
+ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
+ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
+ ths_trail, ddr2ns(ths_trail),
+ ths_exit, ddr2ns(ths_exit));
+
+ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
+ "tclk_zero %u (%uns)\n",
+ tlpx_half, ddr2ns(tlpx_half),
+ tclk_trail, ddr2ns(tclk_trail),
+ tclk_zero, ddr2ns(tclk_zero));
+ DSSDBG("tclk_prepare %u (%uns)\n",
+ tclk_prepare, ddr2ns(tclk_prepare));
+
+ /* program timings */
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
+ r = FLD_MOD(r, ths_prepare, 31, 24);
+ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
+ r = FLD_MOD(r, ths_trail, 15, 8);
+ r = FLD_MOD(r, ths_exit, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG0, r);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+ r = FLD_MOD(r, tlpx_half, 22, 16);
+ r = FLD_MOD(r, tclk_trail, 15, 8);
+ r = FLD_MOD(r, tclk_zero, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG1, r);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
+ r = FLD_MOD(r, tclk_prepare, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG2, r);
+}
+
+
+static int dsi_complexio_init(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("dsi_complexio_init\n");
+
+ /* CIO_CLK_ICG, enable L3 clk to CIO */
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
+ /* A dummy read using the SCP interface to any DSIPHY register is
+ * required after DSIPHY reset to complete the reset of the DSI complex
+ * I/O. */
+ dsi_read_reg(DSI_DSIPHY_CFG5);
+
+ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
+ DSSERR("ComplexIO PHY not coming out of reset.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ dsi_complexio_config(dssdev);
+
+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+
+ if (r)
+ goto err;
+
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
+ DSSERR("ComplexIO not coming out of reset.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+ DSSERR("ComplexIO LDO power down.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ dsi_complexio_timings();
+
+ /*
+ The configuration of the DSI complex I/O (number of data lanes,
+ position, differential order) should not be changed while
+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
+ hardware to recognize a new configuration of the complex I/O (done
+ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
+ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
+ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
+ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
+ bit to 1. If the sequence is not followed, the DSi complex I/O
+ configuration is undetermined.
+ */
+ dsi_if_enable(1);
+ dsi_if_enable(0);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+ dsi_if_enable(1);
+ dsi_if_enable(0);
+
+ DSSDBG("CIO init done\n");
+err:
+ return r;
+}
+
+static void dsi_complexio_uninit(void)
+{
+ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
+}
+
+static int _dsi_wait_reset(void)
+{
+ int i = 0;
+
+ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
+ if (i++ > 5) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _dsi_reset(void)
+{
+ /* Soft reset */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
+ return _dsi_wait_reset();
+}
+
+
+static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
+ enum fifo_size size3, enum fifo_size size4)
+{
+ u32 r = 0;
+ int add = 0;
+ int i;
+
+ dsi.vc[0].fifo_size = size1;
+ dsi.vc[1].fifo_size = size2;
+ dsi.vc[2].fifo_size = size3;
+ dsi.vc[3].fifo_size = size4;
+
+ for (i = 0; i < 4; i++) {
+ u8 v;
+ int size = dsi.vc[i].fifo_size;
+
+ if (add + size > 4) {
+ DSSERR("Illegal FIFO configuration\n");
+ BUG();
+ }
+
+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+ r |= v << (8 * i);
+ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
+ add += size;
+ }
+
+ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
+}
+
+static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
+ enum fifo_size size3, enum fifo_size size4)
+{
+ u32 r = 0;
+ int add = 0;
+ int i;
+
+ dsi.vc[0].fifo_size = size1;
+ dsi.vc[1].fifo_size = size2;
+ dsi.vc[2].fifo_size = size3;
+ dsi.vc[3].fifo_size = size4;
+
+ for (i = 0; i < 4; i++) {
+ u8 v;
+ int size = dsi.vc[i].fifo_size;
+
+ if (add + size > 4) {
+ DSSERR("Illegal FIFO configuration\n");
+ BUG();
+ }
+
+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+ r |= v << (8 * i);
+ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
+ add += size;
+ }
+
+ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
+}
+
+static int dsi_force_tx_stop_mode_io(void)
+{
+ u32 r;
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
+ dsi_write_reg(DSI_TIMING1, r);
+
+ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
+ DSSERR("TX_STOP bit not going down\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void dsi_vc_print_status(int channel)
+{
+ u32 r;
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
+ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
+ channel,
+ FLD_GET(r, 5, 5),
+ FLD_GET(r, 6, 6),
+ FLD_GET(r, 15, 15),
+ FLD_GET(r, 16, 16),
+ FLD_GET(r, 20, 20));
+
+ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
+ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
+}
+
+static int dsi_vc_enable(int channel, bool enable)
+{
+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("dsi_vc_enable channel %d, enable %d\n",
+ channel, enable);
+
+ enable = enable ? 1 : 0;
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
+
+ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
+ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void dsi_vc_initial_config(int channel)
+{
+ u32 r;
+
+ DSSDBGF("%d", channel);
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+
+ if (FLD_GET(r, 15, 15)) /* VC_BUSY */
+ DSSERR("VC(%d) busy when trying to configure it!\n",
+ channel);
+
+ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+
+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+ dsi_write_reg(DSI_VC_CTRL(channel), r);
+ dsi.vc[channel].mode = DSI_VC_MODE_L4;
+}
+
+static void dsi_vc_config_l4(int channel)
+{
+ if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
+ return;
+
+ DSSDBGF("%d", channel);
+
+ dsi_vc_enable(channel, 0);
+
+ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
+ DSSERR("vc(%d) busy when trying to config for L4\n", channel);
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
+
+ dsi_vc_enable(channel, 1);
+
+ dsi.vc[channel].mode = DSI_VC_MODE_L4;
+}
+
+static void dsi_vc_config_vp(int channel)
+{
+ if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
+ return;
+
+ DSSDBGF("%d", channel);
+
+ dsi_vc_enable(channel, 0);
+
+ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
+ DSSERR("vc(%d) busy when trying to config for VP\n", channel);
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
+
+ dsi_vc_enable(channel, 1);
+
+ dsi.vc[channel].mode = DSI_VC_MODE_VP;
+}
+
+
+static void dsi_vc_enable_hs(int channel, bool enable)
+{
+ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
+
+ dsi_vc_enable(channel, 0);
+ dsi_if_enable(0);
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
+
+ dsi_vc_enable(channel, 1);
+ dsi_if_enable(1);
+
+ dsi_force_tx_stop_mode_io();
+}
+
+static void dsi_vc_flush_long_data(int channel)
+{
+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+ u32 val;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
+ (val >> 0) & 0xff,
+ (val >> 8) & 0xff,
+ (val >> 16) & 0xff,
+ (val >> 24) & 0xff);
+ }
+}
+
+static void dsi_show_rx_ack_with_err(u16 err)
+{
+ DSSERR("\tACK with ERROR (%#x):\n", err);
+ if (err & (1 << 0))
+ DSSERR("\t\tSoT Error\n");
+ if (err & (1 << 1))
+ DSSERR("\t\tSoT Sync Error\n");
+ if (err & (1 << 2))
+ DSSERR("\t\tEoT Sync Error\n");
+ if (err & (1 << 3))
+ DSSERR("\t\tEscape Mode Entry Command Error\n");
+ if (err & (1 << 4))
+ DSSERR("\t\tLP Transmit Sync Error\n");
+ if (err & (1 << 5))
+ DSSERR("\t\tHS Receive Timeout Error\n");
+ if (err & (1 << 6))
+ DSSERR("\t\tFalse Control Error\n");
+ if (err & (1 << 7))
+ DSSERR("\t\t(reserved7)\n");
+ if (err & (1 << 8))
+ DSSERR("\t\tECC Error, single-bit (corrected)\n");
+ if (err & (1 << 9))
+ DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
+ if (err & (1 << 10))
+ DSSERR("\t\tChecksum Error\n");
+ if (err & (1 << 11))
+ DSSERR("\t\tData type not recognized\n");
+ if (err & (1 << 12))
+ DSSERR("\t\tInvalid VC ID\n");
+ if (err & (1 << 13))
+ DSSERR("\t\tInvalid Transmission Length\n");
+ if (err & (1 << 14))
+ DSSERR("\t\t(reserved14)\n");
+ if (err & (1 << 15))
+ DSSERR("\t\tDSI Protocol Violation\n");
+}
+
+static u16 dsi_vc_flush_receive_data(int channel)
+{
+ /* RX_FIFO_NOT_EMPTY */
+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+ u32 val;
+ u8 dt;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+ DSSDBG("\trawval %#08x\n", val);
+ dt = FLD_GET(val, 5, 0);
+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ u16 err = FLD_GET(val, 23, 8);
+ dsi_show_rx_ack_with_err(err);
+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ DSSDBG("\tDCS short response, 1 byte: %#x\n",
+ FLD_GET(val, 23, 8));
+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ DSSDBG("\tDCS short response, 2 byte: %#x\n",
+ FLD_GET(val, 23, 8));
+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ DSSDBG("\tDCS long response, len %d\n",
+ FLD_GET(val, 23, 8));
+ dsi_vc_flush_long_data(channel);
+ } else {
+ DSSERR("\tunknown datatype 0x%02x\n", dt);
+ }
+ }
+ return 0;
+}
+
+static int dsi_vc_send_bta(int channel)
+{
+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
+ (dsi.debug_write || dsi.debug_read))
+ DSSDBG("dsi_vc_send_bta %d\n", channel);
+
+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
+ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
+ dsi_vc_flush_receive_data(channel);
+ }
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
+
+ return 0;
+}
+
+int dsi_vc_send_bta_sync(int channel)
+{
+ int r = 0;
+ u32 err;
+
+ INIT_COMPLETION(dsi.bta_completion);
+
+ dsi_vc_enable_bta_irq(channel);
+
+ r = dsi_vc_send_bta(channel);
+ if (r)
+ goto err;
+
+ if (wait_for_completion_timeout(&dsi.bta_completion,
+ msecs_to_jiffies(500)) == 0) {
+ DSSERR("Failed to receive BTA\n");
+ r = -EIO;
+ goto err;
+ }
+
+ err = dsi_get_errors();
+ if (err) {
+ DSSERR("Error while sending BTA: %x\n", err);
+ r = -EIO;
+ goto err;
+ }
+err:
+ dsi_vc_disable_bta_irq(channel);
+
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_send_bta_sync);
+
+static inline void dsi_vc_write_long_header(int channel, u8 data_type,
+ u16 len, u8 ecc)
+{
+ u32 val;
+ u8 data_id;
+
+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+ /*data_id = data_type | channel << 6; */
+ data_id = data_type | dsi.vc[channel].dest_per << 6;
+
+ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
+ FLD_VAL(ecc, 31, 24);
+
+ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
+}
+
+static inline void dsi_vc_write_long_payload(int channel,
+ u8 b1, u8 b2, u8 b3, u8 b4)
+{
+ u32 val;
+
+ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
+
+/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
+ b1, b2, b3, b4, val); */
+
+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
+}
+
+static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
+ u8 ecc)
+{
+ /*u32 val; */
+ int i;
+ u8 *p;
+ int r = 0;
+ u8 b1, b2, b3, b4;
+
+ if (dsi.debug_write)
+ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
+
+ /* len + header */
+ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
+ DSSERR("unable to send long packet: packet too long.\n");
+ return -EINVAL;
+ }
+ dsi_vc_config_l4(channel);
+
+ dsi_vc_write_long_header(channel, data_type, len, ecc);
+
+ /*dsi_vc_print_status(0); */
+
+ p = data;
+ for (i = 0; i < len >> 2; i++) {
+ if (dsi.debug_write)
+ DSSDBG("\tsending full packet %d\n", i);
+ /*dsi_vc_print_status(0); */
+
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ b4 = *p++;
+
+ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
+ }
+
+ i = len % 4;
+ if (i) {
+ b1 = 0; b2 = 0; b3 = 0;
+
+ if (dsi.debug_write)
+ DSSDBG("\tsending remainder bytes %d\n", i);
+
+ switch (i) {
+ case 3:
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ break;
+ case 2:
+ b1 = *p++;
+ b2 = *p++;
+ break;
+ case 1:
+ b1 = *p++;
+ break;
+ }
+
+ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
+ }
+
+ return r;
+}
+
+static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
+{
+ u32 r;
+ u8 data_id;
+
+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+ if (dsi.debug_write)
+ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
+ channel,
+ data_type, data & 0xff, (data >> 8) & 0xff);
+
+ dsi_vc_config_l4(channel);
+
+ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
+ DSSERR("ERROR FIFO FULL, aborting transfer\n");
+ return -EINVAL;
+ }
+
+ data_id = data_type | channel << 6;
+
+ r = (data_id << 0) | (data << 8) | (ecc << 24);
+
+ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
+
+ return 0;
+}
+
+int dsi_vc_send_null(int channel)
+{
+ u8 nullpkg[] = {0, 0, 0, 0};
+ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
+}
+EXPORT_SYMBOL(dsi_vc_send_null);
+
+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
+{
+ int r;
+
+ BUG_ON(len == 0);
+
+ if (len == 1) {
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
+ data[0], 0);
+ } else if (len == 2) {
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
+ data[0] | (data[1] << 8), 0);
+ } else {
+ /* 0x39 = DCS Long Write */
+ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
+ data, len, 0);
+ }
+
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
+
+int dsi_vc_dcs_write(int channel, u8 *data, int len)
+{
+ int r;
+
+ r = dsi_vc_dcs_write_nosync(channel, data, len);
+ if (r)
+ return r;
+
+ /* Some devices need time to process the msg in low power mode.
+ This also makes the write synchronous, and checks that
+ the peripheral is still alive */
+ r = dsi_vc_send_bta_sync(channel);
+
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write);
+
+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
+{
+ u32 val;
+ u8 dt;
+ int r;
+
+ if (dsi.debug_read)
+ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
+
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
+ if (r)
+ return r;
+
+ r = dsi_vc_send_bta_sync(channel);
+ if (r)
+ return r;
+
+ /* RX_FIFO_NOT_EMPTY */
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
+ DSSERR("RX fifo empty when trying to read.\n");
+ return -EIO;
+ }
+
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+ if (dsi.debug_read)
+ DSSDBG("\theader: %08x\n", val);
+ dt = FLD_GET(val, 5, 0);
+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ u16 err = FLD_GET(val, 23, 8);
+ dsi_show_rx_ack_with_err(err);
+ return -EIO;
+
+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ u8 data = FLD_GET(val, 15, 8);
+ if (dsi.debug_read)
+ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
+
+ if (buflen < 1)
+ return -EIO;
+
+ buf[0] = data;
+
+ return 1;
+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ u16 data = FLD_GET(val, 23, 8);
+ if (dsi.debug_read)
+ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
+
+ if (buflen < 2)
+ return -EIO;
+
+ buf[0] = data & 0xff;
+ buf[1] = (data >> 8) & 0xff;
+
+ return 2;
+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ int w;
+ int len = FLD_GET(val, 23, 8);
+ if (dsi.debug_read)
+ DSSDBG("\tDCS long response, len %d\n", len);
+
+ if (len > buflen)
+ return -EIO;
+
+ /* two byte checksum ends the packet, not included in len */
+ for (w = 0; w < len + 2;) {
+ int b;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+ if (dsi.debug_read)
+ DSSDBG("\t\t%02x %02x %02x %02x\n",
+ (val >> 0) & 0xff,
+ (val >> 8) & 0xff,
+ (val >> 16) & 0xff,
+ (val >> 24) & 0xff);
+
+ for (b = 0; b < 4; ++b) {
+ if (w < len)
+ buf[w] = (val >> (b * 8)) & 0xff;
+ /* we discard the 2 byte checksum */
+ ++w;
+ }
+ }
+
+ return len;
+
+ } else {
+ DSSERR("\tunknown datatype 0x%02x\n", dt);
+ return -EIO;
+ }
+}
+EXPORT_SYMBOL(dsi_vc_dcs_read);
+
+
+int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
+{
+ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
+ len, 0);
+}
+EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
+
+
+static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ DSSERR("LP_TX_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING2);
+ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
+ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
+ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
+ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
+ dsi_write_reg(DSI_TIMING2, r);
+
+ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+
+ return 0;
+}
+
+static int dsi_set_ta_timeout(int ns, int x8, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ DSSERR("TA_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
+ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
+ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
+ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
+ dsi_write_reg(DSI_TIMING1, r);
+
+ DSSDBG("TA_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+
+ return 0;
+}
+
+static int dsi_set_stop_state_counter(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ DSSERR("STOP_STATE_COUNTER_IO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
+ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
+ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
+ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
+ dsi_write_reg(DSI_TIMING1, r);
+
+ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+
+ return 0;
+}
+
+static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+
+ /* ticks in TxByteClkHS */
+
+ fck = dsi.ddr_clk / 4;
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ DSSERR("HS_TX_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING2);
+ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
+ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
+ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
+ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
+ dsi_write_reg(DSI_TIMING2, r);
+
+ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+
+ return 0;
+}
+static int dsi_proto_config(struct omap_dss_device *dssdev)
+{
+ u32 r;
+ int buswidth = 0;
+ int div;
+
+ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0);
+
+ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0);
+
+ /* XXX what values for the timeouts? */
+ dsi_set_stop_state_counter(1000, 0, 0);
+
+ dsi_set_ta_timeout(50000, 1, 1);
+
+ /* 3000ns * 16 */
+ dsi_set_lp_rx_timeout(3000, 0, 1);
+
+ /* 10000ns * 4 */
+ dsi_set_hs_tx_timeout(10000, 1, 0);
+
+ switch (dssdev->ctrl.pixel_size) {
+ case 16:
+ buswidth = 0;
+ break;
+ case 18:
+ buswidth = 1;
+ break;
+ case 24:
+ buswidth = 2;
+ break;
+ default:
+ BUG();
+ }
+
+ r = dsi_read_reg(DSI_CTRL);
+ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
+ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
+ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
+
+ /* TODO: Change for LCD2 support */
+ div = dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD) /
+ dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD);
+ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
+ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
+ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
+ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
+ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
+ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
+ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
+ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
+
+ dsi_write_reg(DSI_CTRL, r);
+
+ dsi_vc_initial_config(0);
+
+ /* set all vc targets to peripheral 0 */
+ dsi.vc[0].dest_per = 0;
+ dsi.vc[1].dest_per = 0;
+ dsi.vc[2].dest_per = 0;
+ dsi.vc[3].dest_per = 0;
+
+ return 0;
+}
+
+static void dsi_proto_timings(struct omap_dss_device *dssdev)
+{
+ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
+ unsigned tclk_pre, tclk_post;
+ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
+ unsigned ths_trail, ths_exit;
+ unsigned ddr_clk_pre, ddr_clk_post;
+ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
+ unsigned ths_eot;
+ u32 r;
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
+ ths_prepare = FLD_GET(r, 31, 24);
+ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
+ ths_zero = ths_prepare_ths_zero - ths_prepare;
+ ths_trail = FLD_GET(r, 15, 8);
+ ths_exit = FLD_GET(r, 7, 0);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+ tlpx = FLD_GET(r, 22, 16) * 2;
+ tclk_trail = FLD_GET(r, 15, 8);
+ tclk_zero = FLD_GET(r, 7, 0);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
+ tclk_prepare = FLD_GET(r, 7, 0);
+
+ /* min 8*UI */
+ tclk_pre = 20;
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
+ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
+ if (dssdev->phy.dsi.data1_lane != 0 &&
+ dssdev->phy.dsi.data2_lane != 0)
+ ths_eot = 2;
+ else
+ ths_eot = 4;
+
+ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
+ 4);
+ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
+
+ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
+ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
+ dsi_write_reg(DSI_CLK_TIMING, r);
+
+ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
+ ddr_clk_pre,
+ ddr_clk_post);
+
+ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
+ DIV_ROUND_UP(ths_prepare, 4) +
+ DIV_ROUND_UP(ths_zero + 3, 4);
+
+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+ FLD_VAL(exit_hs_mode_lat, 15, 0);
+ dsi_write_reg(DSI_VM_TIMING7, r);
+
+ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
+ enter_hs_mode_lat, exit_hs_mode_lat);
+}
+
+
+#define DSI_DECL_VARS \
+ int __dsi_cb = 0; u32 __dsi_cv = 0;
+
+#define DSI_FLUSH(ch) \
+ if (__dsi_cb > 0) { \
+ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
+ __dsi_cb = __dsi_cv = 0; \
+ }
+
+#define DSI_PUSH(ch, data) \
+ do { \
+ __dsi_cv |= (data) << (__dsi_cb * 8); \
+ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
+ if (++__dsi_cb > 3) \
+ DSI_FLUSH(ch); \
+ } while (0)
+
+static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ int x, int y, int w, int h)
+{
+ /* Note: supports only 24bit colors in 32bit container */
+ int first = 1;
+ int fifo_stalls = 0;
+ int max_dsi_packet_size;
+ int max_data_per_packet;
+ int max_pixels_per_packet;
+ int pixels_left;
+ int bytespp = dssdev->ctrl.pixel_size / 8;
+ int scr_width;
+ u32 __iomem *data;
+ int start_offset;
+ int horiz_inc;
+ int current_x;
+ struct omap_overlay *ovl;
+
+ debug_irq = 0;
+
+ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
+ x, y, w, h);
+
+ ovl = dssdev->manager->overlays[0];
+
+ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
+ return -EINVAL;
+
+ if (dssdev->ctrl.pixel_size != 24)
+ return -EINVAL;
+
+ scr_width = ovl->info.screen_width;
+ data = ovl->info.vaddr;
+
+ start_offset = scr_width * y + x;
+ horiz_inc = scr_width - w;
+ current_x = x;
+
+ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
+ * in fifo */
+
+ /* When using CPU, max long packet size is TX buffer size */
+ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
+
+ /* we seem to get better perf if we divide the tx fifo to half,
+ and while the other half is being sent, we fill the other half
+ max_dsi_packet_size /= 2; */
+
+ max_data_per_packet = max_dsi_packet_size - 4 - 1;
+
+ max_pixels_per_packet = max_data_per_packet / bytespp;
+
+ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
+
+ pixels_left = w * h;
+
+ DSSDBG("total pixels %d\n", pixels_left);
+
+ data += start_offset;
+
+ while (pixels_left > 0) {
+ /* 0x2c = write_memory_start */
+ /* 0x3c = write_memory_continue */
+ u8 dcs_cmd = first ? 0x2c : 0x3c;
+ int pixels;
+ DSI_DECL_VARS;
+ first = 0;
+
+#if 1
+ /* using fifo not empty */
+ /* TX_FIFO_NOT_EMPTY */
+ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
+ udelay(1);
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#elif 1
+ /* using fifo emptiness */
+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
+ max_dsi_packet_size) {
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#else
+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#endif
+ pixels = min(max_pixels_per_packet, pixels_left);
+
+ pixels_left -= pixels;
+
+ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
+ 1 + pixels * bytespp, 0);
+
+ DSI_PUSH(0, dcs_cmd);
+
+ while (pixels-- > 0) {
+ u32 pix = __raw_readl(data++);
+
+ DSI_PUSH(0, (pix >> 16) & 0xff);
+ DSI_PUSH(0, (pix >> 8) & 0xff);
+ DSI_PUSH(0, (pix >> 0) & 0xff);
+
+ current_x++;
+ if (current_x == x+w) {
+ current_x = x;
+ data += horiz_inc;
+ }
+ }
+
+ DSI_FLUSH(0);
+ }
+
+ return 0;
+}
+
+static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int bytespp = dssdev->ctrl.pixel_size / 8;
+ int len;
+ int total_len;
+ int packet_payload;
+ int packet_len;
+ u32 l;
+ bool use_te_trigger;
+ const int channel = 0;
+
+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+
+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+ x, y, w, h);
+
+ len = w * h * bytespp;
+
+ /* XXX: one packet could be longer, I think? Line buffer is
+ * 1024 x 24bits, but we have to put DCS cmd there also.
+ * 1023 * 3 should work, but causes strange color effects. */
+ packet_payload = min(w, (u16)1020) * bytespp;
+
+ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
+ total_len = (len / packet_payload) * packet_len;
+
+ if (len % packet_payload)
+ total_len += (len % packet_payload) + 1;
+
+ if (0)
+ dsi_vc_print_status(1);
+
+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+ dsi_write_reg(DSI_VC_TE(channel), l);
+
+ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
+
+ if (use_te_trigger)
+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+ else
+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+ dsi_write_reg(DSI_VC_TE(channel), l);
+
+ /* We put SIDLEMODE to no-idle for the duration of the transfer,
+ * because DSS interrupts are not capable of waking up the CPU and the
+ * framedone interrupt could be delayed for quite a long time. I think
+ * the same goes for any DSS interrupts, but for some reason I have not
+ * seen the problem anywhere else than here.
+ */
+ dispc_disable_sidle();
+
+ dss_start_update(dssdev);
+
+ if (use_te_trigger) {
+ /* disable LP_RX_TO, so that we can receive TE. Time to wait
+ * for TE is longer than the timer allows */
+ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+
+ dsi_vc_send_bta(channel);
+ }
+}
+
+static void dsi_framedone_irq_callback(void *data, u32 mask)
+{
+ /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
+ * turns itself off. However, DSI still has the pixels in its buffers,
+ * and is sending the data.
+ */
+
+ /* SIDLEMODE back to smart-idle */
+ dispc_enable_sidle();
+
+ dsi.framedone_received = true;
+ wake_up(&dsi.waitqueue);
+}
+
+static void dsi_set_update_region(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ spin_lock(&dsi.update_lock);
+ if (dsi.update_region.dirty) {
+ dsi.update_region.x = min(x, dsi.update_region.x);
+ dsi.update_region.y = min(y, dsi.update_region.y);
+ dsi.update_region.w = max(w, dsi.update_region.w);
+ dsi.update_region.h = max(h, dsi.update_region.h);
+ } else {
+ dsi.update_region.x = x;
+ dsi.update_region.y = y;
+ dsi.update_region.w = w;
+ dsi.update_region.h = h;
+ }
+
+ dsi.update_region.device = dssdev;
+ dsi.update_region.dirty = true;
+
+ spin_unlock(&dsi.update_lock);
+
+}
+
+static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+{
+ u16 w, h;
+ int i;
+
+ DSSDBG("starting auto update\n");
+
+ /* In automatic mode the overlay settings are applied like on DPI/SDI.
+ * Mark the overlays dirty, so that we get the overlays configured, as
+ * manual mode has left them in bad shape after config partia planes */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+ if (ovl->manager == dssdev->manager)
+ ovl->info_dirty = true;
+ }
+ dssdev->manager->apply(dssdev->manager);
+
+ dssdev->get_resolution(dssdev, &w, &h);
+
+ dsi_set_update_region(dssdev, 0, 0, w, h);
+
+ dsi_perf_mark_start_auto();
+
+ wake_up(&dsi.waitqueue);
+}
+
+static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
+{
+ dssdev->driver->enable_te(dssdev, enable);
+ int r;
+ printk(KERN_INFO "\n dsi_set_te ");
+ r = dssdev->driver->enable_te(dssdev, enable);
+ printk(KERN_INFO "\n dsi_set_te DONE ");
+ /* XXX for some reason, DSI TE breaks if we don't wait here.
+ * Panel bug? Needs more studying */
+ msleep(100);
+ return r;
+}
+
+static void dsi_handle_framedone(void)
+{
+ int r;
+ const int channel = 0;
+ bool use_te_trigger;
+
+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+
+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("FRAMEDONE\n");
+
+ if (use_te_trigger) {
+ /* enable LP_RX_TO again after the TE */
+ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+ }
+
+ /* Send BTA after the frame. We need this for the TE to work, as TE
+ * trigger is only sent for BTAs without preceding packet. Thus we need
+ * to BTA after the pixel packets so that next BTA will cause TE
+ * trigger.
+ *
+ * This is not needed when TE is not in use, but we do it anyway to
+ * make sure that the transfer has been completed. It would be more
+ * optimal, but more complex, to wait only just before starting next
+ * transfer. */
+ r = dsi_vc_send_bta_sync(channel);
+ if (r)
+ DSSERR("BTA after framedone failed\n");
+
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+ dispc_fake_vsync_irq();
+#endif
+}
+
+static int dsi_update_thread(void *data)
+ {
+ unsigned long timeout;
+ struct omap_dss_device *device;
+ u16 x, y, w, h;
+
+ while (1) {
+ bool sched;
+
+ wait_event_interruptible(dsi.waitqueue,
+ dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
+ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
+ dsi.update_region.dirty == true) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ dsi_bus_lock();
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
+ kthread_should_stop()) {
+ dsi_bus_unlock();
+ break;
+ }
+
+ dsi_perf_mark_setup();
+
+ if (dsi.update_region.dirty) {
+ spin_lock(&dsi.update_lock);
+ dsi.active_update_region = dsi.update_region;
+ dsi.update_region.dirty = false;
+ spin_unlock(&dsi.update_lock);
+ }
+
+ device = dsi.active_update_region.device;
+ x = dsi.active_update_region.x;
+ y = dsi.active_update_region.y;
+ w = dsi.active_update_region.w;
+ h = dsi.active_update_region.h;
+
+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
+ dss_setup_partial_planes(device,
+ &x, &y, &w, &h);
+#if 1
+ /* XXX there seems to be a bug in this driver
+ * or OMAP hardware. Some updates with certain
+ * widths and x coordinates fail. These widths
+ * are always odd, so "fix" it here for now */
+ if (w & 1) {
+ u16 dw, dh;
+ device->get_resolution(device,
+ &dw, &dh);
+ if (x + w == dw)
+ x &= ~1;
+ ++w;
+ dss_setup_partial_planes(device,
+ &x, &y, &w, &h);
+ }
+#endif
+ }
+
+ dispc_set_lcd_size(OMAP_DSS_CHANNEL_LCD, w, h);
+ /* TODO: Correct this while adding support for LCD2 */
+ }
+
+ if (dsi.active_update_region.dirty) {
+ dsi.active_update_region.dirty = false;
+ /* XXX TODO we don't need to send the coords, if they
+ * are the same that are already programmed to the
+ * panel. That should speed up manual update a bit */
+ device->driver->setup_update(device, x, y, w, h);
+ }
+
+ dsi_perf_mark_start();
+
+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ dsi_vc_config_vp(0);
+
+ if (dsi.te_enabled && dsi.use_ext_te)
+ device->driver->wait_for_te(device);
+
+ dsi.framedone_received = false;
+
+ dsi_update_screen_dispc(device, x, y, w, h);
+
+ /* wait for framedone */
+ timeout = msecs_to_jiffies(1000);
+ timeout = wait_event_timeout(dsi.waitqueue,
+ dsi.framedone_received == true,
+ timeout);
+
+ if (timeout == 0) {
+ DSSERR("framedone timeout\n");
+ DSSERR("failed update %d,%d %dx%d\n",
+ x, y, w, h);
+
+ dispc_enable_sidle();
+ /* TODO: update for LCD2 support */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+ } else {
+ dsi_handle_framedone();
+ dsi_perf_show("DISPC");
+ }
+ } else {
+ dsi_update_screen_l4(device, x, y, w, h);
+ dsi_perf_show("L4");
+ }
+
+ sched = atomic_read(&dsi.bus_lock.count) < 0;
+
+ complete_all(&dsi.update_completion);
+
+ dsi_bus_unlock();
+
+ /* XXX We need to give others chance to get the bus lock. Is
+ * there a better way for this? */
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
+ schedule_timeout_interruptible(1);
+ }
+
+ DSSDBG("update thread exiting\n");
+
+ return 0;
+ }
+
+
+/* Display funcs */
+
+static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ if (r) {
+ DSSERR("can't get FRAMEDONE irq\n");
+ return r;
+ }
+ /* TODO: Change here for LCD2 support*/
+ dispc_set_lcd_display_type(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_LCD_DISPLAY_TFT);
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_PARALLELMODE_DSI);
+ dispc_enable_fifohandcheck(1);
+
+ dispc_set_tft_data_lines(OMAP_DSS_CHANNEL_LCD, dssdev->ctrl.pixel_size);
+
+ {
+ struct omap_video_timings timings = {
+ .hsw = 1,
+ .hfp = 1,
+ .hbp = 1,
+ .vsw = 1,
+ .vfp = 0,
+ .vbp = 0,
+ };
+
+ dispc_set_lcd_timings(OMAP_DSS_CHANNEL_LCD, &timings);
+ }
+
+ return 0;
+}
+
+static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
+{
+ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+}
+
+static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+{
+ struct dsi_clock_info cinfo;
+ int r;
+
+ _dsi_print_reset_status();
+
+ r = dsi_pll_init(1, 0);
+ if (r)
+ goto err0;
+
+ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo);
+ if (r)
+ goto err1;
+
+ r = dsi_pll_program(&cinfo);
+ if (r)
+ goto err1;
+
+ DSSDBG("PLL OK\n");
+
+ r = dsi_complexio_init(dssdev);
+ if (r)
+ goto err1;
+
+ _dsi_print_reset_status();
+
+ dsi_proto_timings(dssdev);
+ dsi_set_lp_clk_divisor(dssdev);
+
+ if (1)
+ _dsi_print_reset_status();
+
+ r = dsi_proto_config(dssdev);
+ if (r)
+ goto err2;
+
+ /* enable interface */
+ dsi_vc_enable(0, 1);
+ dsi_if_enable(1);
+ dsi_force_tx_stop_mode_io();
+
+ if (dssdev->driver->enable) {
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err3;
+ }
+
+ /* enable high-speed after initial config */
+ dsi_vc_enable_hs(0, 1);
+
+ return 0;
+err3:
+ dsi_if_enable(0);
+err2:
+ dsi_complexio_uninit();
+err1:
+ dsi_pll_uninit();
+err0:
+ return r;
+}
+
+static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
+{
+ if (dssdev->driver->disable)
+ dssdev->driver->disable(dssdev);
+
+ dsi_complexio_uninit();
+ dsi_pll_uninit();
+}
+
+static int dsi_core_init(void)
+{
+ /* Autoidle */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
+
+ /* ENWAKEUP */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
+
+ /* SIDLEMODE smart-idle */
+ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
+
+ _dsi_initialize_irq();
+
+ return 0;
+}
+
+static int dsi_display_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("dsi_display_enable\n");
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ r = omap_dss_start_device(dssdev);
+ if (r) {
+ DSSERR("failed to start device\n");
+ goto err0;
+ }
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ DSSERR("dssdev already enabled\n");
+ r = -EINVAL;
+ goto err1;
+ }
+
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ r = _dsi_reset();
+ if (r)
+ goto err2;
+
+ dsi_core_init();
+
+ r = dsi_display_init_dispc(dssdev);
+ if (r)
+ goto err2;
+
+ r = dsi_display_init_dsi(dssdev);
+ if (r)
+ goto err3;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ dsi.use_ext_te = dssdev->phy.dsi.ext_te;
+ r = dsi_set_te(dssdev, dsi.te_enabled);
+ if (r)
+ goto err3;
+
+ dsi.update_mode = dsi.user_update_mode;
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+ dsi_start_auto_update(dssdev);
+
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ return 0;
+
+err3:
+ dsi_display_uninit_dispc(dssdev);
+err2:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+err1:
+ omap_dss_stop_device(dssdev);
+err0:
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+ DSSDBG("dsi_display_enable FAILED\n");
+ return r;
+}
+
+static void dsi_display_disable(struct omap_dss_device *dssdev)
+{
+ DSSDBG("dsi_display_disable\n");
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ goto end;
+
+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ dsi_display_uninit_dispc(dssdev);
+
+ dsi_display_uninit_dsi(dssdev);
+
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+
+ omap_dss_stop_device(dssdev);
+end:
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+}
+
+static int dsi_display_suspend(struct omap_dss_device *dssdev)
+{
+ DSSDBG("dsi_display_suspend\n");
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ goto end;
+
+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ dsi_display_uninit_dispc(dssdev);
+
+ dsi_display_uninit_dsi(dssdev);
+
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+end:
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ return 0;
+}
+
+static int dsi_display_resume(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ DSSDBG("dsi_display_resume\n");
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+ DSSERR("dssdev not suspended\n");
+ r = -EINVAL;
+ goto err0;
+ }
+
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ r = _dsi_reset();
+ if (r)
+ goto err1;
+
+ dsi_core_init();
+
+ r = dsi_display_init_dispc(dssdev);
+ if (r)
+ goto err1;
+
+ r = dsi_display_init_dsi(dssdev);
+ if (r)
+ goto err2;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ r = dsi_set_te(dssdev, dsi.te_enabled);
+ if (r)
+ goto err2;
+
+ dsi.update_mode = dsi.user_update_mode;
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+ dsi_start_auto_update(dssdev);
+
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ return 0;
+
+err2:
+ dsi_display_uninit_dispc(dssdev);
+err1:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+err0:
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+ DSSDBG("dsi_display_resume FAILED\n");
+ return r;
+}
+
+static int dsi_display_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int r = 0;
+ u16 dw, dh;
+
+ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
+
+ mutex_lock(&dsi.lock);
+
+ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
+ goto end;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ goto end;
+
+ dssdev->get_resolution(dssdev, &dw, &dh);
+
+ if (x > dw || y > dh)
+ goto end;
+
+ if (x + w > dw)
+ w = dw - x;
+
+ if (y + h > dh)
+ h = dh - y;
+
+ if (w == 0 || h == 0)
+ goto end;
+
+ dsi_set_update_region(dssdev, x, y, w, h);
+
+ wake_up(&dsi.waitqueue);
+
+end:
+ mutex_unlock(&dsi.lock);
+
+ return r;
+}
+
+static int dsi_display_sync(struct omap_dss_device *dssdev)
+{
+ bool wait;
+
+ DSSDBG("dsi_display_sync()\n");
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
+ dsi.update_region.dirty) {
+ INIT_COMPLETION(dsi.update_completion);
+ wait = true;
+ } else {
+ wait = false;
+ }
+
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ if (wait)
+ wait_for_completion_interruptible(&dsi.update_completion);
+
+ DSSDBG("dsi_display_sync() done\n");
+ return 0;
+}
+
+static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ DSSDBGF("%d", mode);
+
+ mutex_lock(&dsi.lock);
+ dsi_bus_lock();
+
+ if (dsi.update_mode != mode) {
+ dsi.user_update_mode = mode;
+ dsi.update_mode = mode;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
+ mode == OMAP_DSS_UPDATE_AUTO)
+ dsi_start_auto_update(dssdev);
+ }
+
+ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ return 0;
+}
+
+static enum omap_dss_update_mode dsi_display_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return dsi.update_mode;
+}
+
+
+static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+{
+ int r = 0;
+ DSSDBGF("%d", enable);
+
+ if (!dssdev->driver->enable_te)
+ return -ENOENT;
+
+ dsi_bus_lock();
+
+ dsi.te_enabled = enable;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ goto end;
+
+ r = dsi_set_te(dssdev, enable);
+end:
+ dsi_bus_unlock();
+
+ return r;
+}
+
+static int dsi_display_get_te(struct omap_dss_device *dssdev)
+{
+ return dsi.te_enabled;
+}
+
+static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
+{
+
+ DSSDBGF("%d", rotate);
+
+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return -EINVAL;
+
+ dsi_bus_lock();
+ dssdev->driver->set_rotate(dssdev, rotate);
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
+ u16 w, h;
+ /* the display dimensions may have changed, so set a new
+ * update region */
+ dssdev->get_resolution(dssdev, &w, &h);
+ dsi_set_update_region(dssdev, 0, 0, w, h);
+ }
+ dsi_bus_unlock();
+
+ return 0;
+}
+
+static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
+{
+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return 0;
+
+ return dssdev->driver->get_rotate(dssdev);
+}
+
+static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
+{
+ DSSDBGF("%d", mirror);
+
+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return -EINVAL;
+
+ dsi_bus_lock();
+ dssdev->driver->set_mirror(dssdev, mirror);
+ dsi_bus_unlock();
+
+ return 0;
+}
+
+static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
+{
+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return 0;
+
+ return dssdev->driver->get_mirror(dssdev);
+}
+
+static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
+{
+ int r;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+ DSSDBGF("%d", test_num);
+
+ dsi_bus_lock();
+
+ /* run test first in low speed mode */
+ dsi_vc_enable_hs(0, 0);
+
+ if (dssdev->driver->run_test) {
+ r = dssdev->driver->run_test(dssdev, test_num);
+ if (r)
+ goto end;
+ }
+
+ /* then in high speed */
+ dsi_vc_enable_hs(0, 1);
+
+ if (dssdev->driver->run_test) {
+ r = dssdev->driver->run_test(dssdev, test_num);
+ if (r)
+ goto end;
+ }
+
+end:
+ dsi_vc_enable_hs(0, 1);
+
+ dsi_bus_unlock();
+
+ return r;
+}
+
+static int dsi_display_memory_read(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int r;
+
+ DSSDBGF("");
+
+ if (!dssdev->driver->memory_read)
+ return -EINVAL;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+ dsi_bus_lock();
+
+ r = dssdev->driver->memory_read(dssdev, buf, size,
+ x, y, w, h);
+
+ dsi_bus_unlock();
+
+ return r;
+}
+
+void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
+ u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 *fifo_low, u32 *fifo_high)
+{
+ unsigned burst_size_bytes;
+
+ *burst_size = OMAP_DSS_BURST_16x32;
+ burst_size_bytes = 16 * 32 / 8;
+
+ *fifo_high = fifo_size - burst_size_bytes;
+ *fifo_low = 0;
+}
+
+int dsi_init_display(struct omap_dss_device *dssdev)
+{
+ DSSDBG("DSI init\n");
+
+ dssdev->enable = dsi_display_enable;
+ dssdev->disable = dsi_display_disable;
+ dssdev->suspend = dsi_display_suspend;
+ dssdev->resume = dsi_display_resume;
+ dssdev->update = dsi_display_update;
+ dssdev->sync = dsi_display_sync;
+ dssdev->set_update_mode = dsi_display_set_update_mode;
+ dssdev->get_update_mode = dsi_display_get_update_mode;
+ dssdev->enable_te = dsi_display_enable_te;
+ dssdev->get_te = dsi_display_get_te;
+
+ dssdev->get_rotate = dsi_display_get_rotate;
+ dssdev->set_rotate = dsi_display_set_rotate;
+
+ dssdev->get_mirror = dsi_display_get_mirror;
+ dssdev->set_mirror = dsi_display_set_mirror;
+
+ dssdev->run_test = dsi_display_run_test;
+ dssdev->memory_read = dsi_display_memory_read;
+
+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ dsi.vc[0].dssdev = dssdev;
+ dsi.vc[1].dssdev = dssdev;
+
+ return 0;
+}
+
+int dsi_init(struct platform_device *pdev)
+{
+ u32 rev;
+ struct sched_param param = {
+ .sched_priority = MAX_USER_RT_PRIO-1
+ };
+
+ spin_lock_init(&dsi.errors_lock);
+ dsi.errors = 0;
+
+ /* XXX fail properly */
+
+ init_completion(&dsi.bta_completion);
+ init_completion(&dsi.update_completion);
+
+ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
+ if (IS_ERR(dsi.thread)) {
+ DSSERR("cannot create kthread\n");
+ return PTR_ERR(dsi.thread);
+ }
+ sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
+
+ init_waitqueue_head(&dsi.waitqueue);
+ spin_lock_init(&dsi.update_lock);
+
+ mutex_init(&dsi.lock);
+ mutex_init(&dsi.bus_lock);
+
+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
+
+ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+ if (!dsi.base) {
+ DSSERR("can't ioremap DSI\n");
+ return -ENOMEM;
+ }
+
+ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
+ if (IS_ERR(dsi.vdds_dsi_reg)) {
+ iounmap(dsi.base);
+ DSSERR("can't get VDDS_DSI regulator\n");
+ return PTR_ERR(dsi.vdds_dsi_reg);
+ }
+
+ enable_clocks(1);
+
+ rev = dsi_read_reg(DSI_REVISION);
+ printk(KERN_INFO "OMAP DSI rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ enable_clocks(0);
+
+ wake_up_process(dsi.thread);
+
+ return 0;
+}
+
+void dsi_exit(void)
+{
+ kthread_stop(dsi.thread);
+
+ regulator_put(dsi.vdds_dsi_reg);
+
+ iounmap(dsi.base);
+
+ DSSDBG("omap_dsi_exit\n");
+}
+
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
new file mode 100644
index 000000000000..2697af0cbfd4
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.c
@@ -0,0 +1,373 @@
+/*
+ * linux/drivers/video/omap2/dss/dss.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSS"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+
+#include <mach/display.h>
+#include "dss.h"
+
+#ifndef CONFIG_ARCH_OMAP4
+/* DSS */
+#define DSS_BASE 0x48050000
+/* DISPLAY CONTROLLER */
+#define DISPC_BASE 0x48050400
+#else
+/* DSS */
+#define DSS_BASE 0x48042000
+/* DISPLAY CONTROLLER */
+#define DISPC_BASE 0x48043000
+#endif
+
+#define DSS_SZ_REGS SZ_512
+
+struct dss_reg {
+ u16 idx;
+};
+
+#define DSS_REG(idx) ((const struct dss_reg) { idx })
+
+#define DSS_REVISION DSS_REG(0x0000)
+#define DSS_SYSCONFIG DSS_REG(0x0010)
+#define DSS_SYSSTATUS DSS_REG(0x0014)
+#define DSS_IRQSTATUS DSS_REG(0x0018)
+#define DSS_CONTROL DSS_REG(0x0040)
+#define DSS_SDI_CONTROL DSS_REG(0x0044)
+#define DSS_PLL_CONTROL DSS_REG(0x0048)
+#define DSS_SDI_STATUS DSS_REG(0x005C)
+
+#ifdef CONFIG_ARCH_OMAP4
+#define DSS_STATUS DSS_REG(0x005C)
+#endif
+
+
+
+#define REG_GET(idx, start, end) \
+ FLD_GET(dss_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
+
+static struct {
+ void __iomem *base;
+
+ u32 ctx[DSS_SZ_REGS / sizeof(u32)];
+} dss;
+
+static int _omap_dss_wait_reset(void);
+
+static inline void dss_write_reg(const struct dss_reg idx, u32 val)
+{
+ __raw_writel(val, dss.base + idx.idx);
+}
+
+static inline u32 dss_read_reg(const struct dss_reg idx)
+{
+ return __raw_readl(dss.base + idx.idx);
+}
+
+#define SR(reg) \
+ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
+#define RR(reg) \
+ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
+
+void dss_save_context(void)
+{
+ if (cpu_is_omap24xx())
+ return;
+
+ SR(SYSCONFIG);
+ SR(CONTROL);
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+ SR(SDI_CONTROL);
+ SR(PLL_CONTROL);
+#endif
+}
+
+void dss_restore_context(void)
+{
+ if (_omap_dss_wait_reset())
+ DSSERR("DSS not coming out of reset after sleep\n");
+
+ RR(SYSCONFIG);
+ RR(CONTROL);
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+ RR(SDI_CONTROL);
+ RR(PLL_CONTROL);
+#endif
+}
+
+#undef SR
+#undef RR
+
+void dss_sdi_init(u8 datapairs)
+{
+ u32 l;
+
+ BUG_ON(datapairs > 3 || datapairs < 1);
+
+ l = dss_read_reg(DSS_SDI_CONTROL);
+ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
+ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
+ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
+ dss_write_reg(DSS_SDI_CONTROL, l);
+
+ l = dss_read_reg(DSS_PLL_CONTROL);
+ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
+ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
+ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
+ dss_write_reg(DSS_PLL_CONTROL, l);
+}
+
+void dss_sdi_enable(void)
+{
+ dispc_pck_free_enable(1);
+
+ /* Reset SDI PLL */
+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
+ udelay(1); /* wait 2x PCLK */
+
+ /* Lock SDI PLL */
+ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
+
+ /* Waiting for PLL lock request to complete */
+ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
+ ;
+
+ /* Clearing PLL_GO bit */
+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
+
+ /* Waiting for PLL to lock */
+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
+ ;
+
+ dispc_lcd_enable_signal(1);
+
+ /* Waiting for SDI reset to complete */
+ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
+ ;
+}
+
+void dss_sdi_disable(void)
+{
+ dispc_lcd_enable_signal(0);
+
+ dispc_pck_free_enable(0);
+
+ /* Reset SDI PLL */
+ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
+}
+
+void dss_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ DUMPREG(DSS_REVISION);
+ DUMPREG(DSS_SYSCONFIG);
+ DUMPREG(DSS_SYSSTATUS);
+ DUMPREG(DSS_IRQSTATUS);
+ DUMPREG(DSS_CONTROL);
+ DUMPREG(DSS_SDI_CONTROL);
+ DUMPREG(DSS_PLL_CONTROL);
+ DUMPREG(DSS_SDI_STATUS);
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+#undef DUMPREG
+}
+
+void dss_select_clk_source(bool dsi, bool dispc)
+{
+ u32 r;
+ r = dss_read_reg(DSS_CONTROL);
+ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
+ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
+ /* TODO: extend for LCD2 and HDMI */
+ dss_write_reg(DSS_CONTROL, r);
+}
+
+int dss_get_dsi_clk_source(void)
+{
+ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
+}
+
+int dss_get_dispc_clk_source(void)
+{
+ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
+}
+
+static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
+{
+ dispc_irq_handler();
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
+{
+ u32 irqstatus;
+
+ irqstatus = dss_read_reg(DSS_IRQSTATUS);
+
+ if (irqstatus & (1<<0)) /* DISPC_IRQ */
+ dispc_irq_handler();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ if (irqstatus & (1<<1)) /* DSI_IRQ */
+ dsi_irq_handler();
+#endif
+
+ return IRQ_HANDLED;
+}
+
+static int _omap_dss_wait_reset(void)
+{
+ unsigned timeout = 1000;
+
+ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
+ udelay(1);
+ if (!--timeout) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int _omap_dss_reset(void)
+{
+ /* Soft reset */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
+ return _omap_dss_wait_reset();
+}
+
+void dss_set_venc_output(enum omap_dss_venc_type type)
+{
+ int l = 0;
+
+ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+ l = 0;
+ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
+ l = 1;
+ else
+ BUG();
+
+ /* venc out selection. 0 = comp, 1 = svideo */
+ REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
+}
+
+void dss_set_dac_pwrdn_bgz(bool enable)
+{
+ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
+}
+
+int dss_init(bool skip_init)
+{
+ int r;
+ u32 rev;
+
+ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
+ if (!dss.base) {
+ DSSERR("can't ioremap DSS\n");
+ r = -ENOMEM;
+ goto fail0;
+ }
+
+ if (!skip_init) {
+ /* disable LCD and DIGIT output. This seems to fix the synclost
+ * problem that we get, if the bootloader starts the DSS and
+ * the kernel resets it */
+ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+
+ /* We need to wait here a bit, otherwise we sometimes start to
+ * get synclost errors, and after that only power cycle will
+ * restore DSS functionality. I have no idea why this happens.
+ * And we have to wait _before_ resetting the DSS, but after
+ * enabling clocks.
+ */
+ msleep(50);
+
+ _omap_dss_reset();
+ }
+
+ /* autoidle */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+ /* Select DPLL */
+ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
+ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
+ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
+#endif
+
+#ifndef CONFIG_ARCH_OMAP4
+ r = request_irq(INT_24XX_DSS_IRQ,
+ cpu_is_omap24xx()
+ ? dss_irq_handler_omap2
+ : dss_irq_handler_omap3,
+ 0, "OMAP DSS", NULL);
+#else
+ r = request_irq(INT_44XX_DSS_IRQ,
+ dss_irq_handler_omap3,
+ 0, "OMAP DSS", (void *)1);
+#endif
+ if (r < 0) {
+ DSSERR("omap2 dss: request_irq failed\n");
+ goto fail1;
+ }
+
+ dss_save_context();
+
+ rev = dss_read_reg(DSS_REVISION);
+ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ return 0;
+
+fail1:
+ iounmap(dss.base);
+fail0:
+ return r;
+}
+
+void dss_exit(void)
+{
+#ifndef CONFIG_ARCH_OMAP4
+ free_irq(INT_24XX_DSS_IRQ, NULL);
+#else
+ free_irq(INT_44XX_DSS_IRQ, NULL);
+#endif
+
+ iounmap(dss.base);
+}
+
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
new file mode 100644
index 000000000000..883ab8362622
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.h
@@ -0,0 +1,377 @@
+/*
+ * linux/drivers/video/omap2/dss/dss.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_H
+#define __OMAP2_DSS_H
+
+#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
+#define DEBUG
+#endif
+
+#ifdef DEBUG
+extern unsigned int dss_debug;
+#ifdef DSS_SUBSYS_NAME
+#define DSSDBG(format, ...) \
+ if (dss_debug) \
+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
+ ## __VA_ARGS__)
+#else
+#define DSSDBG(format, ...) \
+ if (dss_debug) \
+ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSDBGF(format, ...) \
+ if (dss_debug) \
+ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
+ ": %s(" format ")\n", \
+ __func__, \
+ ## __VA_ARGS__)
+#else
+#define DSSDBGF(format, ...) \
+ if (dss_debug) \
+ printk(KERN_DEBUG "omapdss: " \
+ ": %s(" format ")\n", \
+ __func__, \
+ ## __VA_ARGS__)
+#endif
+
+#else /* DEBUG */
+#define DSSDBG(format, ...)
+#define DSSDBGF(format, ...)
+#endif
+
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSERR(format, ...) \
+ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
+ ## __VA_ARGS__)
+#else
+#define DSSERR(format, ...) \
+ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSINFO(format, ...) \
+ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
+ ## __VA_ARGS__)
+#else
+#define DSSINFO(format, ...) \
+ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSWARN(format, ...) \
+ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
+ ## __VA_ARGS__)
+#else
+#define DSSWARN(format, ...) \
+ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
+#endif
+
+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
+ number. For example 7:0 */
+#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+#define DISPC_MAX_FCK 173000000
+
+enum omap_burst_size {
+ OMAP_DSS_BURST_4x32 = 0, /*OMAP_DSS_BURST_2x128 in OMAP4*/
+ OMAP_DSS_BURST_8x32 = 1, /*OMAP_DSS_BURST_4x128 in OMAP4*/
+ OMAP_DSS_BURST_16x32 = 2, /*OMAP_DSS_BURST_8x128 in OMAP4*/
+};
+
+enum omap_parallel_interface_mode {
+ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
+ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
+ OMAP_DSS_PARALLELMODE_DSI,
+};
+
+enum dss_clock {
+ DSS_CLK_ICK = 1 << 0,
+ DSS_CLK_FCK1 = 1 << 1,
+ DSS_CLK_FCK2 = 1 << 2,
+ DSS_CLK_54M = 1 << 3,
+ DSS_CLK_96M = 1 << 4,
+};
+
+struct dispc_clock_info {
+ /* rates that we get with dividers below */
+ unsigned long fck;
+ unsigned long lck;
+ unsigned long pck;
+
+ /* dividers */
+ u16 fck_div;
+ u16 lck_div;
+ u16 pck_div;
+};
+
+struct dsi_clock_info {
+ /* rates that we get with dividers below */
+ unsigned long fint;
+ unsigned long dsiphy;
+ unsigned long clkin;
+ unsigned long dsi1_pll_fclk;
+ unsigned long dsi2_pll_fclk;
+ unsigned long lck;
+ unsigned long pck;
+
+ /* dividers */
+ u16 regn;
+ u16 regm;
+ u16 regm3;
+ u16 regm4;
+
+ u16 lck_div;
+ u16 pck_div;
+
+ u8 highfreq;
+ bool use_dss2_fck;
+};
+
+struct seq_file;
+struct platform_device;
+
+/* core */
+void dss_clk_enable(enum dss_clock clks);
+void dss_clk_disable(enum dss_clock clks);
+unsigned long dss_clk_get_rate(enum dss_clock clk);
+int dss_need_ctx_restore(void);
+void dss_dump_clocks(struct seq_file *s);
+struct bus_type *dss_get_bus(void);
+
+/* display */
+int dss_suspend_all_devices(void);
+int dss_resume_all_devices(void);
+
+void dss_init_device(struct platform_device *pdev,
+ struct omap_dss_device *dssdev);
+void dss_uninit_device(struct platform_device *pdev,
+ struct omap_dss_device *dssdev);
+bool dss_use_replication(struct omap_dss_device *dssdev,
+ enum omap_color_mode mode);
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
+void dss_setup_partial_planes(struct omap_dss_device *dssdev,
+ u16 *x, u16 *y, u16 *w, u16 *h);
+void dss_start_update(struct omap_dss_device *dssdev);
+void default_get_overlay_fifo_thresholds(enum omap_plane plane,
+ u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 *fifo_low, u32 *fifo_high);
+
+/* manager */
+int dss_init_overlay_managers(struct platform_device *pdev);
+void dss_uninit_overlay_managers(struct platform_device *pdev);
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
+void dss_setup_partial_planes(struct omap_dss_device *dssdev,
+ u16 *x, u16 *y, u16 *w, u16 *h);
+void dss_start_update(struct omap_dss_device *dssdev);
+
+/* overlay */
+void dss_init_overlays(struct platform_device *pdev);
+void dss_uninit_overlays(struct platform_device *pdev);
+int dss_check_overlay(struct omap_overlay *ovl,
+ struct omap_dss_device *dssdev);
+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
+#ifdef L4_EXAMPLE
+void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
+#endif
+void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
+
+/* DSS */
+int dss_init(bool skip_init);
+void dss_exit(void);
+
+void dss_save_context(void);
+void dss_restore_context(void);
+
+void dss_dump_regs(struct seq_file *s);
+
+void dss_sdi_init(u8 datapairs);
+void dss_sdi_enable(void);
+void dss_sdi_disable(void);
+
+void dss_select_clk_source(bool dsi, bool dispc);
+int dss_get_dsi_clk_source(void);
+int dss_get_dispc_clk_source(void);
+void dss_set_venc_output(enum omap_dss_venc_type type);
+void dss_set_dac_pwrdn_bgz(bool enable);
+
+/* SDI */
+int sdi_init(bool skip_init);
+void sdi_exit(void);
+int sdi_init_display(struct omap_dss_device *display);
+
+/* DSI */
+int dsi_init(struct platform_device *pdev);
+void dsi_exit(void);
+
+void dsi_dump_clocks(struct seq_file *s);
+void dsi_dump_regs(struct seq_file *s);
+
+void dsi_save_context(void);
+void dsi_restore_context(void);
+
+int dsi_init_display(struct omap_dss_device *display);
+void dsi_irq_handler(void);
+unsigned long dsi_get_dsi1_pll_rate(void);
+unsigned long dsi_get_dsi2_pll_rate(void);
+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ struct dsi_clock_info *cinfo);
+int dsi_pll_program(struct dsi_clock_info *cinfo);
+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
+void dsi_pll_uninit(void);
+void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
+ u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 *fifo_low, u32 *fifo_high);
+
+/* DPI */
+int dpi_init(void);
+void dpi_exit(void);
+int dpi_init_display(struct omap_dss_device *dssdev);
+
+/* DISPC */
+int dispc_init(void);
+void dispc_exit(void);
+void dispc_dump_clocks(struct seq_file *s);
+void dispc_dump_regs(struct seq_file *s);
+void dispc_irq_handler(void);
+void dispc_fake_vsync_irq(void);
+
+void dispc_save_context(void);
+void dispc_restore_context(void);
+
+void dispc_enable_sidle(void);
+void dispc_disable_sidle(void);
+
+void dispc_lcd_enable_signal_polarity(bool act_high);
+void dispc_lcd_enable_signal(bool enable);
+void dispc_pck_free_enable(bool enable);
+void dispc_enable_fifohandcheck(bool enable);
+
+void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
+void dispc_set_digit_size(u16 width, u16 height);
+u32 dispc_get_plane_fifo_size(enum omap_plane plane);
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_enable_fifomerge(bool enable);
+void dispc_set_burst_size(enum omap_plane plane,
+ enum omap_burst_size burst_size);
+
+void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
+#ifdef CONFIG_ARCH_OMAP4
+void dispc_set_plane_ba_uv0(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_ba_uv1(enum omap_plane plane, u32 paddr);
+void dispc_set_zorder(enum omap_plane plane,
+ enum omap_overlay_zorder zorder);
+void dispc_enable_zorder(enum omap_plane plane, bool enable);
+#endif
+
+void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
+void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
+void dispc_set_channel_out(enum omap_plane plane,
+ enum omap_channel channel_out);
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror,
+ u8 global_alpha, enum omap_channel channel
+#ifdef CONFIG_ARCH_OMAP4
+ , u32 p_uv_addr
+#endif
+ );
+
+bool dispc_go_busy(enum omap_channel channel);
+void dispc_go(enum omap_channel channel);
+void dispc_enable_lcd_out(enum omap_channel channel, bool enable);
+void dispc_enable_digit_out(bool enable);
+int dispc_enable_plane(enum omap_plane plane, bool enable);
+void dispc_enable_replication(enum omap_plane plane, bool enable);
+
+void dispc_set_parallel_interface_mode(enum omap_channel channel,
+ enum omap_parallel_interface_mode mode);
+void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
+void dispc_set_lcd_display_type(enum omap_channel channel,
+ enum omap_lcd_display_type type);
+void dispc_set_loadmode(enum omap_dss_load_mode mode);
+
+void dispc_set_default_color(enum omap_channel channel, u32 color);
+u32 dispc_get_default_color(enum omap_channel channel);
+void dispc_set_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type type,
+ u32 trans_key);
+void dispc_get_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type *type,
+ u32 *trans_key);
+void dispc_enable_trans_key(enum omap_channel ch, bool enable);
+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
+bool dispc_trans_key_enabled(enum omap_channel ch);
+bool dispc_alpha_blending_enabled(enum omap_channel ch);
+
+bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
+void dispc_set_lcd_timings(enum omap_channel channel,
+ struct omap_video_timings *timings);
+unsigned long dispc_fclk_rate(void);
+unsigned long dispc_lclk_rate(enum omap_channel channel);
+unsigned long dispc_pclk_rate(enum omap_channel channel);
+void dispc_set_pol_freq(enum omap_channel channel,
+ enum omap_panel_config config, u8 acbi, u8 acb);
+void find_lck_pck_divs(bool is_tft, unsigned long req_pck,
+ unsigned long fck, u16 *lck_div, u16 *pck_div);
+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
+ struct dispc_clock_info *cinfo);
+int dispc_set_clock_div(struct dispc_clock_info *cinfo);
+int dispc_get_clock_div(struct dispc_clock_info *cinfo);
+void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
+ u16 pck_div);
+
+/* VENC */
+int venc_init(struct platform_device *pdev);
+void venc_exit(void);
+void venc_dump_regs(struct seq_file *s);
+int venc_init_display(struct omap_dss_device *display);
+
+/* RFBI */
+int rfbi_init(void);
+void rfbi_exit(void);
+void rfbi_dump_regs(struct seq_file *s);
+
+int rfbi_configure(int rfbi_module, int bpp, int lines);
+void rfbi_enable_rfbi(bool enable);
+void rfbi_transfer_area(u16 width, u16 height,
+ void (callback)(void *data), void *data);
+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
+unsigned long rfbi_get_max_tx_rate(void);
+int rfbi_init_display(struct omap_dss_device *display);
+
+#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
new file mode 100644
index 000000000000..2cab326b3a77
--- /dev/null
+++ b/drivers/video/omap2/dss/manager.c
@@ -0,0 +1,1551 @@
+/*
+ * linux/drivers/video/omap2/dss/manager.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "MANAGER"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+
+#include <mach/display.h>
+#include <mach/cpu.h>
+
+#include "dss.h"
+
+
+#ifdef CONFIG_ARCH_OMAP4
+#define MAX_DSS_MANAGERS 3
+#else
+#define MAX_DSS_MANAGERS 2
+#endif
+
+static int num_managers;
+static struct list_head manager_list;
+
+static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
+}
+
+static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ mgr->device ? mgr->device->name : "<none>");
+}
+
+static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ int r = 0;
+ size_t len = size;
+ struct omap_dss_device *dssdev = NULL;
+
+ int match(struct omap_dss_device *dssdev, void *data)
+ {
+ const char *str = data;
+ return sysfs_streq(dssdev->name, str);
+ }
+
+ if (buf[size-1] == '\n')
+ --len;
+
+ if (len > 0)
+ dssdev = omap_dss_find_device((void *)buf, match);
+
+ if (len > 0 && dssdev == NULL)
+ return -EINVAL;
+
+ if (dssdev)
+ DSSDBG("display %s found\n", dssdev->name);
+
+ if (mgr->device) {
+ r = mgr->unset_device(mgr);
+ if (r) {
+ DSSERR("failed to unset display\n");
+ goto put_device;
+ }
+ }
+
+ if (dssdev) {
+ r = mgr->set_device(mgr, dssdev);
+ if (r) {
+ DSSERR("failed to set manager\n");
+ goto put_device;
+ }
+
+ r = mgr->apply(mgr);
+ if (r) {
+ DSSERR("failed to apply dispc config\n");
+ goto put_device;
+ }
+ }
+
+put_device:
+ if (dssdev)
+ omap_dss_put_device(dssdev);
+
+ return r ? r : size;
+}
+
+static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
+}
+
+static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ u32 color;
+ int r;
+
+ if (sscanf(buf, "%d", &color) != 1)
+ return -EINVAL;
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.default_color = color;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static const char *trans_key_type_str[] = {
+ "gfx-destination",
+ "video-source",
+};
+
+static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ enum omap_dss_trans_key_type key_type;
+
+ key_type = mgr->info.trans_key_type;
+ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
+}
+
+static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ enum omap_dss_trans_key_type key_type;
+ struct omap_overlay_manager_info info;
+ int r;
+
+ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
+ if (sysfs_streq(buf, trans_key_type_str[key_type]))
+ break;
+ }
+
+ if (key_type == ARRAY_SIZE(trans_key_type_str))
+ return -EINVAL;
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.trans_key_type = key_type;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
+}
+
+static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ u32 key_value;
+ int r;
+
+ if (sscanf(buf, "%d", &key_value) != 1)
+ return -EINVAL;
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.trans_key = key_value;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
+}
+
+static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ int enable;
+ int r;
+
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.trans_enabled = enable ? true : false;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t manager_alpha_blending_enabled_show(
+ struct omap_overlay_manager *mgr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
+}
+
+static ssize_t manager_alpha_blending_enabled_store(
+ struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ int enable;
+ int r;
+
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.alpha_enabled = enable ? true : false;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+struct manager_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay_manager *, char *);
+ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
+};
+
+#define MANAGER_ATTR(_name, _mode, _show, _store) \
+ struct manager_attribute manager_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
+ manager_display_show, manager_display_store);
+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
+ manager_default_color_show, manager_default_color_store);
+static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
+ manager_trans_key_type_show, manager_trans_key_type_store);
+static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
+ manager_trans_key_value_show, manager_trans_key_value_store);
+static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
+ manager_trans_key_enabled_show,
+ manager_trans_key_enabled_store);
+static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+ manager_alpha_blending_enabled_show,
+ manager_alpha_blending_enabled_store);
+
+
+static struct attribute *manager_sysfs_attrs[] = {
+ &manager_attr_name.attr,
+ &manager_attr_display.attr,
+ &manager_attr_default_color.attr,
+ &manager_attr_trans_key_type.attr,
+ &manager_attr_trans_key_value.attr,
+ &manager_attr_trans_key_enabled.attr,
+ &manager_attr_alpha_blending_enabled.attr,
+ NULL
+};
+
+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct omap_overlay_manager *manager;
+ struct manager_attribute *manager_attr;
+
+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
+ manager_attr = container_of(attr, struct manager_attribute, attr);
+
+ if (!manager_attr->show)
+ return -ENOENT;
+
+ return manager_attr->show(manager, buf);
+}
+
+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager *manager;
+ struct manager_attribute *manager_attr;
+
+ manager = container_of(kobj, struct omap_overlay_manager, kobj);
+ manager_attr = container_of(attr, struct manager_attribute, attr);
+
+ if (!manager_attr->store)
+ return -ENOENT;
+
+ return manager_attr->store(manager, buf, size);
+}
+
+static struct sysfs_ops manager_sysfs_ops = {
+ .show = manager_attr_show,
+ .store = manager_attr_store,
+};
+
+static struct kobj_type manager_ktype = {
+ .sysfs_ops = &manager_sysfs_ops,
+ .default_attrs = manager_sysfs_attrs,
+};
+
+/*
+ * We have 4 levels of cache for the dispc settings. First two are in SW and
+ * the latter two in HW.
+ *
+ * +--------------------+
+ * |overlay/manager_info|
+ * +--------------------+
+ * v
+ * apply()
+ * v
+ * +--------------------+
+ * | dss_cache |
+ * +--------------------+
+ * v
+ * configure()
+ * v
+ * +--------------------+
+ * | shadow registers |
+ * +--------------------+
+ * v
+ * VFP or lcd/digit_enable
+ * v
+ * +--------------------+
+ * | registers |
+ * +--------------------+
+ */
+
+struct overlay_cache_data {
+ /* If true, cache changed, but not written to shadow registers. Set
+ * in apply(), cleared when registers written. */
+ bool dirty;
+ /* If true, shadow registers contain changed values not yet in real
+ * registers. Set when writing to shadow registers, cleared at
+ * VSYNC/EVSYNC */
+ bool shadow_dirty;
+
+ bool enabled;
+
+ u32 paddr;
+ void __iomem *vaddr;
+ u16 screen_width;
+ u16 width;
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
+ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+
+ u16 pos_x;
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
+ u8 global_alpha;
+
+ enum omap_channel channel;
+ bool replication;
+ bool ilace;
+
+ enum omap_burst_size burst_size;
+ u32 fifo_low;
+ u32 fifo_high;
+
+ bool manual_update;
+
+#ifdef CONFIG_ARCH_OMAP4
+ u32 p_uv_addr; /* relevant for NV12 format only */
+ enum omap_overlay_zorder zorder;
+#endif
+};
+
+struct manager_cache_data {
+ /* If true, cache changed, but not written to shadow registers. Set
+ * in apply(), cleared when registers written. */
+ bool dirty;
+ /* If true, shadow registers contain changed values not yet in real
+ * registers. Set when writing to shadow registers, cleared at
+ * VSYNC/EVSYNC */
+ bool shadow_dirty;
+
+ u32 default_color;
+
+ enum omap_dss_trans_key_type trans_key_type;
+ u32 trans_key;
+ bool trans_enabled;
+
+ bool alpha_enabled;
+
+ bool manual_upd_display;
+ bool manual_update;
+ bool do_manual_update;
+
+ /* manual update region */
+ u16 x, y, w, h;
+};
+
+static struct {
+ spinlock_t lock;
+#ifdef CONFIG_ARCH_OMAP4
+ struct overlay_cache_data overlay_cache[4];
+ struct manager_cache_data manager_cache[3];
+#else
+ struct overlay_cache_data overlay_cache[3];
+ struct manager_cache_data manager_cache[2];
+#endif
+
+
+ bool irq_enabled;
+} dss_cache;
+
+static int omap_dss_set_device(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+{
+ int i;
+ int r;
+
+ if (dssdev->manager) {
+ DSSERR("display '%s' already has a manager '%s'\n",
+ dssdev->name, dssdev->manager->name);
+ return -EINVAL;
+ }
+
+ if ((mgr->supported_displays & dssdev->type) == 0) {
+ DSSERR("display '%s' does not support manager '%s'\n",
+ dssdev->name, mgr->name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mgr->num_overlays; i++) {
+ struct omap_overlay *ovl = mgr->overlays[i];
+
+ if (ovl->manager != mgr || !ovl->info.enabled)
+ continue;
+
+ r = dss_check_overlay(ovl, dssdev);
+ if (r)
+ return r;
+ }
+
+ dssdev->manager = mgr;
+ mgr->device = dssdev;
+ mgr->device_changed = true;
+
+ return 0;
+}
+
+static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
+{
+ if (!mgr->device) {
+ DSSERR("failed to unset display, display not set.\n");
+ return -EINVAL;
+ }
+
+ mgr->device->manager = NULL;
+ mgr->device = NULL;
+ mgr->device_changed = true;
+
+ return 0;
+}
+
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ struct manager_cache_data *mc;
+ enum omap_channel channel;
+ u32 irq;
+ int r;
+ int i;
+
+ if (!mgr->device)
+ return 0;
+ channel = mgr->device->channel;
+
+ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
+ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
+ } else {
+ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = mgr->device->get_update_mode(mgr->device);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+#ifdef CONFIG_ARCH_OMAP4
+ irq = (channel == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+#else
+ irq = DISPC_IRQ_FRAMEDONE;
+#endif
+ } else {
+#ifdef CONFIG_ARCH_OMAP4
+ irq = (channel == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+#else
+ irq = DISPC_IRQ_VSYNC;
+#endif
+ }
+ }
+
+ mc = &dss_cache.manager_cache[mgr->id];
+ i = 0;
+ while (1) {
+ unsigned long flags;
+ bool shadow_dirty, dirty;
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ dirty = mc->dirty;
+ shadow_dirty = mc->shadow_dirty;
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ if (!dirty && !shadow_dirty) {
+ r = 0;
+ break;
+ }
+
+ /* 4 iterations is the worst case:
+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+ * 2 - first VSYNC, dirty = true
+ * 3 - dirty = false, shadow_dirty = true
+ * 4 - shadow_dirty = false */
+ if (i++ == 3) {
+ DSSERR("mgr(%d)->wait_for_go() not finishing\n",
+ mgr->id);
+ r = 0;
+ break;
+ }
+
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ if (r == -ERESTARTSYS)
+ break;
+
+ if (r) {
+ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
+ break;
+ }
+ }
+
+ return r;
+}
+
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ enum omap_channel channel;
+ struct overlay_cache_data *oc;
+ struct omap_dss_device *dssdev;
+ u32 irq;
+ int r;
+ int i;
+
+ if (!ovl->manager || !ovl->manager->device)
+ return 0;
+
+ dssdev = ovl->manager->device;
+ channel = dssdev->channel;
+
+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
+ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
+ } else {
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = dssdev->get_update_mode(dssdev);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+#ifdef CONFIG_ARCH_OMAP4
+ irq = (channel == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+#else
+ irq = DISPC_IRQ_FRAMEDONE;
+#endif
+ } else {
+#ifdef CONFIG_ARCH_OMAP4
+ irq = (channel == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+#else
+ irq = DISPC_IRQ_VSYNC;
+#endif
+ }
+ }
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+ i = 0;
+ while (1) {
+ unsigned long flags;
+ bool shadow_dirty, dirty;
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ dirty = oc->dirty;
+ shadow_dirty = oc->shadow_dirty;
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ if (!dirty && !shadow_dirty) {
+ r = 0;
+ break;
+ }
+
+ /* 4 iterations is the worst case:
+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+ * 2 - first VSYNC, dirty = true
+ * 3 - dirty = false, shadow_dirty = true
+ * 4 - shadow_dirty = false */
+ if (i++ == 3) {
+ DSSERR("ovl(%d)->wait_for_go() not finishing\n",
+ ovl->id);
+ r = 0;
+ break;
+ }
+
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ if (r == -ERESTARTSYS)
+ break;
+
+ if (r) {
+ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
+ break;
+ }
+ }
+
+ return r;
+}
+
+static int overlay_enabled(struct omap_overlay *ovl)
+{
+ return ovl->info.enabled && ovl->manager && ovl->manager->device;
+}
+
+/* Is rect1 a subset of rect2? */
+static bool rectangle_subset(int x1, int y1, int w1, int h1,
+ int x2, int y2, int w2, int h2)
+{
+ if (x1 < x2 || y1 < y2)
+ return false;
+
+ if (x1 + w1 > x2 + w2)
+ return false;
+
+ if (y1 + h1 > y2 + h2)
+ return false;
+
+ return true;
+}
+
+/* Do rect1 and rect2 overlap? */
+static bool rectangle_intersects(int x1, int y1, int w1, int h1,
+ int x2, int y2, int w2, int h2)
+{
+ if (x1 >= x2 + w2)
+ return false;
+
+ if (x2 >= x1 + w1)
+ return false;
+
+ if (y1 >= y2 + h2)
+ return false;
+
+ if (y2 >= y1 + h1)
+ return false;
+
+ return true;
+}
+
+static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
+{
+ if (oc->out_width != 0 && oc->width != oc->out_width)
+ return true;
+
+ if (oc->out_height != 0 && oc->height != oc->out_height)
+ return true;
+
+ return false;
+}
+
+static int configure_overlay(enum omap_plane plane)
+{
+ struct overlay_cache_data *c;
+ struct manager_cache_data *mc;
+ u16 outw, outh;
+ u16 x, y, w, h;
+ u32 paddr;
+ int r;
+
+ DSSDBGF("%d", plane);
+
+ c = &dss_cache.overlay_cache[plane];
+
+ if (!c->enabled) {
+ dispc_enable_plane(plane, 0);
+ return 0;
+ }
+
+ mc = &dss_cache.manager_cache[c->channel];
+
+ x = c->pos_x;
+ y = c->pos_y;
+ w = c->width;
+ h = c->height;
+ outw = c->out_width == 0 ? c->width : c->out_width;
+ outh = c->out_height == 0 ? c->height : c->out_height;
+ paddr = c->paddr;
+/* TODO: OMAP4: check if changes are needed here for NV12 ?*/
+ if (c->manual_update && mc->do_manual_update) {
+ unsigned bpp;
+ /* If the overlay is outside the update region, disable it */
+ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
+ x, y, outw, outh)) {
+ dispc_enable_plane(plane, 0);
+ return 0;
+ }
+
+ switch (c->color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ bpp = 16;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ bpp = 24;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ bpp = 32;
+ break;
+
+ default:
+ BUG();
+ }
+
+ if (mc->x > c->pos_x) {
+ x = 0;
+ w -= (mc->x - c->pos_x);
+ paddr += (mc->x - c->pos_x) * bpp / 8;
+ } else {
+ x = c->pos_x - mc->x;
+ }
+
+ if (mc->y > c->pos_y) {
+ y = 0;
+ h -= (mc->y - c->pos_y);
+ paddr += (mc->y - c->pos_y) * c->screen_width * bpp / 8;
+ } else {
+ y = c->pos_y - mc->y;
+ }
+
+ if (mc->w < (x+w))
+ w -= (x+w) - (mc->w);
+
+ if (mc->h < (y+h))
+ h -= (y+h) - (mc->h);
+
+ if (!dispc_is_overlay_scaled(c)) {
+ outw = w;
+ outh = h;
+ }
+ }
+
+ r = dispc_setup_plane(plane,
+ paddr,
+ c->screen_width,
+ x, y,
+ w, h,
+ outw, outh,
+ c->color_mode,
+ c->ilace,
+ c->rotation_type,
+ c->rotation,
+ c->mirror,
+ c->global_alpha, c->channel
+#ifdef CONFIG_ARCH_OMAP4
+ , c->p_uv_addr
+#endif
+ );
+
+ if (r) {
+ /* this shouldn't happen */
+ DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
+ dispc_enable_plane(plane, 0);
+ return r;
+ }
+
+ dispc_enable_replication(plane, c->replication);
+
+ dispc_set_burst_size(plane, c->burst_size);
+ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
+
+#ifdef CONFIG_ARCH_OMAP4
+ dispc_set_zorder(plane, c->zorder);
+ dispc_enable_zorder(plane, 1);
+#endif
+ dispc_enable_plane(plane, 1);
+
+ return 0;
+}
+
+static void configure_manager(enum omap_channel channel)
+{
+ struct manager_cache_data *c;
+
+ DSSDBGF("%d", channel);
+
+ c = &dss_cache.manager_cache[channel];
+
+ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
+ dispc_enable_trans_key(channel, c->trans_enabled);
+ dispc_enable_alpha_blending(channel, c->alpha_enabled);
+}
+
+/* configure_dispc() tries to write values from cache to shadow registers.
+ * It writes only to those managers/overlays that are not busy.
+ * returns 0 if everything could be written to shadow registers.
+ * returns 1 if not everything could be written to shadow registers. */
+static int configure_dispc(void)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+ int i;
+ int r;
+
+ bool mgr_busy[MAX_DSS_MANAGERS];
+ bool mgr_go[MAX_DSS_MANAGERS];
+ bool busy;
+
+ r = 0;
+ busy = false;
+
+ for (i = 0; i < num_mgrs; i++) {
+ mgr_busy[i] = dispc_go_busy(i);
+ mgr_go[i] = false;
+ }
+
+ /* Commit overlay settings */
+ for (i = 0; i < num_ovls; ++i) {
+ oc = &dss_cache.overlay_cache[i];
+ mc = &dss_cache.manager_cache[oc->channel];
+
+ if (!oc->dirty)
+ continue;
+
+ if (oc->manual_update && !mc->do_manual_update)
+ continue;
+
+ if (mgr_busy[oc->channel]) {
+ busy = true;
+ continue;
+ }
+
+ r = configure_overlay(i);
+ if (r)
+ DSSERR("configure_overlay %d failed\n", i);
+ oc->dirty = false;
+ oc->shadow_dirty = true;
+ mgr_go[oc->channel] = true;
+ }
+
+ /* Commit manager settings */
+ for (i = 0; i < num_mgrs; ++i) {
+ mc = &dss_cache.manager_cache[i];
+
+ if (!mc->dirty)
+ continue;
+
+ if (mc->manual_update && !mc->do_manual_update)
+ continue;
+
+ if (mgr_busy[i]) {
+ busy = true;
+ continue;
+ }
+
+ configure_manager(i);
+ mc->dirty = false;
+ mc->shadow_dirty = true;
+ mgr_go[i] = true;
+ }
+
+ /* set GO */
+ for (i = 0; i < num_mgrs; ++i) {
+ mc = &dss_cache.manager_cache[i];
+
+ if (!mgr_go[i])
+ continue;
+ /* We don't need GO with manual update display. LCD iface will
+ * always be turned off after frame, and new settings will be
+ * taken in to use at next update */
+ if (!mc->manual_upd_display)
+ dispc_go(i);
+ }
+
+ if (busy)
+ r = 1;
+ else
+ r = 0;
+
+ return r;
+}
+
+/* Configure dispc for partial update. Return possibly modified update
+ * area */
+void dss_setup_partial_planes(struct omap_dss_device *dssdev,
+ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+ struct omap_overlay_manager *mgr;
+ int i;
+ u16 x, y, w, h;
+ unsigned long flags;
+
+ x = *xi;
+ y = *yi;
+ w = *wi;
+ h = *hi;
+
+ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
+ *xi, *yi, *wi, *hi);
+
+ mgr = dssdev->manager;
+
+ if (!mgr) {
+ DSSDBG("no manager\n");
+ return;
+ }
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+
+ /* We need to show the whole overlay if it is scaled. So look for
+ * those, and make the update area larger if found.
+ * Also mark the overlay cache dirty */
+ for (i = 0; i < num_ovls; ++i) {
+ unsigned x1, y1, x2, y2;
+ unsigned outw, outh;
+
+ oc = &dss_cache.overlay_cache[i];
+
+ if (oc->channel != mgr->id)
+ continue;
+
+ oc->dirty = true;
+
+ if (!oc->enabled)
+ continue;
+
+ if (!dispc_is_overlay_scaled(oc))
+ continue;
+
+ outw = oc->out_width == 0 ? oc->width : oc->out_width;
+ outh = oc->out_height == 0 ? oc->height : oc->out_height;
+
+ /* is the overlay outside the update region? */
+ if (!rectangle_intersects(x, y, w, h,
+ oc->pos_x, oc->pos_y,
+ outw, outh))
+ continue;
+
+ /* if the overlay totally inside the update region? */
+ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
+ x, y, w, h))
+ continue;
+
+ if (x > oc->pos_x)
+ x1 = oc->pos_x;
+ else
+ x1 = x;
+
+ if (y > oc->pos_y)
+ y1 = oc->pos_y;
+ else
+ y1 = y;
+
+ if ((x + w) < (oc->pos_x + outw))
+ x2 = oc->pos_x + outw;
+ else
+ x2 = x + w;
+
+ if ((y + h) < (oc->pos_y + outh))
+ y2 = oc->pos_y + outh;
+ else
+ y2 = y + h;
+
+ x = x1;
+ y = y1;
+ w = x2 - x1;
+ h = y2 - y1;
+
+ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
+ i, x, y, w, h);
+ }
+
+ mc = &dss_cache.manager_cache[mgr->id];
+ mc->do_manual_update = true;
+ mc->x = x;
+ mc->y = y;
+ mc->w = w;
+ mc->h = h;
+
+ configure_dispc();
+
+ mc->do_manual_update = false;
+
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ *xi = x;
+ *yi = y;
+ *wi = w;
+ *hi = h;
+}
+
+void dss_start_update(struct omap_dss_device *dssdev)
+{
+ struct manager_cache_data *mc;
+ struct overlay_cache_data *oc;
+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+ struct omap_overlay_manager *mgr;
+ int i;
+
+ mgr = dssdev->manager;
+
+ for (i = 0; i < num_ovls; ++i) {
+ oc = &dss_cache.overlay_cache[i];
+ if (oc->channel != mgr->id)
+ continue;
+
+ oc->shadow_dirty = false;
+ }
+
+ for (i = 0; i < num_mgrs; ++i) {
+ mc = &dss_cache.manager_cache[i];
+ if (mgr->id != i)
+ continue;
+
+ mc->shadow_dirty = false;
+ }
+
+ dispc_enable_lcd_out(dssdev->channel, 1);
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask)
+{
+ struct manager_cache_data *mc;
+ struct overlay_cache_data *oc;
+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+ int i, r;
+ bool mgr_busy[MAX_DSS_MANAGERS];
+
+ for (i = 0; i < num_mgrs; i++)
+ mgr_busy[i] = dispc_go_busy(i);
+
+ spin_lock(&dss_cache.lock);
+
+ for (i = 0; i < num_ovls; ++i) {
+ oc = &dss_cache.overlay_cache[i];
+ if (!mgr_busy[oc->channel])
+ oc->shadow_dirty = false;
+ }
+
+ for (i = 0; i < num_mgrs; ++i) {
+ mc = &dss_cache.manager_cache[i];
+ if (!mgr_busy[i])
+ mc->shadow_dirty = false;
+ }
+
+ r = configure_dispc();
+ if (r == 1)
+ goto end;
+
+ /* re-read busy flags */
+ mgr_busy[0] = dispc_go_busy(0);
+ mgr_busy[1] = dispc_go_busy(1);
+
+ /* keep running as long as there are busy managers, so that
+ * we can collect overlay-applied information */
+ for (i = 0; i < num_mgrs; ++i)
+ if (mgr_busy[i])
+ goto end;
+
+ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
+ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
+ DISPC_IRQ_EVSYNC_EVEN
+#ifdef CONFIG_ARCH_OMAP4
+ | DISPC_IRQ_VSYNC2
+#endif
+ );
+
+ dss_cache.irq_enabled = false;
+
+end:
+ spin_unlock(&dss_cache.lock);
+}
+
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ int i;
+ struct omap_overlay *ovl;
+ int num_planes_enabled = 0;
+ bool use_fifomerge;
+ unsigned long flags;
+ int r;
+
+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+
+ /* Configure overlays */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_dss_device *dssdev;
+
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+ oc = &dss_cache.overlay_cache[ovl->id];
+
+ if (!overlay_enabled(ovl)) {
+ if (oc->enabled) {
+ oc->enabled = false;
+ oc->dirty = true;
+ }
+ continue;
+ }
+
+ if (!ovl->info_dirty) {
+ if (oc->enabled)
+ ++num_planes_enabled;
+ continue;
+ }
+
+ dssdev = ovl->manager->device;
+
+ if (dss_check_overlay(ovl, dssdev)) {
+ if (oc->enabled) {
+ oc->enabled = false;
+ oc->dirty = true;
+ }
+ continue;
+ }
+
+ ovl->info_dirty = false;
+ oc->dirty = true;
+
+ oc->paddr = ovl->info.paddr;
+#ifdef CONFIG_ARCH_OMAP4
+ oc->p_uv_addr = ovl->info.p_uv_addr;
+ oc->zorder = ovl->info.zorder;
+#endif
+ oc->vaddr = ovl->info.vaddr;
+ oc->screen_width = ovl->info.screen_width;
+ oc->width = ovl->info.width;
+ oc->height = ovl->info.height;
+ oc->color_mode = ovl->info.color_mode;
+ oc->rotation = ovl->info.rotation;
+ oc->rotation_type = ovl->info.rotation_type;
+ oc->mirror = ovl->info.mirror;
+ oc->pos_x = ovl->info.pos_x;
+ oc->pos_y = ovl->info.pos_y;
+ oc->out_width = ovl->info.out_width;
+ oc->out_height = ovl->info.out_height;
+ oc->global_alpha = ovl->info.global_alpha;
+
+ oc->replication =
+ dss_use_replication(dssdev, ovl->info.color_mode);
+
+ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
+
+ oc->channel = ovl->manager->id;
+ /* TODO: to change with dssdev->channel? */
+
+ oc->enabled = true;
+
+ oc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
+
+ ++num_planes_enabled;
+
+ }
+ /* Configure managers */
+ list_for_each_entry(mgr, &manager_list, list) {
+ struct omap_dss_device *dssdev;
+
+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
+ continue;
+ mc = &dss_cache.manager_cache[mgr->id];
+
+ if (mgr->device_changed) {
+ mgr->device_changed = false;
+ mgr->info_dirty = true;
+ }
+
+ if (!mgr->info_dirty)
+ continue;
+
+ if (!mgr->device)
+ continue;
+
+ dssdev = mgr->device;
+
+ mgr->info_dirty = false;
+ mc->dirty = true;
+
+ mc->default_color = mgr->info.default_color;
+ mc->trans_key_type = mgr->info.trans_key_type;
+ mc->trans_key = mgr->info.trans_key;
+ mc->trans_enabled = mgr->info.trans_enabled;
+ mc->alpha_enabled = mgr->info.alpha_enabled;
+
+ mc->manual_upd_display =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ mc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
+ }
+
+ /* XXX TODO: Try to get fifomerge working. The problem is that it
+ * affects both managers, not individually but at the same time. This
+ * means the change has to be well synchronized. I guess the proper way
+ * is to have a two step process for fifo merge:
+ * fifomerge enable:
+ * 1. disable other planes, leaving one plane enabled
+ * 2. wait until the planes are disabled on HW
+ * 3. config merged fifo thresholds, enable fifomerge
+ * fifomerge disable:
+ * 1. config unmerged fifo thresholds, disable fifomerge
+ * 2. wait until fifo changes are in HW
+ * 3. enable planes
+ */
+ use_fifomerge = false;
+
+ /* Configure overlay fifos */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_dss_device *dssdev;
+ u32 size;
+
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+
+ if (!oc->enabled)
+ continue;
+
+ dssdev = ovl->manager->device;
+
+ size = dispc_get_plane_fifo_size(ovl->id);
+ if (use_fifomerge)
+ size *= 3;
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_SDI:
+ case OMAP_DISPLAY_TYPE_VENC:
+ default_get_overlay_fifo_thresholds(ovl->id, size,
+ &oc->burst_size, &oc->fifo_low,
+ &oc->fifo_high);
+ break;
+#ifdef CONFIG_OMAP2_DSS_DSI
+ case OMAP_DISPLAY_TYPE_DSI:
+ dsi_get_overlay_fifo_thresholds(ovl->id, size,
+ &oc->burst_size, &oc->fifo_low,
+ &oc->fifo_high);
+ break;
+#endif
+ default:
+ BUG();
+ }
+ }
+
+ r = 0;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ if (!dss_cache.irq_enabled) {
+ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
+ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
+ DISPC_IRQ_EVSYNC_EVEN
+#ifdef CONFIG_ARCH_OMAP4
+ | DISPC_IRQ_VSYNC2
+#endif
+ );
+
+ dss_cache.irq_enabled = true;
+ }
+ configure_dispc();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ return r;
+}
+
+static int dss_check_manager(struct omap_overlay_manager *mgr)
+{
+ /* OMAP does not support destination color keying and alpha blending
+ * simultaneously. */
+
+ if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
+ mgr->info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
+ return -EINVAL;
+
+ mgr->info_dirty = true;
+
+ return 0;
+}
+
+static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info)
+{
+ int r;
+ struct omap_overlay_manager_info old_info;
+
+ old_info = mgr->info;
+ mgr->info = *info;
+
+ r = dss_check_manager(mgr);
+ if (r) {
+ mgr->info = old_info;
+ return r;
+ }
+
+ return 0;
+}
+
+static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info)
+{
+ *info = mgr->info;
+}
+
+static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
+{
+ ++num_managers;
+ list_add_tail(&manager->list, &manager_list);
+}
+
+int dss_init_overlay_managers(struct platform_device *pdev)
+{
+ int i, r;
+
+ spin_lock_init(&dss_cache.lock);
+ INIT_LIST_HEAD(&manager_list);
+
+ num_managers = 0;
+
+ for (i = 0; i < MAX_DSS_MANAGERS; ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+
+ BUG_ON(mgr == NULL);
+
+ switch (i) {
+ case 0:
+ mgr->name = "lcd";
+ mgr->id = OMAP_DSS_CHANNEL_LCD;
+ mgr->supported_displays =
+ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
+ break;
+ case 1:
+ mgr->name = "tv";
+ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
+ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
+ break;
+#ifdef CONFIG_ARCH_OMAP4
+ case 2:
+ mgr->name = "lcd2";
+ mgr->id = OMAP_DSS_CHANNEL_LCD2;
+ mgr->supported_displays =
+ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_SDI |
+ OMAP_DISPLAY_TYPE_DSI;
+ break;
+#endif
+ }
+
+ mgr->set_device = &omap_dss_set_device;
+ mgr->unset_device = &omap_dss_unset_device;
+ mgr->apply = &omap_dss_mgr_apply;
+ mgr->set_manager_info = &omap_dss_mgr_set_info;
+ mgr->get_manager_info = &omap_dss_mgr_get_info;
+ mgr->wait_for_go = &dss_mgr_wait_for_go;
+
+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+
+ dss_overlay_setup_dispc_manager(mgr);
+
+ omap_dss_add_overlay_manager(mgr);
+
+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
+ &pdev->dev.kobj, "manager%d", i);
+
+ if (r) {
+ DSSERR("failed to create sysfs file\n");
+ continue;
+ }
+ }
+
+#ifdef L4_EXAMPLE
+ {
+ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
+ {
+ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
+
+ return 0;
+ }
+
+ struct omap_overlay_manager *mgr;
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+
+ BUG_ON(mgr == NULL);
+
+ mgr->name = "l4";
+ mgr->supported_displays =
+ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
+
+ mgr->set_device = &omap_dss_set_device;
+ mgr->unset_device = &omap_dss_unset_device;
+ mgr->apply = &omap_dss_mgr_apply_l4;
+ mgr->set_manager_info = &omap_dss_mgr_set_info;
+ mgr->get_manager_info = &omap_dss_mgr_get_info;
+
+ dss_overlay_setup_l4_manager(mgr);
+
+ omap_dss_add_overlay_manager(mgr);
+
+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
+ &pdev->dev.kobj, "managerl4");
+
+ if (r)
+ DSSERR("failed to create sysfs file\n");
+ }
+#endif
+
+ return 0;
+}
+
+void dss_uninit_overlay_managers(struct platform_device *pdev)
+{
+ struct omap_overlay_manager *mgr;
+
+ while (!list_empty(&manager_list)) {
+ mgr = list_first_entry(&manager_list,
+ struct omap_overlay_manager, list);
+ list_del(&mgr->list);
+ kobject_del(&mgr->kobj);
+ kobject_put(&mgr->kobj);
+ kfree(mgr);
+ }
+
+ num_managers = 0;
+}
+
+int omap_dss_get_num_overlay_managers(void)
+{
+ return num_managers;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
+
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
+{
+ int i = 0;
+ struct omap_overlay_manager *mgr;
+
+ list_for_each_entry(mgr, &manager_list, list) {
+ if (i++ == num)
+ return mgr;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
+
+#ifdef L4_EXAMPLE
+static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
+{
+ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
+ return 0;
+}
+#endif
+
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
new file mode 100644
index 000000000000..9ba2af1c802a
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay.c
@@ -0,0 +1,769 @@
+/*
+ * linux/drivers/video/omap2/dss/overlay.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/display.h>
+
+#include "dss.h"
+
+#ifdef CONFIG_ARCH_OMAP4
+#define MAX_DSS_OVERLAYS 4
+#else
+#define MAX_DSS_OVERLAYS 3
+#endif
+
+static int num_overlays;
+static struct list_head overlay_list;
+
+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+}
+
+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ovl->manager ? ovl->manager->name : "<none>");
+}
+
+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+ size_t size)
+{
+ int i, r;
+ struct omap_overlay_manager *mgr = NULL;
+ struct omap_overlay_manager *old_mgr;
+ int len = size;
+
+ if (buf[size-1] == '\n')
+ --len;
+
+ if (len > 0) {
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (strncmp(buf, mgr->name, len) == 0)
+ break;
+
+ mgr = NULL;
+ }
+ }
+
+ if (len > 0 && mgr == NULL)
+ return -EINVAL;
+
+ if (mgr)
+ DSSDBG("manager %s found\n", mgr->name);
+
+ if (mgr == ovl->manager)
+ return size;
+
+ old_mgr = ovl->manager;
+
+ /* detach old manager */
+ if (old_mgr) {
+ r = ovl->unset_manager(ovl);
+ if (r) {
+ DSSERR("detach failed\n");
+ return r;
+ }
+
+ r = old_mgr->apply(old_mgr);
+ if (r)
+ return r;
+ }
+
+ if (mgr) {
+ r = ovl->set_manager(ovl, mgr);
+ if (r) {
+ DSSERR("Failed to attach overlay\n");
+ return r;
+ }
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+ }
+ return size;
+}
+
+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ ovl->info.width, ovl->info.height);
+}
+
+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
+}
+
+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ ovl->info.pos_x, ovl->info.pos_y);
+}
+
+static ssize_t overlay_position_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ char *last;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.pos_x = simple_strtoul(buf, &last, 10);
+ ++last;
+ if (last - buf >= size)
+ return -EINVAL;
+
+ info.pos_y = simple_strtoul(last, &last, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ ovl->info.out_width, ovl->info.out_height);
+}
+
+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ char *last;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.out_width = simple_strtoul(buf, &last, 10);
+ ++last;
+ if (last - buf >= size)
+ return -EINVAL;
+
+ info.out_height = simple_strtoul(last, &last, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
+}
+
+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+ size_t size)
+{
+ int r;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.enabled = simple_strtoul(buf, NULL, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ ovl->info.global_alpha);
+}
+
+static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+#ifndef CONFIG_ARCH_OMAP4
+ /* In OMAP2/3: Video1 plane does not support global alpha
+ * to always make it 255 completely opaque
+ */
+ if (ovl->id == OMAP_DSS_VIDEO1)
+ info.global_alpha = 255;
+ else
+#endif
+ info.global_alpha = simple_strtoul(buf, NULL, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+#ifdef CONFIG_ARCH_OMAP4
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ ovl->info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.zorder = simple_strtoul(buf, NULL, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+#endif
+
+struct overlay_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay *, char *);
+ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
+};
+
+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
+ struct overlay_attribute overlay_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
+ overlay_manager_show, overlay_manager_store);
+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
+ overlay_position_show, overlay_position_store);
+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+ overlay_output_size_show, overlay_output_size_store);
+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+ overlay_enabled_show, overlay_enabled_store);
+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
+ overlay_global_alpha_show, overlay_global_alpha_store);
+
+#ifdef CONFIG_ARCH_OMAP4
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+ overlay_zorder_show, overlay_zorder_store);
+#endif
+
+static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_name.attr,
+ &overlay_attr_manager.attr,
+ &overlay_attr_input_size.attr,
+ &overlay_attr_screen_width.attr,
+ &overlay_attr_position.attr,
+ &overlay_attr_output_size.attr,
+ &overlay_attr_enabled.attr,
+ &overlay_attr_global_alpha.attr,
+#ifdef CONFIG_ARCH_OMAP4
+ &overlay_attr_zorder.attr,
+#endif
+ NULL
+};
+
+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct omap_overlay *overlay;
+ struct overlay_attribute *overlay_attr;
+
+ overlay = container_of(kobj, struct omap_overlay, kobj);
+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+ if (!overlay_attr->show)
+ return -ENOENT;
+
+ return overlay_attr->show(overlay, buf);
+}
+
+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay *overlay;
+ struct overlay_attribute *overlay_attr;
+
+ overlay = container_of(kobj, struct omap_overlay, kobj);
+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+ if (!overlay_attr->store)
+ return -ENOENT;
+
+ return overlay_attr->store(overlay, buf, size);
+}
+
+static struct sysfs_ops overlay_sysfs_ops = {
+ .show = overlay_attr_show,
+ .store = overlay_attr_store,
+};
+
+static struct kobj_type overlay_ktype = {
+ .sysfs_ops = &overlay_sysfs_ops,
+ .default_attrs = overlay_sysfs_attrs,
+};
+
+/* Check if overlay parameters are compatible with display */
+int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
+{
+ struct omap_overlay_info *info;
+ u16 outw, outh;
+ u16 dw, dh;
+
+ if (!dssdev)
+ return 0;
+
+ if (!ovl->info.enabled)
+ return 0;
+
+ info = &ovl->info;
+
+ if (info->paddr == 0) {
+ DSSDBG("check_overlay failed: paddr 0\n");
+ return -EINVAL;
+ }
+
+ dssdev->get_resolution(dssdev, &dw, &dh);
+
+ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
+ ovl->id,
+ info->pos_x, info->pos_y,
+ info->width, info->height,
+ info->out_width, info->out_height,
+ dw, dh);
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ outw = info->width;
+ outh = info->height;
+ } else {
+ if (info->out_width == 0)
+ outw = info->width;
+ else
+ outw = info->out_width;
+
+ if (info->out_height == 0)
+ outh = info->height;
+ else
+ outh = info->out_height;
+ }
+
+ if (dw < info->pos_x + outw) {
+ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
+ dw, info->pos_x, outw);
+ return -EINVAL;
+ }
+
+ if (dh < info->pos_y + outh) {
+ DSSDBG("check_overlay failed 2: %d < %d + %d\n",
+ dh, info->pos_y, outh);
+ return -EINVAL;
+ }
+
+ if ((ovl->supported_modes & info->color_mode) == 0) {
+ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_ARCH_OMAP4
+ if ((info->zorder < OMAP_DSS_OVL_ZORDER_0) ||
+ (info->zorder > OMAP_DSS_OVL_ZORDER_3)) {
+ DSSERR("overlay doesn't support zorder %d\n", info->zorder);
+ return -EINVAL;
+ }
+
+#endif
+
+ return 0;
+}
+
+static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info)
+{
+ int r;
+ struct omap_overlay_info old_info;
+
+ old_info = ovl->info;
+ ovl->info = *info;
+
+ if (ovl->manager) {
+ r = dss_check_overlay(ovl, ovl->manager->device);
+ if (r) {
+ ovl->info = old_info;
+ return r;
+ }
+ }
+
+ ovl->info_dirty = true;
+
+ return 0;
+}
+
+static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info)
+{
+ *info = ovl->info;
+}
+
+static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
+{
+ return dss_mgr_wait_for_go_ovl(ovl);
+}
+
+static int omap_dss_set_manager(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr)
+{
+
+ if (!mgr)
+ return -EINVAL;
+
+ if (ovl->manager) {
+ DSSERR("overlay '%s' already has a manager '%s'\n",
+ ovl->name, ovl->manager->name);
+ return -EINVAL;
+ }
+
+
+ if (ovl->info.enabled) {
+ DSSERR("overlay has to be disabled to change the manager\n");
+ return -EINVAL;
+ }
+
+ ovl->manager = mgr;
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ /* XXX: on manual update display, in auto update mode, a bug happens
+ * here. When an overlay is first enabled on LCD, then it's disabled,
+ * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
+ * errors. Waiting before changing the channel_out fixes it. I'm
+ * guessing that the overlay is still somehow being used for the LCD,
+ * but I don't understand how or why. */
+ msleep(40);
+ dispc_set_channel_out(ovl->id, mgr->id);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ return 0;
+}
+
+static int omap_dss_unset_manager(struct omap_overlay *ovl)
+{
+ int r;
+ if (!ovl->manager) {
+ DSSERR("failed to detach overlay: manager not set\n");
+ return -EINVAL;
+ }
+
+ if (ovl->info.enabled) {
+ DSSERR("overlay has to be disabled to unset the manager\n");
+ return -EINVAL;
+ }
+
+ r = ovl->wait_for_go(ovl);
+ if (r)
+ return r;
+ ovl->manager = NULL;
+ /* XXX disable overlay? */
+
+ return 0;
+}
+
+int omap_dss_get_num_overlays(void)
+{
+ return num_overlays;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlays);
+
+struct omap_overlay *omap_dss_get_overlay(int num)
+{
+ int i = 0;
+ struct omap_overlay *ovl;
+
+ list_for_each_entry(ovl, &overlay_list, list) {
+ if (i++ == num)
+ return ovl;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(omap_dss_get_overlay);
+
+static void omap_dss_add_overlay(struct omap_overlay *overlay)
+{
+ ++num_overlays;
+ list_add_tail(&overlay->list, &overlay_list);
+}
+
+static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
+
+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
+{
+ mgr->num_overlays = MAX_DSS_OVERLAYS;
+ mgr->overlays = dispc_overlays;
+}
+
+#ifdef L4_EXAMPLE
+static struct omap_overlay *l4_overlays[1];
+void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
+{
+ mgr->num_overlays = 1;
+ mgr->overlays = l4_overlays;
+}
+#endif
+
+void dss_init_overlays(struct platform_device *pdev)
+{
+ int i, r;
+
+ INIT_LIST_HEAD(&overlay_list);
+
+ num_overlays = 0;
+
+ for (i = 0; i < MAX_DSS_OVERLAYS; ++i) {
+ struct omap_overlay *ovl;
+ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
+
+ BUG_ON(ovl == NULL);
+
+ switch (i) {
+ case 0:
+ ovl->name = "gfx";
+ ovl->id = OMAP_DSS_GFX;
+ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
+ ovl->info.global_alpha = 255;
+#ifdef CONFIG_ARCH_OMAP4
+ ovl->info.zorder = OMAP_DSS_OVL_ZORDER_0;
+#endif
+ break;
+ case 1:
+ ovl->name = "vid1";
+ ovl->id = OMAP_DSS_VIDEO1;
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
+ ovl->info.global_alpha = 255;
+#ifdef CONFIG_ARCH_OMAP4
+ ovl->info.zorder = OMAP_DSS_OVL_ZORDER_3;
+#endif
+ break;
+ case 2:
+ ovl->name = "vid2";
+ ovl->id = OMAP_DSS_VIDEO2;
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
+ ovl->info.global_alpha = 255;
+#ifdef CONFIG_ARCH_OMAP4
+ ovl->info.zorder = OMAP_DSS_OVL_ZORDER_2;
+#endif
+ break;
+#ifdef CONFIG_ARCH_OMAP4
+ case 3:
+ ovl->name = "vid3";
+ ovl->id = OMAP_DSS_VIDEO3;
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
+ ovl->info.global_alpha = 255;
+#ifdef CONFIG_ARCH_OMAP4
+ ovl->info.zorder = OMAP_DSS_OVL_ZORDER_1;
+#endif
+
+ break;
+#endif
+ }
+
+ ovl->set_manager = &omap_dss_set_manager;
+ ovl->unset_manager = &omap_dss_unset_manager;
+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
+ ovl->wait_for_go = &dss_ovl_wait_for_go;
+
+ omap_dss_add_overlay(ovl);
+
+ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+ &pdev->dev.kobj, "overlay%d", i);
+
+ if (r) {
+ DSSERR("failed to create sysfs file\n");
+ continue;
+ }
+
+ dispc_overlays[i] = ovl;
+ }
+
+#ifdef L4_EXAMPLE
+ {
+ struct omap_overlay *ovl;
+ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
+
+ BUG_ON(ovl == NULL);
+
+ ovl->name = "l4";
+ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
+
+ ovl->set_manager = &omap_dss_set_manager;
+ ovl->unset_manager = &omap_dss_unset_manager;
+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
+
+ omap_dss_add_overlay(ovl);
+
+ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+ &pdev->dev.kobj, "overlayl4");
+
+ if (r)
+ DSSERR("failed to create sysfs file\n");
+
+ l4_overlays[0] = ovl;
+ }
+#endif
+}
+
+/* connect overlays to the new device, if not already connected. if force
+ * selected, connect always. */
+void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
+{
+ int i;
+ struct omap_overlay_manager *lcd_mgr;
+ struct omap_overlay_manager *tv_mgr;
+#ifdef CONFIG_ARCH_OMAP4
+ struct omap_overlay_manager *lcd2_mgr;
+#endif
+ struct omap_overlay_manager *mgr = NULL;
+
+ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
+ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
+
+#ifdef CONFIG_ARCH_OMAP4
+ lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2);
+
+ if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
+ if (!lcd2_mgr->device || force) {
+ if (lcd2_mgr->device)
+ lcd2_mgr->unset_device(lcd2_mgr);
+ lcd2_mgr->set_device(lcd2_mgr, dssdev);
+ mgr = lcd2_mgr;
+ }
+ } else
+#endif
+
+ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
+ if (!lcd_mgr->device || force) {
+ if (lcd_mgr->device)
+ lcd_mgr->unset_device(lcd_mgr);
+ lcd_mgr->set_device(lcd_mgr, dssdev);
+ mgr = lcd_mgr;
+ }
+ }
+
+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
+ if (!tv_mgr->device || force) {
+ if (tv_mgr->device)
+ tv_mgr->unset_device(tv_mgr);
+ tv_mgr->set_device(tv_mgr, dssdev);
+ mgr = tv_mgr;
+ }
+ }
+
+ if (mgr) {
+ for (i = 0; i < MAX_DSS_OVERLAYS; i++) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+ if (!ovl->manager || force) {
+ if (ovl->manager)
+ omap_dss_unset_manager(ovl);
+ omap_dss_set_manager(ovl, mgr);
+ }
+ }
+ }
+}
+
+void dss_uninit_overlays(struct platform_device *pdev)
+{
+ struct omap_overlay *ovl;
+
+ while (!list_empty(&overlay_list)) {
+ ovl = list_first_entry(&overlay_list,
+ struct omap_overlay, list);
+ list_del(&ovl->list);
+ kobject_del(&ovl->kobj);
+ kobject_put(&ovl->kobj);
+ kfree(ovl);
+ }
+
+ num_overlays = 0;
+}
+
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
new file mode 100644
index 000000000000..f2436f8d60f0
--- /dev/null
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -0,0 +1,1315 @@
+/*
+ * linux/drivers/video/omap2/dss/rfbi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "RFBI"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/kfifo.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/seq_file.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include "dss.h"
+
+/*#define MEASURE_PERF*/
+
+#define RFBI_BASE 0x48050800
+
+struct rfbi_reg { u16 idx; };
+
+#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
+
+#define RFBI_REVISION RFBI_REG(0x0000)
+#define RFBI_SYSCONFIG RFBI_REG(0x0010)
+#define RFBI_SYSSTATUS RFBI_REG(0x0014)
+#define RFBI_CONTROL RFBI_REG(0x0040)
+#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
+#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
+#define RFBI_CMD RFBI_REG(0x004c)
+#define RFBI_PARAM RFBI_REG(0x0050)
+#define RFBI_DATA RFBI_REG(0x0054)
+#define RFBI_READ RFBI_REG(0x0058)
+#define RFBI_STATUS RFBI_REG(0x005c)
+
+#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
+#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
+#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
+#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
+#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
+#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
+
+#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
+#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
+
+#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
+
+/* To work around an RFBI transfer rate limitation */
+#define OMAP_RFBI_RATE_LIMIT 1
+
+enum omap_rfbi_cycleformat {
+ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
+ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
+ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
+ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
+};
+
+enum omap_rfbi_datatype {
+ OMAP_DSS_RFBI_DATATYPE_12 = 0,
+ OMAP_DSS_RFBI_DATATYPE_16 = 1,
+ OMAP_DSS_RFBI_DATATYPE_18 = 2,
+ OMAP_DSS_RFBI_DATATYPE_24 = 3,
+};
+
+enum omap_rfbi_parallelmode {
+ OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
+ OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
+ OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
+ OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
+};
+
+enum update_cmd {
+ RFBI_CMD_UPDATE = 0,
+ RFBI_CMD_SYNC = 1,
+};
+
+static int rfbi_convert_timings(struct rfbi_timings *t);
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
+static void process_cmd_fifo(void);
+
+static struct {
+ void __iomem *base;
+
+ unsigned long l4_khz;
+
+ enum omap_rfbi_datatype datatype;
+ enum omap_rfbi_parallelmode parallelmode;
+
+ enum omap_rfbi_te_mode te_mode;
+ int te_enabled;
+
+ void (*framedone_callback)(void *data);
+ void *framedone_callback_data;
+
+ struct omap_dss_device *dssdev[2];
+
+ struct kfifo *cmd_fifo;
+ spinlock_t cmd_lock;
+ struct completion cmd_done;
+ atomic_t cmd_fifo_full;
+ atomic_t cmd_pending;
+#ifdef MEASURE_PERF
+ unsigned perf_bytes;
+ ktime_t perf_setup_time;
+ ktime_t perf_start_time;
+#endif
+} rfbi;
+
+struct update_region {
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+};
+
+struct update_param {
+ u8 rfbi_module;
+ u8 cmd;
+
+ union {
+ struct update_region r;
+ struct completion *sync;
+ } par;
+};
+
+static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
+{
+ __raw_writel(val, rfbi.base + idx.idx);
+}
+
+static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
+{
+ return __raw_readl(rfbi.base + idx.idx);
+}
+
+static void rfbi_enable_clocks(bool enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+void omap_rfbi_write_command(const void *buf, u32 len)
+{
+ rfbi_enable_clocks(1);
+ switch (rfbi.parallelmode) {
+ case OMAP_DSS_RFBI_PARALLELMODE_8:
+ {
+ const u8 *b = buf;
+ for (; len; len--)
+ rfbi_write_reg(RFBI_CMD, *b++);
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_16:
+ {
+ const u16 *w = buf;
+ BUG_ON(len & 1);
+ for (; len; len -= 2)
+ rfbi_write_reg(RFBI_CMD, *w++);
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_9:
+ case OMAP_DSS_RFBI_PARALLELMODE_12:
+ default:
+ BUG();
+ }
+ rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_command);
+
+void omap_rfbi_read_data(void *buf, u32 len)
+{
+ rfbi_enable_clocks(1);
+ switch (rfbi.parallelmode) {
+ case OMAP_DSS_RFBI_PARALLELMODE_8:
+ {
+ u8 *b = buf;
+ for (; len; len--) {
+ rfbi_write_reg(RFBI_READ, 0);
+ *b++ = rfbi_read_reg(RFBI_READ);
+ }
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_16:
+ {
+ u16 *w = buf;
+ BUG_ON(len & ~1);
+ for (; len; len -= 2) {
+ rfbi_write_reg(RFBI_READ, 0);
+ *w++ = rfbi_read_reg(RFBI_READ);
+ }
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_9:
+ case OMAP_DSS_RFBI_PARALLELMODE_12:
+ default:
+ BUG();
+ }
+ rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_read_data);
+
+void omap_rfbi_write_data(const void *buf, u32 len)
+{
+ rfbi_enable_clocks(1);
+ switch (rfbi.parallelmode) {
+ case OMAP_DSS_RFBI_PARALLELMODE_8:
+ {
+ const u8 *b = buf;
+ for (; len; len--)
+ rfbi_write_reg(RFBI_PARAM, *b++);
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_16:
+ {
+ const u16 *w = buf;
+ BUG_ON(len & 1);
+ for (; len; len -= 2)
+ rfbi_write_reg(RFBI_PARAM, *w++);
+ break;
+ }
+
+ case OMAP_DSS_RFBI_PARALLELMODE_9:
+ case OMAP_DSS_RFBI_PARALLELMODE_12:
+ default:
+ BUG();
+
+ }
+ rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_data);
+
+void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
+ u16 x, u16 y,
+ u16 w, u16 h)
+{
+ int start_offset = scr_width * y + x;
+ int horiz_offset = scr_width - w;
+ int i;
+
+ rfbi_enable_clocks(1);
+
+ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+ const u16 __iomem *pd = buf;
+ pd += start_offset;
+
+ for (; h; --h) {
+ for (i = 0; i < w; ++i) {
+ const u8 __iomem *b = (const u8 __iomem *)pd;
+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
+ ++pd;
+ }
+ pd += horiz_offset;
+ }
+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+ const u32 __iomem *pd = buf;
+ pd += start_offset;
+
+ for (; h; --h) {
+ for (i = 0; i < w; ++i) {
+ const u8 __iomem *b = (const u8 __iomem *)pd;
+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
+ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
+ ++pd;
+ }
+ pd += horiz_offset;
+ }
+ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
+ const u16 __iomem *pd = buf;
+ pd += start_offset;
+
+ for (; h; --h) {
+ for (i = 0; i < w; ++i) {
+ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
+ ++pd;
+ }
+ pd += horiz_offset;
+ }
+ } else {
+ BUG();
+ }
+
+ rfbi_enable_clocks(0);
+}
+EXPORT_SYMBOL(omap_rfbi_write_pixels);
+
+#ifdef MEASURE_PERF
+static void perf_mark_setup(void)
+{
+ rfbi.perf_setup_time = ktime_get();
+}
+
+static void perf_mark_start(void)
+{
+ rfbi.perf_start_time = ktime_get();
+}
+
+static void perf_show(const char *name)
+{
+ ktime_t t, setup_time, trans_time;
+ u32 total_bytes;
+ u32 setup_us, trans_us, total_us;
+
+ t = ktime_get();
+
+ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
+ setup_us = (u32)ktime_to_us(setup_time);
+ if (setup_us == 0)
+ setup_us = 1;
+
+ trans_time = ktime_sub(t, rfbi.perf_start_time);
+ trans_us = (u32)ktime_to_us(trans_time);
+ if (trans_us == 0)
+ trans_us = 1;
+
+ total_us = setup_us + trans_us;
+
+ total_bytes = rfbi.perf_bytes;
+
+ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
+ "%u kbytes/sec\n",
+ name,
+ setup_us,
+ trans_us,
+ total_us,
+ 1000*1000 / total_us,
+ total_bytes,
+ total_bytes * 1000 / total_us);
+}
+#else
+#define perf_mark_setup()
+#define perf_mark_start()
+#define perf_show(x)
+#endif
+
+void rfbi_transfer_area(u16 width, u16 height,
+ void (callback)(void *data), void *data)
+{
+ u32 l;
+
+ /*BUG_ON(callback == 0);*/
+ BUG_ON(rfbi.framedone_callback != NULL);
+
+ DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
+
+ dispc_set_lcd_size(OMAP_DSS_CHANNEL_LCD, width, height);
+ /* TODO: update for LCD2*/
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+
+ rfbi.framedone_callback = callback;
+ rfbi.framedone_callback_data = data;
+
+ rfbi_enable_clocks(1);
+
+ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+ l = rfbi_read_reg(RFBI_CONTROL);
+ l = FLD_MOD(l, 1, 0, 0); /* enable */
+ if (!rfbi.te_enabled)
+ l = FLD_MOD(l, 1, 4, 4); /* ITE */
+
+ perf_mark_start();
+
+ rfbi_write_reg(RFBI_CONTROL, l);
+}
+
+static void framedone_callback(void *data, u32 mask)
+{
+ void (*callback)(void *data);
+
+ DSSDBG("FRAMEDONE\n");
+
+ perf_show("DISPC");
+
+ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
+
+ rfbi_enable_clocks(0);
+
+ callback = rfbi.framedone_callback;
+ rfbi.framedone_callback = NULL;
+
+ /*callback(rfbi.framedone_callback_data);*/
+
+ atomic_set(&rfbi.cmd_pending, 0);
+
+ process_cmd_fifo();
+}
+
+#if 1 /* VERBOSE */
+static void rfbi_print_timings(void)
+{
+ u32 l;
+ u32 time;
+
+ l = rfbi_read_reg(RFBI_CONFIG(0));
+ time = 1000000000 / rfbi.l4_khz;
+ if (l & (1 << 4))
+ time *= 2;
+
+ DSSDBG("Tick time %u ps\n", time);
+ l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
+ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+ "REONTIME %d, REOFFTIME %d\n",
+ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
+ l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
+ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+ "ACCESSTIME %d\n",
+ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+ (l >> 22) & 0x3f);
+}
+#else
+static void rfbi_print_timings(void) {}
+#endif
+
+
+
+
+static u32 extif_clk_period;
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+ int bus_tick = extif_clk_period * div;
+ return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(struct rfbi_timings *t, int div)
+{
+ t->clk_div = div;
+
+ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
+
+ t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
+ t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
+ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
+
+ t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
+ t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
+ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
+
+ t->access_time = round_to_extif_ticks(t->access_time, div);
+ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
+ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
+
+ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
+ t->we_on_time, t->we_off_time, t->re_cycle_time,
+ t->we_cycle_time);
+ DSSDBG("[reg]rdaccess %d cspulse %d\n",
+ t->access_time, t->cs_pulse_width);
+
+ return rfbi_convert_timings(t);
+}
+
+static int calc_extif_timings(struct rfbi_timings *t)
+{
+ u32 max_clk_div;
+ int div;
+
+ rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
+ for (div = 1; div <= max_clk_div; div++) {
+ if (calc_reg_timing(t, div) == 0)
+ break;
+ }
+
+ if (div <= max_clk_div)
+ return 0;
+
+ DSSERR("can't setup timings\n");
+ return -1;
+}
+
+
+void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
+{
+ int r;
+
+ if (!t->converted) {
+ r = calc_extif_timings(t);
+ if (r < 0)
+ DSSERR("Failed to calc timings\n");
+ }
+
+ BUG_ON(!t->converted);
+
+ rfbi_enable_clocks(1);
+ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
+ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
+
+ /* TIMEGRANULARITY */
+ REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
+ (t->tim[2] ? 1 : 0), 4, 4);
+
+ rfbi_print_timings();
+ rfbi_enable_clocks(0);
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+ unsigned long tick_ps;
+ int ret;
+
+ /* Calculate in picosecs to yield more exact results */
+ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+ ret = (time + tick_ps - 1) / tick_ps;
+
+ return ret;
+}
+
+#ifdef OMAP_RFBI_RATE_LIMIT
+unsigned long rfbi_get_max_tx_rate(void)
+{
+ unsigned long l4_rate, dss1_rate;
+ int min_l4_ticks = 0;
+ int i;
+
+ /* According to TI this can't be calculated so make the
+ * adjustments for a couple of known frequencies and warn for
+ * others.
+ */
+ static const struct {
+ unsigned long l4_clk; /* HZ */
+ unsigned long dss1_clk; /* HZ */
+ unsigned long min_l4_ticks;
+ } ftab[] = {
+ { 55, 132, 7, }, /* 7.86 MPix/s */
+ { 110, 110, 12, }, /* 9.16 MPix/s */
+ { 110, 132, 10, }, /* 11 Mpix/s */
+ { 120, 120, 10, }, /* 12 Mpix/s */
+ { 133, 133, 10, }, /* 13.3 Mpix/s */
+ };
+
+ l4_rate = rfbi.l4_khz / 1000;
+ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
+
+ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
+ /* Use a window instead of an exact match, to account
+ * for different DPLL multiplier / divider pairs.
+ */
+ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
+ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
+ min_l4_ticks = ftab[i].min_l4_ticks;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(ftab)) {
+ /* Can't be sure, return anyway the maximum not
+ * rate-limited. This might cause a problem only for the
+ * tearing synchronisation.
+ */
+ DSSERR("can't determine maximum RFBI transfer rate\n");
+ return rfbi.l4_khz * 1000;
+ }
+ return rfbi.l4_khz * 1000 / min_l4_ticks;
+}
+#else
+int rfbi_get_max_tx_rate(void)
+{
+ return rfbi.l4_khz * 1000;
+}
+#endif
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+ *clk_period = 1000000000 / rfbi.l4_khz;
+ *max_clk_div = 2;
+}
+
+static int rfbi_convert_timings(struct rfbi_timings *t)
+{
+ u32 l;
+ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+ int actim, recyc, wecyc;
+ int div = t->clk_div;
+
+ if (div <= 0 || div > 2)
+ return -1;
+
+ /* Make sure that after conversion it still holds that:
+ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+ */
+ weon = ps_to_rfbi_ticks(t->we_on_time, div);
+ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+ if (weoff <= weon)
+ weoff = weon + 1;
+ if (weon > 0x0f)
+ return -1;
+ if (weoff > 0x3f)
+ return -1;
+
+ reon = ps_to_rfbi_ticks(t->re_on_time, div);
+ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+ if (reoff <= reon)
+ reoff = reon + 1;
+ if (reon > 0x0f)
+ return -1;
+ if (reoff > 0x3f)
+ return -1;
+
+ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+ if (csoff <= cson)
+ csoff = cson + 1;
+ if (csoff < max(weoff, reoff))
+ csoff = max(weoff, reoff);
+ if (cson > 0x0f)
+ return -1;
+ if (csoff > 0x3f)
+ return -1;
+
+ l = cson;
+ l |= csoff << 4;
+ l |= weon << 10;
+ l |= weoff << 14;
+ l |= reon << 20;
+ l |= reoff << 24;
+
+ t->tim[0] = l;
+
+ actim = ps_to_rfbi_ticks(t->access_time, div);
+ if (actim <= reon)
+ actim = reon + 1;
+ if (actim > 0x3f)
+ return -1;
+
+ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+ if (wecyc < weoff)
+ wecyc = weoff;
+ if (wecyc > 0x3f)
+ return -1;
+
+ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+ if (recyc < reoff)
+ recyc = reoff;
+ if (recyc > 0x3f)
+ return -1;
+
+ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+ if (cs_pulse > 0x3f)
+ return -1;
+
+ l = wecyc;
+ l |= recyc << 6;
+ l |= cs_pulse << 12;
+ l |= actim << 22;
+
+ t->tim[1] = l;
+
+ t->tim[2] = div - 1;
+
+ t->converted = 1;
+
+ return 0;
+}
+
+/* xxx FIX module selection missing */
+int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+ unsigned hs_pulse_time, unsigned vs_pulse_time,
+ int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+ int hs, vs;
+ int min;
+ u32 l;
+
+ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+ if (hs < 2)
+ return -EDOM;
+ if (mode == OMAP_DSS_RFBI_TE_MODE_2)
+ min = 2;
+ else /* OMAP_DSS_RFBI_TE_MODE_1 */
+ min = 4;
+ if (vs < min)
+ return -EDOM;
+ if (vs == hs)
+ return -EINVAL;
+ rfbi.te_mode = mode;
+ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
+ mode, hs, vs, hs_pol_inv, vs_pol_inv);
+
+ rfbi_enable_clocks(1);
+ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+ l = rfbi_read_reg(RFBI_CONFIG(0));
+ if (hs_pol_inv)
+ l &= ~(1 << 21);
+ else
+ l |= 1 << 21;
+ if (vs_pol_inv)
+ l &= ~(1 << 20);
+ else
+ l |= 1 << 20;
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_rfbi_setup_te);
+
+/* xxx FIX module selection missing */
+int omap_rfbi_enable_te(bool enable, unsigned line)
+{
+ u32 l;
+
+ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
+ if (line > (1 << 11) - 1)
+ return -EINVAL;
+
+ rfbi_enable_clocks(1);
+ l = rfbi_read_reg(RFBI_CONFIG(0));
+ l &= ~(0x3 << 2);
+ if (enable) {
+ rfbi.te_enabled = 1;
+ l |= rfbi.te_mode << 2;
+ } else
+ rfbi.te_enabled = 0;
+ rfbi_write_reg(RFBI_CONFIG(0), l);
+ rfbi_write_reg(RFBI_LINE_NUMBER, line);
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_rfbi_enable_te);
+
+#if 0
+static void rfbi_enable_config(int enable1, int enable2)
+{
+ u32 l;
+ int cs = 0;
+
+ if (enable1)
+ cs |= 1<<0;
+ if (enable2)
+ cs |= 1<<1;
+
+ rfbi_enable_clocks(1);
+
+ l = rfbi_read_reg(RFBI_CONTROL);
+
+ l = FLD_MOD(l, cs, 3, 2);
+ l = FLD_MOD(l, 0, 1, 1);
+
+ rfbi_write_reg(RFBI_CONTROL, l);
+
+
+ l = rfbi_read_reg(RFBI_CONFIG(0));
+ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
+ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
+ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
+
+ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
+ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
+ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
+
+ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
+ rfbi_write_reg(RFBI_CONFIG(0), l);
+
+ rfbi_enable_clocks(0);
+}
+#endif
+
+int rfbi_configure(int rfbi_module, int bpp, int lines)
+{
+ u32 l;
+ int cycle1 = 0, cycle2 = 0, cycle3 = 0;
+ enum omap_rfbi_cycleformat cycleformat;
+ enum omap_rfbi_datatype datatype;
+ enum omap_rfbi_parallelmode parallelmode;
+
+ switch (bpp) {
+ case 12:
+ datatype = OMAP_DSS_RFBI_DATATYPE_12;
+ break;
+ case 16:
+ datatype = OMAP_DSS_RFBI_DATATYPE_16;
+ break;
+ case 18:
+ datatype = OMAP_DSS_RFBI_DATATYPE_18;
+ break;
+ case 24:
+ datatype = OMAP_DSS_RFBI_DATATYPE_24;
+ break;
+ default:
+ BUG();
+ return 1;
+ }
+ rfbi.datatype = datatype;
+
+ switch (lines) {
+ case 8:
+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
+ break;
+ case 9:
+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
+ break;
+ case 12:
+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
+ break;
+ case 16:
+ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
+ break;
+ default:
+ BUG();
+ return 1;
+ }
+ rfbi.parallelmode = parallelmode;
+
+ if ((bpp % lines) == 0) {
+ switch (bpp / lines) {
+ case 1:
+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
+ break;
+ case 2:
+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
+ break;
+ case 3:
+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
+ break;
+ default:
+ BUG();
+ return 1;
+ }
+ } else if ((2 * bpp % lines) == 0) {
+ if ((2 * bpp / lines) == 3)
+ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
+ else {
+ BUG();
+ return 1;
+ }
+ } else {
+ BUG();
+ return 1;
+ }
+
+ switch (cycleformat) {
+ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
+ cycle1 = lines;
+ break;
+
+ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
+ cycle1 = lines;
+ cycle2 = lines;
+ break;
+
+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
+ cycle1 = lines;
+ cycle2 = lines;
+ cycle3 = lines;
+ break;
+
+ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
+ cycle1 = lines;
+ cycle2 = (lines / 2) | ((lines / 2) << 16);
+ cycle3 = (lines << 16);
+ break;
+ }
+
+ rfbi_enable_clocks(1);
+
+ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
+
+ l = 0;
+ l |= FLD_VAL(parallelmode, 1, 0);
+ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
+ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
+ l |= FLD_VAL(datatype, 6, 5);
+ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
+ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
+ l |= FLD_VAL(cycleformat, 10, 9);
+ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
+ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
+ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
+ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
+ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
+ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
+ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
+ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
+
+ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
+ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
+ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
+
+
+ l = rfbi_read_reg(RFBI_CONTROL);
+ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
+ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
+ rfbi_write_reg(RFBI_CONTROL, l);
+
+
+ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
+ bpp, lines, cycle1, cycle2, cycle3);
+
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+EXPORT_SYMBOL(rfbi_configure);
+
+static int rfbi_find_display(struct omap_dss_device *dssdev)
+{
+ if (dssdev == rfbi.dssdev[0])
+ return 0;
+
+ if (dssdev == rfbi.dssdev[1])
+ return 1;
+
+ BUG();
+ return -1;
+}
+
+
+static void signal_fifo_waiters(void)
+{
+ if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
+ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
+ complete(&rfbi.cmd_done);
+ atomic_dec(&rfbi.cmd_fifo_full);
+ }
+}
+
+/* returns 1 for async op, and 0 for sync op */
+static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
+{
+ u16 x = upd->x;
+ u16 y = upd->y;
+ u16 w = upd->w;
+ u16 h = upd->h;
+
+ perf_mark_setup();
+
+ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ /*dssdev->driver->enable_te(dssdev, 1); */
+ dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
+ }
+
+#ifdef MEASURE_PERF
+ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
+#endif
+
+ dssdev->driver->setup_update(dssdev, x, y, w, h);
+
+ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ rfbi_transfer_area(w, h, NULL, NULL);
+ return 1;
+ } else {
+ struct omap_overlay *ovl;
+ void __iomem *addr;
+ int scr_width;
+
+ ovl = dssdev->manager->overlays[0];
+ scr_width = ovl->info.screen_width;
+ addr = ovl->info.vaddr;
+
+ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
+
+ perf_show("L4");
+
+ return 0;
+ }
+}
+
+static void process_cmd_fifo(void)
+{
+ int len;
+ struct update_param p;
+ struct omap_dss_device *dssdev;
+ unsigned long flags;
+
+ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
+ return;
+
+ while (true) {
+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
+
+ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
+ sizeof(struct update_param));
+ if (len == 0) {
+ DSSDBG("nothing more in fifo\n");
+ atomic_set(&rfbi.cmd_pending, 0);
+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+ break;
+ }
+
+ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
+
+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+
+ BUG_ON(len != sizeof(struct update_param));
+ BUG_ON(p.rfbi_module > 1);
+
+ dssdev = rfbi.dssdev[p.rfbi_module];
+
+ if (p.cmd == RFBI_CMD_UPDATE) {
+ if (do_update(dssdev, &p.par.r))
+ break; /* async op */
+ } else if (p.cmd == RFBI_CMD_SYNC) {
+ DSSDBG("Signaling SYNC done!\n");
+ complete(p.par.sync);
+ } else
+ BUG();
+ }
+
+ signal_fifo_waiters();
+}
+
+static void rfbi_push_cmd(struct update_param *p)
+{
+ int ret;
+
+ while (1) {
+ unsigned long flags;
+ int available;
+
+ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
+ available = RFBI_CMD_FIFO_LEN_BYTES -
+ __kfifo_len(rfbi.cmd_fifo);
+
+/* DSSDBG("%d bytes left in fifo\n", available); */
+ if (available < sizeof(struct update_param)) {
+ DSSDBG("Going to wait because FIFO FULL..\n");
+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+ atomic_inc(&rfbi.cmd_fifo_full);
+ wait_for_completion(&rfbi.cmd_done);
+ /*DSSDBG("Woke up because fifo not full anymore\n");*/
+ continue;
+ }
+
+ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
+ sizeof(struct update_param));
+/* DSSDBG("pushed %d bytes\n", ret);*/
+
+ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
+
+ BUG_ON(ret != sizeof(struct update_param));
+
+ break;
+ }
+}
+
+static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
+{
+ struct update_param p;
+
+ p.rfbi_module = rfbi_module;
+ p.cmd = RFBI_CMD_UPDATE;
+
+ p.par.r.x = x;
+ p.par.r.y = y;
+ p.par.r.w = w;
+ p.par.r.h = h;
+
+ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
+
+ rfbi_push_cmd(&p);
+
+ process_cmd_fifo();
+}
+
+static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
+{
+ struct update_param p;
+
+ p.rfbi_module = rfbi_module;
+ p.cmd = RFBI_CMD_SYNC;
+ p.par.sync = sync_comp;
+
+ rfbi_push_cmd(&p);
+
+ DSSDBG("RFBI sync pushed to cmd fifo\n");
+
+ process_cmd_fifo();
+}
+
+void rfbi_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ DUMPREG(RFBI_REVISION);
+ DUMPREG(RFBI_SYSCONFIG);
+ DUMPREG(RFBI_SYSSTATUS);
+ DUMPREG(RFBI_CONTROL);
+ DUMPREG(RFBI_PIXEL_CNT);
+ DUMPREG(RFBI_LINE_NUMBER);
+ DUMPREG(RFBI_CMD);
+ DUMPREG(RFBI_PARAM);
+ DUMPREG(RFBI_DATA);
+ DUMPREG(RFBI_READ);
+ DUMPREG(RFBI_STATUS);
+
+ DUMPREG(RFBI_CONFIG(0));
+ DUMPREG(RFBI_ONOFF_TIME(0));
+ DUMPREG(RFBI_CYCLE_TIME(0));
+ DUMPREG(RFBI_DATA_CYCLE1(0));
+ DUMPREG(RFBI_DATA_CYCLE2(0));
+ DUMPREG(RFBI_DATA_CYCLE3(0));
+
+ DUMPREG(RFBI_CONFIG(1));
+ DUMPREG(RFBI_ONOFF_TIME(1));
+ DUMPREG(RFBI_CYCLE_TIME(1));
+ DUMPREG(RFBI_DATA_CYCLE1(1));
+ DUMPREG(RFBI_DATA_CYCLE2(1));
+ DUMPREG(RFBI_DATA_CYCLE3(1));
+
+ DUMPREG(RFBI_VSYNC_WIDTH);
+ DUMPREG(RFBI_HSYNC_WIDTH);
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+#undef DUMPREG
+}
+
+int rfbi_init(void)
+{
+ u32 rev;
+ u32 l;
+
+ spin_lock_init(&rfbi.cmd_lock);
+ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
+ &rfbi.cmd_lock);
+ if (IS_ERR(rfbi.cmd_fifo))
+ return -ENOMEM;
+
+ init_completion(&rfbi.cmd_done);
+ atomic_set(&rfbi.cmd_fifo_full, 0);
+ atomic_set(&rfbi.cmd_pending, 0);
+
+ rfbi.base = ioremap(RFBI_BASE, SZ_256);
+ if (!rfbi.base) {
+ DSSERR("can't ioremap RFBI\n");
+ return -ENOMEM;
+ }
+
+ rfbi_enable_clocks(1);
+
+ msleep(10);
+
+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+
+ /* Enable autoidle and smart-idle */
+ l = rfbi_read_reg(RFBI_SYSCONFIG);
+ l |= (1 << 0) | (2 << 3);
+ rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+ rev = rfbi_read_reg(RFBI_REVISION);
+ printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+
+void rfbi_exit(void)
+{
+ DSSDBG("rfbi_exit\n");
+
+ kfifo_free(rfbi.cmd_fifo);
+
+ iounmap(rfbi.base);
+}
+
+/* struct omap_display support */
+static int rfbi_display_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int rfbi_module;
+
+ if (w == 0 || h == 0)
+ return 0;
+
+ rfbi_module = rfbi_find_display(dssdev);
+
+ rfbi_push_update(rfbi_module, x, y, w, h);
+
+ return 0;
+}
+
+static int rfbi_display_sync(struct omap_dss_device *dssdev)
+{
+ struct completion sync_comp;
+ int rfbi_module;
+
+ rfbi_module = rfbi_find_display(dssdev);
+
+ init_completion(&sync_comp);
+ rfbi_push_sync(rfbi_module, &sync_comp);
+ DSSDBG("Waiting for SYNC to happen...\n");
+ wait_for_completion(&sync_comp);
+ DSSDBG("Released from SYNC\n");
+ return 0;
+}
+
+static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+{
+ dssdev->driver->enable_te(dssdev, enable);
+ return 0;
+}
+
+static int rfbi_display_enable(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = omap_dss_start_device(dssdev);
+ if (r) {
+ DSSERR("failed to start device\n");
+ goto err0;
+ }
+
+ r = omap_dispc_register_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ if (r) {
+ DSSERR("can't get FRAMEDONE irq\n");
+ goto err1;
+ }
+
+ /* TODO: change here for LCD2 support */
+ dispc_set_lcd_display_type(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_LCD_DISPLAY_TFT);
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_PARALLELMODE_RFBI);
+
+ dispc_set_tft_data_lines(OMAP_DSS_CHANNEL_LCD, dssdev->ctrl.pixel_size);
+
+ rfbi_configure(dssdev->phy.rfbi.channel,
+ dssdev->ctrl.pixel_size,
+ dssdev->phy.rfbi.data_lines);
+
+ rfbi_set_timings(dssdev->phy.rfbi.channel,
+ &dssdev->ctrl.rfbi_timings);
+
+
+ if (dssdev->driver->enable) {
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err2;
+ }
+
+ return 0;
+err2:
+ omap_dispc_unregister_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+err1:
+ omap_dss_stop_device(dssdev);
+err0:
+ return r;
+}
+
+static void rfbi_display_disable(struct omap_dss_device *dssdev)
+{
+ dssdev->driver->disable(dssdev);
+ omap_dispc_unregister_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ omap_dss_stop_device(dssdev);
+}
+
+int rfbi_init_display(struct omap_dss_device *dssdev)
+{
+ dssdev->enable = rfbi_display_enable;
+ dssdev->disable = rfbi_display_disable;
+ dssdev->update = rfbi_display_update;
+ dssdev->sync = rfbi_display_sync;
+ dssdev->enable_te = rfbi_display_enable_te;
+
+ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
+
+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ return 0;
+}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
new file mode 100644
index 000000000000..47c841b3db3b
--- /dev/null
+++ b/drivers/video/omap2/dss/sdi.c
@@ -0,0 +1,381 @@
+/*
+ * linux/drivers/video/omap2/dss/sdi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "SDI"
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/board.h>
+#include <mach/display.h>
+#include "dss.h"
+
+#define CONTROL_PADCONF_BASE 0x48002000
+
+#define OMAP_SDI_PAD_DIS(pe, pu) ((7 << 0) | /* MODE 7 = safe */ \
+ (((pe) ? 1 : 0) << 3) | /* PULL_ENA */ \
+ (((pu) ? 1 : 0) << 4) | /* PULL_UP */ \
+ (1 << 8)) /* INPUT_EN */
+
+#define OMAP_SDI_PAD_EN (1 << 0) /* MODE 1 = SDI_xx */
+
+#define OMAP_SDI_PAD_MASK OMAP_SDI_PAD_DIS(1, 1)
+
+static struct {
+ bool skip_init;
+ bool update_enabled;
+} sdi;
+
+/* CONTROL_PADCONF_DSS_DATAXX */
+static const u16 sdi_pads[] =
+{
+ 0x0f0, /* 10[ 7..0]:SDI_DAT1N */
+ 0x0f2, /* 10[15..0]:SDI_DAT1P */
+ 0x0f4, /* 12[ 7..0]:SDI_DAT2N */
+ 0x0f6, /* 12[15..0]:SDI_DAT2P */
+ 0x0f8, /* 14[ 7..0]:SDI_DAT3N */
+ 0x0fa, /* 14[15..0]:SDI_DAT3P */
+ 0x108, /* 22[ 7..0]:SDI_CLKN */
+ 0x10a, /* 22[15..0]:SDI_CLKP */
+};
+
+/*
+ * Check if bootloader / platform code has configured the SDI pads properly.
+ * This means it either configured all required pads for SDI mode, or that it
+ * left all the required pads unconfigured.
+ */
+static int sdi_pad_init(struct omap_dss_device *dssdev)
+{
+ unsigned req_map;
+ bool configured = false;
+ bool unconfigured = false;
+ int data_pairs;
+ int i;
+
+ data_pairs = dssdev->phy.sdi.datapairs;
+ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
+ req_map |= 3 << 6; /* clk lane */
+ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
+ u32 reg;
+ u32 val;
+
+ if (!((1 << i) & req_map))
+ /* Ignore unneded pads. */
+ continue;
+ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
+ val = omap_readw(reg);
+ switch (val & 0x07) { /* pad mode */
+ case 1:
+ if (unconfigured)
+ break;
+ /* Is the pull configuration ok for SDI mode? */
+ if ((val & OMAP_SDI_PAD_MASK) != OMAP_SDI_PAD_EN)
+ break;
+ configured = true;
+ break;
+ case 0:
+ case 7:
+ if (configured)
+ break;
+ unconfigured = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (i != ARRAY_SIZE(sdi_pads)) {
+ DSSERR("SDI: invalid pad configuration\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void sdi_pad_config(struct omap_dss_device *dssdev, bool enable)
+{
+ int data_pairs;
+ bool pad_off_pe, pad_off_pu;
+ unsigned req_map;
+ int i;
+
+ data_pairs = dssdev->phy.sdi.datapairs;
+ pad_off_pe = dssdev->phy.sdi.pad_off_pe;
+ pad_off_pu = dssdev->phy.sdi.pad_off_pu;
+ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
+ req_map |= 3 << 6; /* clk lane */
+ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
+ u32 reg;
+ u16 val;
+
+ if (!((1 << i) & req_map))
+ continue;
+ if (enable)
+ val = OMAP_SDI_PAD_EN;
+ else
+ val = OMAP_SDI_PAD_DIS(pad_off_pe, pad_off_pu);
+ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
+ omap_writew(val, reg);
+ }
+}
+
+static void sdi_basic_init(void)
+{
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_PARALLELMODE_BYPASS);
+
+ /* TODO: change here for LCD2 support */
+ dispc_set_lcd_display_type(OMAP_DSS_CHANNEL_LCD,
+ OMAP_DSS_LCD_DISPLAY_TFT);
+ dispc_set_tft_data_lines(OMAP_DSS_CHANNEL_LCD, 24);
+ dispc_lcd_enable_signal_polarity(1);
+}
+
+static int sdi_display_enable(struct omap_dss_device *dssdev)
+{
+ struct omap_video_timings *t = &dssdev->panel.timings;
+ struct dispc_clock_info cinfo;
+ u16 lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+ int r;
+
+ r = omap_dss_start_device(dssdev);
+ if (r) {
+ DSSERR("failed to start device\n");
+ goto err0;
+ }
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ DSSERR("dssdev already enabled\n");
+ r = -EINVAL;
+ goto err1;
+ }
+
+ sdi_pad_config(dssdev, 1);
+
+ /* In case of skip_init sdi_init has already enabled the clocks */
+ if (!sdi.skip_init)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ sdi_basic_init();
+
+ /* 15.5.9.1.2 */
+ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
+
+ /* TODO: update for LCD2 here */
+ dispc_set_pol_freq(OMAP_DSS_CHANNEL_LCD, dssdev->panel.config,
+ dssdev->panel.acbi, dssdev->panel.acb);
+
+ if (!sdi.skip_init)
+ r = dispc_calc_clock_div(1, t->pixel_clock * 1000,
+ &cinfo);
+ else
+ r = dispc_get_clock_div(&cinfo);
+
+ if (r)
+ goto err2;
+
+ fck = cinfo.fck;
+ lck_div = cinfo.lck_div;
+ pck_div = cinfo.pck_div;
+
+ pck = fck / lck_div / pck_div / 1000;
+
+ if (pck != t->pixel_clock) {
+ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
+ "got %lu kHz\n",
+ t->pixel_clock, pck);
+
+ t->pixel_clock = pck;
+ }
+
+ /* TODO: if needed, add LCD2 support here*/
+ dispc_set_lcd_timings(OMAP_DSS_CHANNEL_LCD, t);
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r)
+ goto err2;
+
+ if (!sdi.skip_init) {
+ dss_sdi_init(dssdev->phy.sdi.datapairs);
+ dss_sdi_enable();
+ mdelay(2);
+ }
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+
+ if (dssdev->driver->enable) {
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err3;
+ }
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ sdi.skip_init = 0;
+
+ return 0;
+err3:
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+err1:
+ omap_dss_stop_device(dssdev);
+err0:
+ return r;
+}
+
+static int sdi_display_resume(struct omap_dss_device *dssdev);
+
+static void sdi_display_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ return;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ sdi_display_resume(dssdev);
+
+ if (dssdev->driver->disable)
+ dssdev->driver->disable(dssdev);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ omap_dss_stop_device(dssdev);
+}
+
+static int sdi_display_suspend(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EINVAL;
+
+ if (dssdev->driver->suspend)
+ dssdev->driver->suspend(dssdev);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ return 0;
+}
+
+static int sdi_display_resume(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
+ sdi_pad_config(dssdev, 1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dss_sdi_enable();
+ mdelay(2);
+
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+
+ if (dssdev->driver->resume)
+ dssdev->driver->resume(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ if (mode == OMAP_DSS_UPDATE_MANUAL)
+ return -EINVAL;
+
+ if (mode == OMAP_DSS_UPDATE_DISABLED) {
+ /* TODO: change here if LCD2 support is needed */
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
+ sdi.update_enabled = 0;
+ } else {
+ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);
+ sdi.update_enabled = 1;
+ }
+
+ return 0;
+}
+
+static enum omap_dss_update_mode sdi_display_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+ OMAP_DSS_UPDATE_DISABLED;
+}
+
+static void sdi_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ *timings = dssdev->panel.timings;
+}
+
+int sdi_init_display(struct omap_dss_device *dssdev)
+{
+ DSSDBG("SDI init\n");
+
+ dssdev->enable = sdi_display_enable;
+ dssdev->disable = sdi_display_disable;
+ dssdev->suspend = sdi_display_suspend;
+ dssdev->resume = sdi_display_resume;
+ dssdev->set_update_mode = sdi_display_set_update_mode;
+ dssdev->get_update_mode = sdi_display_get_update_mode;
+ dssdev->get_timings = sdi_get_timings;
+
+ return sdi_pad_init(dssdev);
+}
+
+int sdi_init(bool skip_init)
+{
+ /* we store this for first display enable, then clear it */
+ sdi.skip_init = skip_init;
+
+ /*
+ * Enable clocks already here, otherwise there would be a toggle
+ * of them until sdi_display_enable is called.
+ */
+ if (skip_init)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ return 0;
+}
+
+void sdi_exit(void)
+{
+}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
new file mode 100644
index 000000000000..d8a83b2410e6
--- /dev/null
+++ b/drivers/video/omap2/dss/venc.c
@@ -0,0 +1,782 @@
+/*
+ * linux/drivers/video/omap2/dss/venc.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC settings from TI's DSS 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "VENC"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/display.h>
+#include <mach/cpu.h>
+
+#include "dss.h"
+
+#define VENC_BASE 0x48050C00
+
+/* Venc registers */
+#define VENC_REV_ID 0x00
+#define VENC_STATUS 0x04
+#define VENC_F_CONTROL 0x08
+#define VENC_VIDOUT_CTRL 0x10
+#define VENC_SYNC_CTRL 0x14
+#define VENC_LLEN 0x1C
+#define VENC_FLENS 0x20
+#define VENC_HFLTR_CTRL 0x24
+#define VENC_CC_CARR_WSS_CARR 0x28
+#define VENC_C_PHASE 0x2C
+#define VENC_GAIN_U 0x30
+#define VENC_GAIN_V 0x34
+#define VENC_GAIN_Y 0x38
+#define VENC_BLACK_LEVEL 0x3C
+#define VENC_BLANK_LEVEL 0x40
+#define VENC_X_COLOR 0x44
+#define VENC_M_CONTROL 0x48
+#define VENC_BSTAMP_WSS_DATA 0x4C
+#define VENC_S_CARR 0x50
+#define VENC_LINE21 0x54
+#define VENC_LN_SEL 0x58
+#define VENC_L21__WC_CTL 0x5C
+#define VENC_HTRIGGER_VTRIGGER 0x60
+#define VENC_SAVID__EAVID 0x64
+#define VENC_FLEN__FAL 0x68
+#define VENC_LAL__PHASE_RESET 0x6C
+#define VENC_HS_INT_START_STOP_X 0x70
+#define VENC_HS_EXT_START_STOP_X 0x74
+#define VENC_VS_INT_START_X 0x78
+#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
+#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
+#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
+#define VENC_VS_EXT_STOP_Y 0x88
+#define VENC_AVID_START_STOP_X 0x90
+#define VENC_AVID_START_STOP_Y 0x94
+#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
+#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
+#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
+#define VENC_TVDETGP_INT_START_STOP_X 0xB0
+#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
+#define VENC_GEN_CTRL 0xB8
+#define VENC_OUTPUT_CONTROL 0xC4
+#define VENC_OUTPUT_TEST 0xC8
+#define VENC_DAC_B__DAC_C 0xC8
+
+struct venc_config {
+ u32 f_control;
+ u32 vidout_ctrl;
+ u32 sync_ctrl;
+ u32 llen;
+ u32 flens;
+ u32 hfltr_ctrl;
+ u32 cc_carr_wss_carr;
+ u32 c_phase;
+ u32 gain_u;
+ u32 gain_v;
+ u32 gain_y;
+ u32 black_level;
+ u32 blank_level;
+ u32 x_color;
+ u32 m_control;
+ u32 bstamp_wss_data;
+ u32 s_carr;
+ u32 line21;
+ u32 ln_sel;
+ u32 l21__wc_ctl;
+ u32 htrigger_vtrigger;
+ u32 savid__eavid;
+ u32 flen__fal;
+ u32 lal__phase_reset;
+ u32 hs_int_start_stop_x;
+ u32 hs_ext_start_stop_x;
+ u32 vs_int_start_x;
+ u32 vs_int_stop_x__vs_int_start_y;
+ u32 vs_int_stop_y__vs_ext_start_x;
+ u32 vs_ext_stop_x__vs_ext_start_y;
+ u32 vs_ext_stop_y;
+ u32 avid_start_stop_x;
+ u32 avid_start_stop_y;
+ u32 fid_int_start_x__fid_int_start_y;
+ u32 fid_int_offset_y__fid_ext_start_x;
+ u32 fid_ext_start_y__fid_ext_offset_y;
+ u32 tvdetgp_int_start_stop_x;
+ u32 tvdetgp_int_start_stop_y;
+ u32 gen_ctrl;
+};
+
+/* from TRM */
+static const struct venc_config venc_config_pal_trm = {
+ .f_control = 0,
+ .vidout_ctrl = 1,
+ .sync_ctrl = 0x40,
+ .llen = 0x35F, /* 863 */
+ .flens = 0x270, /* 624 */
+ .hfltr_ctrl = 0,
+ .cc_carr_wss_carr = 0x2F7225ED,
+ .c_phase = 0,
+ .gain_u = 0x111,
+ .gain_v = 0x181,
+ .gain_y = 0x140,
+ .black_level = 0x3B,
+ .blank_level = 0x3B,
+ .x_color = 0x7,
+ .m_control = 0x2,
+ .bstamp_wss_data = 0x3F,
+ .s_carr = 0x2A098ACB,
+ .line21 = 0,
+ .ln_sel = 0x01290015,
+ .l21__wc_ctl = 0x0000F603,
+ .htrigger_vtrigger = 0,
+
+ .savid__eavid = 0x06A70108,
+ .flen__fal = 0x00180270,
+ .lal__phase_reset = 0x00040135,
+ .hs_int_start_stop_x = 0x00880358,
+ .hs_ext_start_stop_x = 0x000F035F,
+ .vs_int_start_x = 0x01A70000,
+ .vs_int_stop_x__vs_int_start_y = 0x000001A7,
+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
+ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
+ .vs_ext_stop_y = 0x00000025,
+ .avid_start_stop_x = 0x03530083,
+ .avid_start_stop_y = 0x026C002E,
+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
+ .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
+
+ .tvdetgp_int_start_stop_x = 0x00140001,
+ .tvdetgp_int_start_stop_y = 0x00010001,
+ .gen_ctrl = 0x00FF0000,
+};
+
+/* from TRM */
+static const struct venc_config venc_config_ntsc_trm = {
+ .f_control = 0,
+ .vidout_ctrl = 1,
+ .sync_ctrl = 0x8040,
+ .llen = 0x359,
+ .flens = 0x20C,
+ .hfltr_ctrl = 0,
+ .cc_carr_wss_carr = 0x043F2631,
+ .c_phase = 0,
+ .gain_u = 0x102,
+ .gain_v = 0x16C,
+ .gain_y = 0x12F,
+ .black_level = 0x43,
+ .blank_level = 0x38,
+ .x_color = 0x7,
+ .m_control = 0x1,
+ .bstamp_wss_data = 0x38,
+ .s_carr = 0x21F07C1F,
+ .line21 = 0,
+ .ln_sel = 0x01310011,
+ .l21__wc_ctl = 0x0000F003,
+ .htrigger_vtrigger = 0,
+
+ .savid__eavid = 0x069300F4,
+ .flen__fal = 0x0016020C,
+ .lal__phase_reset = 0x00060107,
+ .hs_int_start_stop_x = 0x008E0350,
+ .hs_ext_start_stop_x = 0x000F0359,
+ .vs_int_start_x = 0x01A00000,
+ .vs_int_stop_x__vs_int_start_y = 0x020701A0,
+ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
+ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
+ .vs_ext_stop_y = 0x00000006,
+ .avid_start_stop_x = 0x03480078,
+ .avid_start_stop_y = 0x02060024,
+ .fid_int_start_x__fid_int_start_y = 0x0001008A,
+ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
+ .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
+
+ .tvdetgp_int_start_stop_x = 0x00140001,
+ .tvdetgp_int_start_stop_y = 0x00010001,
+ .gen_ctrl = 0x00F90000,
+};
+
+static const struct venc_config venc_config_pal_bdghi = {
+ .f_control = 0,
+ .vidout_ctrl = 0,
+ .sync_ctrl = 0,
+ .hfltr_ctrl = 0,
+ .x_color = 0,
+ .line21 = 0,
+ .ln_sel = 21,
+ .htrigger_vtrigger = 0,
+ .tvdetgp_int_start_stop_x = 0x00140001,
+ .tvdetgp_int_start_stop_y = 0x00010001,
+ .gen_ctrl = 0x00FB0000,
+
+ .llen = 864-1,
+ .flens = 625-1,
+ .cc_carr_wss_carr = 0x2F7625ED,
+ .c_phase = 0xDF,
+ .gain_u = 0x111,
+ .gain_v = 0x181,
+ .gain_y = 0x140,
+ .black_level = 0x3e,
+ .blank_level = 0x3e,
+ .m_control = 0<<2 | 1<<1,
+ .bstamp_wss_data = 0x42,
+ .s_carr = 0x2a098acb,
+ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
+ .savid__eavid = 0x06A70108,
+ .flen__fal = 23<<16 | 624<<0,
+ .lal__phase_reset = 2<<17 | 310<<0,
+ .hs_int_start_stop_x = 0x00920358,
+ .hs_ext_start_stop_x = 0x000F035F,
+ .vs_int_start_x = 0x1a7<<16,
+ .vs_int_stop_x__vs_int_start_y = 0x000601A7,
+ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
+ .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
+ .vs_ext_stop_y = 0x05,
+ .avid_start_stop_x = 0x03530082,
+ .avid_start_stop_y = 0x0270002E,
+ .fid_int_start_x__fid_int_start_y = 0x0005008A,
+ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
+ .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
+};
+
+const struct omap_video_timings omap_dss_pal_timings = {
+ .x_res = 720,
+ .y_res = 574,
+ .pixel_clock = 13500,
+ .hsw = 64,
+ .hfp = 12,
+ .hbp = 68,
+ .vsw = 5,
+ .vfp = 5,
+ .vbp = 41,
+};
+EXPORT_SYMBOL(omap_dss_pal_timings);
+
+const struct omap_video_timings omap_dss_ntsc_timings = {
+ .x_res = 720,
+ .y_res = 482,
+ .pixel_clock = 13500,
+ .hsw = 64,
+ .hfp = 16,
+ .hbp = 58,
+ .vsw = 6,
+ .vfp = 6,
+ .vbp = 31,
+};
+EXPORT_SYMBOL(omap_dss_ntsc_timings);
+
+static struct {
+ void __iomem *base;
+ struct mutex venc_lock;
+ u32 wss_data;
+ struct regulator *vdda_dac_reg;
+} venc;
+
+static inline void venc_write_reg(int idx, u32 val)
+{
+ __raw_writel(val, venc.base + idx);
+}
+
+static inline u32 venc_read_reg(int idx)
+{
+ u32 l = __raw_readl(venc.base + idx);
+ return l;
+}
+
+static void venc_write_config(const struct venc_config *config)
+{
+ DSSDBG("write venc conf\n");
+
+ venc_write_reg(VENC_LLEN, config->llen);
+ venc_write_reg(VENC_FLENS, config->flens);
+ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
+ venc_write_reg(VENC_C_PHASE, config->c_phase);
+ venc_write_reg(VENC_GAIN_U, config->gain_u);
+ venc_write_reg(VENC_GAIN_V, config->gain_v);
+ venc_write_reg(VENC_GAIN_Y, config->gain_y);
+ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
+ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
+ venc_write_reg(VENC_M_CONTROL, config->m_control);
+ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
+ venc.wss_data);
+ venc_write_reg(VENC_S_CARR, config->s_carr);
+ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
+ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
+ venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
+ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
+ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
+ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
+ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
+ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
+ config->vs_int_stop_x__vs_int_start_y);
+ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
+ config->vs_int_stop_y__vs_ext_start_x);
+ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
+ config->vs_ext_stop_x__vs_ext_start_y);
+ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
+ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
+ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
+ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
+ config->fid_int_start_x__fid_int_start_y);
+ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
+ config->fid_int_offset_y__fid_ext_start_x);
+ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
+ config->fid_ext_start_y__fid_ext_offset_y);
+
+ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
+ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
+ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
+ venc_write_reg(VENC_X_COLOR, config->x_color);
+ venc_write_reg(VENC_LINE21, config->line21);
+ venc_write_reg(VENC_LN_SEL, config->ln_sel);
+ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
+ config->tvdetgp_int_start_stop_x);
+ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
+ config->tvdetgp_int_start_stop_y);
+ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
+ venc_write_reg(VENC_F_CONTROL, config->f_control);
+ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
+}
+
+static void venc_reset(void)
+{
+ int t = 1000;
+
+ venc_write_reg(VENC_F_CONTROL, 1<<8);
+ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
+ if (--t == 0) {
+ DSSERR("Failed to reset venc\n");
+ return;
+ }
+ }
+
+ /* the magical sleep that makes things work */
+ msleep(20);
+}
+
+static void venc_enable_clocks(int enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
+ DSS_CLK_96M);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
+ DSS_CLK_96M);
+}
+
+static const struct venc_config *venc_timings_to_config(
+ struct omap_video_timings *timings)
+{
+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+ return &venc_config_pal_trm;
+
+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+ return &venc_config_ntsc_trm;
+
+ BUG();
+}
+
+
+
+
+
+/* driver */
+static int venc_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.timings = omap_dss_pal_timings;
+
+ return 0;
+}
+
+static void venc_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int venc_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+
+ return r;
+}
+
+static void venc_panel_disable(struct omap_dss_device *dssdev)
+{
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ /* wait at least 5 vsyncs after disabling the LCD */
+
+ msleep(100);
+}
+
+static int venc_panel_suspend(struct omap_dss_device *dssdev)
+{
+ venc_panel_disable(dssdev);
+ return 0;
+}
+
+static int venc_panel_resume(struct omap_dss_device *dssdev)
+{
+ return venc_panel_enable(dssdev);
+}
+
+static struct omap_dss_driver venc_driver = {
+ .probe = venc_panel_probe,
+ .remove = venc_panel_remove,
+
+ .enable = venc_panel_enable,
+ .disable = venc_panel_disable,
+ .suspend = venc_panel_suspend,
+ .resume = venc_panel_resume,
+
+ .driver = {
+ .name = "venc",
+ .owner = THIS_MODULE,
+ },
+};
+/* driver end */
+
+
+
+int venc_init(struct platform_device *pdev)
+{
+ u8 rev_id;
+
+ mutex_init(&venc.venc_lock);
+
+ venc.wss_data = 0;
+
+ venc.base = ioremap(VENC_BASE, SZ_1K);
+ if (!venc.base) {
+ DSSERR("can't ioremap VENC\n");
+ return -ENOMEM;
+ }
+
+ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
+ if (IS_ERR(venc.vdda_dac_reg)) {
+ iounmap(venc.base);
+ DSSERR("can't get VDDA_DAC regulator\n");
+ return PTR_ERR(venc.vdda_dac_reg);
+ }
+
+ venc_enable_clocks(1);
+
+ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
+
+ venc_enable_clocks(0);
+
+ return omap_dss_register_driver(&venc_driver);
+}
+
+void venc_exit(void)
+{
+ omap_dss_unregister_driver(&venc_driver);
+
+ regulator_put(venc.vdda_dac_reg);
+
+ iounmap(venc.base);
+}
+
+static void venc_power_on(struct omap_dss_device *dssdev)
+{
+ venc_enable_clocks(1);
+
+ venc_reset();
+ venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
+
+ dss_set_venc_output(dssdev->phy.venc.type);
+ dss_set_dac_pwrdn_bgz(1);
+
+ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
+ if (cpu_is_omap24xx())
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
+ else
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0xa);
+ } else { /* S-Video */
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
+ }
+
+ dispc_set_digit_size(dssdev->panel.timings.x_res,
+ dssdev->panel.timings.y_res/2);
+
+ regulator_enable(venc.vdda_dac_reg);
+
+ if (dssdev->platform_enable)
+ dssdev->platform_enable(dssdev);
+
+ dispc_enable_digit_out(1);
+}
+
+static void venc_power_off(struct omap_dss_device *dssdev)
+{
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+ dss_set_dac_pwrdn_bgz(0);
+
+ dispc_enable_digit_out(0);
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ regulator_disable(venc.vdda_dac_reg);
+
+ venc_enable_clocks(0);
+}
+
+static int venc_enable_display(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("venc_enable_display\n");
+
+ mutex_lock(&venc.venc_lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ venc_power_on(dssdev);
+
+ venc.wss_data = 0;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+}
+
+static void venc_disable_display(struct omap_dss_device *dssdev)
+{
+ DSSDBG("venc_disable_display\n");
+
+ mutex_lock(&venc.venc_lock);
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ goto end;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
+ /* suspended is the same as disabled with venc */
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+ goto end;
+ }
+
+ venc_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+end:
+ mutex_unlock(&venc.venc_lock);
+}
+
+static int venc_display_suspend(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("venc_display_suspend\n");
+
+ mutex_lock(&venc.venc_lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ venc_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+}
+
+static int venc_display_resume(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("venc_display_resume\n");
+
+ mutex_lock(&venc.venc_lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ venc_power_on(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+}
+
+static void venc_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ *timings = dssdev->panel.timings;
+}
+
+static void venc_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ DSSDBG("venc_set_timings\n");
+
+ /* Reset WSS data when the TV standard changes. */
+ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
+ venc.wss_data = 0;
+
+ dssdev->panel.timings = *timings;
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ /* turn the venc off and on to get new timings to use */
+ venc_disable_display(dssdev);
+ venc_enable_display(dssdev);
+ }
+}
+
+static int venc_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ DSSDBG("venc_check_timings\n");
+
+ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+ return 0;
+
+ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+ return 0;
+
+ return -EINVAL;
+}
+
+static u32 venc_get_wss(struct omap_dss_device *dssdev)
+{
+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
+ return (venc.wss_data >> 8) ^ 0xfffff;
+}
+
+static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+ const struct venc_config *config;
+
+ DSSDBG("venc_set_wss\n");
+
+ mutex_lock(&venc.venc_lock);
+
+ config = venc_timings_to_config(&dssdev->panel.timings);
+
+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
+ venc.wss_data = (wss ^ 0xfffff) << 8;
+
+ venc_enable_clocks(1);
+
+ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
+ venc.wss_data);
+
+ venc_enable_clocks(0);
+
+ mutex_unlock(&venc.venc_lock);
+
+ return 0;
+}
+
+int venc_init_display(struct omap_dss_device *dssdev)
+{
+ DSSDBG("init_display\n");
+
+ dssdev->enable = venc_enable_display;
+ dssdev->disable = venc_disable_display;
+ dssdev->suspend = venc_display_suspend;
+ dssdev->resume = venc_display_resume;
+ dssdev->get_timings = venc_get_timings;
+ dssdev->set_timings = venc_set_timings;
+ dssdev->check_timings = venc_check_timings;
+ dssdev->get_wss = venc_get_wss;
+ dssdev->set_wss = venc_set_wss;
+
+ return 0;
+}
+
+void venc_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
+
+ venc_enable_clocks(1);
+
+ DUMPREG(VENC_F_CONTROL);
+ DUMPREG(VENC_VIDOUT_CTRL);
+ DUMPREG(VENC_SYNC_CTRL);
+ DUMPREG(VENC_LLEN);
+ DUMPREG(VENC_FLENS);
+ DUMPREG(VENC_HFLTR_CTRL);
+ DUMPREG(VENC_CC_CARR_WSS_CARR);
+ DUMPREG(VENC_C_PHASE);
+ DUMPREG(VENC_GAIN_U);
+ DUMPREG(VENC_GAIN_V);
+ DUMPREG(VENC_GAIN_Y);
+ DUMPREG(VENC_BLACK_LEVEL);
+ DUMPREG(VENC_BLANK_LEVEL);
+ DUMPREG(VENC_X_COLOR);
+ DUMPREG(VENC_M_CONTROL);
+ DUMPREG(VENC_BSTAMP_WSS_DATA);
+ DUMPREG(VENC_S_CARR);
+ DUMPREG(VENC_LINE21);
+ DUMPREG(VENC_LN_SEL);
+ DUMPREG(VENC_L21__WC_CTL);
+ DUMPREG(VENC_HTRIGGER_VTRIGGER);
+ DUMPREG(VENC_SAVID__EAVID);
+ DUMPREG(VENC_FLEN__FAL);
+ DUMPREG(VENC_LAL__PHASE_RESET);
+ DUMPREG(VENC_HS_INT_START_STOP_X);
+ DUMPREG(VENC_HS_EXT_START_STOP_X);
+ DUMPREG(VENC_VS_INT_START_X);
+ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
+ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
+ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
+ DUMPREG(VENC_VS_EXT_STOP_Y);
+ DUMPREG(VENC_AVID_START_STOP_X);
+ DUMPREG(VENC_AVID_START_STOP_Y);
+ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
+ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
+ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
+ DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
+ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
+ DUMPREG(VENC_GEN_CTRL);
+ DUMPREG(VENC_OUTPUT_CONTROL);
+ DUMPREG(VENC_OUTPUT_TEST);
+
+ venc_enable_clocks(0);
+
+#undef DUMPREG
+}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
new file mode 100644
index 000000000000..77ca9c9d6390
--- /dev/null
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -0,0 +1,35 @@
+menuconfig FB_OMAP2
+ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
+ depends on FB && OMAP2_DSS
+ default y
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Frame buffer driver for OMAP2/3 based boards.
+
+config FB_OMAP2_DEBUG_SUPPORT
+ bool "Debug support for OMAP2/3 FB"
+ default y
+ depends on FB_OMAP2
+ help
+ Support for debug output. You have to enable the actual printing
+ with debug module parameter.
+
+config FB_OMAP2_FORCE_AUTO_UPDATE
+ bool "Force main display to automatic update mode"
+ depends on FB_OMAP2
+ help
+ Forces main display to automatic update mode (if possible),
+ and also enables tearsync (if possible). By default
+ displays that support manual update are started in manual
+ update mode.
+
+config FB_OMAP2_NUM_FBS
+ int "Number of framebuffers"
+ range 1 10
+ default 3
+ depends on FB_OMAP2
+ help
+ Select the number of framebuffers created. OMAP2/3 has 3 overlays
+ so normally this would be 3.
diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
new file mode 100644
index 000000000000..51c2e00d9bf8
--- /dev/null
+++ b/drivers/video/omap2/omapfb/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FB_OMAP2) += omapfb.o
+omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
new file mode 100644
index 000000000000..257f7cbc0e00
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -0,0 +1,709 @@
+/*
+ * linux/drivers/video/omap2/omapfb-ioctl.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/omapfb.h>
+#include <linux/vmalloc.h>
+
+#include <mach/display.h>
+#include <mach/vrfb.h>
+
+#include "omapfb.h"
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ struct omap_overlay *ovl;
+ struct omap_overlay_info info;
+ int r = 0;
+
+ DBG("omapfb_setup_plane\n");
+
+ if (ofbi->num_overlays != 1) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* XXX uses only the first overlay */
+ ovl = ofbi->overlays[0];
+
+ if (pi->enabled && !ofbi->region.size) {
+ /*
+ * This plane's memory was freed, can't enable it
+ * until it's reallocated.
+ */
+ r = -EINVAL;
+ goto out;
+ }
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.pos_x = pi->pos_x;
+ info.pos_y = pi->pos_y;
+ info.out_width = pi->out_width;
+ info.out_height = pi->out_height;
+ info.enabled = pi->enabled;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ goto out;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ goto out;
+ }
+
+ if (display) {
+ u16 w, h;
+
+ if (display->sync)
+ display->sync(display);
+
+ display->get_resolution(display, &w, &h);
+
+ if (display->update)
+ display->update(display, 0, 0, w, h);
+ }
+
+out:
+ if (r)
+ dev_err(fbdev->dev, "setup_plane failed\n");
+ return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ if (ofbi->num_overlays != 1) {
+ memset(pi, 0, sizeof(*pi));
+ } else {
+ struct omap_overlay_info *ovli;
+ struct omap_overlay *ovl;
+
+ ovl = ofbi->overlays[0];
+ ovli = &ovl->info;
+
+ pi->pos_x = ovli->pos_x;
+ pi->pos_y = ovli->pos_y;
+ pi->enabled = ovli->enabled;
+ pi->channel_out = 0; /* xxx */
+ pi->mirror = 0;
+ pi->out_width = ovli->out_width;
+ pi->out_height = ovli->out_height;
+ }
+
+ return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb2_mem_region *rg;
+ int r, i;
+ size_t size;
+
+ if (mi->type > OMAPFB_MEMTYPE_MAX)
+ return -EINVAL;
+
+ size = PAGE_ALIGN(mi->size);
+
+ rg = &ofbi->region;
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->info.enabled)
+ return -EBUSY;
+ }
+
+ if (rg->size != size || rg->type != mi->type) {
+ r = omapfb_realloc_fbmem(fbi, size, mi->type);
+ if (r) {
+ dev_err(fbdev->dev, "realloc fbmem failed\n");
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_mem_region *rg;
+
+ rg = &ofbi->region;
+ memset(mi, 0, sizeof(*mi));
+
+ mi->size = rg->size;
+ mi->type = rg->type;
+
+ return 0;
+}
+
+static int omapfb_update_window(struct fb_info *fbi,
+ u32 x, u32 y, u32 w, u32 h)
+{
+ struct omap_dss_device *display = fb2display(fbi);
+ u16 dw, dh;
+
+ if (!display)
+ return 0;
+
+ if (w == 0 || h == 0)
+ return 0;
+
+ display->get_resolution(display, &dw, &dh);
+
+ if (x + w > dw || y + h > dh)
+ return -EINVAL;
+
+ display->update(display, x, y, w, h);
+
+ return 0;
+}
+
+static int omapfb_set_update_mode(struct fb_info *fbi,
+ enum omapfb_update_mode mode)
+{
+ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode um;
+ int r;
+
+ if (!display || !display->set_update_mode)
+ return -EINVAL;
+
+ switch (mode) {
+ case OMAPFB_UPDATE_DISABLED:
+ um = OMAP_DSS_UPDATE_DISABLED;
+ break;
+
+ case OMAPFB_AUTO_UPDATE:
+ um = OMAP_DSS_UPDATE_AUTO;
+ break;
+
+ case OMAPFB_MANUAL_UPDATE:
+ um = OMAP_DSS_UPDATE_MANUAL;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ r = display->set_update_mode(display, um);
+
+ return r;
+}
+
+static int omapfb_get_update_mode(struct fb_info *fbi,
+ enum omapfb_update_mode *mode)
+{
+ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode m;
+
+ if (!display || !display->get_update_mode)
+ return -EINVAL;
+
+ m = display->get_update_mode(display);
+
+ switch (m) {
+ case OMAP_DSS_UPDATE_DISABLED:
+ *mode = OMAPFB_UPDATE_DISABLED;
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+ *mode = OMAPFB_AUTO_UPDATE;
+ break;
+ case OMAP_DSS_UPDATE_MANUAL:
+ *mode = OMAPFB_MANUAL_UPDATE;
+ break;
+ default:
+ BUG();
+ }
+
+ return 0;
+}
+
+/* XXX this color key handling is a hack... */
+static struct omapfb_color_key omapfb_color_keys[2];
+
+static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ struct omapfb_color_key *ck)
+{
+ struct omap_overlay_manager_info info;
+ enum omap_dss_trans_key_type kt;
+ int r;
+
+ mgr->get_manager_info(mgr, &info);
+
+ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
+ info.trans_enabled = false;
+ omapfb_color_keys[mgr->id] = *ck;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+
+ return r;
+ }
+
+ switch (ck->key_type) {
+ case OMAPFB_COLOR_KEY_GFX_DST:
+ kt = OMAP_DSS_COLOR_KEY_GFX_DST;
+ break;
+ case OMAPFB_COLOR_KEY_VID_SRC:
+ kt = OMAP_DSS_COLOR_KEY_VID_SRC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ info.default_color = ck->background;
+ info.trans_key = ck->trans_key;
+ info.trans_key_type = kt;
+ info.trans_enabled = true;
+
+ omapfb_color_keys[mgr->id] = *ck;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+
+ return r;
+}
+
+static int omapfb_set_color_key(struct fb_info *fbi,
+ struct omapfb_color_key *ck)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ int r;
+ int i;
+ struct omap_overlay_manager *mgr = NULL;
+
+ omapfb_lock(fbdev);
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->manager) {
+ mgr = ofbi->overlays[i]->manager;
+ break;
+ }
+ }
+
+ if (!mgr) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = _omapfb_set_color_key(mgr, ck);
+err:
+ omapfb_unlock(fbdev);
+
+ return r;
+}
+
+static int omapfb_get_color_key(struct fb_info *fbi,
+ struct omapfb_color_key *ck)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_overlay_manager *mgr = NULL;
+ int r = 0;
+ int i;
+
+ omapfb_lock(fbdev);
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->manager) {
+ mgr = ofbi->overlays[i]->manager;
+ break;
+ }
+ }
+
+ if (!mgr) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ *ck = omapfb_color_keys[mgr->id];
+err:
+ omapfb_unlock(fbdev);
+
+ return r;
+}
+
+static int omapfb_memory_read(struct fb_info *fbi,
+ struct omapfb_memory_read *mr)
+{
+ struct omap_dss_device *display = fb2display(fbi);
+ void *buf;
+ int r;
+
+ if (!display || !display->memory_read)
+ return -ENOENT;
+
+ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
+ return -EFAULT;
+
+ if (mr->w * mr->h * 3 > mr->buffer_size)
+ return -EINVAL;
+
+ buf = vmalloc(mr->buffer_size);
+ if (!buf) {
+ DBG("vmalloc failed\n");
+ return -ENOMEM;
+ }
+
+ r = display->memory_read(display, buf, mr->buffer_size,
+ mr->x, mr->y, mr->w, mr->h);
+
+ if (r > 0) {
+ if (copy_to_user(mr->buffer, buf, mr->buffer_size))
+ r = -EFAULT;
+ }
+
+ vfree(buf);
+
+ return r;
+}
+
+static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
+ struct omapfb_ovl_colormode *mode)
+{
+ int ovl_idx = mode->overlay_idx;
+ int mode_idx = mode->mode_idx;
+ struct omap_overlay *ovl;
+ enum omap_color_mode supported_modes;
+ struct fb_var_screeninfo var;
+ int i;
+
+ if (ovl_idx >= fbdev->num_overlays)
+ return -ENODEV;
+ ovl = fbdev->overlays[ovl_idx];
+ supported_modes = ovl->supported_modes;
+
+ mode_idx = mode->mode_idx;
+
+ for (i = 0; i < sizeof(supported_modes) * 8; i++) {
+ if (!(supported_modes & (1 << i)))
+ continue;
+ /*
+ * It's possible that the FB doesn't support a mode
+ * that is supported by the overlay, so call the
+ * following here.
+ */
+ if (dss_mode_to_fb_mode(1 << i, &var) < 0)
+ continue;
+
+ mode_idx--;
+ if (mode_idx < 0)
+ break;
+ }
+
+ if (i == sizeof(supported_modes) * 8)
+ return -ENOENT;
+
+ mode->bits_per_pixel = var.bits_per_pixel;
+ mode->nonstd = var.nonstd;
+ mode->red = var.red;
+ mode->green = var.green;
+ mode->blue = var.blue;
+ mode->transp = var.transp;
+
+ return 0;
+}
+
+static int omapfb_wait_for_go(struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int r = 0;
+ int i;
+
+ for (i = 0; i < ofbi->num_overlays; ++i) {
+ struct omap_overlay *ovl = ofbi->overlays[i];
+ r = ovl->wait_for_go(ovl);
+ if (r)
+ break;
+ }
+
+ return r;
+}
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+
+ union {
+ struct omapfb_update_window_old uwnd_o;
+ struct omapfb_update_window uwnd;
+ struct omapfb_plane_info plane_info;
+ struct omapfb_caps caps;
+ struct omapfb_mem_info mem_info;
+ struct omapfb_color_key color_key;
+ struct omapfb_ovl_colormode ovl_colormode;
+ enum omapfb_update_mode update_mode;
+ int test_num;
+ struct omapfb_memory_read memory_read;
+ } p;
+
+ int r = 0;
+
+ switch (cmd) {
+ case OMAPFB_SYNC_GFX:
+ DBG("ioctl SYNC_GFX\n");
+ if (!display || !display->sync) {
+ /* DSS1 never returns an error here, so we neither */
+ /*r = -EINVAL;*/
+ break;
+ }
+
+ r = display->sync(display);
+ break;
+
+ case OMAPFB_UPDATE_WINDOW_OLD:
+ DBG("ioctl UPDATE_WINDOW_OLD\n");
+ if (!display || !display->update) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&p.uwnd_o,
+ (void __user *)arg,
+ sizeof(p.uwnd_o))) {
+ r = -EFAULT;
+ break;
+ }
+
+ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
+ p.uwnd_o.width, p.uwnd_o.height);
+ break;
+
+ case OMAPFB_UPDATE_WINDOW:
+ DBG("ioctl UPDATE_WINDOW\n");
+ if (!display || !display->update) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&p.uwnd, (void __user *)arg,
+ sizeof(p.uwnd))) {
+ r = -EFAULT;
+ break;
+ }
+
+ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
+ p.uwnd.width, p.uwnd.height);
+ break;
+
+ case OMAPFB_SETUP_PLANE:
+ DBG("ioctl SETUP_PLANE\n");
+ if (copy_from_user(&p.plane_info, (void __user *)arg,
+ sizeof(p.plane_info)))
+ r = -EFAULT;
+ else
+ r = omapfb_setup_plane(fbi, &p.plane_info);
+ break;
+
+ case OMAPFB_QUERY_PLANE:
+ DBG("ioctl QUERY_PLANE\n");
+ r = omapfb_query_plane(fbi, &p.plane_info);
+ if (r < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.plane_info,
+ sizeof(p.plane_info)))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_SETUP_MEM:
+ DBG("ioctl SETUP_MEM\n");
+ if (copy_from_user(&p.mem_info, (void __user *)arg,
+ sizeof(p.mem_info)))
+ r = -EFAULT;
+ else
+ r = omapfb_setup_mem(fbi, &p.mem_info);
+ break;
+
+ case OMAPFB_QUERY_MEM:
+ DBG("ioctl QUERY_MEM\n");
+ r = omapfb_query_mem(fbi, &p.mem_info);
+ if (r < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.mem_info,
+ sizeof(p.mem_info)))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_GET_CAPS:
+ DBG("ioctl GET_CAPS\n");
+ if (!display) {
+ r = -EINVAL;
+ break;
+ }
+
+ memset(&p.caps, 0, sizeof(p.caps));
+ p.caps.ctrl = display->caps;
+
+ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_GET_OVERLAY_COLORMODE:
+ DBG("ioctl GET_OVERLAY_COLORMODE\n");
+ if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
+ sizeof(p.ovl_colormode))) {
+ r = -EFAULT;
+ break;
+ }
+ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
+ if (r < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.ovl_colormode,
+ sizeof(p.ovl_colormode)))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_SET_UPDATE_MODE:
+ DBG("ioctl SET_UPDATE_MODE\n");
+ if (get_user(p.update_mode, (int __user *)arg))
+ r = -EFAULT;
+ else
+ r = omapfb_set_update_mode(fbi, p.update_mode);
+ break;
+
+ case OMAPFB_GET_UPDATE_MODE:
+ DBG("ioctl GET_UPDATE_MODE\n");
+ r = omapfb_get_update_mode(fbi, &p.update_mode);
+ if (r)
+ break;
+ if (put_user(p.update_mode,
+ (enum omapfb_update_mode __user *)arg))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_SET_COLOR_KEY:
+ DBG("ioctl SET_COLOR_KEY\n");
+ if (copy_from_user(&p.color_key, (void __user *)arg,
+ sizeof(p.color_key)))
+ r = -EFAULT;
+ else
+ r = omapfb_set_color_key(fbi, &p.color_key);
+ break;
+
+ case OMAPFB_GET_COLOR_KEY:
+ DBG("ioctl GET_COLOR_KEY\n");
+ r = omapfb_get_color_key(fbi, &p.color_key);
+ if (r)
+ break;
+ if (copy_to_user((void __user *)arg, &p.color_key,
+ sizeof(p.color_key)))
+ r = -EFAULT;
+ break;
+
+ case OMAPFB_WAITFORVSYNC:
+ DBG("ioctl WAITFORVSYNC\n");
+ if (!display) {
+ r = -EINVAL;
+ break;
+ }
+
+ r = display->wait_vsync(display);
+ break;
+
+ case OMAPFB_WAITFORGO:
+ DBG("ioctl WAITFORGO\n");
+ if (!display) {
+ r = -EINVAL;
+ break;
+ }
+
+ r = omapfb_wait_for_go(fbi);
+ break;
+
+ /* LCD and CTRL tests do the same thing for backward
+ * compatibility */
+ case OMAPFB_LCD_TEST:
+ DBG("ioctl LCD_TEST\n");
+ if (get_user(p.test_num, (int __user *)arg)) {
+ r = -EFAULT;
+ break;
+ }
+ if (!display || !display->run_test) {
+ r = -EINVAL;
+ break;
+ }
+
+ r = display->run_test(display, p.test_num);
+
+ break;
+
+ case OMAPFB_CTRL_TEST:
+ DBG("ioctl CTRL_TEST\n");
+ if (get_user(p.test_num, (int __user *)arg)) {
+ r = -EFAULT;
+ break;
+ }
+ if (!display || !display->run_test) {
+ r = -EINVAL;
+ break;
+ }
+
+ r = display->run_test(display, p.test_num);
+
+ break;
+
+ case OMAPFB_MEMORY_READ:
+ DBG("ioctl MEMORY_READ\n");
+
+ if (copy_from_user(&p.memory_read, (void __user *)arg,
+ sizeof(p.memory_read))) {
+ r = -EFAULT;
+ break;
+ }
+
+ r = omapfb_memory_read(fbi, &p.memory_read);
+
+ break;
+
+ default:
+ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
+ r = -EINVAL;
+ }
+
+ if (r < 0)
+ DBG("ioctl failed: %d\n", r);
+
+ return r;
+}
+
+
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
new file mode 100644
index 000000000000..7806d20711c0
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -0,0 +1,2143 @@
+/*
+ * linux/drivers/video/omap2/omapfb-main.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/omapfb.h>
+
+#include <mach/display.h>
+#include <mach/vram.h>
+#include <mach/vrfb.h>
+
+#include "omapfb.h"
+
+#define MODULE_NAME "omapfb"
+
+static char *def_mode;
+static char *def_vram;
+static int def_vrfb;
+static int def_rotate;
+static int def_mirror;
+
+#ifdef DEBUG
+unsigned int omapfb_debug;
+module_param_named(debug, omapfb_debug, bool, 0644);
+static unsigned int omapfb_test_pattern;
+module_param_named(test, omapfb_test_pattern, bool, 0644);
+#endif
+
+#ifdef DEBUG
+static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
+{
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ void __iomem *addr = fbi->screen_base;
+ const unsigned bytespp = var->bits_per_pixel >> 3;
+ const unsigned line_len = fix->line_length / bytespp;
+
+ int r = (color >> 16) & 0xff;
+ int g = (color >> 8) & 0xff;
+ int b = (color >> 0) & 0xff;
+
+ if (var->bits_per_pixel == 16) {
+ u16 __iomem *p = (u16 __iomem *)addr;
+ p += y * line_len + x;
+
+ r = r * 32 / 256;
+ g = g * 64 / 256;
+ b = b * 32 / 256;
+
+ __raw_writew((r << 11) | (g << 5) | (b << 0), p);
+ } else if (var->bits_per_pixel == 24) {
+ u8 __iomem *p = (u8 __iomem *)addr;
+ p += (y * line_len + x) * 3;
+
+ __raw_writeb(b, p + 0);
+ __raw_writeb(g, p + 1);
+ __raw_writeb(r, p + 2);
+ } else if (var->bits_per_pixel == 32) {
+ u32 __iomem *p = (u32 __iomem *)addr;
+ p += y * line_len + x;
+ __raw_writel(color, p);
+ }
+}
+
+static void fill_fb(struct fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->var;
+ const short w = var->xres_virtual;
+ const short h = var->yres_virtual;
+ void __iomem *addr = fbi->screen_base;
+ int y, x;
+
+ if (!addr)
+ return;
+
+ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (x < 20 && y < 20)
+ draw_pixel(fbi, x, y, 0xffffff);
+ else if (x < 20 && (y > 20 && y < h - 20))
+ draw_pixel(fbi, x, y, 0xff);
+ else if (y < 20 && (x > 20 && x < w - 20))
+ draw_pixel(fbi, x, y, 0xff00);
+ else if (x > w - 20 && (y > 20 && y < h - 20))
+ draw_pixel(fbi, x, y, 0xff0000);
+ else if (y > h - 20 && (x > 20 && x < w - 20))
+ draw_pixel(fbi, x, y, 0xffff00);
+ else if (x == 20 || x == w - 20 ||
+ y == 20 || y == h - 20)
+ draw_pixel(fbi, x, y, 0xffffff);
+ else if (x == y || w - x == h - y)
+ draw_pixel(fbi, x, y, 0xff00ff);
+ else if (w - x == y || x == h - y)
+ draw_pixel(fbi, x, y, 0x00ffff);
+ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
+ int t = x * 3 / w;
+ unsigned r = 0, g = 0, b = 0;
+ unsigned c;
+ if (var->bits_per_pixel == 16) {
+ if (t == 0)
+ b = (y % 32) * 256 / 32;
+ else if (t == 1)
+ g = (y % 64) * 256 / 64;
+ else if (t == 2)
+ r = (y % 32) * 256 / 32;
+ } else {
+ if (t == 0)
+ b = (y % 256);
+ else if (t == 1)
+ g = (y % 256);
+ else if (t == 2)
+ r = (y % 256);
+ }
+ c = (r << 16) | (g << 8) | (b << 0);
+ draw_pixel(fbi, x, y, c);
+ } else {
+ draw_pixel(fbi, x, y, 0);
+ }
+ }
+ }
+}
+#endif
+
+static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
+{
+ struct vrfb *vrfb = &ofbi->region.vrfb;
+ unsigned offset;
+
+ switch (rot) {
+ case FB_ROTATE_UR:
+ offset = 0;
+ break;
+ case FB_ROTATE_CW:
+ offset = vrfb->yoffset;
+ break;
+ case FB_ROTATE_UD:
+ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
+ break;
+ case FB_ROTATE_CCW:
+ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
+ break;
+ default:
+ BUG();
+ }
+
+ offset *= vrfb->bytespp;
+
+ return offset;
+}
+
+static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
+{
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ return ofbi->region.vrfb.paddr[rot]
+ + omapfb_get_vrfb_offset(ofbi, rot);
+ } else {
+ return ofbi->region.paddr;
+ }
+}
+
+u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
+{
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return ofbi->region.vrfb.paddr[0];
+ else
+ return ofbi->region.paddr;
+}
+
+void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
+{
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return ofbi->region.vrfb.vaddr[0];
+ else
+ return ofbi->region.vaddr;
+}
+
+static struct omapfb_colormode omapfb_colormodes[] = {
+ {
+ .dssmode = OMAP_DSS_COLOR_UYVY,
+ .bits_per_pixel = 16,
+ .nonstd = OMAPFB_COLOR_YUV422,
+ }, {
+ .dssmode = OMAP_DSS_COLOR_YUV2,
+ .bits_per_pixel = 16,
+ .nonstd = OMAPFB_COLOR_YUY422,
+ }, {
+ .dssmode = OMAP_DSS_COLOR_ARGB16,
+ .bits_per_pixel = 16,
+ .red = { .length = 4, .offset = 8, .msb_right = 0 },
+ .green = { .length = 4, .offset = 4, .msb_right = 0 },
+ .blue = { .length = 4, .offset = 0, .msb_right = 0 },
+ .transp = { .length = 4, .offset = 12, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_RGB16,
+ .bits_per_pixel = 16,
+ .red = { .length = 5, .offset = 11, .msb_right = 0 },
+ .green = { .length = 6, .offset = 5, .msb_right = 0 },
+ .blue = { .length = 5, .offset = 0, .msb_right = 0 },
+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_RGB24P,
+ .bits_per_pixel = 24,
+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_RGB24U,
+ .bits_per_pixel = 32,
+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_ARGB32,
+ .bits_per_pixel = 32,
+ .red = { .length = 8, .offset = 16, .msb_right = 0 },
+ .green = { .length = 8, .offset = 8, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
+ .transp = { .length = 8, .offset = 24, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_RGBA32,
+ .bits_per_pixel = 32,
+ .red = { .length = 8, .offset = 24, .msb_right = 0 },
+ .green = { .length = 8, .offset = 16, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
+ .transp = { .length = 8, .offset = 0, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_RGBX32,
+ .bits_per_pixel = 32,
+ .red = { .length = 8, .offset = 24, .msb_right = 0 },
+ .green = { .length = 8, .offset = 16, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
+ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
+ },
+};
+
+static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
+ struct omapfb_colormode *color)
+{
+ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
+ {
+ return f1->length == f2->length &&
+ f1->offset == f2->offset &&
+ f1->msb_right == f2->msb_right;
+ }
+
+ if (var->bits_per_pixel == 0 ||
+ var->red.length == 0 ||
+ var->blue.length == 0 ||
+ var->green.length == 0)
+ return 0;
+
+ return var->bits_per_pixel == color->bits_per_pixel &&
+ cmp_component(&var->red, &color->red) &&
+ cmp_component(&var->green, &color->green) &&
+ cmp_component(&var->blue, &color->blue) &&
+ cmp_component(&var->transp, &color->transp);
+}
+
+static void assign_colormode_to_var(struct fb_var_screeninfo *var,
+ struct omapfb_colormode *color)
+{
+ var->bits_per_pixel = color->bits_per_pixel;
+ var->nonstd = color->nonstd;
+ var->red = color->red;
+ var->green = color->green;
+ var->blue = color->blue;
+ var->transp = color->transp;
+}
+
+static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
+{
+ enum omap_color_mode dssmode;
+ int i;
+
+ /* first match with nonstd field */
+ if (var->nonstd) {
+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
+ if (var->nonstd == mode->nonstd) {
+ assign_colormode_to_var(var, mode);
+ return mode->dssmode;
+ }
+ }
+
+ return -EINVAL;
+ }
+
+ /* then try exact match of bpp and colors */
+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
+ if (cmp_var_to_colormode(var, mode)) {
+ assign_colormode_to_var(var, mode);
+ return mode->dssmode;
+ }
+ }
+
+ /* match with bpp if user has not filled color fields
+ * properly */
+ switch (var->bits_per_pixel) {
+ case 1:
+ dssmode = OMAP_DSS_COLOR_CLUT1;
+ break;
+ case 2:
+ dssmode = OMAP_DSS_COLOR_CLUT2;
+ break;
+ case 4:
+ dssmode = OMAP_DSS_COLOR_CLUT4;
+ break;
+ case 8:
+ dssmode = OMAP_DSS_COLOR_CLUT8;
+ break;
+ case 12:
+ dssmode = OMAP_DSS_COLOR_RGB12U;
+ break;
+ case 16:
+ dssmode = OMAP_DSS_COLOR_RGB16;
+ break;
+ case 24:
+ dssmode = OMAP_DSS_COLOR_RGB24P;
+ break;
+ case 32:
+ dssmode = OMAP_DSS_COLOR_RGB24U;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
+ if (dssmode == mode->dssmode) {
+ assign_colormode_to_var(var, mode);
+ return mode->dssmode;
+ }
+ }
+
+ return -EINVAL;
+}
+
+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+ struct fb_var_screeninfo *var)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+ struct omapfb_colormode *mode = &omapfb_colormodes[i];
+ if (dssmode == mode->dssmode) {
+ assign_colormode_to_var(var, mode);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+void set_fb_fix(struct fb_info *fbi)
+{
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_mem_region *rg = &ofbi->region;
+
+ DBG("set_fb_fix\n");
+
+ /* used by open/write in fbmem.c */
+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
+ DBG("changing rotation to %d\n", var->rotate);
+
+ /* used by mmap in fbmem.c */
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ switch (var->nonstd) {
+ case OMAPFB_COLOR_YUV422:
+ case OMAPFB_COLOR_YUY422:
+ fix->line_length =
+ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
+ break;
+ default:
+ fix->line_length =
+ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+ break;
+ }
+ } else
+ fix->line_length =
+ (var->xres_virtual * var->bits_per_pixel) >> 3;
+ fix->smem_start = omapfb_get_region_paddr(ofbi);
+ fix->smem_len = rg->size;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+
+ if (var->nonstd)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else {
+ switch (var->bits_per_pixel) {
+ case 32:
+ case 24:
+ case 16:
+ case 12:
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ /* 12bpp is stored in 16 bits */
+ break;
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ }
+ }
+
+ fix->accel = FB_ACCEL_NONE;
+
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+
+ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ enum omap_color_mode mode = 0;
+ mode = fb_mode_to_dss_mode(var);
+
+ omap_vrfb_setup(&rg->vrfb, rg->paddr,
+ var->xres_virtual,
+ var->yres_virtual,
+ mode);
+ }
+}
+
+/* check new var and possibly modify it to be ok */
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omap_dss_device *display = fb2display(fbi);
+ unsigned long max_frame_size;
+ unsigned long line_size;
+ int xres_min, yres_min;
+ int xres_max, yres_max;
+ enum omap_color_mode mode = 0;
+ int i;
+ int bytespp;
+
+ DBG("check_fb_var %d\n", ofbi->id);
+
+ if (ofbi->region.size == 0)
+ return 0;
+
+ mode = fb_mode_to_dss_mode(var);
+ if (mode < 0) {
+ DBG("cannot convert var to omap dss mode\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ofbi->num_overlays; ++i) {
+ if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
+ DBG("invalid mode\n");
+ return -EINVAL;
+ }
+ }
+
+ if (var->rotate < 0 || var->rotate > 3)
+ return -EINVAL;
+
+ xres_min = OMAPFB_PLANE_XRES_MIN;
+ xres_max = 2048;
+ yres_min = OMAPFB_PLANE_YRES_MIN;
+ yres_max = 2048;
+
+ bytespp = var->bits_per_pixel >> 3;
+
+ /* XXX: some applications seem to set virtual res to 0. */
+ if (var->xres_virtual == 0)
+ var->xres_virtual = var->xres;
+
+ if (var->yres_virtual == 0)
+ var->yres_virtual = var->yres;
+
+ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
+ return -EINVAL;
+
+ if (var->xres < xres_min)
+ var->xres = xres_min;
+ if (var->yres < yres_min)
+ var->yres = yres_min;
+ if (var->xres > xres_max)
+ var->xres = xres_max;
+ if (var->yres > yres_max)
+ var->yres = yres_max;
+
+ if (var->xres > var->xres_virtual)
+ var->xres = var->xres_virtual;
+ if (var->yres > var->yres_virtual)
+ var->yres = var->yres_virtual;
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ line_size = OMAP_VRFB_LINE_LEN * bytespp;
+ else
+ line_size = var->xres_virtual * bytespp;
+
+ max_frame_size = ofbi->region.size;
+
+ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
+
+ if (line_size * var->yres_virtual > max_frame_size) {
+ DBG("can't fit FB into memory, reducing y\n");
+ var->yres_virtual = max_frame_size / line_size;
+
+ if (var->yres_virtual < yres_min)
+ var->yres_virtual = yres_min;
+
+ if (var->yres > var->yres_virtual)
+ var->yres = var->yres_virtual;
+ }
+
+ if (line_size * var->yres_virtual > max_frame_size) {
+ DBG("can't fit FB into memory, reducing x\n");
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return -EINVAL;
+
+ var->xres_virtual = max_frame_size / var->yres_virtual /
+ bytespp;
+
+ if (var->xres_virtual < xres_min)
+ var->xres_virtual = xres_min;
+
+ if (var->xres > var->xres_virtual)
+ var->xres = var->xres_virtual;
+
+ line_size = var->xres_virtual * bytespp;
+ }
+
+ if (line_size * var->yres_virtual > max_frame_size) {
+ DBG("cannot fit FB to memory\n");
+ return -EINVAL;
+ }
+
+ if (var->xres + var->xoffset > var->xres_virtual)
+ var->xoffset = var->xres_virtual - var->xres;
+ if (var->yres + var->yoffset > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
+ var->xres, var->yres,
+ var->xres_virtual, var->yres_virtual);
+
+ var->height = -1;
+ var->width = -1;
+ var->grayscale = 0;
+
+ if (display && display->get_timings) {
+ struct omap_video_timings timings;
+ display->get_timings(display, &timings);
+
+ /* pixclock in ps, the rest in pixclock */
+ var->pixclock = timings.pixel_clock != 0 ?
+ KHZ2PICOS(timings.pixel_clock) :
+ 0;
+ var->left_margin = timings.hfp;
+ var->right_margin = timings.hbp;
+ var->upper_margin = timings.vfp;
+ var->lower_margin = timings.vbp;
+ var->hsync_len = timings.hsw;
+ var->vsync_len = timings.vsw;
+ } else {
+ var->pixclock = 0;
+ var->left_margin = 0;
+ var->right_margin = 0;
+ var->upper_margin = 0;
+ var->lower_margin = 0;
+ var->hsync_len = 0;
+ var->vsync_len = 0;
+ }
+
+ /* TODO: get these from panel->config */
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->sync = 0;
+
+ return 0;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks
+ * ---------------------------------------------------------------------------
+ */
+static int omapfb_open(struct fb_info *fbi, int user)
+{
+ return 0;
+}
+
+static int omapfb_release(struct fb_info *fbi, int user)
+{
+#if 0
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+
+ DBG("Closing fb with plane index %d\n", ofbi->id);
+
+ omapfb_lock(fbdev);
+
+ if (display && display->get_update_mode && display->update) {
+ /* XXX this update should be removed, I think. But it's
+ * good for debugging */
+ if (display->get_update_mode(display) ==
+ OMAP_DSS_UPDATE_MANUAL) {
+ u16 w, h;
+
+ if (display->sync)
+ display->sync(display);
+
+ display->get_resolution(display, &w, &h);
+ display->update(display, 0, 0, w, h);
+ }
+ }
+
+ if (display && display->sync)
+ display->sync(display);
+
+ omapfb_unlock(fbdev);
+#endif
+ return 0;
+}
+
+/* setup overlay according to the fb */
+static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ u16 posx, u16 posy, u16 outw, u16 outh)
+{
+ int r = 0;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ enum omap_color_mode mode = 0;
+ int offset;
+ u32 data_start_p;
+ void __iomem *data_start_v;
+ struct omap_overlay_info info;
+ int xres, yres;
+ int screen_width;
+ int mirror;
+ int rotation = var->rotate;
+ int i;
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ovl != ofbi->overlays[i])
+ continue;
+
+ rotation = (rotation + ofbi->rotation[i]) % 4;
+ break;
+ }
+
+ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
+ posx, posy, outw, outh);
+
+ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
+ xres = var->yres;
+ yres = var->xres;
+ } else {
+ xres = var->xres;
+ yres = var->yres;
+ }
+
+ offset = ((var->yoffset * var->xres_virtual +
+ var->xoffset) * var->bits_per_pixel) >> 3;
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+ data_start_v = NULL;
+ } else {
+ data_start_p = omapfb_get_region_paddr(ofbi);
+ data_start_v = omapfb_get_region_vaddr(ofbi);
+ }
+
+ data_start_p += offset;
+ data_start_v += offset;
+
+ mode = fb_mode_to_dss_mode(var);
+
+ if (mode == -EINVAL) {
+ DBG("fb_mode_to_dss_mode failed");
+ r = -EINVAL;
+ goto err;
+ }
+
+ switch (var->nonstd) {
+ case OMAPFB_COLOR_YUV422:
+ case OMAPFB_COLOR_YUY422:
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ screen_width = fix->line_length
+ / (var->bits_per_pixel >> 2);
+ break;
+ }
+ default:
+ screen_width = fix->line_length / (var->bits_per_pixel >> 3);
+ break;
+ }
+
+ ovl->get_overlay_info(ovl, &info);
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ mirror = 0;
+ else
+ mirror = ofbi->mirror;
+
+ info.paddr = data_start_p;
+ info.vaddr = data_start_v;
+ info.screen_width = screen_width;
+ info.width = xres;
+ info.height = yres;
+ info.color_mode = mode;
+ info.rotation_type = ofbi->rotation_type;
+ info.rotation = rotation;
+ info.mirror = mirror;
+
+ info.pos_x = posx;
+ info.pos_y = posy;
+ info.out_width = outw;
+ info.out_height = outh;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r) {
+ DBG("ovl->setup_overlay_info failed\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ DBG("setup_overlay failed\n");
+ return r;
+}
+
+/* apply var to the overlay */
+int omapfb_apply_changes(struct fb_info *fbi, int init)
+{
+ int r = 0;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct omap_overlay *ovl;
+ u16 posx, posy;
+ u16 outw, outh;
+ int i;
+
+#ifdef DEBUG
+ if (omapfb_test_pattern)
+ fill_fb(fbi);
+#endif
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ ovl = ofbi->overlays[i];
+
+ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
+
+ if (ofbi->region.size == 0) {
+ /* the fb is not available. disable the overlay */
+ omapfb_overlay_enable(ovl, 0);
+ if (!init && ovl->manager)
+ ovl->manager->apply(ovl->manager);
+ continue;
+ }
+
+ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ int rotation = (var->rotate + ofbi->rotation[i]) % 4;
+ if (rotation == FB_ROTATE_CW ||
+ rotation == FB_ROTATE_CCW) {
+ outw = var->yres;
+ outh = var->xres;
+ } else {
+ outw = var->xres;
+ outh = var->yres;
+ }
+ } else {
+ outw = ovl->info.out_width;
+ outh = ovl->info.out_height;
+ }
+
+ if (init) {
+ posx = 0;
+ posy = 0;
+ } else {
+ posx = ovl->info.pos_x;
+ posy = ovl->info.pos_y;
+ }
+
+ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
+ if (r)
+ goto err;
+
+ if (!init && ovl->manager)
+ ovl->manager->apply(ovl->manager);
+ }
+ return 0;
+err:
+ DBG("apply_changes failed\n");
+ return r;
+}
+
+/* checks var and eventually tweaks it to something supported,
+ * DO NOT MODIFY PAR */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+ int r;
+
+ DBG("check_var(%d)\n", FB2OFB(fbi)->id);
+
+ r = check_fb_var(fbi, var);
+
+ return r;
+}
+
+/* set the video mode according to info->var */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+ int r;
+
+ DBG("set_par(%d)\n", FB2OFB(fbi)->id);
+
+ set_fb_fix(fbi);
+ r = omapfb_apply_changes(fbi, 0);
+
+ return r;
+}
+
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int r = 0;
+
+ DBG("pan_display(%d)\n", ofbi->id);
+
+ if (var->xoffset != fbi->var.xoffset ||
+ var->yoffset != fbi->var.yoffset) {
+ struct fb_var_screeninfo new_var;
+
+ new_var = fbi->var;
+ new_var.xoffset = var->xoffset;
+ new_var.yoffset = var->yoffset;
+
+ r = check_fb_var(fbi, &new_var);
+
+ if (r == 0) {
+ fbi->var = new_var;
+ set_fb_fix(fbi);
+ r = omapfb_apply_changes(fbi, 0);
+ }
+ }
+
+ return r;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+
+ atomic_inc(&ofbi->map_count);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+
+ atomic_dec(&ofbi->map_count);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+ .open = mmap_user_open,
+ .close = mmap_user_close,
+};
+
+static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ unsigned long off;
+ unsigned long start;
+ u32 len;
+
+ if (vma->vm_end - vma->vm_start == 0)
+ return 0;
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ start = omapfb_get_region_paddr(ofbi);
+ len = fix->smem_len;
+ if (off >= len)
+ return -EINVAL;
+ if ((vma->vm_end - vma->vm_start + off) > len)
+ return -EINVAL;
+
+ off += start;
+
+ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
+
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_ops = &mmap_user_ops;
+ vma->vm_private_data = ofbi;
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ /* vm_ops.open won't be called for mmap itself. */
+ atomic_inc(&ofbi->map_count);
+ return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
+ u_int blue, u_int transp, int update_hw_pal)
+{
+ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
+ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
+ struct fb_var_screeninfo *var = &fbi->var;
+ int r = 0;
+
+ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
+
+ /*switch (plane->color_mode) {*/
+ switch (mode) {
+ case OMAPFB_COLOR_YUV422:
+ case OMAPFB_COLOR_YUV420:
+ case OMAPFB_COLOR_YUY422:
+ r = -EINVAL;
+ break;
+ case OMAPFB_COLOR_CLUT_8BPP:
+ case OMAPFB_COLOR_CLUT_4BPP:
+ case OMAPFB_COLOR_CLUT_2BPP:
+ case OMAPFB_COLOR_CLUT_1BPP:
+ /*
+ if (fbdev->ctrl->setcolreg)
+ r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+ transp, update_hw_pal);
+ */
+ /* Fallthrough */
+ r = -EINVAL;
+ break;
+ case OMAPFB_COLOR_RGB565:
+ case OMAPFB_COLOR_RGB444:
+ case OMAPFB_COLOR_RGB24P:
+ case OMAPFB_COLOR_RGB24U:
+ if (r != 0)
+ break;
+
+ if (regno < 0) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (regno < 16) {
+ u16 pal;
+ pal = ((red >> (16 - var->red.length)) <<
+ var->red.offset) |
+ ((green >> (16 - var->green.length)) <<
+ var->green.offset) |
+ (blue >> (16 - var->blue.length));
+ ((u32 *)(fbi->pseudo_palette))[regno] = pal;
+ }
+ break;
+ default:
+ BUG();
+ }
+ return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ DBG("setcolreg\n");
+
+ return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ int count, index, r;
+ u16 *red, *green, *blue, *transp;
+ u16 trans = 0xffff;
+
+ DBG("setcmap\n");
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ index = cmap->start;
+
+ for (count = 0; count < cmap->len; count++) {
+ if (transp)
+ trans = *transp++;
+ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+ count == cmap->len - 1);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
+{
+ int i;
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+ if (ofbi->region.vrfb.vaddr[0])
+ omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
+ }
+}
+
+static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
+{
+ int i;
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+ if (ofbi->region.vrfb.vaddr[0])
+ omap_vrfb_resume_ctx(&ofbi->region.vrfb);
+ }
+}
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ int do_update = 0;
+ int r = 0;
+
+ omapfb_lock(fbdev);
+
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ goto exit;
+
+ omapfb_vrfb_resume_all(fbdev);
+
+ if (display->resume)
+ r = display->resume(display);
+
+ if (r == 0 && display->get_update_mode &&
+ display->get_update_mode(display) ==
+ OMAP_DSS_UPDATE_MANUAL)
+ do_update = 1;
+
+ break;
+
+ case FB_BLANK_NORMAL:
+ /* FB_BLANK_NORMAL could be implemented.
+ * Needs DSS additions. */
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+ goto exit;
+
+ if (display->suspend)
+ r = display->suspend(display);
+
+ omapfb_vrfb_suspend_all(fbdev);
+
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+exit:
+ omapfb_unlock(fbdev);
+
+ if (r == 0 && do_update && display->update) {
+ u16 w, h;
+ display->get_resolution(display, &w, &h);
+
+ r = display->update(display, 0, 0, w, h);
+ }
+
+ return r;
+}
+
+#if 0
+/* XXX fb_read and fb_write are needed for VRFB */
+ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
+ /* XXX needed for VRFB */
+ return count;
+}
+#endif
+
+static struct fb_ops omapfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = omapfb_open,
+ .fb_release = omapfb_release,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_blank = omapfb_blank,
+ .fb_ioctl = omapfb_ioctl,
+ .fb_check_var = omapfb_check_var,
+ .fb_set_par = omapfb_set_par,
+ .fb_pan_display = omapfb_pan_display,
+ .fb_mmap = omapfb_mmap,
+ .fb_setcolreg = omapfb_setcolreg,
+ .fb_setcmap = omapfb_setcmap,
+ /*.fb_write = omapfb_write,*/
+};
+
+static void omapfb_free_fbmem(struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb2_mem_region *rg;
+
+ rg = &ofbi->region;
+
+ if (rg->paddr)
+ if (omap_vram_free(rg->paddr, rg->size))
+ dev_err(fbdev->dev, "VRAM FREE failed\n");
+
+ if (rg->vaddr)
+ iounmap(rg->vaddr);
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ /* unmap the 0 angle rotation */
+ if (rg->vrfb.vaddr[0]) {
+ iounmap(rg->vrfb.vaddr[0]);
+ omap_vrfb_release_ctx(&rg->vrfb);
+ }
+ }
+
+ rg->vaddr = NULL;
+ rg->paddr = 0;
+ rg->alloc = 0;
+ rg->size = 0;
+}
+
+static void clear_fb_info(struct fb_info *fbi)
+{
+ memset(&fbi->var, 0, sizeof(fbi->var));
+ memset(&fbi->fix, 0, sizeof(fbi->fix));
+ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
+}
+
+static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
+{
+ int i;
+
+ DBG("free all fbmem\n");
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct fb_info *fbi = fbdev->fbs[i];
+ omapfb_free_fbmem(fbi);
+ clear_fb_info(fbi);
+ }
+
+ return 0;
+}
+
+static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ unsigned long paddr)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb2_mem_region *rg;
+ void __iomem *vaddr;
+ int r;
+
+ rg = &ofbi->region;
+ memset(rg, 0, sizeof(*rg));
+
+ size = PAGE_ALIGN(size);
+
+ if (!paddr) {
+ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+ r = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
+ } else {
+ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
+ ofbi->id);
+ r = omap_vram_reserve(paddr, size);
+ }
+
+ if (r) {
+ dev_err(fbdev->dev, "failed to allocate framebuffer\n");
+ return -ENOMEM;
+ }
+
+ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
+ vaddr = ioremap_wc(paddr, size);
+
+ if (!vaddr) {
+ dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
+ omap_vram_free(paddr, size);
+ return -ENOMEM;
+ }
+
+ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
+ } else {
+ void __iomem *va;
+
+ r = omap_vrfb_request_ctx(&rg->vrfb);
+ if (r) {
+ dev_err(fbdev->dev, "vrfb create ctx failed\n");
+ return r;
+ }
+
+ /* only ioremap the 0 angle view */
+ va = ioremap_wc(rg->vrfb.paddr[0], size);
+
+ if (!va) {
+ printk(KERN_ERR "vrfb: ioremap failed\n");
+ omap_vrfb_release_ctx(&rg->vrfb);
+ return -ENOMEM;
+ }
+
+ DBG("ioremapped vrfb area 0 to %p\n", va);
+
+ rg->vrfb.vaddr[0] = va;
+
+ vaddr = NULL;
+ }
+
+ rg->paddr = paddr;
+ rg->vaddr = vaddr;
+ rg->size = size;
+ rg->alloc = 1;
+
+ return 0;
+}
+
+/* allocate fbmem using display resolution as reference */
+static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ unsigned long paddr)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omap_dss_device *display;
+ int bytespp;
+
+ display = fb2display(fbi);
+
+ if (!display)
+ return 0;
+
+ switch (display->get_recommended_bpp(display)) {
+ case 16:
+ bytespp = 2;
+ break;
+ case 24:
+ bytespp = 4;
+ break;
+ default:
+ bytespp = 4;
+ break;
+ }
+
+ if (!size) {
+ u16 w, h;
+
+ display->get_resolution(display, &w, &h);
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+#ifdef DEBUG
+ int oldw = w, oldh = h;
+#endif
+
+ omap_vrfb_adjust_size(&w, &h, bytespp);
+
+ /* Because we change the resolution of the 0 degree
+ * view, we need to alloc max(w, h) for height */
+ h = max(w, h);
+ w = OMAP_VRFB_LINE_LEN;
+
+ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n",
+ oldw, oldh, w, h);
+ }
+
+ size = w * h * bytespp;
+ }
+
+ if (!size)
+ return 0;
+
+ return omapfb_alloc_fbmem(fbi, size, paddr);
+}
+
+static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
+{
+ enum omap_color_mode mode;
+
+ switch (fmt) {
+ case OMAPFB_COLOR_RGB565:
+ mode = OMAP_DSS_COLOR_RGB16;
+ break;
+ case OMAPFB_COLOR_YUV422:
+ mode = OMAP_DSS_COLOR_YUV2;
+ break;
+ case OMAPFB_COLOR_CLUT_8BPP:
+ mode = OMAP_DSS_COLOR_CLUT8;
+ break;
+ case OMAPFB_COLOR_CLUT_4BPP:
+ mode = OMAP_DSS_COLOR_CLUT4;
+ break;
+ case OMAPFB_COLOR_CLUT_2BPP:
+ mode = OMAP_DSS_COLOR_CLUT2;
+ break;
+ case OMAPFB_COLOR_CLUT_1BPP:
+ mode = OMAP_DSS_COLOR_CLUT1;
+ break;
+ case OMAPFB_COLOR_RGB444:
+ mode = OMAP_DSS_COLOR_RGB12U;
+ break;
+ case OMAPFB_COLOR_YUY422:
+ mode = OMAP_DSS_COLOR_UYVY;
+ break;
+ case OMAPFB_COLOR_ARGB16:
+ mode = OMAP_DSS_COLOR_ARGB16;
+ break;
+ case OMAPFB_COLOR_RGB24U:
+ mode = OMAP_DSS_COLOR_RGB24U;
+ break;
+ case OMAPFB_COLOR_RGB24P:
+ mode = OMAP_DSS_COLOR_RGB24P;
+ break;
+ case OMAPFB_COLOR_ARGB32:
+ mode = OMAP_DSS_COLOR_ARGB32;
+ break;
+ case OMAPFB_COLOR_RGBA32:
+ mode = OMAP_DSS_COLOR_RGBA32;
+ break;
+ case OMAPFB_COLOR_RGBX32:
+ mode = OMAP_DSS_COLOR_RGBX32;
+ break;
+ default:
+ mode = -EINVAL;
+ }
+
+ return mode;
+}
+
+static int omapfb_parse_vram_param(const char *param, int max_entries,
+ unsigned long *sizes, unsigned long *paddrs)
+{
+ int fbnum;
+ unsigned long size;
+ unsigned long paddr = 0;
+ char *p, *start;
+
+ start = (char *)param;
+
+ while (1) {
+ p = start;
+
+ fbnum = simple_strtoul(p, &p, 10);
+
+ if (p == param)
+ return -EINVAL;
+
+ if (*p != ':')
+ return -EINVAL;
+
+ if (fbnum >= max_entries)
+ return -EINVAL;
+
+ size = memparse(p + 1, &p);
+
+ if (!size)
+ return -EINVAL;
+
+ paddr = 0;
+
+ if (*p == '@') {
+ paddr = simple_strtoul(p + 1, &p, 16);
+
+ if (!paddr)
+ return -EINVAL;
+
+ }
+
+ paddrs[fbnum] = paddr;
+ sizes[fbnum] = size;
+
+ if (*p == 0)
+ break;
+
+ if (*p != ',')
+ return -EINVAL;
+
+ ++p;
+
+ start = p;
+ }
+
+ return 0;
+}
+
+static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
+{
+ int i, r;
+ unsigned long vram_sizes[10];
+ unsigned long vram_paddrs[10];
+
+ memset(&vram_sizes, 0, sizeof(vram_sizes));
+ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
+
+ if (def_vram && omapfb_parse_vram_param(def_vram, 10,
+ vram_sizes, vram_paddrs)) {
+ dev_err(fbdev->dev, "failed to parse vram parameter\n");
+
+ memset(&vram_sizes, 0, sizeof(vram_sizes));
+ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
+ }
+
+ if (fbdev->dev->platform_data) {
+ struct omapfb_platform_data *opd;
+ opd = fbdev->dev->platform_data;
+ for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
+ if (!vram_sizes[i]) {
+ unsigned long size;
+ unsigned long paddr;
+
+ size = opd->mem_desc.region[i].size;
+ paddr = opd->mem_desc.region[i].paddr;
+
+ vram_sizes[i] = size;
+ vram_paddrs[i] = paddr;
+ }
+ }
+ }
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ /* allocate memory automatically only for fb0, or if
+ * excplicitly defined with vram or plat data option */
+ if (i == 0 || vram_sizes[i] != 0) {
+ r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
+ vram_sizes[i], vram_paddrs[i]);
+
+ if (r)
+ return r;
+ }
+ }
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+ struct omapfb2_mem_region *rg;
+ rg = &ofbi->region;
+
+ DBG("region%d phys %08x virt %p size=%lu\n",
+ i,
+ rg->paddr,
+ rg->vaddr,
+ rg->size);
+ }
+
+ return 0;
+}
+
+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb2_mem_region *rg = &ofbi->region;
+ unsigned long old_size = rg->size;
+ unsigned long old_paddr = rg->paddr;
+ int old_type = rg->type;
+ int r;
+
+ if (type > OMAPFB_MEMTYPE_MAX)
+ return -EINVAL;
+
+ size = PAGE_ALIGN(size);
+
+ if (old_size == size && old_type == type)
+ return 0;
+
+ if (display && display->sync)
+ display->sync(display);
+
+ omapfb_free_fbmem(fbi);
+
+ if (size == 0) {
+ clear_fb_info(fbi);
+ return 0;
+ }
+
+ r = omapfb_alloc_fbmem(fbi, size, 0);
+
+ if (r) {
+ if (old_size)
+ omapfb_alloc_fbmem(fbi, old_size, old_paddr);
+
+ if (rg->size == 0)
+ clear_fb_info(fbi);
+
+ return r;
+ }
+
+ if (old_size == size)
+ return 0;
+
+ if (old_size == 0) {
+ DBG("initializing fb %d\n", ofbi->id);
+ r = omapfb_fb_init(fbdev, fbi);
+ if (r) {
+ DBG("omapfb_fb_init failed\n");
+ goto err;
+ }
+ r = omapfb_apply_changes(fbi, 1);
+ if (r) {
+ DBG("omapfb_apply_changes failed\n");
+ goto err;
+ }
+ } else {
+ struct fb_var_screeninfo new_var;
+ memcpy(&new_var, &fbi->var, sizeof(new_var));
+ r = check_fb_var(fbi, &new_var);
+ if (r)
+ goto err;
+ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+ set_fb_fix(fbi);
+ }
+
+ return 0;
+err:
+ omapfb_free_fbmem(fbi);
+ clear_fb_info(fbi);
+ return r;
+}
+
+/* initialize fb_info, var, fix to something sane based on the display */
+int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int r = 0;
+
+ fbi->fbops = &omapfb_ops;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->pseudo_palette = fbdev->pseudo_palette;
+
+/* strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); */
+
+ if (ofbi->region.size == 0) {
+ memset(&fbi->fix, 0, sizeof(fbi->fix));
+ memset(&fbi->var, 0, sizeof(fbi->var));
+ clear_fb_info(fbi);
+ return 0;
+ }
+
+ var->nonstd = 0;
+ var->bits_per_pixel = 0;
+
+ var->rotate = def_rotate;
+
+ /*
+ * Check if there is a default color format set in the board file,
+ * and use this format instead the default deducted from the
+ * display bpp.
+ */
+ if (fbdev->dev->platform_data) {
+ struct omapfb_platform_data *opd;
+ int id = ofbi->id;
+
+ opd = fbdev->dev->platform_data;
+ if (opd->mem_desc.region[id].format_used) {
+ enum omap_color_mode mode;
+ enum omapfb_color_format format;
+
+ format = opd->mem_desc.region[id].format;
+ mode = fb_format_to_dss_mode(format);
+ if (mode < 0) {
+ r = mode;
+ goto err;
+ }
+ r = dss_mode_to_fb_mode(mode, var);
+ if (r < 0)
+ goto err;
+ }
+ }
+
+ if (display) {
+ u16 w, h;
+ int rotation = (var->rotate + ofbi->rotation[0]) % 4;
+
+ display->get_resolution(display, &w, &h);
+
+ if (rotation == FB_ROTATE_CW ||
+ rotation == FB_ROTATE_CCW) {
+ var->xres = h;
+ var->yres = w;
+ } else {
+ var->xres = w;
+ var->yres = h;
+ }
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ if (!var->bits_per_pixel) {
+ switch (display->get_recommended_bpp(display)) {
+ case 16:
+ var->bits_per_pixel = 16;
+ break;
+ case 24:
+ var->bits_per_pixel = 32;
+ break;
+ default:
+ dev_err(fbdev->dev, "illegal display "
+ "bpp\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* if there's no display, let's just guess some basic values */
+ var->xres = 320;
+ var->yres = 240;
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+ if (!var->bits_per_pixel)
+ var->bits_per_pixel = 16;
+ }
+
+ r = check_fb_var(fbi, var);
+ if (r)
+ goto err;
+
+ set_fb_fix(fbi);
+
+ r = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (r)
+ dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+err:
+ return r;
+}
+
+static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+ fb_dealloc_cmap(&fbi->cmap);
+}
+
+
+static void omapfb_free_resources(struct omapfb2_device *fbdev)
+{
+ int i;
+
+ DBG("free_resources\n");
+
+ if (fbdev == NULL)
+ return;
+
+ for (i = 0; i < fbdev->num_fbs; i++)
+ unregister_framebuffer(fbdev->fbs[i]);
+
+ /* free the reserved fbmem */
+ omapfb_free_all_fbmem(fbdev);
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ fbinfo_cleanup(fbdev, fbdev->fbs[i]);
+ framebuffer_release(fbdev->fbs[i]);
+ }
+
+ for (i = 0; i < fbdev->num_displays; i++) {
+ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
+ fbdev->displays[i]->disable(fbdev->displays[i]);
+
+ omap_dss_put_device(fbdev->displays[i]);
+ }
+
+ dev_set_drvdata(fbdev->dev, NULL);
+ kfree(fbdev);
+}
+
+static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+{
+ int r, i;
+
+ fbdev->num_fbs = 0;
+
+ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
+
+ /* allocate fb_infos */
+ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
+ struct fb_info *fbi;
+ struct omapfb_info *ofbi;
+
+ fbi = framebuffer_alloc(sizeof(struct omapfb_info),
+ fbdev->dev);
+
+ if (fbi == NULL) {
+ dev_err(fbdev->dev,
+ "unable to allocate memory for plane info\n");
+ return -ENOMEM;
+ }
+
+ clear_fb_info(fbi);
+
+ fbdev->fbs[i] = fbi;
+
+ ofbi = FB2OFB(fbi);
+ ofbi->fbdev = fbdev;
+ ofbi->id = i;
+
+ /* assign these early, so that fb alloc can use them */
+ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
+ OMAP_DSS_ROT_DMA;
+ ofbi->mirror = def_mirror;
+
+ fbdev->num_fbs++;
+ }
+
+ DBG("fb_infos allocated\n");
+
+ /* assign overlays for the fbs */
+ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+ ofbi->overlays[0] = fbdev->overlays[i];
+ ofbi->num_overlays = 1;
+ }
+
+ /* allocate fb memories */
+ r = omapfb_allocate_all_fbs(fbdev);
+ if (r) {
+ dev_err(fbdev->dev, "failed to allocate fbmem\n");
+ return r;
+ }
+
+ DBG("fbmems allocated\n");
+
+ /* setup fb_infos */
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
+ if (r) {
+ dev_err(fbdev->dev, "failed to setup fb_info\n");
+ return r;
+ }
+ }
+
+ DBG("fb_infos initialized\n");
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ r = register_framebuffer(fbdev->fbs[i]);
+ if (r != 0) {
+ dev_err(fbdev->dev,
+ "registering framebuffer %d failed\n", i);
+ return r;
+ }
+ }
+
+ DBG("framebuffers registered\n");
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ r = omapfb_apply_changes(fbdev->fbs[i], 1);
+ if (r) {
+ dev_err(fbdev->dev, "failed to change mode\n");
+ return r;
+ }
+ }
+
+ DBG("create sysfs for fbs\n");
+ r = omapfb_create_sysfs(fbdev);
+ if (r) {
+ dev_err(fbdev->dev, "failed to create sysfs entries\n");
+ return r;
+ }
+
+ /* Enable fb0 */
+ if (fbdev->num_fbs > 0) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
+
+ if (ofbi->num_overlays > 0) {
+ struct omap_overlay *ovl = ofbi->overlays[0];
+
+ r = omapfb_overlay_enable(ovl, 1);
+
+ if (r) {
+ dev_err(fbdev->dev,
+ "failed to enable overlay\n");
+ return r;
+ }
+ }
+ }
+
+ DBG("create_framebuffers done\n");
+
+ return 0;
+}
+
+int omapfb_mode_to_timings(const char *mode_str,
+ struct omap_video_timings *timings, u8 *bpp)
+{
+ struct fb_info fbi;
+ struct fb_var_screeninfo var;
+ struct fb_ops fbops;
+ int r;
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+ if (strcmp(mode_str, "pal") == 0) {
+ *timings = omap_dss_pal_timings;
+ *bpp = 0;
+ return 0;
+ } else if (strcmp(mode_str, "ntsc") == 0) {
+ *timings = omap_dss_ntsc_timings;
+ *bpp = 0;
+ return 0;
+ }
+#endif
+
+ /* this is quite a hack, but I wanted to use the modedb and for
+ * that we need fb_info and var, so we create dummy ones */
+
+ memset(&fbi, 0, sizeof(fbi));
+ memset(&var, 0, sizeof(var));
+ memset(&fbops, 0, sizeof(fbops));
+ fbi.fbops = &fbops;
+
+ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
+
+ if (r != 0) {
+ timings->pixel_clock = PICOS2KHZ(var.pixclock);
+ timings->hfp = var.left_margin;
+ timings->hbp = var.right_margin;
+ timings->vfp = var.upper_margin;
+ timings->vbp = var.lower_margin;
+ timings->hsw = var.hsync_len;
+ timings->vsw = var.vsync_len;
+ timings->x_res = var.xres;
+ timings->y_res = var.yres;
+
+ switch (var.bits_per_pixel) {
+ case 16:
+ *bpp = 16;
+ break;
+ case 24:
+ case 32:
+ default:
+ *bpp = 24;
+ break;
+ }
+
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+}
+
+static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
+{
+ int r;
+ u8 bpp;
+ struct omap_video_timings timings;
+
+ r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
+ if (r)
+ return r;
+
+ display->panel.recommended_bpp = bpp;
+
+ if (!display->check_timings || !display->set_timings)
+ return -EINVAL;
+
+ r = display->check_timings(display, &timings);
+ if (r)
+ return r;
+
+ display->set_timings(display, &timings);
+
+ return 0;
+}
+
+static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
+{
+ char *str, *options, *this_opt;
+ int r = 0;
+
+ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
+ strcpy(str, def_mode);
+ options = str;
+
+ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+ char *p, *display_str, *mode_str;
+ struct omap_dss_device *display;
+ int i;
+
+ p = strchr(this_opt, ':');
+ if (!p) {
+ r = -EINVAL;
+ break;
+ }
+
+ *p = 0;
+ display_str = this_opt;
+ mode_str = p + 1;
+
+ display = NULL;
+ for (i = 0; i < fbdev->num_displays; ++i) {
+ if (strcmp(fbdev->displays[i]->name,
+ display_str) == 0) {
+ display = fbdev->displays[i];
+ break;
+ }
+ }
+
+ if (!display) {
+ r = -EINVAL;
+ break;
+ }
+
+ r = omapfb_set_def_mode(display, mode_str);
+ if (r)
+ break;
+ }
+
+ kfree(str);
+
+ return r;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+ struct omapfb2_device *fbdev = NULL;
+ int r = 0;
+ int i;
+ struct omap_overlay *ovl;
+ struct omap_dss_device *def_display;
+ struct omap_dss_device *dssdev;
+
+ DBG("omapfb_probe\n");
+
+ if (pdev->num_resources != 0) {
+ dev_err(&pdev->dev, "probed for an unknown device\n");
+ r = -ENODEV;
+ goto err0;
+ }
+
+ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
+ if (fbdev == NULL) {
+ r = -ENOMEM;
+ goto err0;
+ }
+
+ mutex_init(&fbdev->mtx);
+
+ fbdev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, fbdev);
+
+ fbdev->num_displays = 0;
+ dssdev = NULL;
+ for_each_dss_dev(dssdev) {
+ omap_dss_get_device(dssdev);
+ fbdev->displays[fbdev->num_displays++] = dssdev;
+ }
+
+ if (fbdev->num_displays == 0) {
+ dev_err(&pdev->dev, "no displays\n");
+ r = -EINVAL;
+ goto cleanup;
+ }
+
+ fbdev->num_overlays = omap_dss_get_num_overlays();
+ for (i = 0; i < fbdev->num_overlays; i++)
+ fbdev->overlays[i] = omap_dss_get_overlay(i);
+
+ fbdev->num_managers = omap_dss_get_num_overlay_managers();
+ for (i = 0; i < fbdev->num_managers; i++)
+ fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+
+
+ /* gfx overlay should be the default one. find a display
+ * connected to that, and use it as default display */
+ ovl = omap_dss_get_overlay(0);
+ if (ovl->manager && ovl->manager->device) {
+ def_display = ovl->manager->device;
+ } else {
+ dev_err(&pdev->dev, "cannot find default display\n");
+ r = -EINVAL;
+ goto cleanup;
+ }
+
+ if (def_mode && strlen(def_mode) > 0) {
+ if (omapfb_parse_def_modes(fbdev))
+ dev_err(&pdev->dev, "cannot parse default modes\n");
+ }
+
+ r = omapfb_create_framebuffers(fbdev);
+ if (r)
+ goto cleanup;
+
+ for (i = 0; i < fbdev->num_managers; i++) {
+ struct omap_overlay_manager *mgr;
+ mgr = fbdev->managers[i];
+ r = mgr->apply(mgr);
+ if (r) {
+ dev_err(fbdev->dev, "failed to apply dispc config\n");
+ goto cleanup;
+ }
+ }
+
+ DBG("mgr->apply'ed\n");
+
+ r = def_display->enable(def_display);
+ if (r) {
+ dev_err(fbdev->dev, "Failed to enable display '%s'\n",
+ def_display->name);
+ goto cleanup;
+ }
+
+ /* set the update mode */
+ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
+ if (def_display->enable_te)
+ def_display->enable_te(def_display, 1);
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(def_display,
+ OMAP_DSS_UPDATE_AUTO);
+#else
+ if (def_display->enable_te)
+ def_display->enable_te(def_display, 0);
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(def_display,
+ OMAP_DSS_UPDATE_MANUAL);
+#endif
+ } else {
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(def_display,
+ OMAP_DSS_UPDATE_AUTO);
+ }
+
+ for (i = 0; i < fbdev->num_displays; i++) {
+ struct omap_dss_device *display = fbdev->displays[i];
+ u16 w, h;
+
+ if (!display->get_update_mode || !display->update)
+ continue;
+
+ if (display->get_update_mode(display) ==
+ OMAP_DSS_UPDATE_MANUAL) {
+
+ display->get_resolution(display, &w, &h);
+ display->update(display, 0, 0, w, h);
+ }
+ }
+
+ DBG("display->updated\n");
+
+ return 0;
+
+cleanup:
+ omapfb_free_resources(fbdev);
+err0:
+ dev_err(&pdev->dev, "failed to setup omapfb\n");
+ return r;
+}
+
+static int omapfb_remove(struct platform_device *pdev)
+{
+ struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+
+ /* FIXME: wait till completion of pending events */
+
+ omapfb_remove_sysfs(fbdev);
+
+ omapfb_free_resources(fbdev);
+
+ return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+ .probe = omapfb_probe,
+ .remove = omapfb_remove,
+ .driver = {
+ .name = "omapfb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init omapfb_init(void)
+{
+ DBG("omapfb_init\n");
+
+ if (platform_driver_register(&omapfb_driver)) {
+ printk(KERN_ERR "failed to register omapfb driver\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit omapfb_exit(void)
+{
+ DBG("omapfb_exit\n");
+ platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(mode, def_mode, charp, 0);
+module_param_named(vram, def_vram, charp, 0);
+module_param_named(rotate, def_rotate, int, 0);
+module_param_named(vrfb, def_vrfb, bool, 0);
+module_param_named(mirror, def_mirror, bool, 0);
+
+/* late_initcall to let panel/ctrl drivers loaded first.
+ * I guess better option would be a more dynamic approach,
+ * so that omapfb reacts to new panels when they are loaded */
+late_initcall(omapfb_init);
+/*module_init(omapfb_init);*/
+module_exit(omapfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
new file mode 100644
index 000000000000..23cb986052bd
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -0,0 +1,506 @@
+/*
+ * linux/drivers/video/omap2/omapfb-sysfs.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/omapfb.h>
+
+#include <mach/display.h>
+#include <mach/vrfb.h>
+
+#include "omapfb.h"
+
+static ssize_t show_rotate_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
+}
+
+static ssize_t store_rotate_type(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ enum omap_dss_rotation_type rot_type;
+ int r;
+
+ rot_type = simple_strtoul(buf, NULL, 0);
+
+ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
+ return -EINVAL;
+
+ lock_fb_info(fbi);
+
+ r = 0;
+ if (rot_type == ofbi->rotation_type)
+ goto out;
+
+ if (ofbi->region.size) {
+ r = -EBUSY;
+ goto out;
+ }
+
+ ofbi->rotation_type = rot_type;
+
+ /*
+ * Since the VRAM for this FB is not allocated at the moment we don't
+ * need to do any further parameter checking at this point.
+ */
+out:
+ unlock_fb_info(fbi);
+
+ return r ? r : count;
+}
+
+
+static ssize_t show_mirror(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
+}
+
+static ssize_t store_mirror(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ bool mirror;
+ int r;
+ struct fb_var_screeninfo new_var;
+
+ mirror = simple_strtoul(buf, NULL, 0);
+
+ if (mirror != 0 && mirror != 1)
+ return -EINVAL;
+
+ lock_fb_info(fbi);
+
+ ofbi->mirror = mirror;
+
+ memcpy(&new_var, &fbi->var, sizeof(new_var));
+ r = check_fb_var(fbi, &new_var);
+ if (r)
+ goto out;
+ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+
+ set_fb_fix(fbi);
+
+ r = omapfb_apply_changes(fbi, 0);
+ if (r)
+ goto out;
+
+ r = count;
+out:
+ unlock_fb_info(fbi);
+
+ return r;
+}
+
+static ssize_t show_overlays(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ ssize_t l = 0;
+ int t;
+
+ omapfb_lock(fbdev);
+ lock_fb_info(fbi);
+
+ for (t = 0; t < ofbi->num_overlays; t++) {
+ struct omap_overlay *ovl = ofbi->overlays[t];
+ int ovlnum;
+
+ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
+ if (ovl == fbdev->overlays[ovlnum])
+ break;
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+ t == 0 ? "" : ",", ovlnum);
+ }
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+ unlock_fb_info(fbi);
+ omapfb_unlock(fbdev);
+
+ return l;
+}
+
+static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
+ struct omap_overlay *ovl)
+{
+ int i, t;
+
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+ for (t = 0; t < ofbi->num_overlays; t++) {
+ if (ofbi->overlays[t] == ovl)
+ return ofbi;
+ }
+ }
+
+ return NULL;
+}
+
+static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
+ struct omap_overlay *ovl;
+ int num_ovls, r, i;
+ int len;
+ bool added = false;
+
+ num_ovls = 0;
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ len = len - 1;
+
+ omapfb_lock(fbdev);
+ lock_fb_info(fbi);
+
+ if (len > 0) {
+ char *p = (char *)buf;
+ int ovlnum;
+
+ while (p < buf + len) {
+ int found;
+ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ ovlnum = simple_strtoul(p, &p, 0);
+ if (ovlnum > fbdev->num_overlays) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ found = 0;
+ for (i = 0; i < num_ovls; ++i) {
+ if (ovls[i] == fbdev->overlays[ovlnum]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ ovls[num_ovls++] = fbdev->overlays[ovlnum];
+
+ p++;
+ }
+ }
+
+ for (i = 0; i < num_ovls; ++i) {
+ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
+ if (ofbi2 && ofbi2 != ofbi) {
+ dev_err(fbdev->dev, "overlay already in use\n");
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* detach unused overlays */
+ for (i = 0; i < ofbi->num_overlays; ++i) {
+ int t, found;
+
+ ovl = ofbi->overlays[i];
+
+ found = 0;
+
+ for (t = 0; t < num_ovls; ++t) {
+ if (ovl == ovls[t]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ DBG("detaching %d\n", ofbi->overlays[i]->id);
+
+ omapfb_overlay_enable(ovl, 0);
+
+ if (ovl->manager)
+ ovl->manager->apply(ovl->manager);
+
+ for (t = i + 1; t < ofbi->num_overlays; t++) {
+ ofbi->rotation[t-1] = ofbi->rotation[t];
+ ofbi->overlays[t-1] = ofbi->overlays[t];
+ }
+
+ ofbi->num_overlays--;
+ i--;
+ }
+
+ for (i = 0; i < num_ovls; ++i) {
+ int t, found;
+
+ ovl = ovls[i];
+
+ found = 0;
+
+ for (t = 0; t < ofbi->num_overlays; ++t) {
+ if (ovl == ofbi->overlays[t]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+ ofbi->rotation[ofbi->num_overlays] = 0;
+ ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+ added = true;
+ }
+
+ if (added) {
+ r = omapfb_apply_changes(fbi, 0);
+ if (r)
+ goto out;
+ }
+
+ r = count;
+out:
+ unlock_fb_info(fbi);
+ omapfb_unlock(fbdev);
+
+ return r;
+}
+
+static ssize_t show_overlays_rotate(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ ssize_t l = 0;
+ int t;
+
+ lock_fb_info(fbi);
+
+ for (t = 0; t < ofbi->num_overlays; t++) {
+ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+ t == 0 ? "" : ",", ofbi->rotation[t]);
+ }
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+ unlock_fb_info(fbi);
+
+ return l;
+}
+
+static ssize_t store_overlays_rotate(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int num_ovls = 0, r, i;
+ int len;
+ bool changed = false;
+ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ len = len - 1;
+
+ lock_fb_info(fbi);
+
+ if (len > 0) {
+ char *p = (char *)buf;
+
+ while (p < buf + len) {
+ int rot;
+
+ if (num_ovls == ofbi->num_overlays) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ rot = simple_strtoul(p, &p, 0);
+ if (rot < 0 || rot > 3) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (ofbi->rotation[num_ovls] != rot)
+ changed = true;
+
+ rotation[num_ovls++] = rot;
+
+ p++;
+ }
+ }
+
+ if (num_ovls != ofbi->num_overlays) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (changed) {
+ for (i = 0; i < num_ovls; ++i)
+ ofbi->rotation[i] = rotation[i];
+
+ r = omapfb_apply_changes(fbi, 0);
+ if (r)
+ goto out;
+
+ /* FIXME error handling? */
+ }
+
+ r = count;
+out:
+ unlock_fb_info(fbi);
+
+ return r;
+}
+
+static ssize_t show_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
+}
+
+static ssize_t store_size(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ unsigned long size;
+ int r;
+ int i;
+
+ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
+
+ lock_fb_info(fbi);
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->info.enabled) {
+ r = -EBUSY;
+ goto out;
+ }
+ }
+
+ if (size != ofbi->region.size) {
+ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
+ if (r) {
+ dev_err(dev, "realloc fbmem failed\n");
+ goto out;
+ }
+ }
+
+ r = count;
+out:
+ unlock_fb_info(fbi);
+
+ return r;
+}
+
+static ssize_t show_phys(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
+}
+
+static ssize_t show_virt(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+
+ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
+}
+
+static struct device_attribute omapfb_attrs[] = {
+ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, store_rotate_type),
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR,
+ show_overlays_rotate, store_overlays_rotate),
+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+};
+
+int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+{
+ int i;
+ int r;
+
+ DBG("create sysfs for fbs\n");
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ int t;
+ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
+ r = device_create_file(fbdev->fbs[i]->dev,
+ &omapfb_attrs[t]);
+
+ if (r) {
+ dev_err(fbdev->dev, "failed to create sysfs "
+ "file\n");
+ return r;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
+{
+ int i, t;
+
+ DBG("remove sysfs for fbs\n");
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
+ device_remove_file(fbdev->fbs[i]->dev,
+ &omapfb_attrs[t]);
+ }
+}
+
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
new file mode 100644
index 000000000000..83be0a7d9be0
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -0,0 +1,153 @@
+/*
+ * linux/drivers/video/omap2/omapfb.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+
+#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
+#define DEBUG
+#endif
+
+#include <mach/display.h>
+
+#ifdef DEBUG
+extern unsigned int omapfb_debug;
+#define DBG(format, ...) \
+ if (omapfb_debug) \
+ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
+
+/* max number of overlays to which a framebuffer data can be direct */
+#define OMAPFB_MAX_OVL_PER_FB 3
+
+struct omapfb2_mem_region {
+ u32 paddr;
+ void __iomem *vaddr;
+ struct vrfb vrfb;
+ unsigned long size;
+ u8 type; /* OMAPFB_PLANE_MEM_* */
+ bool alloc; /* allocated by the driver */
+ bool map; /* kernel mapped by the driver */
+};
+
+/* appended to fb_info */
+struct omapfb_info {
+ int id;
+ struct omapfb2_mem_region region;
+ atomic_t map_count;
+ int num_overlays;
+ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
+ struct omapfb2_device *fbdev;
+ enum omap_dss_rotation_type rotation_type;
+ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
+ bool mirror;
+};
+
+struct omapfb2_device {
+ struct device *dev;
+ struct mutex mtx;
+
+ u32 pseudo_palette[17];
+
+ int state;
+
+ unsigned num_fbs;
+ struct fb_info *fbs[10];
+
+ unsigned num_displays;
+ struct omap_dss_device *displays[10];
+ unsigned num_overlays;
+ struct omap_overlay *overlays[10];
+ unsigned num_managers;
+ struct omap_overlay_manager *managers[10];
+};
+
+struct omapfb_colormode {
+ enum omap_color_mode dssmode;
+ u32 bits_per_pixel;
+ u32 nonstd;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+};
+
+u32 omapfb_get_region_paddr(struct omapfb_info *ofbi);
+void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi);
+
+void set_fb_fix(struct fb_info *fbi);
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
+int omapfb_apply_changes(struct fb_info *fbi, int init);
+int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
+
+int omapfb_create_sysfs(struct omapfb2_device *fbdev);
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
+
+int omapfb_mode_to_timings(const char *mode_str,
+ struct omap_video_timings *timings, u8 *bpp);
+
+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+ struct fb_var_screeninfo *var);
+
+/* find the display connected to this fb, if any */
+static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
+{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int i;
+
+ /* XXX: returns the display connected to first attached overlay */
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->manager)
+ return ofbi->overlays[i]->manager->device;
+ }
+
+ return NULL;
+}
+
+static inline void omapfb_lock(struct omapfb2_device *fbdev)
+{
+ mutex_lock(&fbdev->mtx);
+}
+
+static inline void omapfb_unlock(struct omapfb2_device *fbdev)
+{
+ mutex_unlock(&fbdev->mtx);
+}
+
+static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
+ int enable)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+ info.enabled = enable;
+ return ovl->set_overlay_info(ovl, &info);
+}
+
+#endif
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b1ccc04f3c9a..29fd42631b19 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -187,7 +187,7 @@ config EP93XX_WATCHDOG
config OMAP_WATCHDOG
tristate "OMAP Watchdog"
- depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
+ depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4
help
Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430 watchdog. Say 'Y'
here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430 watchdog timer.
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 3ed571a2ab18..b1b23bfd28a9 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -293,17 +293,20 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
wdev->omap_wdt_users = 0;
wdev->mem = mem;
- wdev->ick = clk_get(&pdev->dev, "ick");
- if (IS_ERR(wdev->ick)) {
- ret = PTR_ERR(wdev->ick);
- wdev->ick = NULL;
- goto err_clk;
- }
- wdev->fck = clk_get(&pdev->dev, "fck");
- if (IS_ERR(wdev->fck)) {
- ret = PTR_ERR(wdev->fck);
- wdev->fck = NULL;
- goto err_clk;
+ /* FIXME: Enable this ones correct clk nodes available */
+ if (!cpu_is_omap44xx()) {
+ wdev->ick = clk_get(&pdev->dev, "ick");
+ if (IS_ERR(wdev->ick)) {
+ ret = PTR_ERR(wdev->ick);
+ wdev->ick = NULL;
+ goto err_clk;
+ }
+ wdev->fck = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(wdev->fck)) {
+ ret = PTR_ERR(wdev->fck);
+ wdev->fck = NULL;
+ goto err_clk;
+ }
}
wdev->base = ioremap(res->start, res->end - res->start + 1);
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl.h
index 0dc80ef24975..99f57fae1f01 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl.h
@@ -22,8 +22,8 @@
*
*/
-#ifndef __TWL4030_H_
-#define __TWL4030_H_
+#ifndef __TWL_H_
+#define __TWL_H_
/*
* Using the twl4030 core we address registers using a pair
@@ -66,20 +66,166 @@
#define TWL4030_MODULE_RTC 0x14
#define TWL4030_MODULE_SECURED_REG 0x15
+#ifdef CONFIG_TWL4030_CORE
+#define TWL_MODULE_USB TWL4030_MODULE_USB
+#define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE
+#define TWL_MODULE_GPIO TWL4030_MODULE_GPIO
+#define TWL_MODULE_INTBR TWL4030_MODULE_INTBR
+#define TWL_MODULE_PIH TWL4030_MODULE_PIH
+#define TWL_MODULE_TEST TWL4030_MODULE_TEST
+#define TWL_MODULE_KEYPAD TWL4030_MODULE_KEYPAD
+#define TWL_MODULE_MADC TWL4030_MODULE_MADC
+#define TWL_MODULE_INTERRUPTS TWL4030_MODULE_INTERRUPTS
+#define TWL_MODULE_LED TWL4030_MODULE_LED
+#define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE
+#define TWL_MODULE_PRECHARGE TWL4030_MODULE_PRECHARGE
+#define TWL_MODULE_PWM0 TWL4030_MODULE_PWM0
+#define TWL_MODULE_PWM1 TWL4030_MODULE_PWM1
+#define TWL_MODULE_PWMA TWL4030_MODULE_PWMA
+#define TWL_MODULE_PWMB TWL4030_MODULE_PWMB
+#define TWL_MODULE_BACKUP TWL4030_MODULE_BACKUP
+#define TWL_MODULE_INT TWL4030_MODULE_INT
+#define TWL_MODULE_PM_MASTER TWL4030_MODULE_PM_MASTER
+#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
+#define TWL_MODULE_PM_SLAVE_LDO TWL_MODULE_PM_RECEIVER
+#define TWL_MODULE_RTC TWL4030_MODULE_RTC
+#define TWL_MODULE_SECURED_REG TWL4030_MODULE_SECURED_REG
+
+#define GPIO_INTR_OFFSET 0
+#define KEYPAD_INTR_OFFSET 1
+#define BCI_INTR_OFFSET 2
+#define MADC_INTR_OFFSET 3
+#define USB_INTR_OFFSET 4
+#define BCI_PRES_INTR_OFFSET 9
+#define USB_PRES_INTR_OFFSET 10
+#define RTC_INTR_OFFSET 11
+#endif
+
+/*
+ * Using the twl6030 core we address registers using a pair
+ * { module id, relative register offset }
+ * which that core then maps to the relevant
+ * { i2c slave, absolute register address }
+ *
+ * The module IDs are meaningful only to the twl6030 core code,
+ * which uses them as array indices to look up the first register
+ * address each module uses within a given i2c slave.
+ */
+/* subchip/slave 0 0x48 - POWER */
+#define TWL6030_MODULE_RTC 0x00
+#define TWL6030_MODULE_MEM 0x01
+#define TWL6030_MODULE_PM_MASTER 0x02
+#define TWL6030_MODULE_PM_SLAVE_MISC 0x03
+#define TWL6030_MODULE_PM_SLAVE_SMPS 0x04
+#define TWL6030_MODULE_PM_SLAVE_LDO 0x05
+#define TWL6030_MODULE_PM_SLAVE_RES 0x06
+#define TWL6030_MODULE_PM_MISC 0x07
+#define TWL6030_MODULE_PM_PUPD 0x08
+
+/* subchip/slave 1 0x49 - FEATURE */
+#define TWL6030_MODULE_USB 0x09
+#define TWL6030_MODULE_GPADC_CTRL 0x0A
+#define TWL6030_MODULE_GPADC_RT 0x0B
+#define TWL6030_MODULE_GPADC 0x0C
+#define TWL6030_MODULE_AUX 0x0D
+#define TWL6030_MODULE_PWM 0x0E
+#define TWL6030_MODULE_GASGAUGE 0x0F
+#define TWL6030_MODULE_PIH 0x10
+#define TWL6030_MODULE_CHARGER 0x11
+
+/* subchip/slave 2 0x4A - DFT */
+#define TWL6030_MODULE_DIEID 0x12
+
+/* subchip/slave 3 0x4B - AUDIO */
+#define TWL6030_MODULE_AUDIO 0x13
+
+#ifdef CONFIG_TWL6030_CORE
+#define TWL_MODULE_RTC TWL6030_MODULE_RTC
+#define TWL_MODULE_MEM TWL6030_MODULE_MEM
+#define TWL_MODULE_PM_MASTER TWL6030_MODULE_PM_MASTER
+#define TWL_MODULE_PM_SLAVE_MISC TWL6030_MODULE_PM_SLAVE_MISC
+#define TWL_MODULE_PM_SLAVE_SMPS TWL6030_MODULE_PM_SLAVE_SMP
+#define TWL_MODULE_PM_SLAVE_LDO TWL6030_MODULE_PM_SLAVE_LDO
+#define TWL_MODULE_PM_SLAVE_RES TWL6030_MODULE_PM_SLAVE_RES
+#define TWL_MODULE_PM_MISC TWL6030_MODULE_PM_MISC
+#define TWL_MODULE_PM_PUPD TWL6030_MODULE_PM_PUPD
+#define TWL_MODULE_USB TWL6030_MODULE_USB
+#define TWL_MODULE_GPADC_CTRL TWL6030_MODULE_GPADC_CTRL
+#define TWL_MODULE_GPADC_RT TWL6030_MODULE_GPADC_RT
+#define TWL_MODULE_GPADC TWL6030_MODULE_GPADC
+#define TWL_MODULE_AUX TWL6030_MODULE_AUX
+#define TWL_MODULE_PWM TWL6030_MODULE_PWM
+#define TWL_MODULE_GASGAUGE TWL6030_MODULE_GASGAUGE
+#define TWL_MODULE_PIH TWL6030_MODULE_PIH
+#define TWL_MODULE_CHARGER TWL6030_MODULE_CHARGER
+#define TWL_MODULE_DIEID TWL6030_MODULE_DIEID
+#define TWL_MODULE_AUDIO TWL6030_MODULE_AUDIO
+
+/* INT register offsets */
+#define REG_INT_STS_A 0x00
+#define REG_INT_STS_B 0x01
+#define REG_INT_STS_C 0x02
+
+#define REG_INT_MSK_LINE_A 0x03
+#define REG_INT_MSK_LINE_B 0x04
+#define REG_INT_MSK_LINE_C 0x05
+
+#define REG_INT_MSK_STS_A 0x06
+#define REG_INT_MSK_STS_B 0x07
+#define REG_INT_MSK_STS_C 0x08
+
+#define TWL6030_PWR_INT_MASK 0x0F
+#define TWL6030_RTC_INT_MASK 0x30
+#define TWL6030_HOTDIE_INT_MASK 0x40
+#define TWL6030_SMPSLDOA_INT_MASK 0x80
+
+#define TWL6030_SMPSLDOB_INT_MASK 0x03
+#define TWL6030_SIMDETECT_INT_MASK 0x04
+#define TWL6030_MMCDETECT_INT_MASK 0x08
+#define TWL6030_GPADC_INT_MASK 0x60
+#define TWL6030_GASGAUGE_INT_MASK 0x80
+
+#define TWL6030_USBOTG_INT_MASK 0x0F
+#define TWL6030_CHARGER_CTRL_INT_MASK 0x10
+#define TWL6030_CHARGER_FAULT_INT_MASK 0x60
+
+/*
+ * Offset from TWL6030_IRQ_BASE / pdata->irq_base
+ */
+#define PWR_INTR_OFFSET 0
+#define RTC_INTR_OFFSET 1
+#define HOTDIE_INTR_OFFSET 2
+#define SMPSLDO_INTR_OFFSET 3
+#define SIMDETECT_INTR_OFFSET 4
+#define MMCDETECT_INTR_OFFSET 5
+#define GPADC_INTR_OFFSET 6
+#define GASGAUGE_INTR_OFFSET 7
+#define USBOTG_INTR_OFFSET 8
+#define CHARGER_INTR_OFFSET 9
+#define RSV_INTR_OFFSET 0
+
+#define BCI_PRES_INTR_OFFSET 9
+#define MADC_INTR_OFFSET 6
+#define BCI_INTR_OFFSET 8
+#define USB_PRES_INTR_OFFSET 8
+#define USB_INTR_OFFSET 8
+#define GPIO_INTR_OFFSET 0 /* NOT SUPPORTED IN TWL6030 */
+#define KEYPAD_INTR_OFFSET 0 /* ADDED FOR COMPILATION ONLY */
+#endif
/*
* Read and write single 8-bit registers
*/
-int twl4030_i2c_write_u8(u8 mod_no, u8 val, u8 reg);
-int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
+int twl_i2c_write_u8(u8 mod_no, u8 val, u8 reg);
+int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
/*
* Read and write several 8-bit registers at once.
*
- * IMPORTANT: For twl4030_i2c_write(), allocate num_bytes + 1
+ * IMPORTANT: For twl_i2c_write(), allocate num_bytes + 1
* for the value, and populate your data starting at offset 1.
*/
-int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
-int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
/*----------------------------------------------------------------------*/
@@ -216,6 +362,7 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
#define TWL4030_INT_PWR_EDR2 0x6
#define TWL4030_INT_PWR_SIH_CTRL 0x7
+
/*----------------------------------------------------------------------*/
/* Power bus message definitions */
@@ -257,21 +404,27 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
*/
#define MSG_BROADCAST(devgrp, grp, type, type2, state) \
- ( (devgrp) << 13 | 1 << 12 | (grp) << 9 | (type2) << 7 \
+ ((devgrp) << 13 | 1 << 12 | (grp) << 9 | (type2) << 7 \
| (type) << 4 | (state))
#define MSG_SINGULAR(devgrp, id, state) \
((devgrp) << 13 | 0 << 12 | (id) << 4 | (state))
+#define MSG_BROADCAST_ALL(devgrp, state) \
+ ((devgrp) << 5 | (state))
+
+#define MSG_BROADCAST_REF MSG_BROADCAST_ALL
+#define MSG_BROADCAST_PROV MSG_BROADCAST_ALL
+#define MSG_BROADCAST__CLK_RST MSG_BROADCAST_ALL
/*----------------------------------------------------------------------*/
-struct twl4030_bci_platform_data {
+struct twl_bci_platform_data {
int *battery_tmp_tbl;
unsigned int tblsize;
};
/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
-struct twl4030_gpio_platform_data {
+struct twl_gpio_platform_data {
int gpio_base;
unsigned irq_base, irq_end;
@@ -298,11 +451,11 @@ struct twl4030_gpio_platform_data {
unsigned gpio, unsigned ngpio);
};
-struct twl4030_madc_platform_data {
+struct twl_madc_platform_data {
int irq_line;
};
-struct twl4030_keypad_data {
+struct twl_keypad_data {
int rows;
int cols;
int *keymap;
@@ -311,35 +464,49 @@ struct twl4030_keypad_data {
unsigned int rep:1;
};
-enum twl4030_usb_mode {
+enum twl_usb_mode {
T2_USB_MODE_ULPI = 1,
T2_USB_MODE_CEA2011_3PIN = 2,
};
-struct twl4030_usb_data {
- enum twl4030_usb_mode usb_mode;
+struct twl_usb_data {
+ enum twl_usb_mode usb_mode;
};
-struct twl4030_platform_data {
- unsigned irq_base, irq_end;
- struct twl4030_bci_platform_data *bci;
- struct twl4030_gpio_platform_data *gpio;
- struct twl4030_madc_platform_data *madc;
- struct twl4030_keypad_data *keypad;
- struct twl4030_usb_data *usb;
+struct twl_codec_data {
+ /* twl6030 */
+ int audpwron_gpio; /* audio power-on gpio */
+ int naudint_irq; /* audio interrupt */
+};
- /* LDO regulators */
+struct twl_platform_data {
+ unsigned irq_base, irq_end;
+ struct twl_bci_platform_data *bci;
+ struct twl_gpio_platform_data *gpio;
+ struct twl_madc_platform_data *madc;
+ struct twl_keypad_data *keypad;
+ struct twl_usb_data *usb;
+ struct twl_codec_data *codec;
+
+ /* LDO regulators common to TWL4030/TWL6030 */
struct regulator_init_data *vdac;
+ struct regulator_init_data *vaux1;
+ struct regulator_init_data *vaux2;
+ struct regulator_init_data *vaux3;
+ /* TWL4030 LDO regulators */
struct regulator_init_data *vpll1;
struct regulator_init_data *vpll2;
struct regulator_init_data *vmmc1;
struct regulator_init_data *vmmc2;
struct regulator_init_data *vsim;
- struct regulator_init_data *vaux1;
- struct regulator_init_data *vaux2;
- struct regulator_init_data *vaux3;
struct regulator_init_data *vaux4;
-
+ /* TWL6030 LDO regulators */
+ struct regulator_init_data *vmmc;
+ struct regulator_init_data *vpp;
+ struct regulator_init_data *vusim;
+ struct regulator_init_data *vana;
+ struct regulator_init_data *vcxio;
+ struct regulator_init_data *vusb;
/* REVISIT more to come ... _nothing_ should be hard-wired */
};
@@ -373,6 +540,7 @@ int twl4030_sih_setup(int module);
* VIO is generally fixed.
*/
+/* TWL4030 SMPS/LDO's */
/* EXTERNAL dc-to-dc buck converters */
#define TWL4030_REG_VDD1 0
#define TWL4030_REG_VDD2 1
@@ -399,4 +567,36 @@ int twl4030_sih_setup(int module);
#define TWL4030_REG_VUSB1V8 18
#define TWL4030_REG_VUSB3V1 19
+/* TWL6030 SMPS/LDO's */
+/* EXTERNAL dc-to-dc buck convertor contollable via SR */
+#define TWL6030_REG_VDD1 0
+#define TWL6030_REG_VDD2 1
+#define TWL6030_REG_VDD3 2
+
+/* Non SR compliant dc-to-dc buck convertors */
+#define TWL6030_REG_VMEM 3
+#define TWL6030_REG_V2V1 4
+#define TWL6030_REG_V1V29 5
+#define TWL6030_REG_V1V8 6
+
+/* EXTERNAL LDOs */
+#define TWL6030_REG_VAUX1_6030 7
+#define TWL6030_REG_VAUX2_6030 8
+#define TWL6030_REG_VAUX3_6030 9
+#define TWL6030_REG_VMMC 10
+#define TWL6030_REG_VPP 11
+#define TWL6030_REG_VUSIM 12
+#define TWL6030_REG_VANA 13
+#define TWL6030_REG_VCXIO 14
+#define TWL6030_REG_VDAC 15
+#define TWL6030_REG_VUSB 16
+
+/* INTERNAL LDOs */
+#define TWL6030_REG_VRTC 17
+
+int twl_int_mask_reset(u8 bit_mask, u8 offset);
+int twl_int_mask_set(u8 bit_mask, u8 offset);
+int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+int twl_exit_irq(void);
+
#endif /* End of __TWL4030_H */
diff --git a/include/linux/i2c/twl6030-gpadc.h b/include/linux/i2c/twl6030-gpadc.h
new file mode 100644
index 000000000000..4e2207eaaa6c
--- /dev/null
+++ b/include/linux/i2c/twl6030-gpadc.h
@@ -0,0 +1,110 @@
+/*
+ * include/linux/i2c/twl6030-gpadc.h
+ *
+ * TWL6030 GPADC module driver header
+ *
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Nishant Kamat <nskamat@ti.com>
+ *
+ * Based on twl4030-madc.h
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@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 _TWL6030_GPADC_H
+#define _TWL6030_GPADC_H
+
+struct twl6030_gpadc_conversion_method {
+ u8 sel;
+ u8 rbase;
+ u8 ctrl;
+ u8 enable;
+};
+
+#define TWL6030_GPADC_MAX_CHANNELS 17
+
+struct twl6030_gpadc_request {
+ u16 channels;
+ u16 do_avg;
+ u16 method;
+ u16 type;
+ int active;
+ int result_pending;
+ int rbuf[TWL6030_GPADC_MAX_CHANNELS];
+ void (*func_cb)(int len, int channels, int *buf);
+};
+
+enum conversion_methods {
+ TWL6030_GPADC_RT,
+ TWL6030_GPADC_SW1,
+ TWL6030_GPADC_SW2,
+ TWL6030_GPADC_NUM_METHODS
+};
+
+enum sample_type {
+ TWL6030_GPADC_WAIT,
+ TWL6030_GPADC_IRQ_ONESHOT,
+ TWL6030_GPADC_IRQ_REARM
+};
+
+#define TWL6030_GPADC_CTRL 0x00 /* 0x2e */
+
+#define TWL6030_GPADC_RTSELECT_LSB 0x02 /* 0x30 */
+#define TWL6030_GPADC_RTSELECT_ISB 0x03
+#define TWL6030_GPADC_RTSELECT_MSB 0x04
+
+#define TWL6030_GPADC_CTRL_P1 0x05
+#define TWL6030_GPADC_CTRL_P2 0x06
+#define TWL6030_GPADC_CTRL_P1_SP1 (1 << 3)
+#define TWL6030_GPADC_CTRL_P1_EOCRT (1 << 2)
+#define TWL6030_GPADC_CTRL_P1_EOCP1 (1 << 1)
+#define TWL6030_GPADC_CTRL_P1_BUSY (1 << 0)
+
+#define TWL6030_GPADC_CTRL_P2_SP2 (1 << 2)
+#define TWL6030_GPADC_CTRL_P2_EOCP2 (1 << 1)
+#define TWL6030_GPADC_CTRL_P1_BUSY (1 << 0)
+
+#define TWL6030_GPADC_EOC_SW (1 << 1)
+#define TWL6030_GPADC_BUSY (1 << 0)
+
+#define TWL6030_GPADC_RTCH0_LSB (0x07)
+#define TWL6030_GPADC_GPCH0_LSB (0x29)
+
+/* Fixed channels */
+#define TWL6030_GPADC_CTRL_TEMP1_EN (1 << 0) /* input ch 1 */
+#define TWL6030_GPADC_CTRL_TEMP2_EN (1 << 1) /* input ch 4 */
+#define TWL6030_GPADC_CTRL_SCALER_EN (1 << 2) /* input ch 2 */
+#define TWL6030_GPADC_CTRL_SCALER_DIV4 (1 << 3)
+#define TWL6030_GPADC_CTRL_SCALER_EN_CH11 (1 << 4) /* input ch 11 */
+#define TWL6030_GPADC_CTRL_TEMP1_EN_MONITOR (1 << 5)
+#define TWL6030_GPADC_CTRL_TEMP2_EN_MONITOR (1 << 6)
+#define TWL6030_GPADC_CTRL_ISOURCE_EN (1 << 7)
+
+
+#define TWL6030_GPADC_IOC_MAGIC '`'
+#define TWL6030_GPADC_IOCX_ADC_RAW_READ _IO(TWL6030_GPADC_IOC_MAGIC, 0)
+
+struct twl6030_gpadc_user_parms {
+ int channel;
+ int status;
+ u16 result;
+};
+
+int twl6030_gpadc_conversion(struct twl6030_gpadc_request *conv);
+
+#endif
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 35e7df1e9f30..1ac57e522a1f 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -50,6 +50,9 @@
* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
* registered first in an shared interrupt is considered for
* performance reasons)
+ * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
+ * Used by threaded interrupts which need to keep the
+ * irq line disabled until the threaded handler has been run.
*/
#define IRQF_DISABLED 0x00000020
#define IRQF_SAMPLE_RANDOM 0x00000040
@@ -59,6 +62,7 @@
#define IRQF_PERCPU 0x00000400
#define IRQF_NOBALANCING 0x00000800
#define IRQF_IRQPOLL 0x00001000
+#define IRQF_ONESHOT 0x00002000
/*
* Bits used by threaded handlers:
diff --git a/include/linux/irq.h b/include/linux/irq.h
index cb2e77a3f7f7..5e7c6ee8c35c 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -69,6 +69,7 @@ typedef void (*irq_flow_handler_t)(unsigned int irq,
#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
#define IRQ_AFFINITY_SET 0x02000000 /* IRQ affinity was set from userspace*/
#define IRQ_SUSPENDED 0x04000000 /* IRQ has gone through suspend sequence */
+#define IRQ_ONESHOT 0x08000000 /* IRQ is not unmasked after hardirq */
#ifdef CONFIG_IRQ_PER_CPU
# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/include/linux/omapfb.h
index 7b74d1255e0b..56991944364f 100644
--- a/arch/arm/plat-omap/include/mach/omapfb.h
+++ b/include/linux/omapfb.h
@@ -24,6 +24,8 @@
#ifndef __OMAPFB_H
#define __OMAPFB_H
+#include <linux/fb.h>
+
#include <asm/ioctl.h>
#include <asm/types.h>
@@ -50,6 +52,10 @@
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
+#define OMAPFB_WAITFORVSYNC OMAP_IO(57)
+#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
+#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
+#define OMAPFB_WAITFORGO OMAP_IO(60)
#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
@@ -90,6 +96,13 @@ enum omapfb_color_format {
OMAPFB_COLOR_CLUT_1BPP,
OMAPFB_COLOR_RGB444,
OMAPFB_COLOR_YUY422,
+
+ OMAPFB_COLOR_ARGB16,
+ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */
+ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */
+ OMAPFB_COLOR_ARGB32,
+ OMAPFB_COLOR_RGBA32,
+ OMAPFB_COLOR_RGBX32,
};
struct omapfb_update_window {
@@ -161,11 +174,30 @@ enum omapfb_update_mode {
OMAPFB_MANUAL_UPDATE
};
+struct omapfb_memory_read {
+ __u16 x;
+ __u16 y;
+ __u16 w;
+ __u16 h;
+ size_t buffer_size;
+ void __user *buffer;
+};
+
+struct omapfb_ovl_colormode {
+ __u8 overlay_idx;
+ __u8 mode_idx;
+ __u32 bits_per_pixel;
+ __u32 nonstd;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+};
+
#ifdef __KERNEL__
#include <linux/completion.h>
#include <linux/interrupt.h>
-#include <linux/fb.h>
#include <linux/mutex.h>
#include <mach/board.h>
@@ -256,7 +288,7 @@ struct lcd_ctrl_extif {
void (*read_data) (void *buf, unsigned int len);
void (*write_data) (const void *buf, unsigned int len);
void (*transfer_area) (int width, int height,
- void (callback)(void * data), void *data);
+ void (callback)(void *data), void *data);
int (*setup_tearsync) (unsigned pin_cnt,
unsigned hs_pulse_time, unsigned vs_pulse_time,
int hs_pol_inv, int vs_pol_inv, int div);
@@ -276,10 +308,15 @@ typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
void *fbi);
struct omapfb_mem_region {
- dma_addr_t paddr;
- void *vaddr;
+ u32 paddr;
+ void __iomem *vaddr;
unsigned long size;
u8 type; /* OMAPFB_PLANE_MEM_* */
+ enum omapfb_color_format format;/* OMAPFB_COLOR_* */
+ unsigned format_used:1; /* Must be set when format is set.
+ * Needed b/c of the badly chosen 0
+ * base for OMAPFB_COLOR_* values
+ */
unsigned alloc:1; /* allocated by the driver */
unsigned map:1; /* kernel mapped by the driver */
};
@@ -332,7 +369,7 @@ struct lcd_ctrl {
enum omapfb_state {
OMAPFB_DISABLED = 0,
- OMAPFB_SUSPENDED= 99,
+ OMAPFB_SUSPENDED = 99,
OMAPFB_ACTIVE = 100
};
@@ -346,7 +383,7 @@ struct omapfb_plane_struct {
struct omapfb_device {
int state;
int ext_lcdc; /* Using external
- LCD controller */
+ LCD controller */
struct mutex rqueue_mutex;
int palette_size;
@@ -356,7 +393,7 @@ struct omapfb_device {
const struct lcd_ctrl *ctrl; /* LCD controller */
const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
- interface */
+ interface */
struct device *dev;
struct fb_var_screeninfo new_var; /* for mode changes */
@@ -376,6 +413,8 @@ extern struct lcd_ctrl omap1_lcd_ctrl;
extern struct lcd_ctrl omap2_disp_ctrl;
#endif
+extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
+
extern void omapfb_reserve_sdram(void);
extern void omapfb_register_panel(struct lcd_panel *panel);
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 74f16876f38d..3a107dba2a6c 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -554,6 +554,7 @@ struct v4l2_framebuffer {
#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
+#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080
/* Flags for the 'flags' field. */
#define V4L2_FBUF_FLAG_PRIMARY 0x0001
#define V4L2_FBUF_FLAG_OVERLAY 0x0002
@@ -561,6 +562,7 @@ struct v4l2_framebuffer {
#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
+#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040
struct v4l2_clip {
struct v4l2_rect c;
@@ -899,9 +901,11 @@ enum v4l2_colorfx {
V4L2_COLORFX_SEPIA = 2,
};
#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
+#define V4L2_CID_ROTATE (V4L2_CID_BASE+33)
+#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+34)
/* last CID + 1 */
-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+33)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+35)
/* MPEG-class control IDs defined by V4L2 */
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1213,6 +1217,18 @@ struct v4l2_hw_freq_seek {
};
/*
+ * Color conversion
+ * User needs to pass pointer to color conversion matrix
+ * defined by hardware
+ */
+struct v4l2_color_space_conversion {
+ __s32 coefficients[3][3];
+ __s32 const_factor;
+ __s32 input_offs[3];
+ __s32 output_offs[3];
+};
+
+/*
* A U D I O
*/
struct v4l2_audio {
@@ -1551,6 +1567,9 @@ struct v4l2_dbg_chip_ident {
#endif
#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
+#define VIDIOC_S_COL_SPC_CONV _IOW('V', 83, struct v4l2_color_space_conversion)
+#define VIDIOC_G_COL_SPC_CONV _IOR('V', 84, struct v4l2_color_space_conversion)
+
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 7a4529defa88..1e0698248bb0 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -242,6 +242,11 @@ struct v4l2_ioctl_ops {
/* For other private ioctls */
long (*vidioc_default) (struct file *file, void *fh,
int cmd, void *arg);
+
+ int (*vidioc_s_color_space_conv)(struct file *file, void *fh,
+ struct v4l2_color_space_conversion *a);
+ int (*vidioc_g_color_space_conv)(struct file *file, void *fh,
+ struct v4l2_color_space_conversion *a);
};
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 352d7eee9b6d..9239cb0c14c3 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -30,6 +30,7 @@ struct snd_pcm_substream;
#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */
#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */
#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
+#define SND_SOC_DAIFMT_PDM 6 /* Pulse density modulation */
/* left and right justified also known as MSB and LSB respectively */
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 13c68e71b726..b08c0d24f202 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -382,7 +382,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
- if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+
+ if (unlikely(desc->status & IRQ_ONESHOT))
+ desc->status |= IRQ_MASKED;
+ else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
desc->chip->unmask(irq);
out_unlock:
spin_unlock(&desc->lock);
@@ -478,8 +481,13 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
kstat_incr_irqs_this_cpu(irq, desc);
/* Start handling the irq */
- if (desc->chip->ack)
- desc->chip->ack(irq);
+ if (unlikely(desc->status & IRQ_ONESHOT)) {
+ desc->status |= IRQ_MASKED;
+ mask_ack_irq(desc, irq);
+ } else {
+ if (desc->chip->ack)
+ desc->chip->ack(irq);
+ }
/* Mark the IRQ currently in progress.*/
desc->status |= IRQ_INPROGRESS;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 0ec9ed831737..561187db8f96 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -436,6 +436,16 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
return ret;
}
+/*
+ * Default primary interrupt handler for threaded interrupts. Is
+ * assigned as primary handler when request_threaded_irq is called
+ * with handler == NULL. Useful for oneshot interrupts.
+ */
+static irqreturn_t irq_default_primary_handler(int irq, void *dev_id)
+{
+ return IRQ_WAKE_THREAD;
+}
+
static int irq_wait_for_interrupt(struct irqaction *action)
{
while (!kthread_should_stop()) {
@@ -451,6 +461,21 @@ static int irq_wait_for_interrupt(struct irqaction *action)
return -1;
}
+/*
+ * Oneshot interrupts keep the irq line masked until the threaded
+ * handler finished. unmask if the interrupt has not been disabled and
+ * is marked MASKED.
+ */
+static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
+{
+ spin_lock_irq(&desc->lock);
+ if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
+ desc->status &= ~IRQ_MASKED;
+ desc->chip->unmask(irq);
+ }
+ spin_unlock_irq(&desc->lock);
+}
+
#ifdef CONFIG_SMP
/*
* Check whether we need to change the affinity of the interrupt thread.
@@ -492,7 +517,7 @@ static int irq_thread(void *data)
struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
struct irqaction *action = data;
struct irq_desc *desc = irq_to_desc(action->irq);
- int wake;
+ int wake, oneshot = desc->status & IRQ_ONESHOT;
sched_setscheduler(current, SCHED_FIFO, &param);
current->irqaction = action;
@@ -518,6 +543,9 @@ static int irq_thread(void *data)
spin_unlock_irq(&desc->lock);
action->thread_fn(action->irq, action->dev_id);
+
+ if (oneshot)
+ irq_finalize_oneshot(action->irq, desc);
}
wake = atomic_dec_and_test(&desc->threads_active);
@@ -590,6 +618,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
rand_initialize_irq(irq);
}
+ /* Oneshot interrupts are not allowed with shared */
+ if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))
+ return -EINVAL;
+
/*
* Threaded handler ?
*/
@@ -662,9 +694,12 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
desc->status |= IRQ_PER_CPU;
#endif
- desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
+ desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |
IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
+ if (new->flags & IRQF_ONESHOT)
+ desc->status |= IRQ_ONESHOT;
+
if (!(desc->status & IRQ_NOAUTOEN)) {
desc->depth = 0;
desc->status &= ~IRQ_DISABLED;
@@ -884,6 +919,8 @@ EXPORT_SYMBOL(free_irq);
* @irq: Interrupt line to allocate
* @handler: Function to be called when the IRQ occurs.
* Primary handler for threaded interrupts
+ * If NULL and thread_fn != NULL the default
+ * primary handler is installed
* @thread_fn: Function called from the irq handler thread
* If NULL, no irq thread is created
* @irqflags: Interrupt type flags
@@ -963,8 +1000,12 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
if (desc->status & IRQ_NOREQUEST)
return -EINVAL;
- if (!handler)
- return -EINVAL;
+
+ if (!handler) {
+ if (!thread_fn)
+ return -EINVAL;
+ handler = irq_default_primary_handler;
+ }
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bbc97fd76648..987a358714a3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -25,6 +25,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TWL4030 if TWL4030_CORE
+ select SND_SOC_ABE_TWL6030 if TWL6030_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
select SND_SOC_WM8350 if MFD_WM8350
@@ -114,6 +115,9 @@ config SND_SOC_TLV320AIC3X
config SND_SOC_TWL4030
tristate
+config SND_SOC_ABE_TWL6030
+ tristate
+
config SND_SOC_UDA134X
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8b7530546f4d..ec2e5ee68b17 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -13,6 +13,7 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-twl4030-objs := twl4030.o
+snd-soc-abe-twl6030-objs := abe-twl6030.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wm8350-objs := wm8350.o
@@ -50,6 +51,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
+obj-$(CONFIG_SND_SOC_ABE_TWL6030) += snd-soc-abe-twl6030.o abe/
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
diff --git a/sound/soc/codecs/abe-twl6030.c b/sound/soc/codecs/abe-twl6030.c
new file mode 100644
index 000000000000..c1ad80e38189
--- /dev/null
+++ b/sound/soc/codecs/abe-twl6030.c
@@ -0,0 +1,1377 @@
+/*
+ * ALSA SoC ABE-TWL6030 codec driver
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "twl6030.h"
+#include "abe-twl6030.h"
+#include "abe/abe_main.h"
+
+#define ABE_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+/* codec private data */
+struct twl6030_data {
+ struct snd_soc_codec codec;
+ int audpwron;
+ int naudint;
+ int codec_powered;
+ int pll;
+ int non_lp;
+ unsigned int sysclk;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
+ struct completion ready;
+ int configure;
+};
+
+/*
+ * twl6030 register cache & default register settings
+ */
+static const u8 twl6030_reg[TWL6030_CACHEREGNUM] = {
+ 0x00, /* not used 0x00 */
+ 0x4B, /* TWL6030_ASICID (ro) 0x01 */
+ 0x00, /* TWL6030_ASICREV (ro) 0x02 */
+ 0x00, /* TWL6030_INTID 0x03 */
+ 0x00, /* TWL6030_INTMR 0x04 */
+ 0x00, /* TWL6030_NCPCTRL 0x05 */
+ 0x00, /* TWL6030_LDOCTL 0x06 */
+ 0x00, /* TWL6030_HPPLLCTL 0x07 */
+ 0x00, /* TWL6030_LPPLLCTL 0x08 */
+ 0x00, /* TWL6030_LPPLLDIV 0x09 */
+ 0x00, /* TWL6030_AMICBCTL 0x0A */
+ 0x00, /* TWL6030_DMICBCTL 0x0B */
+ 0x18, /* TWL6030_MICLCTL 0x0C */
+ 0x18, /* TWL6030_MICRCTL 0x0D */
+ 0x00, /* TWL6030_MICGAIN 0x0E */
+ 0x1B, /* TWL6030_LINEGAIN 0x0F */
+ 0x00, /* TWL6030_HSLCTL 0x10 */
+ 0x00, /* TWL6030_HSRCTL 0x11 */
+ 0x00, /* TWL6030_HSGAIN 0x12 */
+ 0x06, /* TWL6030_EARCTL 0x13 */
+ 0x00, /* TWL6030_HFLCTL 0x14 */
+ 0x03, /* TWL6030_HFLGAIN 0x15 */
+ 0x00, /* TWL6030_HFRCTL 0x16 */
+ 0x03, /* TWL6030_HFRGAIN 0x17 */
+ 0x00, /* TWL6030_VIBCTLL 0x18 */
+ 0x00, /* TWL6030_VIBDATL 0x19 */
+ 0x00, /* TWL6030_VIBCTLR 0x1A */
+ 0x00, /* TWL6030_VIBDATR 0x1B */
+ 0x00, /* TWL6030_HKCTL1 0x1C */
+ 0x00, /* TWL6030_HKCTL2 0x1D */
+ 0x00, /* TWL6030_GPOCTL 0x1E */
+ 0x00, /* TWL6030_ALB 0x1F */
+ 0x00, /* TWL6030_DLB 0x20 */
+ 0x00, /* not used 0x21 */
+ 0x00, /* not used 0x22 */
+ 0x00, /* not used 0x23 */
+ 0x00, /* not used 0x24 */
+ 0x00, /* not used 0x25 */
+ 0x00, /* not used 0x26 */
+ 0x00, /* not used 0x27 */
+ 0x00, /* TWL6030_TRIM1 0x28 */
+ 0x00, /* TWL6030_TRIM2 0x29 */
+ 0x00, /* TWL6030_TRIM3 0x2A */
+ 0x00, /* TWL6030_HSOTRIM 0x2B */
+ 0x00, /* TWL6030_HFOTRIM 0x2C */
+ 0x09, /* TWL6030_ACCCTL 0x2D */
+ 0x00, /* TWL6030_STATUS (ro) 0x2E */
+};
+
+/*
+ * twl6030 vio/gnd registers:
+ * registers under vio/gnd supply can be accessed
+ * before the power-up sequence, after NRESPWRON goes high
+ */
+static const int twl6030_vio_reg[TWL6030_VIOREGNUM] = {
+ TWL6030_REG_ASICID,
+ TWL6030_REG_ASICREV,
+ TWL6030_REG_INTID,
+ TWL6030_REG_INTMR,
+ TWL6030_REG_NCPCTL,
+ TWL6030_REG_LDOCTL,
+ TWL6030_REG_AMICBCTL,
+ TWL6030_REG_DMICBCTL,
+ TWL6030_REG_HKCTL1,
+ TWL6030_REG_HKCTL2,
+ TWL6030_REG_GPOCTL,
+ TWL6030_REG_TRIM1,
+ TWL6030_REG_TRIM2,
+ TWL6030_REG_TRIM3,
+ TWL6030_REG_HSOTRIM,
+ TWL6030_REG_HFOTRIM,
+ TWL6030_REG_ACCCTL,
+ TWL6030_REG_STATUS,
+};
+
+/*
+ * twl6030 vdd/vss registers:
+ * registers under vdd/vss supplies can only be accessed
+ * after the power-up sequence
+ */
+static const int twl6030_vdd_reg[TWL6030_VDDREGNUM] = {
+ TWL6030_REG_HPPLLCTL,
+ TWL6030_REG_LPPLLCTL,
+ TWL6030_REG_LPPLLDIV,
+ TWL6030_REG_MICLCTL,
+ TWL6030_REG_MICRCTL,
+ TWL6030_REG_MICGAIN,
+ TWL6030_REG_LINEGAIN,
+ TWL6030_REG_HSLCTL,
+ TWL6030_REG_HSRCTL,
+ TWL6030_REG_HSGAIN,
+ TWL6030_REG_EARCTL,
+ TWL6030_REG_HFLCTL,
+ TWL6030_REG_HFLGAIN,
+ TWL6030_REG_HFRCTL,
+ TWL6030_REG_HFRGAIN,
+ TWL6030_REG_VIBCTLL,
+ TWL6030_REG_VIBDATL,
+ TWL6030_REG_VIBCTLR,
+ TWL6030_REG_VIBDATR,
+ TWL6030_REG_ALB,
+ TWL6030_REG_DLB,
+};
+
+/*
+ * read twl6030 register cache
+ */
+static inline unsigned int twl6030_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= TWL6030_CACHEREGNUM)
+ return -EIO;
+
+ return cache[reg];
+}
+
+/*
+ * write twl6030 register cache
+ */
+static inline void twl6030_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, u8 value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= TWL6030_CACHEREGNUM)
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * read from twl6030 hardware register
+ */
+static int twl6030_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 value;
+
+ if (reg >= TWL6030_CACHEREGNUM)
+ return -EIO;
+
+ twl_i2c_read_u8(TWL6030_MODULE_AUDIO, &value, reg);
+ twl6030_write_reg_cache(codec, reg, value);
+
+ return value;
+}
+
+/*
+ * write to the twl6030 register space
+ */
+static int twl6030_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ if (reg >= TWL6030_CACHEREGNUM)
+ return -EIO;
+
+ twl6030_write_reg_cache(codec, reg, value);
+ return twl_i2c_write_u8(TWL6030_MODULE_AUDIO, value, reg);
+}
+
+static void twl6030_init_vio_regs(struct snd_soc_codec *codec)
+{
+ u8 *cache = codec->reg_cache;
+ int reg, i;
+
+ /* allow registers to be accessed by i2c */
+ twl6030_write(codec, TWL6030_REG_ACCCTL, cache[TWL6030_REG_ACCCTL]);
+
+ for (i = 0; i < TWL6030_VIOREGNUM; i++) {
+ reg = twl6030_vio_reg[i];
+ /* skip read-only registers (ASICID, ASICREV, STATUS) */
+ if ((reg == TWL6030_REG_ASICID) ||
+ (reg == TWL6030_REG_ASICREV) ||
+ (reg == TWL6030_REG_STATUS))
+ continue;
+ twl6030_write(codec, reg, cache[reg]);
+ }
+}
+
+static void twl6030_init_vdd_regs(struct snd_soc_codec *codec)
+{
+ u8 *cache = codec->reg_cache;
+ int reg, i;
+
+ for (i = 0; i < TWL6030_VDDREGNUM; i++) {
+ reg = twl6030_vdd_reg[i];
+ twl6030_write(codec, reg, cache[reg]);
+ }
+}
+
+static void abe_init_chip(struct snd_soc_codec *codec)
+{
+ abe_reset_hal();
+}
+
+/* twl6030 codec manual power-up sequence */
+static void twl6030_power_up(struct snd_soc_codec *codec)
+{
+ u8 ncpctl, ldoctl, lppllctl, accctl;
+
+ ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
+ ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
+ lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+ accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
+
+ /* enable reference system */
+ ldoctl |= TWL6030_REFENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ mdelay(10);
+ /* enable internal oscillator */
+ ldoctl |= TWL6030_OSCENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(10);
+ /* enable high-side ldo */
+ ldoctl |= TWL6030_HSLDOENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(244);
+ /* enable negative charge pump */
+ ncpctl |= TWL6030_NCPENA | TWL6030_NCPOPEN;
+ twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
+ udelay(488);
+ /* enable low-side ldo */
+ ldoctl |= TWL6030_LSLDOENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(244);
+ /* enable low-power pll */
+ lppllctl |= TWL6030_LPLLENA;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+ /* reset state machine */
+ accctl |= TWL6030_RESETSPLIT;
+ twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
+ mdelay(5);
+ accctl &= ~TWL6030_RESETSPLIT;
+ twl6030_write(codec, TWL6030_REG_ACCCTL, accctl);
+ /* disable internal oscillator */
+ ldoctl &= ~TWL6030_OSCENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+}
+
+/* twl6030 codec manual power-down sequence */
+static void twl6030_power_down(struct snd_soc_codec *codec)
+{
+ u8 ncpctl, ldoctl, lppllctl, accctl;
+
+ ncpctl = twl6030_read_reg_cache(codec, TWL6030_REG_NCPCTL);
+ ldoctl = twl6030_read_reg_cache(codec, TWL6030_REG_LDOCTL);
+ lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+ accctl = twl6030_read_reg_cache(codec, TWL6030_REG_ACCCTL);
+
+ /* enable internal oscillator */
+ ldoctl |= TWL6030_OSCENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(10);
+ /* disable low-power pll */
+ lppllctl &= ~TWL6030_LPLLENA;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+ /* disable low-side ldo */
+ ldoctl &= ~TWL6030_LSLDOENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(244);
+ /* disable negative charge pump */
+ ncpctl &= ~(TWL6030_NCPENA | TWL6030_NCPOPEN);
+ twl6030_write(codec, TWL6030_REG_NCPCTL, ncpctl);
+ udelay(488);
+ /* disable high-side ldo */
+ ldoctl &= ~TWL6030_HSLDOENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ udelay(244);
+ /* disable internal oscillator */
+ ldoctl &= ~TWL6030_OSCENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ /* disable reference system */
+ ldoctl &= ~TWL6030_REFENA;
+ twl6030_write(codec, TWL6030_REG_LDOCTL, ldoctl);
+ mdelay(10);
+}
+
+/* set headset dac and driver power mode */
+static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
+{
+ int hslctl, hsrctl;
+ int mask = TWL6030_HSDRVMODEL | TWL6030_HSDACMODEL;
+
+ hslctl = twl6030_read_reg_cache(codec, TWL6030_REG_HSLCTL);
+ hsrctl = twl6030_read_reg_cache(codec, TWL6030_REG_HSRCTL);
+
+ if (high_perf) {
+ hslctl &= ~mask;
+ hsrctl &= ~mask;
+ } else {
+ hslctl |= mask;
+ hsrctl |= mask;
+ }
+
+ twl6030_write(codec, TWL6030_REG_HSLCTL, hslctl);
+ twl6030_write(codec, TWL6030_REG_HSRCTL, hsrctl);
+
+ return 0;
+}
+
+static int twl6030_power_mode_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct twl6030_data *priv = codec->private_data;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ priv->non_lp++;
+ else
+ priv->non_lp--;
+
+ return 0;
+}
+
+/* audio interrupt handler */
+static irqreturn_t twl6030_naudint_handler(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+ struct twl6030_data *priv = codec->private_data;
+ u8 intid;
+
+ twl_i2c_read_u8(TWL6030_MODULE_AUDIO, &intid, TWL6030_REG_INTID);
+
+ switch (intid) {
+ case TWL6030_THINT:
+ dev_alert(codec->dev, "die temp over-limit detection\n");
+ break;
+ case TWL6030_PLUGINT:
+ case TWL6030_UNPLUGINT:
+ case TWL6030_HOOKINT:
+ break;
+ case TWL6030_HFINT:
+ dev_alert(codec->dev, "hf drivers over current detection\n");
+ break;
+ case TWL6030_VIBINT:
+ dev_alert(codec->dev, "vib drivers over current detection\n");
+ break;
+ case TWL6030_READYINT:
+ complete(&priv->ready);
+ break;
+ default:
+ dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * MICATT volume control:
+ * from -6 to 0 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
+
+/*
+ * MICGAIN volume control:
+ * from 6 to 30 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
+
+/*
+ * HSGAIN volume control:
+ * from -30 to 0 dB in 2 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
+
+/*
+ * HFGAIN volume control:
+ * from -52 to 6 dB in 2 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
+
+/* Left analog microphone selection */
+static const char *twl6030_amicl_texts[] =
+ {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
+
+/* Right analog microphone selection */
+static const char *twl6030_amicr_texts[] =
+ {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
+
+static const struct soc_enum twl6030_enum[] = {
+ SOC_ENUM_SINGLE(TWL6030_REG_MICLCTL, 3, 3, twl6030_amicl_texts),
+ SOC_ENUM_SINGLE(TWL6030_REG_MICRCTL, 3, 3, twl6030_amicr_texts),
+};
+
+static const struct snd_kcontrol_new amicl_control =
+ SOC_DAPM_ENUM("Route", twl6030_enum[0]);
+
+static const struct snd_kcontrol_new amicr_control =
+ SOC_DAPM_ENUM("Route", twl6030_enum[1]);
+
+/* Headset DAC playback switches */
+static const struct snd_kcontrol_new hsdacl_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HSLCTL, 5, 1, 0);
+
+static const struct snd_kcontrol_new hsdacr_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HSRCTL, 5, 1, 0);
+
+/* Handsfree DAC playback switches */
+static const struct snd_kcontrol_new hfdacl_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HFLCTL, 2, 1, 0);
+
+static const struct snd_kcontrol_new hfdacr_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HFRCTL, 2, 1, 0);
+
+/* Headset driver switches */
+static const struct snd_kcontrol_new hsl_driver_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HSLCTL, 2, 1, 0);
+
+static const struct snd_kcontrol_new hsr_driver_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HSRCTL, 2, 1, 0);
+
+/* Handsfree driver switches */
+static const struct snd_kcontrol_new hfl_driver_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HFLCTL, 4, 1, 0);
+
+static const struct snd_kcontrol_new hfr_driver_switch_controls =
+ SOC_DAPM_SINGLE("Switch", TWL6030_REG_HFRCTL, 4, 1, 0);
+
+static const struct snd_kcontrol_new twl6030_snd_controls[] = {
+ /* Capture gains */
+ SOC_DOUBLE_TLV("Capture Preamplifier Volume",
+ TWL6030_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
+ SOC_DOUBLE_TLV("Capture Volume",
+ TWL6030_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
+
+ /* Playback gains */
+ SOC_DOUBLE_TLV("Headset Playback Volume",
+ TWL6030_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
+ SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
+ TWL6030_REG_HFLGAIN, TWL6030_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
+
+};
+
+static const struct snd_soc_dapm_widget twl6030_dapm_widgets[] = {
+ /* Inputs */
+ SND_SOC_DAPM_INPUT("MAINMIC"),
+ SND_SOC_DAPM_INPUT("HSMIC"),
+ SND_SOC_DAPM_INPUT("SUBMIC"),
+ SND_SOC_DAPM_INPUT("AFML"),
+ SND_SOC_DAPM_INPUT("AFMR"),
+
+ /* Outputs */
+ SND_SOC_DAPM_OUTPUT("HSOL"),
+ SND_SOC_DAPM_OUTPUT("HSOR"),
+ SND_SOC_DAPM_OUTPUT("HFL"),
+ SND_SOC_DAPM_OUTPUT("HFR"),
+
+ /* Analog input muxes for the capture amplifiers */
+ SND_SOC_DAPM_MUX("Analog Left Capture Route",
+ SND_SOC_NOPM, 0, 0, &amicl_control),
+ SND_SOC_DAPM_MUX("Analog Right Capture Route",
+ SND_SOC_NOPM, 0, 0, &amicr_control),
+
+ /* Analog capture PGAs */
+ SND_SOC_DAPM_PGA("MicAmpL",
+ TWL6030_REG_MICLCTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MicAmpR",
+ TWL6030_REG_MICRCTL, 0, 0, NULL, 0),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
+ TWL6030_REG_MICLCTL, 2, 0),
+ SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
+ TWL6030_REG_MICRCTL, 2, 0),
+
+ /* Microphone bias */
+ SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
+ TWL6030_REG_AMICBCTL, 0, 0),
+ SND_SOC_DAPM_MICBIAS("Main Mic Bias",
+ TWL6030_REG_AMICBCTL, 4, 0),
+ SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
+ TWL6030_REG_DMICBCTL, 0, 0),
+ SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
+ TWL6030_REG_DMICBCTL, 4, 0),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback",
+ TWL6030_REG_HSLCTL, 0, 0),
+ SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback",
+ TWL6030_REG_HSRCTL, 0, 0),
+ SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
+ TWL6030_REG_HFLCTL, 0, 0,
+ twl6030_power_mode_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
+ TWL6030_REG_HFRCTL, 0, 0,
+ twl6030_power_mode_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Analog playback switches */
+ SND_SOC_DAPM_SWITCH("HSDAC Left Playback",
+ SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls),
+ SND_SOC_DAPM_SWITCH("HSDAC Right Playback",
+ SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls),
+ SND_SOC_DAPM_SWITCH("HFDAC Left Playback",
+ SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls),
+ SND_SOC_DAPM_SWITCH("HFDAC Right Playback",
+ SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls),
+
+ SND_SOC_DAPM_SWITCH("Headset Left Driver",
+ SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls),
+ SND_SOC_DAPM_SWITCH("Headset Right Driver",
+ SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls),
+ SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver",
+ SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls,
+ twl6030_power_mode_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver",
+ SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls,
+ twl6030_power_mode_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Analog playback PGAs */
+ SND_SOC_DAPM_PGA("HFDAC Left PGA",
+ TWL6030_REG_HFLCTL, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HFDAC Right PGA",
+ TWL6030_REG_HFRCTL, 1, 0, NULL, 0),
+
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ /* Capture path */
+ {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
+ {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
+ {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
+
+ {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
+ {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
+ {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
+
+ {"MicAmpL", NULL, "Analog Left Capture Route"},
+ {"MicAmpR", NULL, "Analog Right Capture Route"},
+
+ {"ADC Left", NULL, "MicAmpL"},
+ {"ADC Right", NULL, "MicAmpR"},
+
+ /* Headset playback path */
+ {"HSDAC Left Playback", "Switch", "HSDAC Left"},
+ {"HSDAC Right Playback", "Switch", "HSDAC Right"},
+
+ {"Headset Left Driver", "Switch", "HSDAC Left Playback"},
+ {"Headset Right Driver", "Switch", "HSDAC Right Playback"},
+
+ {"HSOL", NULL, "Headset Left Driver"},
+ {"HSOR", NULL, "Headset Right Driver"},
+
+ /* Handsfree playback path */
+ {"HFDAC Left Playback", "Switch", "HFDAC Left"},
+ {"HFDAC Right Playback", "Switch", "HFDAC Right"},
+
+ {"HFDAC Left PGA", NULL, "HFDAC Left Playback"},
+ {"HFDAC Right PGA", NULL, "HFDAC Right Playback"},
+
+ {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
+ {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
+
+ {"HFL", NULL, "Handsfree Left Driver"},
+ {"HFR", NULL, "Handsfree Right Driver"},
+};
+
+static int abe_twl6030_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, twl6030_dapm_widgets,
+ ARRAY_SIZE(twl6030_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+
+ return 0;
+}
+
+static int twl6030_power_up_completion(struct snd_soc_codec *codec,
+ int naudint)
+{
+ struct twl6030_data *priv = codec->private_data;
+ int time_left;
+ u8 intid;
+
+ if (naudint) {
+ /* wait for ready interrupt with 48 ms timeout */
+ time_left = wait_for_completion_timeout(&priv->ready,
+ msecs_to_jiffies(48));
+ } else {
+ /* retry 3 times only */
+ for (time_left = 3; time_left > 0; time_left--) {
+ mdelay(16);
+ twl_i2c_read_u8(TWL6030_MODULE_AUDIO, &intid,
+ TWL6030_REG_INTID);
+ if (intid & TWL6030_READYINT)
+ break;
+ }
+ }
+
+ if (!time_left) {
+ dev_err(codec->dev, "timeout waiting for READYINT\n");
+ return -ETIMEDOUT;
+ }
+
+ priv->codec_powered = 1;
+
+ return 0;
+}
+
+static int abe_twl6030_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct twl6030_data *priv = codec->private_data;
+ int audpwron = priv->audpwron;
+ int naudint = priv->naudint;
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ case SND_SOC_BIAS_STANDBY:
+ if (priv->codec_powered)
+ break;
+
+ if (gpio_is_valid(audpwron)) {
+ /* use AUDPWRON line */
+ gpio_set_value(audpwron, 1);
+
+ /* wait for power-up completion */
+ ret = twl6030_power_up_completion(codec, naudint);
+ if (ret)
+ return ret;
+
+ /* sync registers updated during power-up sequence */
+ twl6030_read(codec, TWL6030_REG_NCPCTL);
+ twl6030_read(codec, TWL6030_REG_LDOCTL);
+ twl6030_read(codec, TWL6030_REG_LPPLLCTL);
+ } else {
+ /* use manual power-up sequence */
+ twl6030_power_up(codec);
+ priv->codec_powered = 1;
+ }
+
+ /* initialize vdd/vss registers with reg_cache */
+ twl6030_init_vdd_regs(codec);
+ break;
+ case SND_SOC_BIAS_OFF:
+ if (!priv->codec_powered)
+ break;
+
+ if (gpio_is_valid(audpwron)) {
+ /* use AUDPWRON line */
+ gpio_set_value(audpwron, 0);
+
+ /* power-down sequence latency */
+ udelay(500);
+
+ /* sync registers updated during power-down sequence */
+ twl6030_read(codec, TWL6030_REG_NCPCTL);
+ twl6030_read(codec, TWL6030_REG_LDOCTL);
+ twl6030_write_reg_cache(codec, TWL6030_REG_LPPLLCTL,
+ 0x00);
+ } else {
+ /* use manual power-down sequence */
+ twl6030_power_down(codec);
+ }
+
+ priv->codec_powered = 0;
+ break;
+ }
+
+ codec->bias_level = level;
+
+ return 0;
+}
+
+/* set of rates for each pll: low-power and high-performance */
+
+static unsigned int lp_rates[] = {
+ 44100,
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list lp_constraints = {
+ .count = ARRAY_SIZE(lp_rates),
+ .list = lp_rates,
+};
+
+static unsigned int hp_rates[] = {
+ 8000,
+ 16000,
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list hp_constraints = {
+ .count = ARRAY_SIZE(hp_rates),
+ .list = hp_rates,
+};
+
+static int twl6030_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl6030_data *priv = codec->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /*
+ * low-power playback mode is restricted
+ * for headset path only
+ */
+ if ((priv->sysclk == 17640000) && priv->non_lp) {
+ dev_err(codec->dev,
+ "some enabled paths aren't supported at %dHz\n",
+ priv->sysclk);
+ return -EPERM;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int twl6030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct twl6030_data *priv = codec->private_data;
+ u8 hppllctl, lppllctl;
+
+ hppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_HPPLLCTL);
+ lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+
+ switch (clk_id) {
+ case TWL6030_SYSCLK_SEL_LPPLL:
+ switch (freq) {
+ case 32768:
+ /* headset dac and driver must be in low-power mode */
+ headset_power_mode(codec, 0);
+
+ /* clk32k input requires low-power pll */
+ lppllctl |= TWL6030_LPLLENA;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+ mdelay(5);
+ lppllctl &= ~TWL6030_HPLLSEL;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+ hppllctl &= ~TWL6030_HPLLENA;
+ twl6030_write(codec, TWL6030_REG_HPPLLCTL, hppllctl);
+ break;
+ default:
+ dev_err(codec->dev, "unknown mclk freq %d\n", freq);
+ return -EINVAL;
+ }
+
+ /* lppll divider */
+ switch (priv->sysclk) {
+ case 17640000:
+ lppllctl |= TWL6030_LPLLFIN;
+ break;
+ case 19200000:
+ lppllctl &= ~TWL6030_LPLLFIN;
+ break;
+ default:
+ /* sysclk not yet configured */
+ lppllctl &= ~TWL6030_LPLLFIN;
+ priv->sysclk = 19200000;
+ break;
+ }
+
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+
+ priv->pll = TWL6030_LPPLL_ID;
+ priv->sysclk_constraints = &lp_constraints;
+ break;
+ case TWL6030_SYSCLK_SEL_HPPLL:
+ hppllctl &= ~TWL6030_MCLK_MSK;
+
+ switch (freq) {
+ case 12000000:
+ /* mclk input, pll enabled */
+ hppllctl |= TWL6030_MCLK_12000KHZ |
+ TWL6030_HPLLSQRBP |
+ TWL6030_HPLLENA;
+ break;
+ case 19200000:
+ /* mclk input, pll disabled */
+ hppllctl |= TWL6030_MCLK_19200KHZ |
+ TWL6030_HPLLSQRBP |
+ TWL6030_HPLLBP;
+ break;
+ case 26000000:
+ /* mclk input, pll enabled */
+ hppllctl |= TWL6030_MCLK_26000KHZ |
+ TWL6030_HPLLSQRBP |
+ TWL6030_HPLLENA;
+ break;
+ case 38400000:
+ /* clk slicer, pll disabled */
+ hppllctl |= TWL6030_MCLK_38400KHZ |
+ TWL6030_HPLLSQRENA |
+ TWL6030_HPLLBP;
+ break;
+ default:
+ dev_err(codec->dev, "unknown mclk freq %d\n", freq);
+ return -EINVAL;
+ }
+
+ /* headset dac and driver must be in high-performance mode */
+ headset_power_mode(codec, 1);
+
+ twl6030_write(codec, TWL6030_REG_HPPLLCTL, hppllctl);
+ udelay(500);
+ lppllctl |= TWL6030_HPLLSEL;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+ lppllctl &= ~TWL6030_LPLLENA;
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+
+ /* high-performance pll can provide only 19.2 MHz */
+ priv->pll = TWL6030_HPPLL_ID;
+ priv->sysclk = 19200000;
+ priv->sysclk_constraints = &hp_constraints;
+ break;
+ default:
+ dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+static int abe_mm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl6030_data *priv = codec->private_data;
+ abe_uint32 event;
+
+ if (!priv->sysclk) {
+ dev_err(codec->dev,
+ "no mclk configured, call set_sysclk() on init\n");
+ return -EINVAL;
+ }
+
+ /*
+ * capture is not supported at 17.64 MHz,
+ * it's reserved for headset low-power playback scenario
+ */
+ if ((priv->sysclk == 17640000) && substream->stream) {
+ dev_err(codec->dev,
+ "capture mode is not supported at %dHz\n",
+ priv->sysclk);
+ return -EINVAL;
+ }
+
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ priv->sysclk_constraints);
+
+ if (!priv->configure++)
+ abe_default_configuration(UC2_VOICE_CALL_AND_IHF_MMDL);
+
+ if (substream->stream)
+ event = ABE_ATC_MCPDMUL_DMA_REQ;
+ else
+ event = ABE_ATC_MCPDMDL_DMA_REQ;
+
+ abe_block_copy (COPY_FROM_HOST_TO_ABE, ABE_ATC, AUDIO_ENGINE_SCHEDULER, &event, 4);
+
+ return 0;
+}
+
+static int abe_mm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl6030_data *priv = codec->private_data;
+ unsigned int *dst_ptr;
+ u8 lppllctl;
+ int rate;
+
+ /* nothing to do for high-perf pll, it supports only 48 kHz */
+ if (priv->pll == TWL6030_HPPLL_ID) {
+ if (!substream->stream) {
+ /* Circular buffer 0 (MM_DL path) write pointer address
+ * increases by 2 to avoid loosing DMA request
+ */
+ dst_ptr = (unsigned int*) (ABE_DMEM_BASE_ADDRESS_MPU + 0x100);
+ *dst_ptr = 0x1a004800;
+
+ dst_ptr = (unsigned int*) (ABE_DMEM_BASE_ADDRESS_MPU + 0x108);
+ *dst_ptr = 0x04000c00;
+ }
+ return 0;
+ }
+
+ lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+
+ rate = params_rate(params);
+ switch (rate) {
+ case 48000:
+ lppllctl &= ~TWL6030_LPLLFIN;
+ priv->sysclk = 19200000;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported rate %d\n", rate);
+ return -EINVAL;
+ }
+
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops abe_mm_dai_ops = {
+ .startup = abe_mm_startup,
+ .hw_params = abe_mm_hw_params,
+ .trigger = twl6030_trigger,
+ .set_sysclk = twl6030_set_dai_sysclk,
+};
+
+static int abe_voice_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl6030_data *priv = codec->private_data;
+ unsigned int *dst_ptr;
+ u8 lppllctl;
+ int rate;
+
+ /* nothing to do for high-perf pll, it supports only 48 kHz */
+ if (priv->pll == TWL6030_HPPLL_ID) {
+ if (!substream->stream) {
+ /* Circular buffer 0 (MM_DL path) write pointer address
+ * increases by 2 to avoid loosing DMA request
+ */
+ dst_ptr = (unsigned int*) (ABE_DMEM_BASE_ADDRESS_MPU + 0x100);
+ *dst_ptr = 0x1a004800;
+
+ dst_ptr = (unsigned int*) (ABE_DMEM_BASE_ADDRESS_MPU + 0x108);
+ *dst_ptr = 0x04000c00;
+ }
+ return 0;
+ }
+
+ lppllctl = twl6030_read_reg_cache(codec, TWL6030_REG_LPPLLCTL);
+
+ rate = params_rate(params);
+ switch (rate) {
+ case 8000:
+ case 16000:
+ lppllctl &= ~TWL6030_LPLLFIN;
+ priv->sysclk = 19200000;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported rate %d\n", rate);
+ return -EINVAL;
+ }
+
+ twl6030_write(codec, TWL6030_REG_LPPLLCTL, lppllctl);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops abe_voice_dai_ops = {
+ .startup = abe_mm_startup,
+ .hw_params = abe_voice_hw_params,
+ .trigger = twl6030_trigger,
+ .set_sysclk = twl6030_set_dai_sysclk,
+};
+
+/* Audio Backend DAIs */
+struct snd_soc_dai abe_dai[] = {
+ /* Multimedia: MM-UL2, MM-DL */
+ {
+ .name = "Multimedia",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = ABE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = ABE_FORMATS,
+ },
+ .ops = &abe_mm_dai_ops,
+ },
+ /* Tones DL: MM-DL2 */
+ {
+ .name = "Tones DL",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = ABE_FORMATS,
+ },
+ .ops = &abe_mm_dai_ops,
+ },
+ /* Voice: VX-UL, VX-DL */
+ {
+ .name = "Voice",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = ABE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = ABE_FORMATS,
+ },
+ .ops = &abe_voice_dai_ops,
+ },
+ /* Digital Uplink: MM-UL */
+ {
+ .name = "Digital Uplink",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = ABE_FORMATS,
+ },
+ },
+ /* Vibrator: VIB-DL */
+ {
+ .name = "Vibrator",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = ABE_FORMATS,
+ },
+ },
+ };
+
+static int abe_twl6030_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ abe_twl6030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int abe_twl6030_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ abe_twl6030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ abe_twl6030_set_bias_level(codec, codec->suspend_bias_level);
+
+ return 0;
+}
+
+static struct snd_soc_codec *twl6030_codec;
+
+static int abe_twl6030_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ BUG_ON(!twl6030_codec);
+
+ codec = twl6030_codec;
+ socdev->card->codec = codec;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to create pcms\n");
+ return ret;
+ }
+
+ abe_init_chip(codec);
+ snd_soc_add_controls(codec, twl6030_snd_controls,
+ ARRAY_SIZE(twl6030_snd_controls));
+ abe_twl6030_add_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+ return ret;
+}
+
+static int abe_twl6030_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ abe_twl6030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+ kfree(codec);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_abe_twl6030 = {
+ .probe = abe_twl6030_probe,
+ .remove = abe_twl6030_remove,
+ .suspend = abe_twl6030_suspend,
+ .resume = abe_twl6030_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_abe_twl6030);
+
+static int __devinit abe_twl6030_codec_probe(struct platform_device *pdev)
+{
+ struct twl_codec_data *twl_codec = pdev->dev.platform_data;
+ struct snd_soc_codec *codec;
+ struct twl6030_data *priv;
+ int audpwron, naudint;
+ int ret = 0;
+
+ priv = kzalloc(sizeof(struct twl6030_data), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ if (twl_codec) {
+ audpwron = twl_codec->audpwron_gpio;
+ naudint = twl_codec->naudint_irq;
+ } else {
+ audpwron = -EINVAL;
+ naudint = 0;
+ }
+
+ priv->audpwron = audpwron;
+ priv->naudint = naudint;
+
+ codec = &priv->codec;
+ codec->dev = &pdev->dev;
+ codec->name = "twl6030";
+ codec->owner = THIS_MODULE;
+ codec->read = twl6030_read_reg_cache;
+ codec->write = twl6030_write;
+ codec->set_bias_level = abe_twl6030_set_bias_level;
+ codec->private_data = priv;
+ codec->dai = abe_dai;
+ codec->num_dai = ARRAY_SIZE(abe_dai);
+ codec->reg_cache_size = ARRAY_SIZE(twl6030_reg);
+ codec->reg_cache = kmemdup(twl6030_reg, sizeof(twl6030_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL) {
+ ret = -ENOMEM;
+ goto cache_err;
+ }
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ init_completion(&priv->ready);
+
+ if (gpio_is_valid(audpwron)) {
+ ret = gpio_request(audpwron, "audpwron");
+ if (ret)
+ goto gpio1_err;
+
+ ret = gpio_direction_output(audpwron, 0);
+ if (ret)
+ goto gpio2_err;
+
+ priv->codec_powered = 0;
+ }
+
+ if (naudint) {
+ /* audio interrupt */
+ ret = request_threaded_irq(naudint, NULL,
+ twl6030_naudint_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "twl6030_codec", codec);
+ if (ret)
+ goto gpio2_err;
+ } else {
+ if (gpio_is_valid(audpwron)) {
+ /* enable only codec ready interrupt */
+ twl6030_write_reg_cache(codec, TWL6030_REG_INTMR,
+ ~TWL6030_READYMSK & TWL6030_ALLINT_MSK);
+ } else {
+ /* no interrupts at all */
+ twl6030_write_reg_cache(codec, TWL6030_REG_INTMR,
+ TWL6030_ALLINT_MSK);
+ }
+ }
+
+ /* init vio registers */
+ twl6030_init_vio_regs(codec);
+
+ /* power on device */
+ ret = abe_twl6030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (ret)
+ goto irq_err;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret)
+ goto reg_err;
+
+ twl6030_codec = codec;
+
+ ret = snd_soc_register_dais(abe_dai, ARRAY_SIZE(abe_dai));
+ if (ret)
+ goto dai_err;
+
+ return 0;
+
+dai_err:
+ snd_soc_unregister_codec(codec);
+ twl6030_codec = NULL;
+reg_err:
+ abe_twl6030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+irq_err:
+ if (naudint)
+ free_irq(naudint, codec);
+gpio2_err:
+ if (gpio_is_valid(audpwron))
+ gpio_free(audpwron);
+gpio1_err:
+ kfree(codec->reg_cache);
+cache_err:
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit abe_twl6030_codec_remove(struct platform_device *pdev)
+{
+ struct twl6030_data *priv = twl6030_codec->private_data;
+ int audpwron = priv->audpwron;
+ int naudint = priv->naudint;
+
+ if (gpio_is_valid(audpwron))
+ gpio_free(audpwron);
+
+ if (naudint)
+ free_irq(naudint, twl6030_codec);
+
+ snd_soc_unregister_dais(abe_dai, ARRAY_SIZE(abe_dai));
+ snd_soc_unregister_codec(twl6030_codec);
+
+ kfree(twl6030_codec);
+ twl6030_codec = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int abe_twl6030_codec_suspend(struct platform_device *pdev,
+ pm_message_t msg)
+{
+ return snd_soc_suspend_device(&pdev->dev);
+}
+
+static int abe_twl6030_codec_resume(struct platform_device *pdev)
+{
+ return snd_soc_resume_device(&pdev->dev);
+}
+#else
+#define abe_twl6030_codec_suspend NULL
+#define abe_twl6030_codec_resume NULL
+#endif
+
+static struct platform_driver abe_twl6030_codec_driver = {
+ .driver = {
+ .name = "twl6030_codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = abe_twl6030_codec_probe,
+ .remove = __devexit_p(abe_twl6030_codec_remove),
+ .suspend = abe_twl6030_codec_suspend,
+ .resume = abe_twl6030_codec_resume,
+};
+
+static int __init abe_twl6030_codec_init(void)
+{
+ return platform_driver_register(&abe_twl6030_codec_driver);
+}
+module_init(abe_twl6030_codec_init);
+
+static void __exit abe_twl6030_codec_exit(void)
+{
+ platform_driver_unregister(&abe_twl6030_codec_driver);
+}
+module_exit(abe_twl6030_codec_exit);
+
+MODULE_DESCRIPTION("ASoC ABE-TWL6030 codec driver");
+MODULE_AUTHOR("Misael Lopez Cruz");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/abe-twl6030.h b/sound/soc/codecs/abe-twl6030.h
new file mode 100644
index 000000000000..6484aec30bf1
--- /dev/null
+++ b/sound/soc/codecs/abe-twl6030.h
@@ -0,0 +1,32 @@
+/*
+ * ALSA SoC ABE-TWL6030 codec driver
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __ABE_TWL6030_H__
+#define __ABE_TWL6030_H__
+
+extern struct snd_soc_dai abe_dai[];
+extern struct snd_soc_codec_device soc_codec_dev_abe_twl6030;
+
+struct twl6030_setup_data {
+ void (*codec_enable)(int enable);
+};
+
+#endif /* End of __ABE_TWL6030_H__ */
diff --git a/sound/soc/codecs/abe/C_ABE_FW.CM b/sound/soc/codecs/abe/C_ABE_FW.CM
new file mode 100644
index 000000000000..a3cfacda1f1c
--- /dev/null
+++ b/sound/soc/codecs/abe/C_ABE_FW.CM
@@ -0,0 +1,1638 @@
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x151000,
+0x001000,
+0x001000,
+0x141000,
+0x001000,
+0x001000,
+0x000000,
+0x000000,
+0x000000,
+0x001000,
+0x001001,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001001,
+0x001001,
+0x001001,
+0x000000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001081,
+0x001000,
+0x000000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001001,
+0x001001,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001001,
+0x001001,
+0x001000,
+0x001001,
+0x001001,
+0x001000,
+0x001001,
+0x001001,
+0x001000,
+0x001001,
+0x001001,
+0x001001,
+0x001001,
+0x001001,
+0x001001,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001001,
+0x001000,
+0x000006,
+0x000012,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x000000,
+0x001081,
+0x001000,
+0x001081,
+0x001000,
+0x001081,
+0x001000,
+0x001081,
+0x001000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x001081,
+0x000000,
+0x000000,
+0x001000,
+0x000018,
+0x001000,
+0x001000,
+0x001000,
+0x001000,
+0x000063,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x001000,
+0x001000,
+0x000000,
+0x001000,
+0x001000,
+0x001000,
+0x001001,
+0x000001,
+0x001000,
+0x001a58,
+0x001000,
+0x001001,
+0x000001,
+0x001000,
+0x001a98,
+0x151000,
+0x000000,
+0x001a58,
+0x001a98,
+0x151000,
+0x001000,
+0x001001,
+0x000001,
+0x001000,
+0x001ad8,
+0x001000,
+0x001001,
+0x001001,
+0x001000,
+0x001000,
+0x001001,
+0x001001,
+0x001001,
+0x0010c1,
+0x001000,
+0x0010c1,
+0x001001,
+0x001000,
+0x001000,
+0x001061,
+0x001061,
+0x000000,
+0x000000,
+0x001071,
+0x000000,
+0x001071,
+0x001000,
+0x001000,
+0x001031,
+0x001061,
+0x000000,
+0x001000,
+0x001061,
+0x001061,
+0x000000,
+0x000000,
+0x001000,
+0x001000,
+0x001031,
+0x001061,
+0x000000,
+0x001000,
+0x001000,
+0x001000,
+0x001041,
+0x001001,
+0x000000,
+0x001000,
+0x001011,
+0x001001,
+0x000000,
+0x001000,
+0x001001,
+0x000001,
+0x001000,
+0x001a98,
+0x001a98,
+0x001041,
+0x001001,
+0x001011,
+0x001001,
+0x001011,
+0x001001,
+0x001011,
+0x021031,
+0x041051,
+0x061071,
+0x0c10d1,
+0x0e10f1,
+0x101111,
+0x001000,
+0x001001,
+0x001001,
+0x001031,
+0x001061,
+0x001061,
+0x001061,
+0x151000,
+0x001000,
+0x001000,
+0x001081,
+0x001001,
+0x001001,
+0x001001,
+0x001001,
+0x0000d2,
+0x001041,
+0x001000,
+0x001041,
+0x001001,
+0x001001,
+0x000000,
+0x000000,
+0x001001,
+0x001000,
+0x001051,
+0x001000,
+0x001001,
+0x001001,
+0x001001,
+0x0000e1,
+0x001000,
+0x001001,
+0x001001,
+0x001001,
+0x001001,
+0x00fff9,
+0x001000,
+0x001000,
+0x000000,
+0x001000,
+0x001071,
+0x001000,
+0x000000,
+0x001071,
+0x001071,
+0x001071,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x800001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x100001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x700001,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000002,
+0x000002,
+0x040002,
+0x000002,
+0x040002,
+0x000002,
+0x000002,
+0x000002,
+0x040002,
+0x040002,
+0x000002,
+0x040002,
+0x000002,
+0x000002,
+0x000002,
+0x000002,
+0x000002,
+0x000002,
+0x040002,
+0x000002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x023c94,
+0x5ed280,
+0x6a9a5d,
+0xbf42f0,
+0x056260,
+0x0f02e8,
+0xeb9d08,
+0x13f0e8,
+0xeed498,
+0x0d8628,
+0xf610e8,
+0x06dac8,
+0xfb8ca8,
+0x02b6a8,
+0x9d1d03,
+0x3411d3,
+0xe7110b,
+0x0a8b43,
+0xfc4793,
+0x0208b8,
+0x6d23e0,
+0x66c791,
+0xb09170,
+0x142c90,
+0x03c304,
+0xf376f8,
+0x0eb9d8,
+0xf220d0,
+0x0b9710,
+0xf71850,
+0x0661c0,
+0xfbb618,
+0x02b430,
+0x99fe5b,
+0x37ceab,
+0xe408e3,
+0x0c8ac3,
+0xfb2e83,
+0x0464a8,
+0x782010,
+0x61b101,
+0xa7ab80,
+0x1ef5c0,
+0xfadbf0,
+0xfa10a0,
+0x0a1678,
+0xf53c30,
+0x09a2c0,
+0xf83d98,
+0x05c418,
+0xfc0144,
+0x0296d8,
+0x9badf3,
+0x386703,
+0xe2e293,
+0x0d8413,
+0xfa9443,
+0x05d8f0,
+0x42ccf5,
+0x5b6439,
+0x9fa4a8,
+0x2a0528,
+0xf141c8,
+0x5c184b,
+0x04be58,
+0xf8ea80,
+0x073f50,
+0xf9b218,
+0x04f108,
+0xfc6e8c,
+0x0264f0,
+0xa04a13,
+0x3770b3,
+0xe2819b,
+0x0e2353,
+0xfa1fab,
+0x07d850,
+0x498425,
+0x53f3c9,
+0x9a9170,
+0x334af8,
+0xe88c00,
+0x0875d0,
+0xdcf763,
+0xfcaf74,
+0x04b6b0,
+0xfb4d68,
+0x03fc0c,
+0xfcf654,
+0x022008,
+0xa80de3,
+0x348833,
+0xe33ce3,
+0x0e2e23,
+0xf9f08b,
+0x0aadb0,
+0x4fdc61,
+0x4b98d9,
+0x989408,
+0x3a6068,
+0xe12888,
+0x0ec210,
+0xfa8240,
+0x14e61b,
+0x022f7c,
+0xfcf624,
+0x02f50c,
+0xfd8f38,
+0x7356ab,
+0xb24bfb,
+0x300053,
+0xe4f083,
+0x0db28b,
+0xfa0193,
+0x0e5198,
+0x55cb8d,
+0x427b21,
+0x9968b8,
+0x3f50c0,
+0xdb27e8,
+0x143b08,
+0xf604a8,
+0x03bf5c,
+0xef1dc3,
+0xa7922b,
+0x7977cb,
+0x8ca91b,
+0x5c4373,
+0xbe654b,
+0x2a32fb,
+0xe76cb3,
+0x0cc843,
+0xfa47fb,
+0x12b270,
+0x5b537d,
+0x716ee8,
+0x9cd140,
+0x423000,
+0xd68e40,
+0x18d298,
+0xf20c30,
+0x06e2f8,
+0xfd6ac0,
+0x0eee5b,
+0x3575db,
+0xb6e5bb,
+0x4398ab,
+0xcbda13,
+0x236a1b,
+0xea894b,
+0x0b83a3,
+0xfaba2b,
+0x17d078,
+0x606a75,
+0x5cd070,
+0xa2a0d0,
+0x4306e0,
+0xd365f8,
+0x1c7720,
+0xeeab88,
+0x09ae08,
+0xfb4778,
+0x7127a3,
+0xf2fbcb,
+0xe1581b,
+0x2a1533,
+0xda3733,
+0x1be75b,
+0xee2313,
+0x09f65b,
+0xfb4feb,
+0x1db640,
+0x64f695,
+0x4768e0,
+0xaaa7f0,
+0x41db98,
+0xd1bd70,
+0x1f1310,
+0xebf900,
+0x0c0d48,
+0xf961f0,
+0x032d94,
+0xb409ab,
+0x0aabc3,
+0x108f73,
+0xe8fccb,
+0x13f29b,
+0xf2141b,
+0x08330b,
+0xfc00bb,
+0x2477b8,
+0x68d739,
+0x318e40,
+0xb4aec0,
+0x3ebd10,
+0xd19bf0,
+0x2095b8,
+0xea0778,
+0x0def88,
+0xf7c838,
+0x046be0,
+0xfdea24,
+0x319613,
+0xf7da9b,
+0xf7ab83,
+0x0bd423,
+0xf635fb,
+0x064ca3,
+0xfcc40b,
+0x2c29d8,
+0x6be82d,
+0x1ba3e0,
+0xc06ee8,
+0x39c7a8,
+0xd2fe70,
+0x20f5c0,
+0xe8e4e8,
+0x0f46d0,
+0xf68680,
+0x0575e0,
+0xfd2110,
+0x54da23,
+0xe0c55b,
+0x05c47b,
+0x03d513,
+0xfa6163,
+0x0456bb,
+0xfd9103,
+0x34dcb8,
+0x6e0619,
+0x0617a0,
+0xcd9208,
+0x3327e0,
+0xd5d488,
+0x2033b8,
+0xe89830,
+0x1009d8,
+0xf5a608,
+0x064398,
+0xfc7b10,
+0x735b3b,
+0xcc0f3b,
+0x12cf0b,
+0xfc3c73,
+0xfe6f83,
+0x0264b3,
+0xfe5ef3,
+0x3ea030,
+0x6f129d,
+0xf14c40,
+0xdbbf58,
+0x2b1358,
+0xda0390,
+0x1e5960,
+0xe92088,
+0x1034f8,
+0xf52c00,
+0x06cfe8,
+0xfbfc98,
+0x023104,
+0xba501b,
+0x1e683b,
+0xf5460b,
+0x023efb,
+0x00878b,
+0xff2633,
+0x497dd8,
+0x6ef2a5,
+0xdda780,
+0xea95d0,
+0x21ca50,
+0xdf6710,
+0x1b7880,
+0xea7720,
+0x0fc900,
+0xf51a98,
+0x071778,
+0xfba8d8,
+0x027b84,
+0xac06cb,
+0x283a63,
+0xef271b,
+0x05b193,
+0xfeceb3,
+0xffdfeb,
+0x5561e0,
+0x6d93e5,
+0xcbaf78,
+0xf99118,
+0x17aaa0,
+0xe5c408,
+0x17b2e0,
+0xec89f0,
+0x0ecde0,
+0xf56fc8,
+0x071978,
+0xfb81d8,
+0x02aad0,
+0xa1a46b,
+0x2ff333,
+0xea151b,
+0x08a803,
+0xfd4a6b,
+0x000003,
+0x000020,
+0x3fffe0,
+0x023c94,
+0x5ed280,
+0x6a9a5d,
+0xbf42f0,
+0x056260,
+0x0f02e8,
+0xeb9d08,
+0x13f0e8,
+0xeed498,
+0x0d8628,
+0xf610e8,
+0x06dac8,
+0xfb8ca8,
+0x02b6a8,
+0x9d1d03,
+0x3411d3,
+0xe7110b,
+0x0a8b43,
+0xfc4793,
+0x0208b8,
+0x6d23e0,
+0x66c791,
+0xb09170,
+0x142c90,
+0x03c304,
+0xf376f8,
+0x0eb9d8,
+0xf220d0,
+0x0b9710,
+0xf71850,
+0x0661c0,
+0xfbb618,
+0x02b430,
+0x99fe5b,
+0x37ceab,
+0xe408e3,
+0x0c8ac3,
+0xfb2e83,
+0x0464a8,
+0x782010,
+0x61b101,
+0xa7ab80,
+0x1ef5c0,
+0xfadbf0,
+0xfa10a0,
+0x0a1678,
+0xf53c30,
+0x09a2c0,
+0xf83d98,
+0x05c418,
+0xfc0144,
+0x0296d8,
+0x9badf3,
+0x386703,
+0xe2e293,
+0x0d8413,
+0xfa9443,
+0x05d8f0,
+0x42ccf5,
+0x5b6439,
+0x9fa4a8,
+0x2a0528,
+0xf141c8,
+0x5c184b,
+0x04be58,
+0xf8ea80,
+0x073f50,
+0xf9b218,
+0x04f108,
+0xfc6e8c,
+0x0264f0,
+0xa04a13,
+0x3770b3,
+0xe2819b,
+0x0e2353,
+0xfa1fab,
+0x07d850,
+0x498425,
+0x53f3c9,
+0x9a9170,
+0x334af8,
+0xe88c00,
+0x0875d0,
+0xdcf763,
+0xfcaf74,
+0x04b6b0,
+0xfb4d68,
+0x03fc0c,
+0xfcf654,
+0x022008,
+0xa80de3,
+0x348833,
+0xe33ce3,
+0x0e2e23,
+0xf9f08b,
+0x0aadb0,
+0x4fdc61,
+0x4b98d9,
+0x989408,
+0x3a6068,
+0xe12888,
+0x0ec210,
+0xfa8240,
+0x14e61b,
+0x022f7c,
+0xfcf624,
+0x02f50c,
+0xfd8f38,
+0x7356ab,
+0xb24bfb,
+0x300053,
+0xe4f083,
+0x0db28b,
+0xfa0193,
+0x0e5198,
+0x55cb8d,
+0x427b21,
+0x9968b8,
+0x3f50c0,
+0xdb27e8,
+0x143b08,
+0xf604a8,
+0x03bf5c,
+0xef1dc3,
+0xa7922b,
+0x7977cb,
+0x8ca91b,
+0x5c4373,
+0xbe654b,
+0x2a32fb,
+0xe76cb3,
+0x0cc843,
+0xfa47fb,
+0x12b270,
+0x5b537d,
+0x716ee8,
+0x9cd140,
+0x423000,
+0xd68e40,
+0x18d298,
+0xf20c30,
+0x06e2f8,
+0xfd6ac0,
+0x0eee5b,
+0x3575db,
+0xb6e5bb,
+0x4398ab,
+0xcbda13,
+0x236a1b,
+0xea894b,
+0x0b83a3,
+0xfaba2b,
+0x17d078,
+0x606a75,
+0x5cd070,
+0xa2a0d0,
+0x4306e0,
+0xd365f8,
+0x1c7720,
+0xeeab88,
+0x09ae08,
+0xfb4778,
+0x7127a3,
+0xf2fbcb,
+0xe1581b,
+0x2a1533,
+0xda3733,
+0x1be75b,
+0xee2313,
+0x09f65b,
+0xfb4feb,
+0x1db640,
+0x64f695,
+0x4768e0,
+0xaaa7f0,
+0x41db98,
+0xd1bd70,
+0x1f1310,
+0xebf900,
+0x0c0d48,
+0xf961f0,
+0x032d94,
+0xb409ab,
+0x0aabc3,
+0x108f73,
+0xe8fccb,
+0x13f29b,
+0xf2141b,
+0x08330b,
+0xfc00bb,
+0x2477b8,
+0x68d739,
+0x318e40,
+0xb4aec0,
+0x3ebd10,
+0xd19bf0,
+0x2095b8,
+0xea0778,
+0x0def88,
+0xf7c838,
+0x046be0,
+0xfdea24,
+0x319613,
+0xf7da9b,
+0xf7ab83,
+0x0bd423,
+0xf635fb,
+0x064ca3,
+0xfcc40b,
+0x2c29d8,
+0x6be82d,
+0x1ba3e0,
+0xc06ee8,
+0x39c7a8,
+0xd2fe70,
+0x20f5c0,
+0xe8e4e8,
+0x0f46d0,
+0xf68680,
+0x0575e0,
+0xfd2110,
+0x54da23,
+0xe0c55b,
+0x05c47b,
+0x03d513,
+0xfa6163,
+0x0456bb,
+0xfd9103,
+0x34dcb8,
+0x6e0619,
+0x0617a0,
+0xcd9208,
+0x3327e0,
+0xd5d488,
+0x2033b8,
+0xe89830,
+0x1009d8,
+0xf5a608,
+0x064398,
+0xfc7b10,
+0x735b3b,
+0xcc0f3b,
+0x12cf0b,
+0xfc3c73,
+0xfe6f83,
+0x0264b3,
+0xfe5ef3,
+0x3ea030,
+0x6f129d,
+0xf14c40,
+0xdbbf58,
+0x2b1358,
+0xda0390,
+0x1e5960,
+0xe92088,
+0x1034f8,
+0xf52c00,
+0x06cfe8,
+0xfbfc98,
+0x023104,
+0xba501b,
+0x1e683b,
+0xf5460b,
+0x023efb,
+0x00878b,
+0xff2633,
+0x497dd8,
+0x6ef2a5,
+0xdda780,
+0xea95d0,
+0x21ca50,
+0xdf6710,
+0x1b7880,
+0xea7720,
+0x0fc900,
+0xf51a98,
+0x071778,
+0xfba8d8,
+0x027b84,
+0xac06cb,
+0x283a63,
+0xef271b,
+0x05b193,
+0xfeceb3,
+0xffdfeb,
+0x5561e0,
+0x6d93e5,
+0xcbaf78,
+0xf99118,
+0x17aaa0,
+0xe5c408,
+0x17b2e0,
+0xec89f0,
+0x0ecde0,
+0xf56fc8,
+0x071978,
+0xfb81d8,
+0x02aad0,
+0xa1a46b,
+0x2ff333,
+0xea151b,
+0x08a803,
+0xfd4a6b,
+0x000003,
+0x000020,
+0x3fffe0,
+0x01b16b,
+0xf855f3,
+0x14740b,
+0xd40cc3,
+0x539323,
+0xfdafb8,
+0x03fef8,
+0xf8cbc0,
+0x107398,
+0x7f26c5,
+0xf19bc0,
+0x06a660,
+0xfc4508,
+0x0228bc,
+0xb2821b,
+0x284343,
+0xeda3d3,
+0x069cf3,
+0x03c6eb,
+0xefdbfb,
+0x2a4a93,
+0xa5ff43,
+0x02a8ac,
+0xfb4da0,
+0x081d20,
+0xf146b8,
+0x22b568,
+0x7ca649,
+0xe57730,
+0x0c8b38,
+0xf8ede8,
+0x041728,
+0xfdb6d0,
+0x4b880b,
+0xddec9b,
+0x0c0373,
+0x06309b,
+0xe6e21b,
+0x40ab93,
+0xfdde98,
+0x040178,
+0xf8f1a0,
+0x0c31f8,
+0xe9b5b8,
+0x367598,
+0x788dfd,
+0xdbb070,
+0x1185c8,
+0xf61488,
+0x05bc08,
+0xfcce9c,
+0x68d11b,
+0xd13c0b,
+0x101e33,
+0x08d62b,
+0xddc993,
+0x56a233,
+0xfd2bf0,
+0x054a20,
+0xf6b500,
+0x1012a8,
+0xe26390,
+0x4b56d0,
+0x72f70d,
+0xd45408,
+0x157878,
+0xf3cc50,
+0x070c10,
+0xfc1754,
+0x7f746f,
+0xc7c91b,
+0x12ea3b,
+0x0b96fb,
+0xd501e3,
+0x6b2573,
+0xfc8844,
+0x067398,
+0xf4b188,
+0x139340,
+0xdb9f08,
+0x60f058,
+0x6c0395,
+0xcf5d50,
+0x185148,
+0xf221f8,
+0x07fff0,
+0xfb9490,
+0x023c70,
+0xc1a1c3,
+0x147503,
+0x0e4b13,
+0xcd04b3,
+0x7d228f,
+0xfbfbf8,
+0x076f18,
+0xf30060,
+0x1688a8,
+0xd5b880,
+0x76d0d4,
+0x63ddc5,
+0xccb738,
+0x1a0988,
+0xf11b68,
+0x089470,
+0xfb4790,
+0x025f04,
+0xbeae3b,
+0x14d9d3,
+0x10c49b,
+0xc650c3,
+0x022e24,
+0xfb8f00,
+0x082ea8,
+0xf1b920,
+0x18ca30,
+0xd0ff50,
+0x4640a1,
+0x5ab67d,
+0xcc3da8,
+0x1aa578,
+0xf0b7e8,
+0x08ca48,
+0xfb2f48,
+0x0266a0,
+0xbeb5b3,
+0x143ecb,
+0x12d1ab,
+0xc1642b,
+0x02555c,
+0xfb48b0,
+0x08a5d0,
+0xf0f0a0,
+0x1a3350,
+0xcdbf38,
+0x50c415,
+0x50c415,
+0xcdbf38,
+0x1a3350,
+0xf0f0a0,
+0x08a5d0,
+0xfb48b0,
+0x02555c,
+0xc1642b,
+0x12d1ab,
+0x143ecb,
+0xbeb5b3,
+0x0266a0,
+0xfb2f48,
+0x08ca48,
+0xf0b7e8,
+0x1aa578,
+0xcc3da8,
+0x5ab67d,
+0x4640a1,
+0xd0ff50,
+0x18ca30,
+0xf1b920,
+0x082ea8,
+0xfb8f00,
+0x022e24,
+0xc650c3,
+0x10c49b,
+0x14d9d3,
+0xbeae3b,
+0x025f04,
+0xfb4790,
+0x089470,
+0xf11b68,
+0x1a0988,
+0xccb738,
+0x63ddc5,
+0x76d0d4,
+0xd5b880,
+0x1688a8,
+0xf30060,
+0x076f18,
+0xfbfbf8,
+0x7d228f,
+0xcd04b3,
+0x0e4b13,
+0x147503,
+0xc1a1c3,
+0x023c70,
+0xfb9490,
+0x07fff0,
+0xf221f8,
+0x185148,
+0xcf5d50,
+0x6c0395,
+0x60f058,
+0xdb9f08,
+0x139340,
+0xf4b188,
+0x067398,
+0xfc8844,
+0x6b2573,
+0xd501e3,
+0x0b96fb,
+0x12ea3b,
+0xc7c91b,
+0x7f746f,
+0xfc1754,
+0x070c10,
+0xf3cc50,
+0x157878,
+0xd45408,
+0x72f70d,
+0x4b56d0,
+0xe26390,
+0x1012a8,
+0xf6b500,
+0x054a20,
+0xfd2bf0,
+0x56a233,
+0xddc993,
+0x08d62b,
+0x101e33,
+0xd13c0b,
+0x68d11b,
+0xfcce9c,
+0x05bc08,
+0xf61488,
+0x1185c8,
+0xdbb070,
+0x788dfd,
+0x367598,
+0xe9b5b8,
+0x0c31f8,
+0xf8f1a0,
+0x040178,
+0xfdde98,
+0x40ab93,
+0xe6e21b,
+0x06309b,
+0x0c0373,
+0xddec9b,
+0x4b880b,
+0xfdb6d0,
+0x041728,
+0xf8ede8,
+0x0c8b38,
+0xe57730,
+0x7ca649,
+0x22b568,
+0xf146b8,
+0x081d20,
+0xfb4da0,
+0x02a8ac,
+0xa5ff43,
+0x2a4a93,
+0xefdbfb,
+0x03c6eb,
+0x069cf3,
+0xeda3d3,
+0x284343,
+0xb2821b,
+0x0228bc,
+0xfc4508,
+0x06a660,
+0xf19bc0,
+0x7f26c5,
+0x107398,
+0xf8cbc0,
+0x03fef8,
+0xfdafb8,
+0x539323,
+0xd40cc3,
+0x14740b,
+0xf855f3,
+0x01b16b,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x040002,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000003,
+0x000020,
+0x3fffe0,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0xb29ef9,
+0x06d0f0,
+0x06f82a,
+0x000003,
+0xf907da,
+0xf92f10,
+0x4d6109,
+0x5b69b8,
+0x28bfdc,
+0xfa6c52,
+0x8de6c0,
+0x074aaa,
+0x7a7c54,
+0x078e34,
+0xe705e8,
+0x2cd4fc,
+0xcb8068,
+0x2cd4fc,
+0xe705e8,
+0x078e34,
+0xbcc9d9,
+0x0d38aa,
+0xdc89f2,
+0x33e6a2,
+0xd43b62,
+0x143386,
+0x4fad57,
+0xfbc240,
+0x07ba10,
+0xf6e0d0,
+0x07ba10,
+0xfbc240,
+0x4fad57,
+0xb8ab0d,
+0x0de5ae,
+0xdb14ea,
+0x358402,
+0xd34f7e,
+0x146b32,
+0x882bbd,
+0x0b38ba,
+0xf4c74a,
+0x77d445,
+0x70255d,
+0xf5085a,
+0x0b75e6,
+0x0b2ce8,
+0xfc17ec,
+0x14ffa0,
+0x9543af,
+0x14ffa0,
+0xfc17ec,
+0x0b2ce8,
+0xb7e094,
+0x0693b6,
+0xee7e42,
+0x1b0bae,
+0xe6318e,
+0x0e8672,
+0x035ac0,
+0xdae2df,
+0x063e74,
+0x1acf33,
+0x063e74,
+0xdae2df,
+0x035ac0,
+0xb1a5e4,
+0x06f542,
+0xedda66,
+0x1b9aa6,
+0xe5f54a,
+0x0e8d72,
+0x666669,
+0x999999,
+0x000003,
+0x08c704,
+0x000003,
+0xf4b6f8,
+0x000003,
+0x0fcca4,
+0x000003,
+0xe5aaf0,
+0x000003,
+0x4eff30,
+0x7c1680,
+0x4eff30,
+0x000003,
+0xe5aaf0,
+0x000003,
+0x0fcca4,
+0x000003,
+0xf4b6f8,
+0x000003,
+0x08c704,
+0x000003,
+0x028e88,
+0xb46d8b,
+0x051de8,
+0x183def,
+0x04d91c,
+0x183def,
+0x051de8,
+0xb46d8b,
+0x028e88,
+0xfd245c,
+0x22e2b4,
+0x9f3a1d,
+0x09cf9e,
+0xeb653a,
+0x1cb806,
+0xe5ac1e,
+0x0ea2c6,
+0x000003,
+0x000003,
+0x02c197,
+0x05832b,
+0x02c197,
+0x000003,
+0x000003,
+0x84a705,
+0x07da1a,
+0x000003,
+0x0430ab,
+0x7ff7a1,
+0x000003,
+0x000003,
+0x02c197,
+0x05832b,
+0x02c197,
+0x000003,
+0x000003,
+0x84a705,
+0x07da1a,
+0x000003,
+0x000003,
+0x02c197,
+0x05832b,
+0x02c197,
+0x000003,
+0x000003,
+0x84a705,
+0x07da1a,
+0x000003,
+0x0430ab,
+0x7ff7a1,
+0x000003,
+0x0430ab,
+0x7ff7a1,
+0x000020,
+0x3fffe0,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x040002,
+0x000000,
+0x000000,
+0x000000,
+0x000000,
+0x269ec3,
+0x0d0ff4,
+0x051eba,
+0x640001,
+0x046bdc,
+0xfcbce0,
+0x03fc14,
+0x03fc14,
+0xfcbce0,
+0x046bdc,
+0x45a895,
+0xf4a186,
+0x18a312,
+0xe445b2,
+0x10419e,
+0x090500,
+0x16c7b0,
+0x2cad48,
+0x3a8790,
+0x3a8790,
+0x2cad48,
+0x16c7b0,
+0x090500,
+0x1d3910,
+0xafcb81,
+0x07030e,
+0xf2f61a,
+0x10728a,
+0xf06caa,
+0x09186a,
+0x048280,
+0x0b63d8,
+0x1656a8,
+0x1d43c8,
+0x1d43c8,
+0x1656a8,
+0x0b63d8,
+0x048280,
+0x1d3910,
+0xafcb81,
+0x07030e,
+0xf2f61a,
+0x10728a,
+0xf06caa,
+0x09186a,
diff --git a/sound/soc/codecs/abe/C_ABE_FW.PM b/sound/soc/codecs/abe/C_ABE_FW.PM
new file mode 100644
index 000000000000..851f1d70a181
--- /dev/null
+++ b/sound/soc/codecs/abe/C_ABE_FW.PM
@@ -0,0 +1,2048 @@
+0x1600b20f,
+0x0a000410,
+0x00000000,
+0x00000000,
+0x07800000,
+0x160172ce,
+0x014000e0,
+0x014000e1,
+0x014000e2,
+0x014000e3,
+0x014000e4,
+0x014000e5,
+0x014000e6,
+0x014000e7,
+0x014000e8,
+0x014000e9,
+0x014000ea,
+0x014000eb,
+0x014000ec,
+0x014000ed,
+0x014000ef,
+0x014000ef,
+0x144000e4,
+0x9e000000,
+0x0a200380,
+0x9e000040,
+0x0a200380,
+0x9e000080,
+0x0a200380,
+0x9e0000c0,
+0x0a200380,
+0x9e080000,
+0x0a200380,
+0x9e080100,
+0x0a200380,
+0x9e080200,
+0x0a200380,
+0x9e080300,
+0x0a200380,
+0x9e080400,
+0x0a200380,
+0x9e080500,
+0x0a200380,
+0x9e080600,
+0x0a200380,
+0x9e080700,
+0x0a200380,
+0x9c050800,
+0x0a200380,
+0x16000010,
+0x16000001,
+0x17000102,
+0x01400042,
+0x17800103,
+0x01400043,
+0x98020000,
+0x07800000,
+0x01400040,
+0x01400041,
+0x01400042,
+0x01400043,
+0x08200000,
+0x07800000,
+0x07800000,
+0x08200000,
+0x048004ff,
+0x0a2003e0,
+0x160116ec,
+0x400000cc,
+0x1600000d,
+0x05800dc0,
+0x0a8006f0,
+0x16017bad,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x4a000700,
+0x1601174c,
+0x1601174c,
+0x400000cd,
+0x1601168e,
+0x013ffcfe,
+0x048008dd,
+0x013ffefd,
+0x400000cc,
+0x1600000d,
+0x160116ce,
+0x000000cc,
+0x410000ec,
+0x05800dc0,
+0x0a800a10,
+0x16017bad,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x403ffcfd,
+0x1601174c,
+0x000000ce,
+0x400000dd,
+0x048002d0,
+0x403ffef0,
+0x048ffe02,
+0x413ffcf2,
+0x120001dd,
+0x04000ded,
+0x410000cd,
+0x05c000d0,
+0x0ac00750,
+0x400000cd,
+0x1601063e,
+0x16011780,
+0x05c00de0,
+0x0ae00ca0,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16055552,
+0x03000102,
+0x01000231,
+0x08400000,
+0x07800000,
+0x07800000,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16011742,
+0x00000022,
+0x03000102,
+0x01000231,
+0x0a001050,
+0x4000000d,
+0x1600000e,
+0x05c00de0,
+0x0ac00cf0,
+0x0a000e80,
+0x1600000d,
+0x1601178e,
+0x010000ed,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16055552,
+0x03000102,
+0x01000231,
+0x08400000,
+0x07800000,
+0x07800000,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16011742,
+0x00000022,
+0x03000102,
+0x01000231,
+0x1601176d,
+0x400000de,
+0x1600fa40,
+0x010000c0,
+0x048001ec,
+0x010000dc,
+0x0a204ef0,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16055552,
+0x03000102,
+0x01000231,
+0x08400000,
+0x07800000,
+0x07800000,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000432,
+0x04800211,
+0x04400211,
+0x16006502,
+0x00000022,
+0x03000102,
+0x01000231,
+0x4a000440,
+0x160116ec,
+0x16000002,
+0x05c00100,
+0x0ac010b0,
+0x16000052,
+0x07800000,
+0x07800000,
+0x07800000,
+0x08200000,
+0x0a001110,
+0x9d0c0118,
+0x9c080018,
+0x98801100,
+0x9d0c0118,
+0x08200000,
+0x0a001170,
+0x9d0c0118,
+0x9c180028,
+0x9c180068,
+0x98801160,
+0x9d0c0118,
+0x08200000,
+0x0a0011e0,
+0x9d0c0108,
+0x9c180028,
+0x988011d0,
+0x9d0c0108,
+0x08200000,
+0x0a001240,
+0x9d180108,
+0x9c0c0038,
+0x98801230,
+0x9d180108,
+0x08200000,
+0xdc0c0018,
+0x04a001dd,
+0x9f040010,
+0x9f03fc10,
+0x9c0c00b8,
+0x9f0400b0,
+0x9d188108,
+0x9f065810,
+0x988012b0,
+0x9f03fc10,
+0x07800000,
+0x07800000,
+0x9d188108,
+0x08200000,
+0x0a001390,
+0x9d180108,
+0x9d180148,
+0x9c0c0018,
+0x98801370,
+0x9d180108,
+0x9d180148,
+0x08200000,
+0x40800605,
+0x144000d3,
+0x144000e1,
+0x1601860e,
+0x12000155,
+0x420005ee,
+0x04a001dd,
+0x0b200000,
+0x9e088000,
+0x40000e05,
+0x1440001e,
+0x40800b01,
+0x16000007,
+0x9e0e8040,
+0x9e0f0070,
+0x04200355,
+0x01000e05,
+0x06000005,
+0x0aa01670,
+0x40000403,
+0x12000f1d,
+0x40800a06,
+0x12800fdd,
+0x0600000d,
+0x4a8015e0,
+0x12000233,
+0x40001604,
+0x04800111,
+0x00001405,
+0x01000e04,
+0x01000c05,
+0x0a001630,
+0x40001204,
+0x04800111,
+0x00001005,
+0x01000e04,
+0x01000c05,
+0x9e0e0530,
+0x01800b01,
+0x9e0e8050,
+0x9d140570,
+0x08200000,
+0x0080070d,
+0x00800203,
+0x40800905,
+0x048002ff,
+0x413ffefe,
+0x040003dd,
+0x00000e04,
+0x9c03a950,
+0x06000004,
+0x0a8017f0,
+0x058004d0,
+0x0ae017e0,
+0x042004d2,
+0x1440004d,
+0x0a2013e0,
+0x00000e04,
+0x05800420,
+0x0ae017b0,
+0x0a0017f0,
+0x1440002d,
+0x0a2013e0,
+0x0a0017f0,
+0x0a2013e0,
+0x003ffefe,
+0x40800905,
+0x048ffeff,
+0x9d03a950,
+0x08200000,
+0x010002fe,
+0x010004f1,
+0x010006f2,
+0x010008f3,
+0x0a201920,
+0x000004f0,
+0x0a201920,
+0x000006f0,
+0x0a201920,
+0x000008f0,
+0x0a201920,
+0x000002fe,
+0x07800000,
+0x08200000,
+0x16000006,
+0x05800600,
+0x0a801df0,
+0x00800b01,
+0x4080070d,
+0x12000211,
+0x00800203,
+0x40800807,
+0x040003dd,
+0x00801105,
+0x9e0e0410,
+0x40800c01,
+0x144000d4,
+0x40800d02,
+0x04a001dd,
+0xdc180404,
+0x10000744,
+0xdc180480,
+0x06000005,
+0x00800903,
+0x0a801af0,
+0x9c053960,
+0x9c053b50,
+0xdc039830,
+0x05800610,
+0x4ac01bb0,
+0x05800260,
+0x0ae01b70,
+0x0a001bf0,
+0x9c043860,
+0x9c043b50,
+0xdc039930,
+0x05800610,
+0x4ac01b70,
+0x05800260,
+0x0ae01bb0,
+0x0a001bf0,
+0x00801005,
+0x40800e04,
+0x04800155,
+0x0a001be0,
+0x00801005,
+0x40800f04,
+0x04a00155,
+0x01801005,
+0x144000e1,
+0x1601860e,
+0x00800605,
+0x12000155,
+0x020005ee,
+0x0b200000,
+0x4b400004,
+0x1440001e,
+0x9c100308,
+0x00801105,
+0x40800b01,
+0x06000005,
+0x0a801ce0,
+0x9d039830,
+0x0a001cf0,
+0x9d039930,
+0x40000404,
+0x12000211,
+0x40800713,
+0x12000244,
+0x40801105,
+0x04d08033,
+0x9e0e0540,
+0x41800713,
+0x04000511,
+0x00800a02,
+0x9e088300,
+0x07800000,
+0x07800000,
+0x9d140530,
+0x12800277,
+0x01800017,
+0x08200000,
+0x048004ff,
+0x9c180408,
+0x9c180488,
+0x08000000,
+0x9c018f10,
+0x9c043e60,
+0x048ffef7,
+0x01000076,
+0x003ffef7,
+0x05c00730,
+0x0ae01ec0,
+0x0a0020e0,
+0x4a001fe0,
+0x16000007,
+0x9c180628,
+0x9c180668,
+0x9c1806a8,
+0x9c1806e8,
+0x9d0c8018,
+0x9d0c8708,
+0x9d0c8758,
+0x9d0c81b8,
+0x9c180628,
+0x9c180668,
+0x9d0c87a8,
+0x9d0c87f8,
+0x9d0c8218,
+0x9d0c8708,
+0x9d0c8758,
+0x04800177,
+0x05c00070,
+0x0ac01ee0,
+0x00000020,
+0x12000907,
+0x12000101,
+0x12800977,
+0x12800911,
+0x04000373,
+0x05c00310,
+0x0ae02090,
+0x0a0020a0,
+0x04200133,
+0x04c07f33,
+0x04cf8000,
+0x04500303,
+0x01000023,
+0x048ffcff,
+0x08200000,
+0x048004ff,
+0x9c180408,
+0x9c180488,
+0x08000000,
+0x9c039b30,
+0x9c053150,
+0x048ffef7,
+0x01000075,
+0x40000007,
+0x16000004,
+0x003ffef6,
+0x12000177,
+0x12800977,
+0x05800460,
+0x048fff77,
+0x04200676,
+0x4a802300,
+0x14400037,
+0x05c00620,
+0x0ae02300,
+0x0a002450,
+0x9c0c0018,
+0x9c0c02b8,
+0x07800000,
+0x9d188108,
+0x9d188148,
+0x9c0c0318,
+0x9d188188,
+0x9d1881c8,
+0x9d188108,
+0x9d188148,
+0x04800144,
+0x05c00140,
+0x0ac02250,
+0x00000201,
+0x04cf7f11,
+0x41000201,
+0x12000113,
+0x40000003,
+0x12800934,
+0x04000242,
+0x12000133,
+0x12800933,
+0x05c00230,
+0x0ae023e0,
+0x0a0023f0,
+0x04200322,
+0x04c07f22,
+0x16080ff3,
+0x04400311,
+0x12000822,
+0x04500212,
+0x01000202,
+0x9d03bb70,
+0x048ffcff,
+0x08200000,
+0x048004ff,
+0x9c180208,
+0x08000000,
+0x9c180288,
+0x08000000,
+0x08000000,
+0x9c053960,
+0x048ffef7,
+0x01000076,
+0x00000027,
+0x003ffef6,
+0x12000177,
+0x12800977,
+0x04200677,
+0x048fff77,
+0x413ffef7,
+0x05c00730,
+0x0ae025b0,
+0x0a002890,
+0x12000107,
+0x04000710,
+0x16000007,
+0x14400076,
+0x9e0f0070,
+0x00000017,
+0x9e0e8070,
+0x4a0026a0,
+0x14400014,
+0x9c0c0010,
+0x14400047,
+0x04800244,
+0x9d188108,
+0x00000277,
+0x9e0e8070,
+0x05c00040,
+0x0ac02640,
+0x9d040008,
+0x04800167,
+0x05c00d70,
+0x0ae025e0,
+0x16000007,
+0x9e0f0070,
+0x0000022d,
+0x00000027,
+0x120001d0,
+0x12000177,
+0x12800900,
+0x12800977,
+0x04000303,
+0x05c00370,
+0x0ac027c0,
+0x0a0027d0,
+0x04200733,
+0x408006cc,
+0x16080ff7,
+0x04c07f33,
+0x044007dd,
+0x12000833,
+0x045003d3,
+0x41000223,
+0x04c0ffc6,
+0x16000007,
+0x08000000,
+0x08000000,
+0x9d140370,
+0x048ffcff,
+0x08200000,
+0x048004ff,
+0x9c180408,
+0x08000000,
+0x9c180488,
+0x08000000,
+0x08000000,
+0x9c043e60,
+0x048ffef7,
+0x01000076,
+0x403ffef4,
+0x12000107,
+0x05c00470,
+0x0ae02990,
+0x0a002b20,
+0x4a002a20,
+0x16000004,
+0x9c180628,
+0x08000000,
+0x9c180668,
+0x08000000,
+0x08000000,
+0x9d0c8118,
+0x04800144,
+0x05c00040,
+0x0ac029b0,
+0x00000020,
+0x12000904,
+0x12000106,
+0x12800944,
+0x12800966,
+0x04000747,
+0x05c00760,
+0x0ae02ad0,
+0x0a002ae0,
+0x04200677,
+0x04c07f77,
+0x04cf8000,
+0x04500700,
+0x01000020,
+0x048ffcff,
+0x08200000,
+0x048004ff,
+0x9c180208,
+0x08000000,
+0x9c180288,
+0x08000000,
+0x08000000,
+0x9c053e60,
+0x048ffef7,
+0x01000076,
+0x00000027,
+0x12000177,
+0x12800977,
+0x413ffef7,
+0x05c00700,
+0x0ae02c40,
+0x0a002e80,
+0x12800107,
+0x4a002cd0,
+0x16000004,
+0x9c0c0018,
+0x08000000,
+0x08000000,
+0x9d188608,
+0x9d188648,
+0x04800144,
+0x05c00740,
+0x0ac02c70,
+0x00000227,
+0x00000024,
+0x12000176,
+0x12000144,
+0x12800966,
+0x12800944,
+0x04000060,
+0x05c00040,
+0x0ae02d90,
+0x0a002da0,
+0x04200400,
+0x16080ff4,
+0x04c07f00,
+0x04400477,
+0x12000800,
+0x04500070,
+0x04cf7f00,
+0x41000220,
+0x16002104,
+0x14400012,
+0x16000003,
+0x9e0e0540,
+0x07800000,
+0x07800000,
+0x9d140530,
+0x048ffcff,
+0x08200000,
+0x16011741,
+0x40000011,
+0x16000000,
+0x07800000,
+0x01000010,
+0x08200000,
+0x00000003,
+0x04500131,
+0x01000001,
+0x00000201,
+0x04500212,
+0x01000202,
+0x08200000,
+0x40000473,
+0x16000004,
+0x00000072,
+0x04200233,
+0x05800430,
+0x0ae02fe0,
+0x0a003000,
+0x00000874,
+0x04000433,
+0x00000a74,
+0x05c00340,
+0x0ac03040,
+0x08200000,
+0x01000025,
+0x00000075,
+0x04800252,
+0x01000072,
+0x01000256,
+0x00000076,
+0x00000675,
+0x04800266,
+0x41000076,
+0x05c00650,
+0x0ac03100,
+0x08200000,
+0x00000276,
+0x01000076,
+0x08200000,
+0x07800000,
+0x07800000,
+0x08200000,
+0x00400202,
+0x00400204,
+0x00000200,
+0x12000100,
+0x4a003200,
+0x04000020,
+0x40000046,
+0x04800244,
+0x41000026,
+0x04800222,
+0x05c00020,
+0x0ac031c0,
+0x08200000,
+0x40400201,
+0x16000003,
+0x40400402,
+0x1440000d,
+0x14400004,
+0x12000222,
+0x40d00021,
+0x12000210,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x400004d0,
+0x16000003,
+0x003ffe41,
+0x12000200,
+0x12000102,
+0x00d00020,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c180728,
+0x9c180768,
+0x07800000,
+0x07800000,
+0x9d0c8618,
+0x988033a0,
+0x08200000,
+0x40400202,
+0x16000003,
+0x40400401,
+0x1440000d,
+0x14400004,
+0x12000220,
+0x12000212,
+0x00d00021,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x400004d0,
+0x16000003,
+0x003ffe41,
+0x12000202,
+0x00d00020,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c180728,
+0x07800000,
+0x07800000,
+0x9d108608,
+0x98803570,
+0x08200000,
+0x40400202,
+0x16000003,
+0x40400401,
+0x1440000d,
+0x14400004,
+0x12000220,
+0x12000212,
+0x00d00021,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x000004d0,
+0x003ffe43,
+0x12000202,
+0x40d00020,
+0x12000231,
+0x14400010,
+0x16000003,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c0c0718,
+0x07800000,
+0x07800000,
+0x9d0c8618,
+0x98803740,
+0x08200000,
+0x40400202,
+0x16000003,
+0x40400401,
+0x1440000d,
+0x14400004,
+0x12000220,
+0x12000212,
+0x00d00021,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x000004d0,
+0x003ffe43,
+0x12000202,
+0x40d00020,
+0x12000231,
+0x14400010,
+0x16000003,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c100708,
+0x07800000,
+0x07800000,
+0x9d108608,
+0x98803910,
+0x08200000,
+0x40400202,
+0x16000003,
+0x4000040d,
+0x14400004,
+0x12000220,
+0x120002d2,
+0x40d0002d,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x0000044d,
+0x9c0c0010,
+0x07800000,
+0x07800000,
+0x9d108608,
+0x98803a60,
+0x08200000,
+0x40400202,
+0x16000003,
+0x4000040d,
+0x14400004,
+0x12000220,
+0x120002d2,
+0x40d0002d,
+0x14400001,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x0000044d,
+0x9c0c0010,
+0x07800000,
+0x07800000,
+0x9d0c8618,
+0x98803b80,
+0x08200000,
+0x40400201,
+0x16000003,
+0x40400402,
+0x1440000d,
+0x14400004,
+0x12000222,
+0x12000122,
+0x00d00020,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x400004d1,
+0x16000003,
+0x003ffe40,
+0x12000212,
+0x40d00020,
+0x12000201,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c0c0718,
+0x07800000,
+0x07800000,
+0x9d188608,
+0x9d188648,
+0x98803d20,
+0x08200000,
+0x40400201,
+0x16000003,
+0x40400402,
+0x1440000d,
+0x14400004,
+0x12000222,
+0x00d00020,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0600,
+0x400004d1,
+0x16000003,
+0x003ffe40,
+0x12000212,
+0x40d00020,
+0x12000201,
+0x14400010,
+0x08000000,
+0x08000000,
+0x9e0c0700,
+0x000004dd,
+0x9c100708,
+0x07800000,
+0x07800000,
+0x9d188608,
+0x98803ef0,
+0x08200000,
+0x40400202,
+0x048004ff,
+0x00400201,
+0x40000202,
+0x14400020,
+0x013ffcfe,
+0x0a202f00,
+0x403ffcfe,
+0x048ffcff,
+0x08200000,
+0x9c0c0018,
+0x1440001d,
+0x04a001dd,
+0x9d0c8318,
+0x07800000,
+0x9c0c0018,
+0xa00602ba,
+0x07800000,
+0x9d0c8318,
+0x9d0c81b8,
+0x9d0c82b8,
+0x98804040,
+0x07800000,
+0xa00602ba,
+0x07800000,
+0x07800000,
+0x9d0c81b8,
+0x9d0c82b8,
+0x08200000,
+0x9c0c0038,
+0x1440001d,
+0x04a001dd,
+0x9d0c8338,
+0x07800000,
+0xa00602ba,
+0xa006821a,
+0x9c0c0038,
+0x07800000,
+0x9d0c8298,
+0x9d0c8338,
+0x9d0c8198,
+0x98804170,
+0x07800000,
+0xa00602ba,
+0xa006821a,
+0x07800000,
+0x07800000,
+0x9d0c8298,
+0x9d0c8198,
+0x08200000,
+0x9f160028,
+0x9f168298,
+0x04a001dd,
+0x07800000,
+0x9d0c8128,
+0x07800000,
+0x9f160028,
+0x9f168298,
+0x988042b0,
+0x9d0c8128,
+0x08200000,
+0x9c0c03b0,
+0x9f160020,
+0x9f168098,
+0x07800000,
+0x9d0c8138,
+0x9d0c8278,
+0x98804330,
+0x08200000,
+0xdc0c0018,
+0x04a00201,
+0x04a001dd,
+0xdd040008,
+0x06000001,
+0x04a00111,
+0x0aa043c0,
+0x9d0c8118,
+0x988043a0,
+0x08200000,
+0x9c0c02b0,
+0x9c0c0018,
+0x04a00205,
+0x07800000,
+0x9d0c8118,
+0xdd0c81b8,
+0x06000005,
+0x04a00155,
+0x0aa04490,
+0x98804450,
+0x08200000,
+0x9f15001a,
+0x9f11041a,
+0x04a001dd,
+0x07800000,
+0x9d0c8118,
+0x07800000,
+0x9f15001a,
+0x9f11041a,
+0x98804530,
+0x9d0c8118,
+0x08200000,
+0x9f16001a,
+0x9f12021a,
+0x9f12031a,
+0x9f12051a,
+0x04a001dd,
+0x07800000,
+0x9d0c8118,
+0x07800000,
+0x9f16001a,
+0x9f12021a,
+0x9f12031a,
+0x9f12051a,
+0x98804600,
+0x9d0c8118,
+0x08200000,
+0x9f160010,
+0x9f168068,
+0x07800000,
+0x07800000,
+0x9d0c8128,
+0x98804690,
+0x08200000,
+0x00000023,
+0x048fff1d,
+0x04a00133,
+0x9c1803a0,
+0x06000003,
+0x0aa04820,
+0x9c0c0018,
+0x07800000,
+0x07800000,
+0x9d0c8118,
+0x9f020810,
+0x9f040020,
+0x9f040060,
+0x07800000,
+0x9d108208,
+0x9d108248,
+0x98804760,
+0x0a002ea0,
+0x9f16801a,
+0x9f120112,
+0x07800000,
+0x07800000,
+0x9d0c8118,
+0x9f03a010,
+0x9f026810,
+0x9f040020,
+0x9f040060,
+0x07800000,
+0x9d108208,
+0x9d108248,
+0x98804820,
+0x08200000,
+0x1600004d,
+0x144000e2,
+0x0a204970,
+0x04800200,
+0x98804920,
+0x1440002e,
+0x08200000,
+0x00800003,
+0x00800105,
+0x144000d7,
+0x1440001d,
+0x9c039830,
+0x9c03aa50,
+0x07800000,
+0x9c0c0018,
+0x9c0c02b8,
+0x07800000,
+0x07800000,
+0x9d0c8128,
+0x988049e0,
+0x1440007d,
+0x08200000,
+0x07800000,
+0x07800000,
+0x07800000,
+0x07800000,
+0x08200000,
+0x048010ff,
+0x413ff0fb,
+0x0480100d,
+0x013ff2fd,
+0x013ff4fa,
+0x013ff6fc,
+0x013ff8f8,
+0x013ffaf9,
+0x013ffcfe,
+0x4000000c,
+0x1600000e,
+0x04800200,
+0x413ffef0,
+0x05800ec0,
+0x0a804e20,
+0x16017bad,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x003ffefc,
+0x003ff2fe,
+0x0a004e40,
+0x003ffefc,
+0x003ff2fe,
+0x003ffef0,
+0x05c00ec0,
+0x0ac04b40,
+0x003ffcfe,
+0x003ff0fb,
+0x003ff4fa,
+0x003ff6fc,
+0x003ff8f8,
+0x403ffaf9,
+0x048ff0ff,
+0x08200000,
+0x048010ff,
+0x413ff0fb,
+0x1600000b,
+0x413ff4f9,
+0x1601218d,
+0x413ff6fc,
+0x16009e83,
+0x413ff2fb,
+0x144000d9,
+0x413ff8fa,
+0x1440003c,
+0x013ffaf8,
+0x013ffcfe,
+0x40400490,
+0x14400098,
+0x0000008e,
+0x058000e0,
+0x0a805270,
+0x0000000e,
+0x05800be0,
+0x0a805070,
+0x048fffee,
+0x0100000e,
+0x0a005270,
+0x4a005180,
+0x0480028a,
+0x0080090e,
+0x04c0ffee,
+0x120001ee,
+0x02000ece,
+0x0b200000,
+0x00000480,
+0x04800c00,
+0x01000480,
+0x0000029e,
+0x05c000e0,
+0x0ae05150,
+0x0a005170,
+0x00000280,
+0x010002a0,
+0x00000480,
+0x0000000e,
+0x05800be0,
+0x0aa051f0,
+0x0000048e,
+0x00000081,
+0x05800e10,
+0x0aa05090,
+0x0000048e,
+0x00000080,
+0x05800e00,
+0x0aa05270,
+0x403ff2f1,
+0x160117c0,
+0x144000b2,
+0x0a202f00,
+0x403ff2fe,
+0x16000020,
+0x04800899,
+0x048001ee,
+0x413ff2fe,
+0x05c000e0,
+0x0ac04fc0,
+0x003ffcfe,
+0x003ff0fb,
+0x003ff4f9,
+0x003ff6fc,
+0x003ff8fa,
+0x403ffaf8,
+0x048ff0ff,
+0x08200000,
+0x40000206,
+0x16000005,
+0x40000007,
+0x048004ff,
+0x413ffcfe,
+0x05800560,
+0x1440003d,
+0x0aa05410,
+0x1600000e,
+0x05800e70,
+0x0a8054e0,
+0x04cfff75,
+0x14400027,
+0x0a202f70,
+0x40000006,
+0x16000007,
+0x14400074,
+0x04cfff66,
+0x08000000,
+0x08000000,
+0x9d140070,
+0x01000204,
+0x01000004,
+0x0a0054f0,
+0x16000004,
+0x00000216,
+0x00000010,
+0x05800460,
+0x0aa05550,
+0x05800400,
+0x0a805630,
+0x144000d7,
+0x04cfff05,
+0x1440004d,
+0x0a202f70,
+0x40000016,
+0x16000007,
+0x003ffcfe,
+0x04cfff66,
+0x08000000,
+0x08000000,
+0x9d140170,
+0x0100021d,
+0x0100001d,
+0x0a005640,
+0x003ffcfe,
+0x048ffcff,
+0x08200000,
+0x9c0c00c0,
+0x9c030f10,
+0x9c009020,
+0x9c0c0468,
+0x9d0c8530,
+0x1600007d,
+0x9f130462,
+0x9f13056a,
+0x9c0c0428,
+0x9f130422,
+0x9d0c8570,
+0x16000004,
+0x9f1780ea,
+0x9f13052a,
+0x9c0c0468,
+0x9f130462,
+0x9d0c8530,
+0x16000005,
+0x9f1380ea,
+0x9f13056a,
+0x9c0c0428,
+0x9f130422,
+0x9d0c8570,
+0x07800000,
+0x9f1380ea,
+0x9f13052a,
+0x9c0c0468,
+0x9f130462,
+0x9d0c8530,
+0x98805780,
+0x9f1380ea,
+0x9f13056a,
+0x9c0c0428,
+0x9f13042a,
+0x9d0c8570,
+0x16000006,
+0x9f1380ea,
+0x9f13052a,
+0x16000007,
+0x07800000,
+0x9d0c8538,
+0x9e048000,
+0x9f1380ea,
+0x9f1380ea,
+0x9c031830,
+0x07800000,
+0x9d0c83c8,
+0x07800000,
+0x07800000,
+0xa007026a,
+0x9f0628b0,
+0x07800000,
+0x9d0c8248,
+0x9d0c8190,
+0x08200000,
+0x40000024,
+0x048002ff,
+0x41000224,
+0x16000005,
+0x413ffefe,
+0x04000400,
+0x01000025,
+0x0a205b40,
+0x003ffefe,
+0x048ffeff,
+0x08200000,
+0x048002ff,
+0x413ffefe,
+0x16000005,
+0x01000025,
+0x0a205b40,
+0x40000024,
+0x16000005,
+0x403ffefe,
+0x04200454,
+0x41000224,
+0x048ffeff,
+0x08200000,
+0x048008ff,
+0x413ff8f8,
+0x1440000d,
+0x9c038e10,
+0x413ffaf9,
+0x04a001dd,
+0x413ffcfa,
+0x16000001,
+0x413ffefb,
+0x160000f0,
+0x9c100400,
+0x9c100480,
+0x9c1d06c8,
+0x9f085030,
+0x9c180678,
+0x9c180650,
+0x058001a0,
+0x0aa05f10,
+0x04800144,
+0x04400044,
+0x07800000,
+0x05800040,
+0x9d180658,
+0x0a805d20,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x07800000,
+0x9e0d0500,
+0x0a005df0,
+0x05800160,
+0x0ac05da0,
+0x9e090000,
+0x07800000,
+0x07800000,
+0x9e0d0500,
+0x9d040508,
+0x0a005df0,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x9d040008,
+0x9e0d0500,
+0x05800160,
+0x0ac05e50,
+0x0480014b,
+0x044000bb,
+0x4a005e80,
+0x1440004a,
+0x0420040a,
+0x04a001ab,
+0x044000bb,
+0x120001aa,
+0x42000a38,
+0x120001bb,
+0x42000b39,
+0x12000288,
+0x12000299,
+0x9e0e8280,
+0xca006020,
+0x1e0e8390,
+0xdd040608,
+0x05800160,
+0x0ac05fc0,
+0x9d040008,
+0x9e090000,
+0x07800000,
+0x05800040,
+0x9e0d0500,
+0x0aa06020,
+0x9d040508,
+0x0a006020,
+0x9e090000,
+0x05800040,
+0x9d040008,
+0x9e0d0500,
+0x0a806020,
+0x9d040508,
+0x9c1d06c8,
+0xdc1d0648,
+0x1f0400b0,
+0x9c100700,
+0xdc1d06c8,
+0x1f040010,
+0x9d108480,
+0x9f0940b0,
+0x9d108700,
+0x000006c9,
+0x06000008,
+0x0aa06210,
+0xdc1d0688,
+0x14400005,
+0x9c1d0608,
+0x04a00255,
+0xdd108480,
+0x16000017,
+0xdd108700,
+0x160ffff8,
+0x05800540,
+0x0aa061d0,
+0x05800160,
+0x0ac061c0,
+0x01000027,
+0x0a0061d0,
+0x01000028,
+0x9e088000,
+0xa0054dba,
+0xa005c81a,
+0x0a0062b0,
+0xdd040608,
+0x1e088000,
+0xa0054dba,
+0xa005c81a,
+0x9f1f80b0,
+0x9f1e0010,
+0x9f040020,
+0x9f040070,
+0x9f020810,
+0x9d040608,
+0x9e0f0070,
+0x9d0c8118,
+0x98805be0,
+0x003ffefb,
+0x003ffcfa,
+0x003ffaf9,
+0x003ff8f8,
+0x048ff8ff,
+0x08200000,
+0x9c0c0018,
+0x9f0b0010,
+0x00000426,
+0x40000627,
+0x04a001dd,
+0x9d0c8318,
+0x16000004,
+0xa00602ba,
+0x9c0c0018,
+0x9f0b0010,
+0x9d0c81b8,
+0x9d0c82b8,
+0x9d0c8318,
+0x988063b0,
+0x07800000,
+0xa00602ba,
+0x16000015,
+0xdc1d0508,
+0x05800460,
+0x9d0c81b8,
+0x9d0c82b8,
+0xdc1d0548,
+0x1f0400b0,
+0x0a806550,
+0x9f093020,
+0x07800000,
+0x07800000,
+0x05800460,
+0x0a8065f0,
+0x01000025,
+0x01000424,
+0x01000625,
+0x0a0065f0,
+0x05800470,
+0x0a8065f0,
+0x9f083860,
+0x07800000,
+0x07800000,
+0x05800470,
+0x0a8065f0,
+0x01000225,
+0x01000425,
+0x01000624,
+0x08200000,
+0x1440000d,
+0x40000004,
+0x16000011,
+0x40000205,
+0x16000002,
+0x40000406,
+0x16000003,
+0x400006d7,
+0x16000000,
+0x9c0c00b0,
+0x9f03a0b0,
+0x9e048000,
+0xdc1803e0,
+0x1f040020,
+0x9e040040,
+0x9f0400d0,
+0x9c0c0090,
+0x9e008000,
+0x9d1883c0,
+0x9c0c0240,
+0xc10000d4,
+0x1f040090,
+0x010002d5,
+0x010004d6,
+0x010006d7,
+0x9d0c8120,
+0x08200000,
+0x9c038600,
+0x07800000,
+0x07800000,
+0x9c180770,
+0xdc100348,
+0x160fff05,
+0x9f000810,
+0x9f118412,
+0x9f001010,
+0x9f002810,
+0x9c0c00b8,
+0x160ffd80,
+0x9d0c8410,
+0x9f1d8012,
+0x9f001810,
+0x9f0400d0,
+0x9c0c0210,
+0x16000204,
+0xdd0e00b0,
+0x16000005,
+0x9f1d80b2,
+0x9f0000b0,
+0x9f0020b0,
+0x9f0400d0,
+0x05800560,
+0x0a806970,
+0x9c0c0510,
+0x0a006980,
+0x9c0c0618,
+0x16000014,
+0x9d0c81e8,
+0x9d0c8148,
+0x0a8069f0,
+0x9c0c05b0,
+0x9c0c0510,
+0x0a006a10,
+0x9c0c06b8,
+0x9c0c0618,
+0x07800000,
+0x9d0c81e8,
+0x9d0c8148,
+0x988067f0,
+0x9d180750,
+0x08200000,
+0x9d019220,
+0x048002ff,
+0x14400004,
+0x413ffefe,
+0x16000040,
+0x9c010910,
+0x0a204440,
+0x14400040,
+0x9c030810,
+0x16000171,
+0x9c009f30,
+0x9c019220,
+0x0a203ff0,
+0x9c009830,
+0x003ffefe,
+0x048ffeff,
+0x08200000,
+0x048004ff,
+0x413ffcfe,
+0x16017bad,
+0x1600be4c,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x16017bad,
+0x1600e6cc,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x16017bad,
+0x1600e4cc,
+0x008001c8,
+0x408000c5,
+0x04c0ff88,
+0x408002c9,
+0x04c0ff55,
+0x408003ca,
+0x04c0ff99,
+0xdc02c080,
+0x12000155,
+0x408004cb,
+0x04c0ffaa,
+0x408005c4,
+0x04c0ffbb,
+0x9e080000,
+0x020005de,
+0x1601b083,
+0x00000030,
+0x00000231,
+0x00000435,
+0x04800211,
+0x04400511,
+0x0300010e,
+0x01000231,
+0x04c0ff44,
+0xdc02c990,
+0x04c3ff2d,
+0xdc01d2a0,
+0x128002dd,
+0xdc02dcb0,
+0x048fffdd,
+0x9c062040,
+0x0b200000,
+0x9d02c080,
+0x9d02c990,
+0x9d01d2a0,
+0x9d02dcb0,
+0x16000161,
+0x07800000,
+0x07800000,
+0x07800000,
+0x9c038e10,
+0x07800000,
+0x07800000,
+0x07800000,
+0x9c180604,
+0x9c180680,
+0x07800000,
+0x07800000,
+0x07800000,
+0x9c043e60,
+0x9c043f60,
+0x07800000,
+0x07800000,
+0x9c0c01b0,
+0x9c180628,
+0x9c180668,
+0x07800000,
+0x07800000,
+0x9f040030,
+0x9f040070,
+0x07800000,
+0x07800000,
+0x9d188708,
+0x9d188748,
+0x403ffcfe,
+0x048ffcff,
+0x08200000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x07800000,
+0x07800000,
+0x07800000,
+0x08400000,
+0x0a000000,
diff --git a/sound/soc/codecs/abe/C_ABE_FW.SM32 b/sound/soc/codecs/abe/C_ABE_FW.SM32
new file mode 100644
index 000000000000..ed17859ac2e6
--- /dev/null
+++ b/sound/soc/codecs/abe/C_ABE_FW.SM32
@@ -0,0 +1,3712 @@
+0x00000000,
+0x00044B03,
+0x00000000,
+0x00044E02,
+0x00000000,
+0x00068503,
+0x00000000,
+0x0004A905,
+0x00000000,
+0x0004AE04,
+0x00000000,
+0x00068005,
+0x00000000,
+0x0001330C,
+0x00000000,
+0x0004B228,
+0x00000000,
+0x00044B03,
+0x00000000,
+0x0004A905,
+0x00000000,
+0x00050228,
+0x00000000,
+0x00070806,
+0x00000000,
+0x0001D918,
+0x0000FA00,
+0x0000FA00,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00059700,
+0x00010E12,
+0x0000FC09,
+0x00010509,
+0x00090012,
+0x0017B800,
+0x00000000,
+0x0000FA00,
+0x00000002,
+0x00000000,
+0x000B0011,
+0x00000000,
+0x00000000,
+0x00000402,
+0x00000000,
+0x00013F0C,
+0x00000000,
+0x00014B0C,
+0x00000000,
+0x0001270C,
+0x00000000,
+0x00011B0C,
+0x00000000,
+0x00010F0C,
+0x00010F0C,
+0x00012C04,
+0x00010F0C,
+0x00013004,
+0x00011B0C,
+0x0001270C,
+0x00001124,
+0x00000000,
+0x00000000,
+0x0001570C,
+0x00000000,
+0x00013402,
+0x00000000,
+0x00016F0C,
+0x00000000,
+0x00017B0C,
+0x00018711,
+0x00018711,
+0x00000000,
+0x00014011,
+0x000B0011,
+0x00000000,
+0x00000000,
+0x0001630C,
+0x00000000,
+0x0006880C,
+0x00000000,
+0x00013602,
+0x00000000,
+0x0001F10C,
+0x0001D918,
+0x0002390C,
+0x0001D918,
+0x0002450C,
+0x00000000,
+0x0001FD0C,
+0x0001D900,
+0x0002510C,
+0x0001D900,
+0x00025D0C,
+0x00000000,
+0x0002090C,
+0x0001D918,
+0x0002690C,
+0x0001D918,
+0x0002750C,
+0x00000000,
+0x0002150C,
+0x0001D918,
+0x0002810C,
+0x0001D918,
+0x00028D0C,
+0x00000000,
+0x0002210C,
+0x0001D918,
+0x0002990C,
+0x0001D918,
+0x0002A50C,
+0x00000000,
+0x00022D0C,
+0x0001D918,
+0x0002B10C,
+0x0001D918,
+0x0002BD0C,
+0x0001D918,
+0x0002C90C,
+0x0001D918,
+0x0002D50C,
+0x0001D918,
+0x0002E10C,
+0x0001D918,
+0x0002ED0C,
+0x00000000,
+0x0002F93C,
+0x00000000,
+0x00033518,
+0x00000000,
+0x00034D18,
+0x00000000,
+0x00036518,
+0x00000000,
+0x00037D18,
+0x00063E01,
+0x00000202,
+0x00000000,
+0x00039506,
+0x00460001,
+0x00000800,
+0x00460003,
+0x00000800,
+0x00000000,
+0x00039B18,
+0x00000000,
+0x0003B318,
+0x00000000,
+0x0003CB18,
+0x00000000,
+0x0003E318,
+0x00000000,
+0x0003FB0C,
+0x00000002,
+0x00000000,
+0x00040711,
+0x00040711,
+0x00000000,
+0x00017311,
+0x00041811,
+0x00041811,
+0x00000000,
+0x00018411,
+0x00042911,
+0x00042911,
+0x00000000,
+0x00019511,
+0x00043A11,
+0x00043A11,
+0x00000000,
+0x0001A611,
+0x000B0019,
+0x00000000,
+0x000B0011,
+0x00000000,
+0x00001318,
+0x00000000,
+0x00001304,
+0x00000000,
+0x00001354,
+0x00000000,
+0x00045011,
+0x00045011,
+0x00000006,
+0x00000000,
+0x000012F0,
+0x00000000,
+0x00000000,
+0x00000602,
+0x0000000C,
+0x00001800,
+0x00000000,
+0x00046118,
+0x00000000,
+0x00047918,
+0x00000000,
+0x00049118,
+0x00000000,
+0x00046118,
+0x000C0010,
+0x00004800,
+0x000B19F4,
+0x00000000,
+0x000B19F2,
+0x00000000,
+0x000B19E8,
+0x00000000,
+0x00080078,
+0x00011800,
+0x00000000,
+0x00004602,
+0x00000000,
+0x0002007A,
+0x00100018,
+0x00012000,
+0x00000000,
+0x00004802,
+0x00000000,
+0x0006401A,
+0x00000000,
+0x0004B228,
+0x0002FC13,
+0x0002E913,
+0x0004B228,
+0x00041900,
+0x00041A00,
+0x00068E08,
+0x00720002,
+0x00130400,
+0x00000000,
+0x0004DA28,
+0x0001CA13,
+0x0001B713,
+0x0004DA28,
+0x0002E700,
+0x0002E800,
+0x00069E08,
+0x00770002,
+0x00131800,
+0x00000000,
+0x0004DA28,
+0x00000003,
+0x00000000,
+0x00720004,
+0x00130400,
+0x00770004,
+0x00131800,
+0x00000000,
+0x0004DA28,
+0x00000000,
+0x00050228,
+0x00042D12,
+0x00041B12,
+0x00050228,
+0x00053B00,
+0x00053C00,
+0x0006AE08,
+0x0081000C,
+0x0012F000,
+0x00000000,
+0x00052A0C,
+0x00011B0C,
+0x00013804,
+0x00016F0C,
+0x00010F0C,
+0x00000000,
+0x0005360C,
+0x00000000,
+0x0005420C,
+0x00011B0C,
+0x00013C04,
+0x0001D918,
+0x00054E0C,
+0x0001D918,
+0x00055A0C,
+0x00057F19,
+0x00057F19,
+0x00000000,
+0x00056F19,
+0x00056619,
+0x00056619,
+0x00055619,
+0x00053D19,
+0x00000000,
+0x0005950D,
+0x00000000,
+0x0005880D,
+0x0005980D,
+0x0005980D,
+0x0005A50D,
+0x0005A50D,
+0x0001000D,
+0x00000000,
+0x000B000D,
+0x00000000,
+0x0005B20F,
+0x0005B20F,
+0x000B000F,
+0x00000000,
+0x0005C10F,
+0x0005C10F,
+0x00000000,
+0x0005AF07,
+0x00000000,
+0x0005B60D,
+0x0005D007,
+0x0005D007,
+0x0005D70D,
+0x0005D70D,
+0x00030007,
+0x00000000,
+0x00000000,
+0x0005A20D,
+0x0005E40D,
+0x0005E40D,
+0x0005F10D,
+0x0005F10D,
+0x0001000D,
+0x00000000,
+0x000B000D,
+0x00000000,
+0x00000000,
+0x0005FE02,
+0x00000000,
+0x0005C30D,
+0x00060007,
+0x00060007,
+0x0006070D,
+0x0006070D,
+0x00030007,
+0x00000000,
+0x00000000,
+0x00061404,
+0x00000000,
+0x0000FD09,
+0x00000000,
+0x00010609,
+0x00064009,
+0x00064009,
+0x0005F809,
+0x0005F809,
+0x000B0009,
+0x00000000,
+0x00000000,
+0x00064C0C,
+0x00064903,
+0x00064903,
+0x0006BE02,
+0x00060103,
+0x00000003,
+0x001B0000,
+0x00000000,
+0x00065828,
+0x0001CA13,
+0x0001B713,
+0x00065828,
+0x00061C00,
+0x00061D00,
+0x0006C408,
+0x00B40002,
+0x00131800,
+0x00B40004,
+0x00131800,
+0x00069409,
+0x00069409,
+0x00060D09,
+0x00060409,
+0x00069D03,
+0x00069D03,
+0x0006BE02,
+0x00061603,
+0x0006A003,
+0x0006A003,
+0x0006BE02,
+0x00061903,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00010E12,
+0x00000000,
+0x0006A30C,
+0x0001D918,
+0x0006AF0C,
+0x0001D918,
+0x0006BB0C,
+0x0006E107,
+0x0006E107,
+0x0006E80D,
+0x0006E80D,
+0x0006C70D,
+0x0006C70D,
+0x0006D40D,
+0x0006D40D,
+0x00000000,
+0x00065828,
+0x00000000,
+0x00063E01,
+0x00000000,
+0x00063F01,
+0x00061811,
+0x00061811,
+0x00062915,
+0x00062915,
+0x0005D002,
+0x0005D215,
+0x00063F01,
+0x00062915,
+0x0005E711,
+0x00063E01,
+0x00D00011,
+0x0000D100,
+0x0006F509,
+0x0006F509,
+0x00000000,
+0x00061E09,
+0x0006FE09,
+0x0006FE09,
+0x00063009,
+0x00062709,
+0x00063800,
+0x00070701,
+0x000018E4,
+0x00000000,
+0x00001368,
+0x00000000,
+0x00000000,
+0x00074006,
+0x0001D900,
+0x00075E18,
+0x0007760B,
+0x0007760B,
+0x00000000,
+0x00063D0B,
+0x0000FA00,
+0x00074618,
+0x0007760B,
+0x0007760B,
+0x00075E18,
+0x00074006,
+0x00DF000B,
+0x0000E000,
+0x00000000,
+0x00070E06,
+0x0001D918,
+0x00071518,
+0x00063904,
+0x00071400,
+0x0000FA00,
+0x00072D00,
+0x0006CC00,
+0x00072E12,
+0x00EA00E7,
+0x000026FF,
+0x00000000,
+0x00070806,
+0x00000000,
+0x00100040,
+0x0000149C,
+0x00000000,
+0x00000000,
+0x0006480F,
+0x0007990F,
+0x0007990F,
+0x00000000,
+0x0006570F,
+0x0017000F,
+0x00000000,
+0x0007A80F,
+0x0007A80F,
+0x0007B70F,
+0x0007B70F,
+0x0007C60F,
+0x0007C60F,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00010000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0000001B,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000003,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000006,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000009,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000005,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000007,
+0x00000000,
+0x00000008,
+0x00000000,
+0x00000008,
+0x00000000,
+0x00000008,
+0x00000000,
diff --git a/sound/soc/codecs/abe/C_ABE_FW.lDM b/sound/soc/codecs/abe/C_ABE_FW.lDM
new file mode 100644
index 000000000000..435f93fb73a3
--- /dev/null
+++ b/sound/soc/codecs/abe/C_ABE_FW.lDM
@@ -0,0 +1,4096 @@
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x03230313,
+0x035D0341,
+0x03BB037A,
+0x039703D9,
+0x03F503A9,
+0x00000316,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000510,
+0x00010D01,
+0x04030F01,
+0x0E0E0E00,
+0x00000F0E,
+0x0E0E0E09,
+0x00001F0E,
+0x1E170608,
+0x00000F1C,
+0x1E180608,
+0x00000F1D,
+0x21201707,
+0x00000F18,
+0x24232202,
+0x00002625,
+0x29272307,
+0x00000F17,
+0x44434211,
+0x00004745,
+0x44434211,
+0x00004845,
+0xED494102,
+0x0000EFEE,
+0x0E4D4905,
+0x00004E0E,
+0x4F364D02,
+0x00005850,
+0xF04A4202,
+0x0000EFEE,
+0x0E4D4A05,
+0x00004E0E,
+0x512A4D02,
+0x00005852,
+0xF14B4302,
+0x0000EFEE,
+0x0E4D4B05,
+0x00004E0E,
+0x532D4D02,
+0x00005854,
+0xF24C4402,
+0x0000EFEE,
+0x0E4D4C05,
+0x00004E0E,
+0x55304D02,
+0x00005856,
+0x2C2B2A04,
+0x00000FBD,
+0x2F2E2D04,
+0x00000FBE,
+0x32313004,
+0x00000FBF,
+0x38373604,
+0x00000FC0,
+0x0E0E0E10,
+0x00000E0E,
+0x0E0E0E10,
+0x00000E0E,
+0x0E0E0E10,
+0x0000590E,
+0x0E0E0E10,
+0x00005A0E,
+0x0E0E0E10,
+0x00005B0E,
+0x0E0E0E10,
+0x00005E0E,
+0x0E0E0E10,
+0x00000E0E,
+0x0E410E12,
+0x0000605F,
+0x620E640F,
+0x00006516,
+0x0E220E13,
+0x0000660E,
+0x0E190E13,
+0x0000670E,
+0x0E400E14,
+0x0000680E,
+0x6A6B401A,
+0x0000690E,
+0x6D6E191A,
+0x00006C0E,
+0x70016F18,
+0x00137371,
+0x75007419,
+0x00137876,
+0x70046F18,
+0x00137B71,
+0x75037419,
+0x00137C76,
+0x7F067E18,
+0x00128280,
+0x85830608,
+0x00000F84,
+0x87868304,
+0x00000FC3,
+0x85220608,
+0x00000F88,
+0x3F3E0604,
+0x00000FC3,
+0x91010102,
+0x00009390,
+0x0C1A0106,
+0x00005D0E,
+0x921A1A02,
+0x0000948F,
+0x9A040402,
+0x00009C98,
+0x0C1A0406,
+0x00007A0E,
+0x9B1A1A02,
+0x00009499,
+0x8B282702,
+0x0000578C,
+0x0E28C40C,
+0x00000FC1,
+0x13612806,
+0x0000140E,
+0x95616102,
+0x000096EC,
+0x8D18181C,
+0x0000578E,
+0x0E18C50C,
+0x00000FC2,
+0x13621806,
+0x0000140E,
+0x97626202,
+0x000096EC,
+0x9F4D2202,
+0x0000A19D,
+0x0EA24D05,
+0x00005D0E,
+0x9E79A202,
+0x0000A090,
+0xA54D2202,
+0x0000A1A3,
+0x0EA74D05,
+0x00007A0E,
+0xA47DA702,
+0x0000A698,
+0x10A9A81B,
+0x00001211,
+0x0F0F0F0A,
+0x00000F0F,
+0xB202B119,
+0x0013B5B3,
+0xB205B119,
+0x0013B6B3,
+0xAAC42802,
+0x0000ACAB,
+0xAEADC417,
+0x0000B0AF,
+0xB7C5181C,
+0x0000ACB8,
+0xC6C5C504,
+0x00000FC3,
+0xB9ADC517,
+0x0000B0BA,
+0xB9ADC617,
+0x0000B0BA,
+0xCA4D2002,
+0x0000A19D,
+0x0EA24D05,
+0x00005D0E,
+0xC9CBA202,
+0x0000A090,
+0xC84D2002,
+0x0000A1A3,
+0x0EA74D05,
+0x00007A0E,
+0xC7CBA702,
+0x0000A698,
+0xCECDCC0D,
+0x0000D3CF,
+0xCCCD461D,
+0x00000F0E,
+0xD4C42802,
+0x0000ACD5,
+0xD6C5181C,
+0x0000ACD7,
+0xD8CC461E,
+0x0000D90E,
+0x0E0E0E10,
+0x0000DA0E,
+0xDDDCDB16,
+0x0000E2DE,
+0xE5E4E315,
+0x0000E8E6,
+0xE3DBE904,
+0x00000FC3,
+0xE463DC03,
+0x00000FC3,
+0x0E0EEA1F,
+0x0000EB0E,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000FA4,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x11841184,
+0x119B1184,
+0x00040018,
+0x119C119C,
+0x11B3119C,
+0x00040018,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x12301230,
+0x128F1230,
+0x000C0060,
+0x12901290,
+0x12EF1290,
+0x000C0060,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000200,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x04A6000A,
+0x03FF0107,
+0x04320427,
+0x0444043A,
+0x045A044F,
+0x04EF04AB,
+0x04690536,
+0x02480566,
+0x01840210,
+0x028B01E0,
+0x04900497,
+0x06A7067B,
+0x05A80634,
+0x02B4059D,
+0x04120470,
+0x066006B8,
+0x00000168,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x0115010F,
+0x0122011C,
+0x01360128,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003FFFF0,
+0x00000000,
+0x00400000,
+0x02FC02E9,
+0x0322030F,
+0x03480335,
+0x036E035B,
+0x03940381,
+0x03BA03A7,
+0x03E003CD,
+0x040603F3,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003FFFF0,
+0x00000000,
+0x00400000,
+0x01CA01B7,
+0x01F001DD,
+0x02160203,
+0x023C0229,
+0x0262024F,
+0x02880275,
+0x02AE029B,
+0x02D402C1,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003FFFF0,
+0x00000000,
+0x00400000,
+0x042D041B,
+0x0451043F,
+0x04750463,
+0x04990487,
+0x04BD04AB,
+0x04E104CF,
+0x050504F3,
+0x05290517,
+0x00008363,
+0x00000428,
+0x00000000,
+0x00000001,
+0x00002000,
+0x000003FF,
+0x00000004,
+0x00000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0x003FFFF0,
+0x00000000,
+0x00400000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
diff --git a/sound/soc/codecs/abe/C_ABE_FW_SIZE.h b/sound/soc/codecs/abe/C_ABE_FW_SIZE.h
new file mode 100644
index 000000000000..f509d6482c9b
--- /dev/null
+++ b/sound/soc/codecs/abe/C_ABE_FW_SIZE.h
@@ -0,0 +1,14 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+/* FW 05.10 MEMORY SIZES */
+#define ABE_DMEM_SIZE_OPTIMIZED 16384
+#define ABE_SMEM_SIZE_OPTIMIZED 14848
+#define ABE_CMEM_SIZE_OPTIMIZED 6552
diff --git a/sound/soc/codecs/abe/Makefile b/sound/soc/codecs/abe/Makefile
new file mode 100644
index 000000000000..40dc15240af4
--- /dev/null
+++ b/sound/soc/codecs/abe/Makefile
@@ -0,0 +1,9 @@
+snd-soc-abe-hal-objs += abe_api.o \
+ abe_dbg.o \
+ abe_ext.o \
+ abe_ini.o \
+ abe_irq.o \
+ abe_lib.o \
+ abe_seq.o \
+
+obj-$(CONFIG_SND_SOC_ABE_TWL6030) += snd-soc-abe-hal.o
diff --git a/sound/soc/codecs/abe/abe_api.c b/sound/soc/codecs/abe/abe_api.c
new file mode 100644
index 000000000000..c28782907114
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_api.c
@@ -0,0 +1,2023 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+#include "C_ABE_FW_SIZE.h" /* used to tune the FW size for faster RTL simulations */
+
+static abe_uint32 ABE_FW_PM[ABE_PMEM_SIZE / 4] = {
+#include "C_ABE_FW.PM"
+};
+static abe_uint32 ABE_FW_CM[ABE_CMEM_SIZE_OPTIMIZED / 4] = {
+#include "C_ABE_FW.CM"
+};
+static abe_uint32 ABE_FW_DM[ABE_DMEM_SIZE_OPTIMIZED / 4] = {
+#include "C_ABE_FW.lDM"
+};
+static abe_uint32 ABE_FW_SM[ABE_SMEM_SIZE_OPTIMIZED / 4] = {
+#include "C_ABE_FW.SM32"
+};
+
+/**
+* @fn abe_reset_hal()
+*
+* Operations : reset the HAL by reloading the static variables and default AESS registers.
+* Called after a PRCM cold-start reset of ABE
+*
+* @see ABE_API.h
+*/
+void abe_reset_hal(void)
+{
+ abe_dbg_output = TERMINAL_OUTPUT;
+
+ /* load firmware */
+ abe_load_fw ();
+
+ /* load default port values */
+ abe_reset_all_ports();
+
+ /* load default sequence list */
+ abe_reset_all_sequence();
+
+ /* build the scheduler tables */
+ abe_build_scheduler_table();
+
+ /* build the default uplink router configurations */
+
+ abe_set_router_configuration(UPROUTE, UPROUTE_CONFIG_AMIC, (abe_router_t *)abe_router_ul_table_preset[UPROUTE_CONFIG_AMIC]);
+#if 0
+ abe_set_router_configuration(UPROUTE, UPROUTE_CONFIG_DMIC1, (abe_router_t *)abe_router_ul_table_preset[UPROUTE_CONFIG_DMIC1]);
+ abe_set_router_configuration(UPROUTE, UPROUTE_CONFIG_DMIC2, (abe_router_t *)abe_router_ul_table_preset[UPROUTE_CONFIG_DMIC2]);
+ abe_set_router_configuration(UPROUTE, UPROUTE_CONFIG_DMIC3, (abe_router_t *)abe_router_ul_table_preset[UPROUTE_CONFIG_DMIC3]);
+#endif
+ /* meaningful other microphone configuration can be added here */
+
+ /* init hardware components */
+ abe_hw_configuration();
+}
+
+/**
+* @fn abe_load_fwl()
+*
+* Operations :
+* loads the Audio Engine firmware, generate a single pulse on the Event generator
+* to let execution start, read the version number returned from this execution.
+*
+* @see ABE_API.h
+*/
+void abe_load_fw(void)
+{
+#if PC_SIMULATION
+#else
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_PMEM, 0, (abe_uint32 *)ABE_FW_PM, sizeof(ABE_FW_PM));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 0, (abe_uint32 *)ABE_FW_CM, sizeof(ABE_FW_CM));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, 0, (abe_uint32 *)ABE_FW_SM, sizeof(ABE_FW_SM));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, 0, (abe_uint32 *)ABE_FW_DM, sizeof(ABE_FW_DM));
+#endif
+}
+
+/*
+ * ABE_HARDWARE_CONFIGURATION
+ *
+ * Parameter :
+ * U : use-case description list (pointer)
+ * H : pointer to the output structure
+ *
+ * Operations :
+ * return a structure with the HW thresholds compatible with the HAL/FW/AESS_ATC
+ * will be upgraded in FW06
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_hardware_configuration(abe_use_case_id *u, abe_opp_t *o, abe_hw_config_init_t *hw)
+{
+ abe_read_use_case_opp(u, o);
+
+ /* @@@ keep OPP 100 for now */
+ (*o) = ABE_OPP100;
+
+ hw->MCPDM_CTRL__DIV_SEL = 0; /* 0: 96kHz 1:192kHz */
+ hw->MCPDM_CTRL__CMD_INT = 1; /* 0: no command in the FIFO, 1: 6 data on each lines (with commands) */
+ hw->MCPDM_CTRL__PDMOUTFORMAT = 0; /* 0:MSB aligned 1:LSB aligned */
+ hw->MCPDM_CTRL__PDM_DN5_EN = 1;
+ hw->MCPDM_CTRL__PDM_DN4_EN = 1;
+ hw->MCPDM_CTRL__PDM_DN3_EN = 1;
+ hw->MCPDM_CTRL__PDM_DN2_EN = 1;
+ hw->MCPDM_CTRL__PDM_DN1_EN = 1;
+ hw->MCPDM_CTRL__PDM_UP3_EN = 0;
+ hw->MCPDM_CTRL__PDM_UP2_EN = 1;
+ hw->MCPDM_CTRL__PDM_UP1_EN = 1;
+ hw->MCPDM_FIFO_CTRL_DN__DN_TRESH = MCPDM_DL_ITER/6; /* All the McPDM_DL FIFOs are enabled simultaneously */
+ hw->MCPDM_FIFO_CTRL_UP__UP_TRESH = MCPDM_UL_ITER/2; /* number of ATC access upon AMIC DMArequests, 2 the FIFOs channels are enabled */
+
+ hw->DMIC_CTRL__DMIC_CLK_DIV = 0; /* 0:2.4MHz 1:3.84MHz */
+ hw->DMIC_CTRL__DMICOUTFORMAT = 0; /* 0:MSB aligned 1:LSB aligned */
+ hw->DMIC_CTRL__DMIC_UP3_EN = 1;
+ hw->DMIC_CTRL__DMIC_UP2_EN = 1;
+ hw->DMIC_CTRL__DMIC_UP1_EN = 1;
+ hw->DMIC_FIFO_CTRL__DMIC_TRESH = DMIC_ITER/6; /* 1*(DMIC_UP1_EN+ 2+ 3)*2 OCP read access every 96/88.1 KHz. */
+
+ hw->MCBSP_SPCR1_REG__RJUST = 1; /* 1:MSB 2:LSB aligned */
+ hw->MCBSP_THRSH2_REG_REG__XTHRESHOLD = 1;
+ hw->MCBSP_THRSH1_REG_REG__RTHRESHOLD = 1;
+
+ hw->AESS_EVENT_GENERATOR_COUNTER__COUNTER_VALUE = EVENT_GENERATOR_COUNTER_DEFAULT; /* 2050 gives about 96kHz */
+ hw->AESS_EVENT_SOURCE_SELECTION__SELECTION = 0; /* 0: DMAreq, 1:Counter */
+ hw->AESS_AUDIO_ENGINE_SCHEDULER__DMA_REQ_SELECTION = ABE_ATC_MCPDMDL_DMA_REQ; /* 5bits DMAreq selection */
+
+ hw->HAL_EVENT_SELECTION = EVENT_MCPDM; /* to be used before calling "abe_event_generator_switch (EVENT_MCPDM)" */
+}
+
+/*
+ * ABE_DEFAULT_CONFIGURATION
+ *
+ * Parameter :
+ * use-case-ID : "LP player", "voice-call" use-cases as defined in the paragraph
+ * "programming use-case sequences"
+ * Param 1, 2, 3, 4 used for non regression tests
+ *
+ * Operations :
+ * private API used during development. Loads all the necessary parameters and data
+ * patterns to allow a stand-alone functional test without the need of.
+ *
+ * Return value :
+ * None.
+ */
+void abe_default_configuration(abe_uint32 use_case)
+{
+ abe_data_format_t format;
+ abe_dma_t dma_sink;
+ abe_uint32 data_sink;
+ abe_use_case_id UC2[] = {ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE, ABE_RINGER_TONES, 0};
+ abe_use_case_id UC5[] = {ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE, 0};
+ abe_opp_t OPP;
+ abe_hw_config_init_t CONFIG;
+
+ /* load the default configuration of HAL memories + FW download */
+ abe_reset_hal();
+
+ /* MM_DL init: connect a DMA channel to VX_DL port (ATC FIFO) */
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ abe_connect_cbpr_dmareq_port(MM_DL_PORT, &format, ABE_CBPR0_IDX, &dma_sink);
+
+ /* VX_DL init: connect a DMA channel to VX_DL port (ATC FIFO) */
+ format.f = 8000; format.samp_format = MONO_MSB;
+ abe_connect_cbpr_dmareq_port(VX_DL_PORT, &format, ABE_CBPR1_IDX, &dma_sink);
+
+ /* VX_UL init: connect a DMA channel to VX_DL port (ATC FIFO) */
+ format.f = 8000; format.samp_format = MONO_MSB;
+ abe_connect_cbpr_dmareq_port(VX_UL_PORT, &format, ABE_CBPR2_IDX, &dma_sink);
+
+ /* MM_UL init: connect a DMA channel to MM_UL port (ATC FIFO) */
+ format.f = 48000; format.samp_format = TEN_MSB;
+ abe_connect_cbpr_dmareq_port(MM_UL_PORT, &format, ABE_CBPR3_IDX, &dma_sink);
+
+ /* MM_UL2 init: connect a DMA channel to MM_UL2 port (ATC FIFO) */
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ abe_connect_cbpr_dmareq_port(MM_UL2_PORT, &format, ABE_CBPR4_IDX, &dma_sink);
+
+ /* TONES init: connect a DMA channel to TONES port (ATC FIFO) */
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ abe_connect_cbpr_dmareq_port(TONES_DL_PORT, &format, ABE_CBPR5_IDX, &dma_sink);
+
+ /* VIBRA/HAPTICS init: connect a DMA channel to VIBRA/HAPTICS port (ATC FIFO) */
+ format.f = 24000; format.samp_format = STEREO_MSB;
+ abe_connect_cbpr_dmareq_port(VIB_DL_PORT, &format, ABE_CBPR6_IDX, &dma_sink);
+
+ /*
+ * mixers default configuration:
+ * voice on earphone + music on hands-free path
+ */
+#if 0
+ abe_write_mixer(MIXDL1, GAIN_0dB, RAMP_0MS, MIX_DL1_INPUT_TONES);
+ abe_write_mixer(MIXDL1, GAIN_0dB, RAMP_1MS, MIX_DL1_INPUT_VX_DL);
+ abe_write_mixer(MIXDL1, GAIN_0dB, RAMP_2MS, MIX_DL1_INPUT_MM_DL);
+ abe_write_mixer(MIXDL1, MUTE_GAIN, RAMP_5MS, MIX_DL1_INPUT_MM_UL2);
+
+ abe_write_mixer(MIXDL2, GAIN_0dB, RAMP_10MS, MIX_DL2_INPUT_TONES);
+ abe_write_mixer(MIXDL2, GAIN_0dB, RAMP_20MS, MIX_DL2_INPUT_VX_DL);
+ abe_write_mixer(MIXDL2, GAIN_0dB, RAMP_50MS, MIX_DL2_INPUT_MM_DL);
+ abe_write_mixer(MIXDL2, MUTE_GAIN, RAMP_100MS, MIX_DL2_INPUT_MM_UL2);
+
+ abe_write_mixer(MIXSDT, GAIN_0dB, RAMP_0MS, MIX_SDT_INPUT_DL1_MIXER);
+ abe_write_mixer(MIXSDT, GAIN_0dB, RAMP_0MS, MIX_SDT_INPUT_DL2_MIXER);
+#endif
+ /*
+ * router default configuration:
+ * analog mics on VX_UL, nothing on MM_UL, MM_UL2
+ */
+ /* enable the VX_UL path with Analog microphones from Phoenix */
+ abe_enable_router_configuration(UPROUTE, UPROUTE_CONFIG_AMIC);
+
+ switch (use_case) {
+ /* voice ul/dl on earpiece + MM_DL on IHF */
+ case UC2_VOICE_CALL_AND_IHF_MMDL:
+ /* enable one of the preloaded and programmable routing
+ * configuration for the uplink paths
+ * Here enable the VX_UL path with Digital microphones:
+ * abe_enable_router_configuration(UPROUTE, UPROUTE_CONFIG_DMIC1);
+ * To be added here:
+ * - Device driver initialization following
+ * abe_read_hardware_configuration() returned data
+ * McPDM_DL : 6 slots activated (5 + Commands)
+ * DMIC : 6 microphones activated
+ * McPDM_UL : 2 microphones activated (No status)
+ */
+ abe_read_hardware_configuration(UC2, &OPP, &CONFIG); /* check hw config and opp config */
+ abe_set_opp_processing(OPP); /* sets the OPP100 on FW05.xx */
+ abe_write_event_generator(CONFIG.HAL_EVENT_SELECTION); /* "tick" of the audio engine */
+
+ abe_enable_data_transfer(MM_DL_PORT); /* enable all the data paths */
+ abe_enable_data_transfer(VX_DL_PORT);
+ abe_enable_data_transfer(VX_UL_PORT);
+ abe_enable_data_transfer(PDM_UL_PORT);
+ abe_enable_data_transfer(DMIC_PORT1); /* DMIC ATC can be enabled even if the DMIC */
+ abe_enable_data_transfer(DMIC_PORT2); /* IP is not enabled. */
+ abe_enable_data_transfer(DMIC_PORT3);
+ abe_enable_data_transfer(PDM_DL1_PORT);
+ break;
+ case UC5_PINGPONG_MMDL:
+ /* Ping-Pong access through MM_DL using Left/Right
+ * 16bits/16bits data format
+ * To be added here:
+ * - Device driver initialization following abe_read_hardware_configuration() returned data
+ * McPDM_DL : 6 slots activated (5 + Commands)
+ * DMIC : 6 microphones activated
+ * McPDM_UL : 2 microphones activated (No status)
+ */
+ abe_read_hardware_configuration(UC5, &OPP, &CONFIG); /* check hw config and opp config */
+ abe_set_opp_processing(OPP); /* sets the OPP100 on FW05.xx */
+ abe_write_event_generator(CONFIG.HAL_EVENT_SELECTION); /* "tick" of the audio engine */
+
+ /* MM_DL init: overwrite the previous default initialization made above */
+ format.f = 48000;
+ format.samp_format = STEREO_16_16;
+
+ /* connect a Ping-Pong SDMA protocol to MM_DL port
+ * with Ping-Pong 576 mono samples
+ * (12x4 bytes for each ping & pong size)
+ */
+ abe_connect_dmareq_ping_pong_port(MM_DL_PORT, &format, ABE_CBPR0_IDX, (12 * 4), &dma_sink);
+
+ /* Here: connect the sDMA to "dma_sink" content */
+ abe_enable_data_transfer(MM_DL_PORT); /* enable all the data paths */
+ abe_enable_data_transfer(PDM_DL1_PORT);
+ break;
+ case UC6_PINGPONG_MMDL_WITH_IRQ:
+ /* Ping-Pong using the IRQ instead of the sDMA */
+ abe_read_hardware_configuration(UC5, &OPP, &CONFIG); /* check hw config and opp config */
+ abe_set_opp_processing(OPP); /* sets the OPP100 on FW05.xx */
+ abe_write_event_generator(CONFIG.HAL_EVENT_SELECTION); /* "tick" of the audio engine */
+
+ /* MM_DL init: overwrite the previous default initialization made above */
+ format.f = 48000;
+ format.samp_format = STEREO_16_16;
+
+ /* connect a Ping-Pong cache-flush protocol to MM_DL port
+ * with 50Hz (20ms) rate
+ */
+ abe_add_subroutine(&abe_irq_pingpong_player_id, (abe_subroutine2) abe_default_irq_pingpong_player, SUB_0_PARAM);
+ #define N_SAMPLES_BYTES (12 *4)
+ abe_connect_irq_ping_pong_port(MM_DL_PORT, &format, abe_irq_pingpong_player_id, N_SAMPLES_BYTES, &data_sink);
+
+ abe_enable_data_transfer(MM_DL_PORT); /* enable all the data paths */
+ abe_enable_data_transfer(PDM_DL1_PORT);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * ABE_IRQ_PROCESSING
+ *
+ * Parameter :
+ * No parameter
+ *
+ * Operations :
+ * This subroutine will check the IRQ_FIFO from the AE and act accordingly.
+ * Some IRQ source are originated for the delivery of "end of time sequenced tasks"
+ * notifications, some are originated from the Ping-Pong protocols, some are generated from
+ * the embedded debugger when the firmware stops on programmable break-points, etc …
+ *
+ * Return value :
+ * None.
+ */
+void abe_irq_processing(void)
+{
+ abe_monitoring();
+ abe_irq_ping_pong();
+ abe_irq_check_for_sequences();
+}
+
+/*
+ * ABE_WRITE_EVENT_GENERATOR
+ *
+ * Parameter :
+ * e: Event Generation Counter, McPDM, DMIC or default.
+ *
+ * Operations :
+ * load the AESS event generator hardware source. Loads the firmware parameters
+ * accordingly. Indicates to the FW which data stream is the most important to preserve
+ * in case all the streams are asynchronous. If the parameter is "default", let the HAL
+ * decide which Event source is the best appropriate based on the opened ports.
+ *
+ * When neither the DMIC and the McPDM are activated the AE will have its EVENT generator programmed
+ * with the EVENT_COUNTER. The event counter will be tuned in order to deliver a pulse frequency higher
+ * than 96 kHz. The DPLL output at 100% OPP is MCLK = (32768kHz x6000) = 196.608kHz
+ * The ratio is (MCLK/96000)+(1<<1) = 2050
+ * (1<<1) in order to have the same speed at 50% and 100% OPP (only 15 MSB bits are used at OPP50%)
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_event_generator(abe_event_id e)
+{
+ abe_uint32 event, selection, counter, start;
+
+ counter = EVENT_GENERATOR_COUNTER_DEFAULT;
+ abe_current_event_id = e;
+
+ switch (e) {
+ case EVENT_MCPDM:
+ selection = EVENT_SOURCE_DMA;
+ start = EVENT_GENERATOR_ON;
+ event = ABE_ATC_MCPDMDL_DMA_REQ;
+ break;
+ case EVENT_DMIC:
+ selection = EVENT_SOURCE_DMA;
+ start = EVENT_GENERATOR_ON;
+ event = ABE_ATC_DMIC_DMA_REQ;
+ break;
+ case EVENT_TIMER:
+ selection = EVENT_SOURCE_COUNTER;
+ start = EVENT_GENERATOR_ON;
+ event = 0;
+ break;
+ case EVENT_McBSP:
+ selection = EVENT_SOURCE_COUNTER;
+ start = EVENT_GENERATOR_ON;
+ event = 0;
+ break;
+ case EVENT_McASP:
+ selection = EVENT_SOURCE_COUNTER;
+ start = EVENT_GENERATOR_ON;
+ event = 0;
+ break;
+ case EVENT_SLIMBUS:
+ selection = EVENT_SOURCE_COUNTER;
+ start = EVENT_GENERATOR_ON;
+ event = 0;
+ break;
+ case EVENT_DEFAULT:
+ selection = EVENT_SOURCE_COUNTER;
+ start = EVENT_GENERATOR_ON;
+ event = 0;
+ break;
+ default:
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ }
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_COUNTER, &counter, 4);
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_SOURCE_SELECTION, &selection, 4);
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_START, &start, 4);
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, AUDIO_ENGINE_SCHEDULER, &event, 4);
+}
+
+/**
+* abe_read_use_case_opp() description for void abe_read_use_case_opp().
+*
+* Operations : returns the expected min OPP for a given use_case list
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_use_case_opp(abe_use_case_id *u, abe_opp_t *o)
+{
+ abe_uint32 opp, i;
+ abe_use_case_id *ptr = u;
+
+ #define MAX_READ_USE_CASE_OPP 10 /* there is no reason to have more use_cases */
+ #define OPP_25 1
+ #define OPP_50 2
+ #define OPP_100 4
+
+ opp = i = 0;
+ while (1) {
+ /* check for pointer errors */
+ if (i > MAX_READ_USE_CASE_OPP) {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_READ_USE_CASE_OPP_ERR);
+ break;
+ }
+
+ /* check for end_of_list */
+ if (*ptr <= 0)
+ break;
+
+ /* check for end_of_list */
+ if (*ptr > ABE_LAST_USE_CASE)
+ break;
+
+ /* OPP selection based on current firmware implementation */
+ switch (*ptr) {
+ case ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE:
+ opp |= OPP_25;
+ break;
+ case ABE_DRIFT_MANAGEMENT_FOR_AUDIO_PLAYER:
+ opp |= OPP_100;
+ break;
+ case ABE_VOICE_CALL_ON_HEADSET_OR_EARPHONE_OR_BT:
+ opp |= OPP_50;
+ break;
+ case ABE_MULTIMEDIA_AUDIO_RECORDER:
+ opp |= OPP_50;
+ break;
+ case ABE_VIBRATOR_OR_HAPTICS:
+ opp |= OPP_100;
+ break;
+ case ABE_VOICE_CALL_ON_HANDS_FREE_SPEAKER:
+ opp |= OPP_100;
+ break;
+ case ABE_RINGER_TONES:
+ opp |= OPP_100;
+ break;
+ case ABE_VOICE_CALL_WITH_EARPHONE_ACTIVE_NOISE_CANCELLER:
+ opp |= OPP_100;
+ break;
+ }
+
+ i++;
+ ptr++;
+ }
+
+ if (opp | OPP_100)
+ *o = ABE_OPP100;
+ else if (opp | OPP_50)
+ *o = ABE_OPP50;
+ else
+ *o = ABE_OPP25;
+}
+
+/*
+ * ABE_READ_LOWEST_OPP
+ *
+ * Parameter :
+ * Data pointer : returned data
+ *
+ * Operations :
+ * Returns the lowest possible OPP based on the current active ports
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_lowest_opp(abe_opp_t *o)
+{
+ *o = ABE_OPP100; /* @@@ RELEASE 5 allows only 100% OPP */
+
+#if 0
+ for (i = 0; i < LAST_PORT_ID; i++)
+
+ abe_port_t abe_port [MAXNBABEPORTS]; /* list of ABE ports */
+const abe_port_t abe_port_init [MAXNBABEPORTS] = {
+
+ /* Status Data Format Drift Call-Back Protocol+selector desc_addr; buf_addr; buf_size; iter; thr_low; irq_addr irq_data DMA_T #Features reseted at start Port Name for the debug trace */
+/* DMIC1 */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_dmic1, 0, {SNK_P, DMIC_PORT_PROT, {dmem_dmic, dmem_dmic_size, DMIC_ITER}}, {0, 0}, {EQDMIC1, 0}, "DMIC_UL" },
+/* DMIC2 */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_dmic2, 0, {SNK_P, DMIC_PORT_PROT, {dmem_dmic, dmem_dmic_size, DMIC_ITER}}, {0, 0}, {EQDMIC2, 0}, "DMIC_UL" },
+/* DMIC3 */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_dmic3, 0, {SNK_P, DMIC_PORT_PROT, {dmem_dmic, dmem_dmic_size, DMIC_ITER}}, {0, 0}, {EQDMIC3, 0}, "DMIC_UL" },
+/* PDM_UL */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_amic, 0, {SNK_P, MCPDMUL_PORT_PROT, {dmem_amic, dmem_amic_size, MCPDM_UL_ITER}}, {0, 0}, {EQAMIC, 0}, "AMIC_UL" },
+/* BT_VX_UL*/ { IDLE_P, { 8000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_bt_vx_ul, 0, {SNK_P, SERIAL_PORT_PROT, {MCBSP1_DMA_TX*ATC_SIZE,dmem_bt_vx_ul,dmem_bt_vx_ul_size, 1 * SCHED_LOOP_8kHz, DEFAULT_THR_WRITE}}, {0, 0}, {0}, "BT_VX_UL" },
+/* MM_UL */ { IDLE_P, {48000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_mm_ul, 0, {SRC_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX3*ATC_SIZE,dmem_mm_ul,dmem_mm_ul_size, 10 * SCHED_LOOP_48kHz, DEFAULT_THR_WRITE,ABE_DMASTATUS_RAW,(1<<3)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__3, 120}, {UPROUTE, 0}, "MM_UL" },
+/* MM_UL2 */ { IDLE_P, {48000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_mm_ul2,0, {SRC_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX4*ATC_SIZE,dmem_mm_ul2,dmem_mm_ul2_size, 2 * SCHED_LOOP_48kHz, DEFAULT_THR_WRITE,ABE_DMASTATUS_RAW,(1<<4)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__4, 24}, {UPROUTE, 0}, "MM_UL2" },
+/* VX_UL */ { IDLE_P, { 8000, MONO_MSB}, NODRIFT, NOCALLBACK, smem_vx_ul, 0, {SRC_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX2*ATC_SIZE,dmem_vx_ul,(dmem_vx_ul_size/2), 1 * SCHED_LOOP_8kHz, DEFAULT_THR_WRITE,ABE_DMASTATUS_RAW,(1<<2)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__2, 4}, {ASRC2, 0}, "VX_UL" },
+/* MM_DL */ { IDLE_P, {48000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_mm_dl, 0, {SNK_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX0*ATC_SIZE,dmem_mm_dl,dmem_mm_dl_size, 2 * SCHED_LOOP_48kHz, DEFAULT_THR_READ ,ABE_DMASTATUS_RAW,(1<<0)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__0, 24}, {ASRC3, 0}, "MM_DL" },
+/* VX_DL */ { IDLE_P, { 8000, MONO_MSB}, NODRIFT, NOCALLBACK, smem_vx_dl, 0, {SNK_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX1*ATC_SIZE,dmem_vx_dl,dmem_vx_dl_size, 1 * SCHED_LOOP_8kHz, DEFAULT_THR_READ ,ABE_DMASTATUS_RAW,(1<<1)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__1, 4}, {ASRC1, 0}, "VX_DL" },
+/* TONES_DL*/ { IDLE_P, {48000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_tones_dl, 0, {SNK_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX5*ATC_SIZE,dmem_tones_dl,dmem_tones_dl_size, 2 * SCHED_LOOP_48kHz, DEFAULT_THR_READ ,ABE_DMASTATUS_RAW,(1<<5)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__5, 24}, {0}, "TONES_DL" },
+/* VIB_DL */ { IDLE_P, {24000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_vib, 0, {SNK_P, DMAREQ_PORT_PROT, {CBPr_DMA_RTX6*ATC_SIZE,dmem_vib_dl,dmem_vib_dl_size, 2 * SCHED_LOOP_24kHz, DEFAULT_THR_READ ,ABE_DMASTATUS_RAW,(1<<6)}}, {CIRCULAR_BUFFER_PERIPHERAL_R__6, 12}, {0}, "VIB_DL" },
+/* BT_VX_DL*/ { IDLE_P, { 8000, MONO_MSB}, NODRIFT, NOCALLBACK, smem_bt_vx_dl, 0, {SRC_P, SERIAL_PORT_PROT, {MCBSP1_DMA_RX*ATC_SIZE,dmem_bt_vx_dl,dmem_bt_vx_dl_size, 1 * SCHED_LOOP_8kHz, DEFAULT_THR_WRITE}}, {0, 0}, {0}, "BT_VX_DL" },
+/* PDM_DL1 */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, 0,0, {SRC_P, MCPDMDL_PORT_PROT, {dmem_mcpdm, dmem_mcpdm_size}}, {0, 0}, {MIXDL1, EQ1, APS1, 0}, "PDM_DL1" },
+/* MM_EXT_OUT*/ { IDLE_P, {48000, STEREO_MSB}, NODRIFT, NOCALLBACK, smem_mm_ext_out, 0, {SRC_P, SERIAL_PORT_PROT, {MCBSP1_DMA_RX*ATC_SIZE,dmem_mm_ext_out,dmem_mm_ext_out_size, 2 * SCHED_LOOP_48kHz, DEFAULT_THR_WRITE}}, {0, 0}, {0}, "MM_EXT_OUT" },
+/* PDM_DL2 */ { IDLE_P, {96000, STEREO_MSB}, NODRIFT, NOCALLBACK, 0, 0, {SRC_P, MCPDMDL_PORT_PROT, {0,0,0,0,0,0,0}}, {0, 0}, {MIXDL2, EQ2L, APS2L, EQ2R, APS2R, 0},"PDM_DL2" },
+/* PDM_VIB */ { IDLE_P, {24000, STEREO_MSB}, NODRIFT, NOCALLBACK, 0, 0, {SRC_P, MCPDMDL_PORT_PROT, {0,0,0,0,0,0,0}}, {0, 0}, {0}, "PDM_VIB" },
+/* SCHD_DBG_PORT*/ { RUN_P, { 8000, MONO_MSB}, NODRIFT, NOCALLBACK, 0, 0, {0, 0, {0,0,0,0,0,0,0}}, {0, 0}, {SEQUENCE, CONTROL, GAINS, 0}, "SCHD_DBG" },
+ };
+
+ DMIC_PORT1, /* digital microphones pairs */
+ DMIC_PORT2,
+ DMIC_PORT3,
+ PDM_UL_PORT, /* analog MICs */
+ BT_VX_UL_PORT, /* BT uplink */
+
+ /* AE source ports - Uplink */
+ MM_UL_PORT, /* up to 5 stereo channels */
+ MM_UL2_PORT, /* stereo FM record path */
+ VX_UL_PORT, /* stereo FM record path */
+
+ /* AE sink ports - Downlink */
+ MM_DL_PORT, /* multimedia player audio path */
+ VX_DL_PORT,
+ TONES_DL_PORT,
+ VIB_DL_PORT,
+
+ BT_VX_DL_PORT, /* AE source ports - Downlink */
+ PDM_DL1_PORT,
+ MM_EXT_OUT_PORT,
+ PDM_DL2_PORT,
+ PDM_VIB_PORT,
+
+ SCHD_DBG_PORT, /* dummy port used to declare the other tasks of the scheduler */
+
+ LAST_PORT_ID
+
+
+ abe_uint32 opp = i = 0;
+ abe_use_case_id *ptr = u;
+ #define MAX_READ_USE_CASE_OPP 10 /* there is no reason to have more use_cases */
+ #define OPP_25 1
+ #define OPP_50 2
+ #define OPP_100 4
+
+ while (1)
+ {
+ if (i > MAX_READ_USE_CASE_OPP) /* check for pointer errors */
+ {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_READ_USE_CASE_OPP_ERR)
+ break;
+ }
+ if (*ptr <= 0) break; /* check for end_of_list */
+ if (*ptr > ABE_LAST_USE_CASE) break; /* check for end_of_list */
+
+ switch (*ptr) /* OPP selection based on current Firmware implementation */
+ {
+ case ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE : opp |= OPP_25; break;
+ case ABE_DRIFT_MANAGEMENT_FOR_AUDIO_PLAYER : opp |= OPP_100; break;
+ case ABE_VOICE_CALL_ON_HEADSET_OR_EARPHONE_OR_BT : opp |= OPP_50; break;
+ case ABE_MULTIMEDIA_AUDIO_RECORDER : opp |= OPP_50; break;
+ case ABE_VIBRATOR_OR_HAPTICS : opp |= OPP_100; break;
+ case ABE_VOICE_CALL_ON_HANDS_FREE_SPEAKER : opp |= OPP_100; break;
+ case ABE_RINGER_TONES : opp |= OPP_100; break;
+ case ABE_VOICE_CALL_WITH_EARPHONE_ACTIVE_NOISE_CANCELLER : opp |= OPP_100; break;
+ }
+ i++;
+ ptr++;
+ }
+
+ if (opp | OPP_100) *o = ABE_OPP100;
+ else if (opp | OPP_50) *o = ABE_OPP50;
+ else *o = ABE_OPP25;
+
+#endif
+}
+
+/*
+ * ABE_SET_OPP_PROCESSING
+ *
+ * Parameter :
+ * New processing network and OPP:
+ * 0: Ultra Lowest power consumption audio player (no post-processing, no mixer)
+ * 1: OPP 25% (simple multimedia features, including low-power player)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (EANC, multimedia complex use-cases)
+ *
+ * Operations :
+ * Rearranges the FW task network to the corresponding OPP list of features.
+ * The corresponding AE ports are supposed to be set/reset accordingly before this switch.
+ *
+ * Return value :
+ * error code when the new OPP do not corresponds the list of activated features
+ */
+void abe_set_opp_processing(abe_opp_t opp)
+{
+ abe_uint32 scheduler_task_steps;
+
+ switch (opp) {
+ case ABE_OPP25:
+ scheduler_task_steps = TASKS_IN_SLOT_OPP_25;
+ break;
+ case ABE_OPP50:
+ scheduler_task_steps = TASKS_IN_SLOT_OPP_50;
+ break;
+ case ABE_OPP100:
+ scheduler_task_steps = TASKS_IN_SLOT_OPP_100;
+ break;
+ case ABE_OPP0:
+ default:
+ /* default = OPP25% processing */
+ scheduler_task_steps = TASKS_IN_SLOT_OPP_25;
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ }
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_taskStep_ADDR, &scheduler_task_steps, sizeof(scheduler_task_steps));
+}
+
+/*
+ * ABE_SET_PING_PONG_BUFFER
+ *
+ * Parameter :
+ * Port_ID :
+ * New data
+ *
+ * Operations :
+ * Updates the next ping-pong buffer with "size" samples copied from the
+ * host processor. This API notifies the FW that the data transfer is done.
+ * The size is added on top of the previous size.
+ */
+void abe_set_ping_pong_buffer(abe_port_id port, abe_uint32 n)
+{
+ abe_uint32 sio_pp_desc_address, struct_offset;
+ ABE_SPingPongDescriptor desc_pp;
+
+ /* ping_pong is only supported on MM_DL */
+ if (port != MM_DL_PORT) {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_PARAMETER_ERROR);
+ }
+
+ /* read the port SIO descriptor and extract the current pointer address after reading the counter */
+ sio_pp_desc_address = D_PingPongDesc_ADDR;
+ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, sio_pp_desc_address, (abe_uint32*)&desc_pp, sizeof(ABE_SPingPongDescriptor));
+
+ if ((desc_pp.counter & 0x1) == 0)
+ desc_pp.nextbuff0_Samples = (abe_uint16) (n >> 2); /* FW uses words numbers instead of bytes */
+ else
+ desc_pp.nextbuff1_Samples = (abe_uint16) (n >> 2);
+
+ struct_offset = (abe_uint32)&(desc_pp.nextbuff0_BaseAddr) - (abe_uint32)&(desc_pp);
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, sio_pp_desc_address + struct_offset,
+ &(desc_pp.nextbuff0_BaseAddr), sizeof(desc_pp) - struct_offset);
+
+}
+
+/*
+ * ABE_READ_NEXT_PING_PONG_BUFFER
+ *
+ * Parameter :
+ * Port_ID :
+ * Returned address to the next buffer (byte offset from DMEM start)
+ *
+ * Operations :
+ * Tell the next base address of the next ping_pong Buffer and reset its size
+ *
+ *
+ */
+void abe_read_next_ping_pong_buffer(abe_port_id port, abe_uint32 *p, abe_uint32 *n)
+{
+ abe_uint32 sio_pp_desc_address;
+ ABE_SPingPongDescriptor desc_pp;
+
+ /* ping_pong is only supported on MM_DL */
+ if (port != MM_DL_PORT) {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_PARAMETER_ERROR);
+ }
+
+ /* read the port SIO descriptor and extract the current pointer address after reading the counter */
+ sio_pp_desc_address = D_PingPongDesc_ADDR;
+ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, sio_pp_desc_address, (abe_uint32*)&desc_pp, sizeof(ABE_SPingPongDescriptor));
+
+ if ((desc_pp.counter & 0x1) == 0) {
+ (*p) = desc_pp.nextbuff0_BaseAddr;
+ (*n) = desc_pp.nextbuff0_Samples;
+ } else {
+ (*p) = desc_pp.nextbuff1_BaseAddr;
+ (*n) = desc_pp.nextbuff1_Samples;
+ }
+}
+
+/*
+ * ABE_INIT_PING_PONG_BUFFER
+ *
+ * Parameter :
+ * size of the ping pong
+ * number of buffers (2 = ping/pong)
+ * returned address of the ping-pong list of base address (byte offset from DMEM start)
+ *
+ * Operations :
+ * Computes the base address of the ping_pong buffers
+ *
+ */
+void abe_init_ping_pong_buffer(abe_port_id id, abe_uint32 s, abe_uint32 n, abe_uint32 *p)
+{
+ abe_uint32 i, dmem_addr;
+
+ abe_size_pingpong = s;
+ abe_nb_pingpong = n;
+
+ /* ping_pong is supported in 2 buffers configuration right now but FW is ready for ping/pong/pung/pang... */
+ if (id != MM_DL_PORT || n > MAX_PINGPONG_BUFFERS) {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_PARAMETER_ERROR);
+ }
+
+ for (i = 0; i < abe_nb_pingpong; i++) {
+ dmem_addr = dmem_ping_pong_buffer + (i * abe_size_pingpong);
+ abe_base_address_pingpong [i] = dmem_addr; /* base addresses of the ping pong buffers in U8 unit */
+ }
+}
+
+/*
+ * ABE_PLUG_SUBROUTINE
+ *
+ * Parameter :
+ * id: returned sequence index after plugging a new subroutine
+ * f : subroutine address to be inserted
+ * n : number of parameters of this subroutine
+ *
+ * Returned value : error code
+ *
+ * Operations : register a list of subroutines for call-back purpose
+ *
+ */
+void abe_plug_subroutine(abe_uint32 *id, abe_subroutine2 f, abe_uint32 n)
+{
+ /* debug trace */
+ abe_add_subroutine(id, f, n);
+}
+
+/*
+ * ABE_PLUG_SEQUENCE
+ *
+ * Parameter :
+ * Id: returned sequence index after pluging a new sequence (index in the tables)
+ * s : sequence to be inserted
+ *
+ * Operations :
+ * Load a time-sequenced operations.
+ *
+ * Return value :
+ * None.
+ */
+void abe_plug_sequence(abe_uint32 *id, abe_sequence_t *s)
+{
+}
+
+/*
+ * ABE_SET_SEQUENCE_TIME_ACCURACY
+ *
+ * Parameter :
+ * patch bit field used to guarantee the code compatibility without conditionnal compilation
+ * Sequence index
+ *
+ * Operations : two counters are implemented in the firmware:
+ * - one "fast" counter, generating an IRQ to the HAL for sequences scheduling, the rate is in the range 1ms .. 100ms
+ * - one "slow" counter, generating an IRQ to the HAL for the management of ASRC drift, the rate is in the range 1s .. 100s
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_sequence_time_accuracy(abe_micros_t fast, abe_micros_t slow)
+{
+}
+
+/*
+ * ABE_LAUNCH_SEQUENCE
+ *
+ * Parameter :
+ * patch bit field used to guarantee the code compatibility without conditionnal compilation
+ * Sequence index
+ *
+ * Operations :
+ * Launch a list a time-sequenced operations.
+ *
+ * Return value :
+ * None.
+ */
+void abe_launch_sequence(abe_patch_rev patch, abe_uint32 n)
+{
+}
+
+/*
+ * ABE_LAUNCH_SEQUENCE_PARAM
+ *
+ * Parameter :
+ * patch bit field used to guarantee the code compatibility without conditionnal compilation
+ * Sequence index
+ * Parameters to the programmable sequence
+ *
+ * Operations :
+ * Launch a list a time-sequenced operations.
+ *
+ * Return value :
+ * None.
+ */
+void abe_launch_sequence_param(abe_patch_rev patch, abe_uint32 n, abe_int32 *param1, abe_int32 *param2, abe_int32 *param3, abe_int32 *param4)
+{
+}
+
+/*
+ * ABE_READ_ANALOG_GAIN_DL
+ *
+ * Parameter :
+ * gain value pointer
+ *
+ * Operations :
+ * returns to the data pointer the gain value of the phoenix headset in case the
+ * dynamic extension is activated.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_analog_gain_dl(abe_gain_t *a)
+{
+}
+
+/*
+ * ABE_READ_ANALOG_GAIN_UL
+ *
+ * Parameter :
+ * gain value pointer
+ *
+ * Operations :
+ * returns to the data pointer the gain value of the phoenix headset in case the
+ * dynamic extension is activated.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_analog_gain_ul(abe_gain_t *a)
+{
+}
+
+/*
+ * ABE_ENABLE_DYN_UL_GAIN
+ *
+ * Parameter :
+ * None.
+ *
+ * Operations :
+ * enables the audio engine capability to change dynamically the analog microphone
+ * amplitude based on the information of analog gain changes.
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_dyn_ul_gain(void)
+{
+}
+
+/*
+ * ABE_DISABLE_DYN_UL_GAIN
+ *
+ * Parameter :
+ *
+ *
+ * Operations :
+ * disables the audio engine capability to change dynamically the analog microphone
+ * amplitude based on the information of analog gain changes.
+ *
+ * Return value :
+ * None.
+ */
+void abe_disable_dyn_ul_gain(void)
+{
+}
+
+/*
+ * ABE_ENABLE_DYN_EXTENSION
+ *
+ * Parameter :
+ * None
+ *
+ * Operations :
+ * enables the audio engine capability to change the analog gain of Phoenix headset port.
+ * This feature enables dynamic range extension by increasing the digital gains and lowering
+ * the analog gains. This API is preferably called at reset time.
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_dyn_extension(void)
+{
+}
+
+/*
+ * ABE_DISABLE_DYN_EXTENSION
+ *
+ * Parameter :
+ * None
+ *
+ * Operations :
+ * disables the audio engine capability to change the analog gain of Phoenix headset port.
+ *
+ * Return value :
+ * None.
+ */
+void abe_disable_dyn_extension(void)
+{
+}
+
+/*
+ * ABE_NOTIFY_ANALOG_GAIN_CHANGED
+ *
+ * Parameter :
+ * Id: name of the Phoenix (or other device) port for which a gain was changed
+ * G: pointer to the notified gain value
+ *
+ * Operations :
+ * The upper layer tells the HAL a new gain was programmed in the analog renderer.
+ * This will help the tuning of the APS parameters.
+ *
+ * Return value :
+ * None.
+ */
+void abe_notify_analog_gain_changed(abe_ana_port_id Id, abe_gain_t *G)
+{
+}
+
+/*
+ * ABE_RESET_PORT
+ *
+ * Parameters :
+ * id: port name
+ *
+ * Returned value : error code
+ *
+ * Operations : stop the port activity and reload default parameters on the associated processing features.
+ * Clears the internal AE buffers.
+ *
+ */
+void abe_reset_port(abe_port_id id)
+{
+ abe_port [id] = ((abe_port_t *) abe_port_init) [id];
+}
+
+/*
+ * ABE_READ_REMAINING_DATA
+ *
+ * Parameter :
+ * Port_ID :
+ * size : pointer to the remaining number of 32bits words
+ *
+ * Operations :
+ * computes the remaining amount of data in the buffer.
+ *
+ * Return value :
+ * error code
+ */
+void abe_read_remaining_data(abe_port_id port, abe_uint32 *n)
+{
+ *n = 0;
+}
+
+/*
+ * ABE_DISABLE_DATA_TRANSFER
+ *
+ * Parameter :
+ * p: port indentifier
+ *
+ * Operations :
+ * disables the ATC descriptor and stop IO/port activities
+ *
+ * Return value :
+ * None.
+ */
+void abe_disable_data_transfer(abe_port_id *p)
+{
+ abe_port_protocol_t *protocol;
+ abe_data_format_t *format;
+
+ protocol = &(abe_port[PDM_DL1_PORT].protocol); format = &(abe_port[PDM_UL_PORT].format);
+
+ abe_init_io_tasks(PDM_UL_PORT, format, protocol); /* @@@@ disable = change the R0123/INITREG, do it in one of the */
+ /* @@@@ three config/port: normal/McBSP/SlimBus */
+
+ /* AESS/ATC descriptor disabled, after the IO/task is stopped */
+ abe_init_atc(*p);
+
+ /* local host variable status: port is idle */
+ abe_port[PDM_DL1_PORT].status = IDLE_P;
+}
+
+/*
+ * ABE_ENABLE_DATA_TRANSFER
+ *
+ * Parameter :
+ * p: port indentifier
+ *
+ * Operations :
+ * enables the ATC descriptor
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_data_transfer(abe_port_id id)
+{
+ abe_port_protocol_t *protocol;
+ abe_data_format_t *format;
+
+ protocol = &(abe_port[id].protocol);
+ format = &(abe_port[id].format);
+
+ /* AESS/ATC descriptor disabled, enabled in the IO task */
+ abe_init_atc(id);
+ /* install a new IO task descriptor */
+ abe_init_io_tasks(id, format, protocol);
+
+ /* local host variable status: port is running */
+ abe_port[PDM_DL1_PORT].status = RUN_P;
+}
+
+/*
+ * ABE_WRITE_CLOCK_MODE
+ *
+ * Parameter :
+ *
+ * Operations :
+ * information from the upper layers of the clock configuration in Phoenix in
+ * order to correctly translate the global counter values in time.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_clock_mode(abe_uint32 mode)
+{
+}
+
+/*
+ * ABE_READ_GLOBAL_COUNTER
+ *
+ * Parameter :
+ * data pointer to the counter value
+ * data pointer to the translated milliseconds
+ *
+ * Operations :
+ * returns the value of the 32bits counter incremented on each firmware scheduling task
+ * loops (250us / 272us with respectively 48kHz / 44.1kHz on Phoenix). Translates this data
+ * in milli seconds format.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_global_counter(abe_time_stamp_t *t, abe_millis_t *m)
+{
+}
+
+/*
+ * ABE_SET_DMIC_FILTER
+ *
+ * Parameter :
+ * DMIC decimation ratio : 16/25/32/40
+ *
+ * Operations :
+ * Loads in CMEM a specific list of coefficients depending on the DMIC sampling
+ * frequency (2.4MHz or 3.84MHz). This table compensates the DMIC decimator roll-off at 20kHz.
+ * The default table is loaded with the DMIC 2.4MHz recommended configuration.
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_dmic_filter(abe_dmic_ratio_t d)
+{
+}
+
+/**
+* @fn abe_connect_cbpr_dmareq_port()
+*
+* Operations : enables the data echange between a DMA and the ABE through the
+* CBPr registers of AESS.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* a : returned pointer to the base address of the CBPr register and number of
+* samples to exchange during a DMA_request.
+*
+* @see ABE_API.h
+*/
+void abe_connect_cbpr_dmareq_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *returned_dma_t)
+{
+ abe_port[id] = ((abe_port_t *)abe_port_init)[id];
+
+ abe_port[id].format = *f;
+ abe_port[id].protocol.protocol_switch = DMAREQ_PORT_PROT;
+ abe_port[id].protocol.p.prot_dmareq.iter = abe_dma_port_iteration(f);
+ abe_port[id].protocol.p.prot_dmareq.dma_addr = ABE_DMASTATUS_RAW;
+ abe_port[id].protocol.p.prot_dmareq.dma_data = (1 << d);
+
+ abe_port[id].status = RUN_P;
+
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port [id]).format), &((abe_port [id]).protocol));
+
+ /* load the dma_t with physical information from AE memory mapping */
+ abe_init_dma_t(id, &((abe_port [id]).protocol));
+
+ /* load the ATC descriptors - disabled */
+ abe_init_atc(id);
+
+ /* return the dma pointer address */
+ abe_read_port_address(id, returned_dma_t);
+}
+
+/**
+* @fn abe_connect_dmareq_port()
+*
+* Operations : enables the data echanges between a DMA and a direct access to
+* the DMEM memory of ABE. On each dma_request activation the DMA will exchange
+* "iter" bytes and rewind its pointer to the base address "l3" waiting for the
+* next activation. The scheme is used for the MM_UL and debug port
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* a : returned pointer to the base address of the ping-pong buffer and number
+* of samples to exchange during a DMA_request..
+*
+* @see ABE_API.h
+*/
+void abe_connect_dmareq_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *a)
+{
+}
+
+/**
+* @fn abe_connect_dmareq_ping_pong_port()
+*
+* Operations : enables the data echanges between a DMA and a direct access to
+* the DMEM memory of ABE. On each dma_request activation the DMA will exchange
+* "s" bytes and switch to the "pong" buffer for a new buffer exchange.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* s : half-buffer (ping) size
+*
+* a : returned pointer to the base address of the ping-pong buffer and number of samples to exchange during a DMA_request.
+*
+* @see ABE_API.h
+*/
+void abe_connect_dmareq_ping_pong_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_dma_t *returned_dma_t)
+{
+ abe_dma_t dma1;
+
+ /* ping_pong is only supported on MM_DL */
+ if (id != MM_DL_PORT)
+ {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_PARAMETER_ERROR);
+ }
+
+ /* declare PP buffer for mono 20ms = 960 samples and prepare the returned dma_t */
+ abe_init_ping_pong_buffer(MM_DL_PORT, s, 2, returned_dma_t->data);
+
+ abe_port [id] = ((abe_port_t *) abe_port_init) [id];
+
+ (abe_port [id]).format = (*f);
+ (abe_port [id]).protocol.protocol_switch = PINGPONG_PORT_PROT;
+ (abe_port [id]).protocol.p.prot_pingpong.buf_addr = dmem_ping_pong_buffer;
+ (abe_port [id]).protocol.p.prot_pingpong.buf_size = s;
+ (abe_port [id]).protocol.p.prot_pingpong.irq_addr = ABE_DMASTATUS_RAW;
+ (abe_port [id]).protocol.p.prot_pingpong.irq_data = (1 << d);
+
+ abe_port [id].status = RUN_P;
+
+ /* load the micro-task parameters DESC_IO_PP */
+ abe_init_io_tasks(id, &((abe_port [id]).format), &((abe_port [id]).protocol));
+
+ /* load the dma_t with physical information from AE memory mapping */
+ abe_init_dma_t(id, &((abe_port [id]).protocol));
+
+ dma1.data = (abe_uint32 *)(abe_port [id].dma.data + ABE_DMEM_BASE_ADDRESS_L3);
+ dma1.iter = abe_port [id].dma.iter;
+ (*returned_dma_t) = dma1;
+}
+
+/**
+* @fn abe_connect_irq_ping_pong_port()
+*
+* Operations : enables the data echanges between a direct access to the DMEM
+* memory of ABE using cache flush. On each IRQ activation a subroutine
+* registered with "abe_plug_subroutine" will be called. This subroutine
+* will generate an amount of samples, send them to DMEM memory and call
+* "abe_set_ping_pong_buffer" to notify the new amount of samples in the
+* pong buffer.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* I : index of the call-back subroutine to call
+* s : half-buffer (ping) size
+*
+* p: returned base address of the first (ping) buffer)
+*
+* @see ABE_API.h
+*/
+void abe_connect_irq_ping_pong_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_uint32 *p)
+{
+ /* ping_pong is only supported on MM_DL */
+ if (id != MM_DL_PORT) {
+ abe_dbg_param |= ERR_API;
+ abe_dbg_error_log(ABE_PARAMETER_ERROR);
+ }
+
+ /* declare PP buffer for mono 20ms = 960 samples */
+ abe_init_ping_pong_buffer(MM_DL_PORT, s, 2, p);
+
+ abe_port [id] = ((abe_port_t *) abe_port_init) [id];
+ (abe_port [id]).format = (*f);
+ (abe_port [id]).protocol.protocol_switch = PINGPONG_PORT_PROT;
+ (abe_port [id]).protocol.p.prot_pingpong.buf_addr = dmem_ping_pong_buffer;
+ (abe_port [id]).protocol.p.prot_pingpong.buf_size = s;
+ (abe_port [id]).protocol.p.prot_pingpong.irq_addr = ABE_MCU_IRQSTATUS_RAW;
+ (abe_port [id]).protocol.p.prot_pingpong.irq_data = (1);
+
+ abe_port [id].status = RUN_P;
+
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port [id]).format), &((abe_port [id]).protocol));
+
+ /* load the ATC descriptors - disabled */
+ abe_init_atc(id);
+
+ (*p)= (abe_port [id]).protocol.p.prot_pingpong.buf_addr;
+}
+
+/**
+* @fn abe_connect_serial_port()
+*
+* Operations : enables the data echanges between a McBSP and an ATC buffer in
+* DMEM. This API is used connect 48kHz McBSP streams to MM_DL and 8/16kHz
+* voice streams to VX_UL, VX_DL, BT_VX_UL, BT_VX_DL. It abstracts the
+* abe_write_port API.
+*
+* Parameters :
+* id: port name
+* f : data format
+* i : peripheral ID (McBSP #1, #2, #3)
+*
+* @see ABE_API.h
+*/
+void abe_connect_serial_port(abe_port_id id, abe_data_format_t *f, abe_uint32 i)
+{
+ abe_port [id] = ((abe_port_t *) abe_port_init) [id];
+ (abe_port [id]).format = (*f);
+ (abe_port [id]).protocol.protocol_switch = SERIAL_PORT_PROT;
+
+ (abe_port [id]).protocol.p.prot_serial.desc_addr; /* McBSP/McASP peripheral connected to ATC */
+ (abe_port [id]).protocol.p.prot_serial.buf_addr; /* Address of ATC McBSP/McASP descriptor's in bytes */
+ (abe_port [id]).protocol.p.prot_serial.buf_size; /* DMEM address in bytes */
+ (abe_port [id]).protocol.p.prot_serial.iter; /* ITERation on each DMAreq signals */
+ (abe_port [id]).protocol.p.prot_serial.thr_flow; /* Data threshold for flow management */
+
+ abe_port [id].status = RUN_P;
+
+ /* load the micro-task parameters */
+ abe_init_io_tasks(id, &((abe_port [id]).format), &((abe_port [id]).protocol));
+
+ /* load the ATC descriptors - disabled */
+ abe_init_atc(id);
+}
+
+/*
+ * ABE_WRITE_PORT_DESCRIPTOR
+ *
+ * Parameter :
+ * id: port name
+ * f : input pointer to the data format
+ * p : input pointer to the protocol description
+ * dma : output pointer to the DMA iteration and data destination pointer :
+ *
+ * Operations :
+ * writes the corresponding port descriptor in the AE memory spaces. The ATC DMEM descriptors
+ * are initialized.
+ * - translates the data format to AE I/O task format
+ * - copy to DMEM
+ * - load ATC descriptor - disabled
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_port_descriptor(abe_port_id id, abe_data_format_t *format, abe_port_protocol_t *prot, abe_dma_t *dma)
+{
+#if 0
+ abe_dbg_log(ID_WRITE_PORT_DESCRIPTOR);
+
+ if (abe_port [id].status)
+ abe_dbg_log(ABE_PORT_REPROGRAMMING);
+
+
+ // load internal HAL data
+
+ abe_port [id].status = RUN_P; // running status
+ abe_port [id].format = (*format); // format = input parameter
+ abe_port [id].drift = 0; // no drift yet
+ abe_port [id].callback = NOCALLBACK;
+ abe_port [id].protocol = (*prot); // protocol = input parameter
+
+
+ // load AE memory space
+
+ abe_init_io_tasks(id, format, prot); // load the micro-task parameters
+ abe_init_dma_t(id, prot); // load the dma_t with physical information from AE memory mapping
+ abe_init_atc(id); // load the ATC descriptors - disabled
+ abe_read_port_address(id, dma); // return the dma pointer address
+
+#endif
+}
+
+/*
+ * ABE_READ_PORT_DESCRIPTOR
+ *
+ * Parameter :
+ * id: port name
+ * f : input pointer to the data format
+ * p : input pointer to the protocol description
+ * dma : output pointer to the DMA iteration and data destination pointer :
+ *
+ * Operations :
+ * returns the port parameters from the HAL internal buffer.
+ *
+ * Return value :
+ * error code in case the Port_id is not compatible with the current OPP value
+ */
+void abe_read_port_descriptor(abe_port_id port, abe_data_format_t *f, abe_port_protocol_t *p)
+{
+ (*f) = (abe_port[port]).format;
+ (*p) = (abe_port[port]).protocol;
+}
+
+/*
+ * ABE_READ_APS_ENERGY
+ *
+ * Parameter :
+ * Port_ID : port ID supporting APS
+ * APS data struct pointer
+ *
+ * Operations :
+ * Returns the estimated amount of energy
+ *
+ * Return value :
+ * error code when the Port is not activated.
+ */
+void abe_read_aps_energy(abe_port_id *p, abe_gain_t *a)
+{
+}
+
+/*
+ * ABE_READ_PORT_ADDRESS
+ *
+ * Parameter :
+ * dma : output pointer to the DMA iteration and data destination pointer
+ *
+ * Operations :
+ * This API returns the address of the DMA register used on this audio port.
+ * Depending on the protocol being used, adds the base address offset L3 (DMA) or MPU (ARM)
+ *
+ * Return value :
+ */
+void abe_read_port_address(abe_port_id port, abe_dma_t *dma2)
+{
+ abe_dma_t_offset dma1;
+ abe_uint32 protocol_switch;
+
+ dma1 = (abe_port[port]).dma;
+ protocol_switch = abe_port[port].protocol.protocol_switch;
+
+ switch (protocol_switch) {
+ case PINGPONG_PORT_PROT:
+ dma1.data = dma1.data + ABE_DMEM_BASE_ADDRESS_L3;
+ break;
+ case DMAREQ_PORT_PROT:
+// if (MM_UL_PORT == port) /* special behavior for the MM_UL port */
+// dma1.data = dma1.data + ABE_DMEM_BASE_ADDRESS_L3; /* DMA points directly to the DMEM instead of CBPr register */
+// else
+ dma1.data = dma1.data + ABE_ATC_BASE_ADDRESS_L3;
+ break;
+ case CIRCULAR_PORT_PROT:
+ dma1.data = dma1.data + ABE_ATC_BASE_ADDRESS_L3;
+ break;
+ case SLIMBUS_PORT_PROT:
+ case SERIAL_PORT_PROT:
+ case DMIC_PORT_PROT:
+ case MCPDMDL_PORT_PROT:
+ case MCPDMUL_PORT_PROT:
+ default:
+ break;
+ }
+
+ (*dma2).data = (void *)(dma1.data);
+ (*dma2).iter = (dma1.iter);
+}
+
+/*
+ * ABE_WRITE_PORT_GAIN
+ *
+ * Parameter :
+ * port : name of the port (VX_DL_PORT, MM_DL_PORT, MM_EXT_DL_PORT, TONES_DL_PORT, …)
+ * dig_gain_port pointer to returned port gain and time constant
+ *
+ * Operations :
+ * saves the gain data in the local HAL-L0 table of gains in native format.
+ * Translate the gain to the AE-FW format and load it in CMEM
+ *
+ * Return value :
+ * error code in case the gain_id is not compatible with the current OPP value.
+ */
+void abe_write_port_gain(abe_port_id port, abe_gain_t g, abe_ramp_t ramp)
+{
+#if 0
+ abe_uint32 port_coef, lin_g, iir_ramp1, iir_ramp1MA;
+ abe_float f_g, f_lin_g, f_ramp, f_iir_ramp1;
+
+ switch (id) {
+ case PDM_UL_PORT:
+ port_coef = cmem_port_pdmul;
+ break;
+ case BT_VX_UL_PORT:
+ port_coef = cmem_port_btul;
+ break;
+ case MM_UL_PORT:
+ port_coef = cmem_port_mmul;
+ break;
+ case MM_UL2_PORT:
+ port_coef = cmem_port_mmul2;
+ break;
+ case VX_UL_PORT:
+ port_coef = cmem_port_vxul;
+ break;
+ case MM_DL_PORT:
+ port_coef = cmem_port_pdmdl;
+ break;
+ case VX_DL_PORT:
+ port_coef = cmem_port_vxdl;
+ break;
+ case TONES_DL_PORT:
+ port_coef = cmem_port_tones;
+ break;
+ case VIB_DL_PORT:
+ port_coef = cmem_port_vibdl;
+ break;
+ case BT_VX_DL_PORT:
+ port_coef = cmem_port_btdl;
+ break;
+ case PDM_DL1_PORT:
+ port_coef = cmem_port_pdmdl1;
+ break;
+ case MM_EXT_OUT_PORT:
+ port_coef = cmem_port_mmext;
+ break;
+ case PDM_DL2_PORT:
+ port_coef = cmem_port_pdmdl2;
+ break;
+ case PDM_VIB_PORT:
+ port_coef = cmem_port_pdmvib;
+ break;
+ case DMIC_PORT2:
+ port_coef = cmem_port_dmic2;
+ break;
+ case DMIC_PORT3:
+ port_coef = cmem_port_dmic3;
+ break;
+ case DMIC_PORT1:
+ default:
+ port_coef = cmem_port_dmic1;
+ break;
+ }
+
+ f_g = (abe_float)g;
+ f_ramp = (abe_float)ramp;
+
+ abe_translate_gain_format(MILLIBELS_TO_LINABE, f_g, &f_lin_g);
+ abe_translate_to_xmem_format(ABE_CMEM, f_lin_g, &lin_g);
+
+ abe_translate_ramp_format(f_ramp, &f_iir_ramp1);
+ abe_translate_to_xmem_format(ABE_CMEM, f_iir_ramp1, &iir_ramp1);
+ abe_translate_to_xmem_format(ABE_CMEM, (1 - f_iir_ramp1), &iir_ramp1MA);
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 4*port_coef, (abe_uint32*)&lin_g, sizeof(lin_g));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 4*cmem_ramp_alpha, (abe_uint32*)&iir_ramp1, sizeof(iir_ramp1));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 4*cmem_ramp_1_M_alpha, (abe_uint32*)&iir_ramp1MA, sizeof(iir_ramp1MA));
+#endif
+}
+
+/*
+ * ABE_READ_GAIN
+ *
+ * Parameter :
+ * port : name of the port (VX_DL_PORT, MM_DL_PORT, MM_EXT_DL_PORT, TONES_DL_PORT, …)
+ * dig_gain_port pointer to returned port gain and time constant
+ *
+ * Operations :
+ * returns the real-time value of the gain from CMEM.
+ *
+ * Return value :
+ * error code in case the gain_id is not compatible with the current OPP value.
+ */
+void abe_read_port_gain(abe_port_id port, abe_gain_t *gain, abe_ramp_t *ramp)
+{
+}
+
+/*
+ * ABE_READ_GAIN_RANGES
+ *
+ * Parameter :
+ * Id : name of the AE port
+ * Gain data pointer to the minimum, maximum gain,
+ * gain steps for the overall digital and/or analog hardware.
+ *
+ * Operations :
+ * returns the gain steps accuracy and range. If the API abe_enable_dyn_extension
+ * was called, the ports connected to Phoenix McPDM will also incorporate the gains
+ * of the analog part, else only the digital part is taken into account.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_gain_range(abe_port_id id, abe_gain_t *min, abe_gain_t *max, abe_gain_t *step)
+{
+}
+
+/*
+ * ABE_WRITE_EQUALIZER
+ *
+ * Parameter :
+ * Id : name of the equalizer
+ * Param : equalizer coefficients
+ *
+ * Operations :
+ * Load the coefficients in CMEM. This API can be called when the corresponding equalizer
+ * is not activated. After reloading the firmware the default coefficients corresponds to
+ * "no equalizer feature". Loading all coefficients with zeroes disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_equalizer(abe_equ_id id, abe_equ_t *param)
+{
+#if 0
+ setCM(C_DMIC1_EQ_Coefs_ADDR, C_DMIC1_EQ_Coefs_ADDR+16, pGain, Sth);
+ setCM(C_DMIC2_EQ_Coefs_ADDR, C_DMIC2_EQ_Coefs_ADDR+16, pGain, Sth);
+ setCM(C_DMIC3_EQ_Coefs_ADDR, C_DMIC3_EQ_Coefs_ADDR+16, pGain, Sth);
+ setCM(C_SDT_Coefs_ADDR, C_SDT_Coefs_ADDR+16, pGain, Sth);
+ setCM(C_DL1_Coefs_ADDR, C_DL1_Coefs_ADDR+16, pGain, Sth);
+
+ setCM(C_DL2_R_Coefs_ADDR, C_DL2_R_Coefs_ADDR+16, pGain, Sth);
+ setCM(C_DL2_L_Coefs_ADDR, C_DL2_L_Coefs_ADDR+16, pGain, Sth)
+#endif
+}
+
+/*
+ * ABE_SET_ASRC_DRIFT_CONTROL
+ *
+ * Parameter :
+ * Id : name of the asrc
+ * f: flag which enables (1) the automatic computation of drift parameters
+ *
+ * Operations :
+ * When an audio port is connected to an hardware peripheral (MM_DL connected to a McBSP for
+ * example), the drift compensation can be managed in "forced mode" (f=0) or "adaptive mode"
+ * (f=1). In the first case the drift is managed with the usage of the API "abe_write_asrc".
+ * In the second case the firmware will generate on periodic basis an information about the
+ * observed drift, the HAL will reload the drift parameter based on those observations.
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_asrc_drift_control(abe_asrc_id id, abe_uint32 f)
+{
+}
+
+/*
+ * ABE_WRITE_ASRC
+ *
+ * Parameter :
+ * Id : name of the asrc
+ * param : drift value t compensate
+ *
+ * Operations :
+ * Load the drift coefficients in FW memory. This API can be called when the corresponding
+ * ASRC is not activated. After reloading the firmware the default coefficients corresponds
+ * to "no ASRC activated". Loading the drift value with zero disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_asrc(abe_asrc_id id, abe_drift_t *param)
+{
+#if 0
+ int dTempValue;
+ int aTempValue32[8];
+
+ /*
+ * x = ppm
+ *
+ * - 1000000/x must be multiple of 16
+ * - DeltaAlpha = round(2^20*x*16/1000000)=round(2^18/5^6*x) on 22 bits. Then shifted by 2
+ * - MinusDeltaAlpha
+ * - OneMinusEpsilon = 1-DeltaAlpha/2.
+ *
+ * PPM = 250
+ * - 1000000/250=4000
+ * - DeltaAlpha = 4194.3 ~ 4195 => 0x00418C
+ */
+
+ if (dPpm != 0)
+ {
+ /* Default value for -6250 ppm */
+ aTempValue32[0] = 4; /* D_ConstAlmost0 */
+ aTempValue32[1] = -1; /* D_DriftSign */
+ aTempValue32[2] = 15; /* D_Subblock */
+ aTempValue32[3] = 0x00066668; /* D_DeltaAlpha */
+ aTempValue32[4] = 0xFFF99998; /* D_MinusDeltaAlpha */
+ aTempValue32[5] = 0x003CCCCC; /* D_OneMinusEpsilon */
+ aTempValue32[6] = 0x00000000; /* D_AlphaZero */
+ aTempValue32[7] = 0x00400000; /* D_BetaOne */
+
+ /* compute new value for the PPM */
+ if (dPpm > 0){
+ aTempValue32[1] = 1; /* D_DriftSign */
+ } else {
+ aTempValue32[1] = -1; /* D_DriftSign */
+ }
+
+ dTempValue = (int)(ceil(262144.0/15625.0*abs(dPpm)));
+ aTempValue32[3] = dTempValue<<2;
+ aTempValue32[4] = (-dTempValue)<<2;
+ aTempValue32[5] = (0x00100000-(dTempValue/2))<<2;
+
+ switch (dPath) {
+ case 0x0000:
+ /* Voice Uplink */
+ /* Init CMem */
+ dTempValue = 0x00000000;
+ setCM(C_AlphaCurrent_UL_VX_ADDR, C_AlphaCurrent_UL_VX_ADDR, &dTempValue, Sth);
+ dTempValue = 0x00400000;
+ setCM(C_BetaCurrent_UL_VX_ADDR, C_BetaCurrent_UL_VX_ADDR, &dTempValue, Sth);
+
+ /* Init DMem */
+ setlDM(D_AsrcVars_UL_VX_ADDR, D_AsrcVars_UL_VX_ADDR+28, &aTempValue32[0], Sth);
+ break;
+ case 0x0001:
+ /* Voice Downlink */
+ /* Init CMem */
+ dTempValue = 0x00000000;
+ setCM(C_AlphaCurrent_DL_VX_ADDR, C_AlphaCurrent_DL_VX_ADDR, &dTempValue, Sth);
+ dTempValue = 0x00400000;
+ setCM(C_BetaCurrent_DL_VX_ADDR, C_BetaCurrent_DL_VX_ADDR, &dTempValue, Sth);
+
+ /* Init DMem */
+ setlDM(D_AsrcVars_DL_VX_ADDR, D_AsrcVars_DL_VX_ADDR+28, &aTempValue32[0], Sth);
+ break;
+ case 0x0002:
+ /* Multimedia Downlink */
+ /* Init CMem */
+ dTempValue = 0x00000000;
+ setCM(C_AlphaCurrent_DL_MM_ADDR, C_AlphaCurrent_DL_MM_ADDR, &dTempValue, Sth);
+ dTempValue = 0x00400000;
+ setCM(C_BetaCurrent_DL_MM_ADDR, C_BetaCurrent_DL_MM_ADDR, &dTempValue, Sth);
+
+ /* Init DMem */
+ setlDM(D_AsrcVars_DL_MM_ADDR, D_AsrcVars_DL_MM_ADDR+28, &aTempValue32[0], Sth);
+ break;
+ }
+#endif
+}
+
+/*
+ * ABE_WRITE_APS
+ *
+ * Parameter :
+ * Id : name of the aps filter
+ * param : table of filter coefficients
+ *
+ * Operations :
+ * Load the filters and thresholds coefficients in FW memory. This API can be called when
+ * the corresponding APS is not activated. After reloading the firmware the default coefficients
+ * corresponds to "no APS activated". Loading all the coefficients value with zero disables
+ * the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_aps(abe_aps_id id, abe_aps_t *param)
+{
+}
+
+/*
+ * ABE_WRITE_MIXER
+ *
+ * Parameter :
+ * Id : name of the mixer
+ * param : list of input gains of the mixer
+ * p : list of port corresponding to the above gains
+ *
+ * Operations :
+ * Load the gain coefficients in FW memory. This API can be called when the corresponding
+ * MIXER is not activated. After reloading the firmware the default coefficients corresponds
+ * to "all input and output mixer's gain in mute state". A mixer is disabled with a network
+ * reconfiguration corresponding to an OPP value.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_mixer(abe_mixer_id id, abe_gain_t f_g, abe_ramp_t f_ramp, abe_port_id p)
+{
+ abe_uint32 mixer_coef, lin_g, iir_ramp1, iir_ramp1MA;
+ abe_float f_lin_g, f_iir_ramp1;
+
+ /* @@@ to be changed when all the gains are managed with Ramps */
+ switch (id) {
+ default:
+ case MIXDL1:
+ mixer_coef = cmem_mixer_dl1;
+ break;
+ case MIXDL2:
+ mixer_coef = cmem_mixer_dl2;
+ break;
+ case MIXSDT:
+ mixer_coef = cmem_mixer_sdt;
+ break;
+ case MIXECHO:
+ mixer_coef = cmem_mixer_echo;
+ break;
+ case MIXAUDUL:
+ mixer_coef = cmem_mixer_audul;
+ break;
+ case MIXVXREC:
+ mixer_coef = cmem_mixer_vxrec;
+ break;
+ }
+
+ abe_translate_gain_format(DECIBELS_TO_LINABE, f_g, &f_lin_g);
+ abe_translate_to_xmem_format(ABE_CMEM, f_lin_g, &lin_g);
+
+#if 0
+ /* there are no RAMPS on Mixers' gain in FW05.xx */
+ abe_translate_ramp_format(f_ramp, &f_iir_ramp1);
+ abe_translate_to_xmem_format(ABE_CMEM, f_iir_ramp1, &iir_ramp1);
+ abe_translate_to_xmem_format(ABE_CMEM, (1 - f_iir_ramp1), &iir_ramp1MA);
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, (cmem_ramp_alpha + p) * 4, (abe_uint32*)&iir_ramp1, sizeof(iir_ramp1));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, (cmem_ramp_1_M_alpha + p) * 4, (abe_uint32*)&iir_ramp1MA, sizeof(iir_ramp1MA));
+#endif
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, (mixer_coef + p) * 4, (abe_uint32*)&lin_g, sizeof(lin_g));
+}
+
+/*
+ * ABE_WRITE_EANC
+ *
+ * Parameter :
+ * param : table of coefficients
+ *
+ * Operations :
+ * Load the EANC coefficients in FW memory. This API can be called when EANC is not
+ * activated. After reloading the firmware the default coefficients corresponds to
+ * "no EANC activated". Loading the coefficients value with zero disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_eanc(abe_eanc_t *param)
+{
+}
+
+/*
+ * ABE_ENABLE_ROUTER_CONFIGURATION
+ *
+ * Parameter :
+ * Id : name of the router
+ * param : list of output index of the route
+ *
+ * Operations : load a pre-computed router configuration
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_router_configuration(abe_router_id id, abe_uint32 configuration)
+{
+}
+
+/*
+ * ABE_SET_ROUTER_CONFIGURATION
+ *
+ * Parameter :
+ * Id : name of the router
+ * Conf : id of the configuration
+ * param : list of output index of the route
+ *
+ * Operations :
+ * The uplink router takes its input from DMIC (6 samples), AMIC (2 samples) and
+ * PORT1/2 (2 stereo ports). Each sample will be individually stored in an intermediate
+ * table of 10 elements. The intermediate table is used to route the samples to
+ * three directions : REC1 mixer, 2 EANC DMIC source of filtering and MM recording audio path.
+ * For example, a use case consisting in AMIC used for uplink voice communication, DMIC 0,1,2,3
+ * used for multimedia recording, , DMIC 5 used for EANC filter, DMIC 4 used for the feedback channel,
+ * will be implemented with the following routing table index list :
+ * [3, 2 , 1, 0, 0, 0 (two dummy indexes to data that will not be on MM_UL), 4, 5, 7, 6]
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_router_configuration(abe_router_id id, abe_uint32 configuration, abe_router_t *param)
+{
+ abe_uint8 aUplinkMuxing[16], n, i;
+
+ n = D_aUplinkRouting_ADDR_END - D_aUplinkRouting_ADDR + 1;
+
+ for(i=0; i < n; i++)
+ aUplinkMuxing[i] = (abe_uint8) (param [i]);
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_aUplinkRouting_ADDR, (abe_uint32 *)aUplinkMuxing, sizeof (aUplinkMuxing));
+}
+
+/*
+ * ABE_READ_ASRC
+ *
+ * Parameter :
+ * Id : name of the asrc
+ * param : drift value to compensate
+ *
+ *
+ * Operations :
+ * read drift ppm value
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_asrc(abe_asrc_id id, abe_drift_t *param)
+{
+}
+
+/*
+ * ABE_READ_APS
+ *
+ * Parameter :
+ * Id : name of the aps filter
+ * param : table of filter coefficients
+ *
+ * Operations :
+ * Read APS coefficients
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_aps(abe_aps_id id, abe_aps_t *param)
+{
+}
+
+/*
+ * ABE_READ_MIXER
+ *
+ * Parameter :
+ * Id : name of the mixer
+ * param : gain
+ * port corresponding to the above gains
+ *
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_mixer(abe_mixer_id id, abe_gain_t *gain, abe_ramp_t *f_ramp, abe_port_id p)
+{
+ abe_uint32 offset; //, lin_g, iir_ramp;
+
+ switch (id) {
+ case MIXSDT:
+ offset = cmem_mixer_sdt;
+ break;
+ case MIXECHO:
+ offset = cmem_mixer_echo;
+ break;
+ case MIXAUDUL:
+ offset = cmem_mixer_audul;
+ break;
+ case MIXVXREC:
+ offset = cmem_mixer_vxrec;
+ break;
+ case MIXDL2:
+ offset = cmem_mixer_dl2;
+ break;
+ case MIXDL1:
+ default:
+ offset = cmem_mixer_dl1;
+ break;
+ }
+
+// abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, 4 * (cmem_gain + offsset + p), (abe_uint32*)&lin_g, sizeof(lin_g));
+// abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, 4 * (cmem_ramp + offsset + p), (abe_uint32*)&iir_ramp, sizeof(iir_ramp));
+//
+// abe_translate_gain_format(LINABE_TO_MILLIBELS, &lin_g, &g);
+// abe_translate_gain_format(IIRABE_TO_MICROS, &iir_ramp, &ramp);
+}
+
+/*
+ * ABE_READ_EANC
+ *
+ * Parameter :
+ * param : table of coefficients
+ *
+ * Operations :
+ * read eanc coefficients
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_eanc(abe_eanc_t *param)
+{
+}
+
+/*
+ * ABE_READ_ROUTER
+ *
+ * Parameter :
+ * Id : name of the router
+ * param : list of output index of the route
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_router(abe_router_id id, abe_router_t *param)
+{
+}
+
+/*
+ * ABE_READ_DEBUG_TRACE
+ *
+ * Parameter :
+ * data destination pointer
+ * max number of data read
+ *
+ * Operations :
+ * reads the AE circular data pointer holding pairs of debug data+timestamps, and store
+ * the pairs in linear addressing to the parameter pointer. Stops the copy when the max
+ * parameter is reached or when the FIFO is empty.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_debug_trace(abe_uint32 *data, abe_uint32 *n)
+{
+}
+
+/*
+ * ABE_SET_DEBUG_TRACE
+ *
+ * Parameter :
+ * debug ID from a list to be defined
+ *
+ * Operations :
+ * load a mask which filters the debug trace to dedicated types of data
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_debug_trace(abe_dbg_t debug)
+{
+}
+
+/*
+ * ABE_SET_DEBUG_PINS
+ *
+ * Parameter :
+ * debugger commands to the AESS register in charge of the debug pins
+ *
+ * Operations :
+ * interpret the debugger commands: activate the AESS debug pins and
+ * allocate those pins to the AE outputs.
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_debug_pins(abe_uint32 debug_pins)
+{
+}
+
+/*
+ * ABE_REMOTE_DEBUGGER_INTERFACE
+ *
+ * Parameter :
+ *
+ * Operations :
+ * interpretation of the UART stream from the remote debugger commands.
+ * The commands consist in setting break points, loading parameter
+ *
+ * Return value :
+ * None.
+ */
+void abe_remote_debugger_interface(abe_uint32 n, abe_uint8 *p)
+{
+}
diff --git a/sound/soc/codecs/abe/abe_api.h b/sound/soc/codecs/abe/abe_api.h
new file mode 100644
index 000000000000..f5a8aa1e5dc3
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_api.h
@@ -0,0 +1,1081 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_API_H_
+#define _ABE_API_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * External API
+ */
+#if PC_SIMULATION
+extern void target_server_write_pmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_write_cmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_write_smem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_write_dmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_write_atc(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_read_pmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_read_cmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_read_smem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_read_dmem(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+extern void target_server_read_atc(abe_uint32 address, abe_uint32 *data, abe_uint32 nb_byte);
+#endif
+
+/*
+ * Internal API
+ */
+
+/**
+* abe_read_sys_clock() description for void abe_read_sys_clock().
+*
+* Operations : returns the current time indication for the LOG
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_sys_clock(abe_micros_t *time);
+
+/**
+* abe_fprintf() description for void abe_fprintf().
+*
+* Operations : returns the current time indication for the LOG
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_fprintf(char *line);
+
+/*
+ * API as part of the HAL paper documentation
+ */
+
+/**
+* abe_reset_hal() description for void abe_reset_hal().
+*
+* Operations : reset the HAL by reloading the static variables and default AESS registers.
+* Called after a PRCM cold-start reset of ABE
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_reset_hal(void);
+
+/**
+* abe_read_use_case_opp() description for void abe_read_use_case_opp().
+*
+* Operations : returns the expected min OPP for a given use_case list
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_use_case_opp(abe_use_case_id *u, abe_opp_t *o);
+
+/**
+* abe_load_fw() description for void abe_load_fw().
+*
+* Operations :
+* loads the Audio Engine firmware, generate a single pulse on the Event generator
+* to let execution start, read the version number returned from this execution.
+*
+* Parameter : No parameter
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code in case the firmware does not start.
+*
+* @see
+*/
+void abe_load_fw(void);
+
+/**
+* abe_read_port_address() description for void abe_read_port_address().
+*
+* Operations :
+* This API returns the address of the DMA register used on this audio port.
+*
+* Parameter : No parameter
+* @param dma : output pointer to the DMA iteration and data destination pointer
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_port_address(abe_port_id port, abe_dma_t *dma);
+
+/**
+* abe_default_configuration() description for void abe_default_configuration().
+*
+* Parameter :
+* use-case-ID : "LP player", "voice-call" use-cases as defined in the paragraph
+* "programming use-case sequences"
+* param1, 2, 3, 4 : two parameters to be used later during FW06 integration
+*
+* Operations :
+* private API used during development. Loads all the necessary parameters and data
+* patterns to allow a stand-alone functional test without the need of.
+*
+* Parameter : No parameter
+* @param dma : output pointer to the DMA iteration and data destination pointer
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_default_configuration(abe_uint32 use_case);
+
+/**
+* abe_irq_processing() description for void abe_irq_processing().
+*
+* Parameter :
+* No parameter
+*
+* Operations :
+* This subroutine will check the IRQ_FIFO from the AE and act accordingly.
+* Some IRQ source are originated for the delivery of "end of time sequenced tasks"
+* notifications, some are originated from the Ping-Pong protocols, some are generated from
+* the embedded debugger when the firmware stops on programmable break-points, etc …
+*
+* @param dma : output pointer to the DMA iteration and data destination pointer
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_irq_processing(void);
+
+/**
+* abe_write_event_generator () description for void abe_event_generator_switch().
+*
+* Operations :
+* load the AESS event generator hardware source. Loads the firmware parameters
+* accordingly. Indicates to the FW which data stream is the most important to preserve
+* in case all the streams are asynchronous. If the parameter is "default", let the HAL
+* decide which Event source is the best appropriate based on the opened ports.
+*
+* @param e: Event Generation Counter, McPDM, DMIC or default.
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_write_event_generator(abe_event_id e);
+
+/**
+* abe_read_lowest_opp() description for void abe_read_lowest_opp().
+*
+* Operations :
+* Returns the lowest possible OPP based on the current active ports.
+*
+* @param o: returned data
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_lowest_opp(abe_opp_t *o);
+
+/**
+* abe_set_opp_processing() description for void abe_set_opp_processing().
+*
+* Parameter :
+* New processing network and OPP:
+* 0: Ultra Lowest power consumption audio player (no post-processing, no mixer);
+* 1: OPP 25% (simple multimedia features, including low-power player);
+* 2: OPP 50% (multimedia and voice calls);
+* 3: OPP100% (EANC, multimedia complex use-cases);
+*
+* Operations :
+* Rearranges the FW task network to the corresponding OPP list of features.
+* The corresponding AE ports are supposed to be set/reset accordingly before this switch.
+*
+* @param o: desired opp
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_set_opp_processing(abe_opp_t opp);
+
+/**
+* abe_set_ping_pong_bufferg() description for void abe_set_ping_pong_buffer().
+*
+* Parameter :
+* Port_ID :
+* Pointer name : Read or Write pointer
+* New data
+*
+* Operations :
+* Updates the ping-pong read/write pointer with the input data.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_set_ping_pong_buffer(abe_port_id port, abe_uint32 n);
+
+/**
+* @fn abe_connect_irq_ping_pong_port()
+*
+* Operations : enables the data echanges between a direct access to the DMEM
+* memory of ABE using cache flush. On each IRQ activation a subroutine
+* registered with "abe_plug_subroutine" will be called. This subroutine
+* will generate an amount of samples, send them to DMEM memory and call
+* "abe_set_ping_pong_buffer" to notify the new amount of samples in the
+* pong buffer.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* I : index of the call-back subroutine to call
+* s : half-buffer (ping) size
+*
+* p: returned base address of the first (ping) buffer)
+*
+* @see ABE_API.h
+*/
+void abe_connect_irq_ping_pong_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_uint32 *p);
+
+/**
+* abe_plug_subroutine() description for void abe_plug_subroutine().
+*
+* Parameter :
+* id: returned sequence index after plugging a new subroutine
+* f : subroutine address to be inserted
+*
+* Operations :
+* register a list of subroutines for call-back purpose.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_plug_subroutine(abe_uint32 *id, abe_subroutine2 f, abe_uint32 n);
+
+/**
+* abe_plug_sequence() description for void abe_plug_sequence().
+*
+ * Parameter :
+ * Id: returned sequence index after pluging a new sequence (index in the tables);
+ * s : sequence to be inserted
+ *
+ * Operations :
+ * Load a list a time-sequenced operations.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_plug_sequence(abe_uint32 *id, abe_sequence_t *s);
+
+/**
+* abe_launch_sequence() description for void abe_launch_sequence().
+*
+* Parameter :
+* Sequence index
+*
+* Operations :
+* Launch a list a time-sequenced operations.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_launch_sequence(abe_patch_rev patch, abe_uint32 n);
+
+/**
+* abe_launch_sequence_param() description for void abe_launch_sequence_param().
+*
+* Parameter :
+* Sequence index
+* Parameters to the programmable sequence
+*
+* Operations :
+* Launch a list a time-sequenced operations.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_launch_sequence_param(abe_patch_rev patch, abe_uint32 n, abe_int32 *param1, abe_int32 *param2, abe_int32 *param3, abe_int32 *param4);;
+
+/**
+* abe_read_analog_gain_dl() description for void abe_read_analog_gain_dl().
+*
+* Parameter :
+* gain value pointer
+*
+* Operations :
+* returns to the data pointer the gain value of the phoenix headset in case the
+* dynamic extension is activated.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_analog_gain_dl(abe_gain_t *a);
+
+/**
+* abe_read_analog_gain_ul() description for void abe_read_analog_gain_ul().
+*
+ * Parameter :
+ * gain value pointer
+ *
+ * Operations :
+ * returns to the data pointer the gain value of the phoenix headset in case the
+ * dynamic extension is activated.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_read_analog_gain_ul(abe_gain_t *a);
+
+/**
+* abe_enable_dyn_ul_gain() description for void abe_enable_dyn_ul_gain().
+*
+* Parameter :
+* None.
+*
+* Operations :
+* enables the audio engine capability to change dynamically the analog microphone
+* amplitude based on the information of analog gain changes..
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_enable_dyn_ul_gain(void);
+
+/**
+* abe_disable_dyn_ul_gain() description for void abe_disable_dyn_ul_gain().
+*
+* Parameter :
+* None.
+*
+* Operations :
+* disables the audio engine capability to change dynamically the analog microphone
+* amplitude based on the information of analog gain changes.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_disable_dyn_ul_gain(void);
+
+/**
+* abe_enable_dyn_extension() description for void abe_enable_dyn_extension().
+*
+* Parameter :
+* None
+*
+* Operations :
+* enables the audio engine capability to change the analog gain of Phoenix headset port.
+* This feature enables dynamic range extension by increasing the digital gains and lowering
+* the analog gains. This API is preferably called at reset time.
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_enable_dyn_extension(void);
+
+/**
+* abe_disable_dyn_extension() description for void abe_disable_dyn_extension().
+*
+* Parameter :
+* None
+*
+* Operations :
+* disables the audio engine capability to change the analog gain of Phoenix heads
+*
+* @param
+*
+* @pre no pre-condition
+*
+* @post
+*
+* @return error code
+*
+* @see
+*/
+void abe_disable_dyn_extension(void);
+
+/*
+ * ABE_NOTIFY_ANALOG_GAIN_CHANGED
+ *
+ * Parameter :
+ * Id: name of the Phoenix (or other device); port for which a gain was changed
+ * G: pointer to the notified gain value
+ *
+ * Operations :
+ * The upper layer tells the HAL a new gain was programmed in the analog renderer.
+ * This will help the tuning of the APS parameters.
+ *
+ * Return value :
+ * None.
+ */
+void abe_notify_analog_gain_changed(abe_ana_port_id Id, abe_gain_t *G);
+
+/*
+ * ABE_RESET_PORT
+ *
+ * Parameters :
+ * id: port name
+ *
+ * Returned value : error code
+ *
+ * Operations : stop the port activity and reload default parameters on the associated processing features.
+ *
+ */
+void abe_reset_port(abe_port_id id);
+
+/*
+ * ABE_READ_REMAINING_DATA
+ *
+ * Parameter :
+ * Port_ID :
+ * size : pointer to the remaining number of 32bits words
+ *
+ * Operations :
+ * computes the remaining amount of data in the buffer.
+ *
+ * Return value :
+ * error code
+ */
+void abe_read_remaining_data(abe_port_id port, abe_uint32 *n);
+
+/*
+ * ABE_DISABLE_DATA_TRANSFER
+ *
+ * Parameter :
+ * p: port indentifier
+ *
+ * Operations :
+ * disables the ATC descriptor
+ *
+ * Return value :
+ * None.
+ */
+void abe_disable_data_transfer(abe_port_id *p);
+
+/*
+ * ABE_ENABLE_DATA_TRANSFER
+ *
+ * Parameter :
+ * p: port indentifier
+ *
+ * Operations :
+ * enables the ATC descriptor
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_data_transfer(abe_port_id p);
+
+/*
+ * ABE_READ_GLOBAL_COUNTER
+ *
+ * Parameter :
+ * data pointer to the counter value
+ * data pointer to the translated milliseconds
+ *
+ * Operations :
+ * returns the value of the 32bits counter incremented on each firmware scheduling task
+ * loops (250us / 272us with respectively 48kHz / 44.1kHz on Phoenix);. Translates this data
+ * in milli seconds format.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_global_counter(abe_time_stamp_t *t, abe_millis_t *m);
+
+/*
+ * ABE_SET_DMIC_FILTER
+ *
+ * Parameter :
+ * DMIC decimation ratio : 16/25/32/40
+ *
+ * Operations :
+ * Loads in CMEM a specific list of coefficients depending on the DMIC sampling
+ * frequency (2.4MHz or 3.84MHz);. This table compensates the DMIC decimator roll-off at 20kHz.
+ * The default table is loaded with the DMIC 2.4MHz recommended configuration.
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_dmic_filter(abe_dmic_ratio_t d);
+
+/**
+* @fn abe_connect_cbpr_dmareq_port()
+*
+* Operations : enables the data echange between a DMA and the ABE through the
+* CBPr registers of AESS.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* a : returned pointer to the base address of the CBPr register and number of
+* samples to exchange during a DMA_request.
+*
+* @see ABE_API.h
+*/
+void abe_connect_cbpr_dmareq_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *a);
+
+/**
+* @fn abe_connect_dmareq_port()
+*
+* Operations : enables the data echange between a DMA and the ABE through the
+* CBPr registers of AESS.
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* a : returned pointer to the base address of the ping-pong buffer and number
+* of samples to exchange during a DMA_request..
+*
+* @see ABE_API.h
+*/
+void abe_connect_dmareq_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *a);
+
+/**
+* @fn abe_connect_dmareq_ping_pong_port()
+*
+* Operations : enables the data echanges between a DMA and a direct access to the
+* DMEM memory of ABE. On each dma_request activation the DMA will exchange "s"
+* bytes and switch to the "pong" buffer for a new buffer exchange.ABE
+*
+* Parameters :
+* id: port name
+* f : desired data format
+* d : desired dma_request line (0..7)
+* s : half-buffer (ping) size
+*
+* a : returned pointer to the base address of the ping-pong buffer and number of samples to exchange during a DMA_request.
+*
+* @see ABE_API.h
+*/
+void abe_connect_dmareq_ping_pong_port(abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_dma_t *a);
+
+/**
+* @fn abe_connect_serial_port()
+*
+* Operations : enables the data echanges between a McBSP and an ATC buffer in
+* DMEM. This API is used connect 48kHz McBSP streams to MM_DL and 8/16kHz
+* voice streams to VX_UL, VX_DL, BT_VX_UL, BT_VX_DL. It abstracts the
+* abe_write_port API.
+*
+* Parameters :
+* id: port name
+* f : data format
+* i : peripheral ID (McBSP #1, #2, #3)
+*
+* @see ABE_API.h
+*/
+void abe_connect_serial_port(abe_port_id id, abe_data_format_t *f, abe_uint32 i);
+
+/*
+ * ABE_WRITE_PORT_DESCRIPTOR
+ *
+ * Parameter :
+ * id: port name
+ * f : input pointer to the data format
+ * p : input pointer to the protocol description
+ * dma : output pointer to the DMA iteration and data destination pointer
+ *
+ * Operations :
+ * writes the corresponding port descriptor in the AE memory spaces. The ATC DMEM descriptors
+ * are initialized.
+ * - translates the data format to AE I/O task format
+ * - copy to DMEM
+ * - load ATC descriptor - disabled
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_port_descriptor(abe_port_id id, abe_data_format_t *f, abe_port_protocol_t *p, abe_dma_t *dma);
+
+/*
+ * ABE_READ_PORT_DESCRIPTOR
+ *
+ * Parameter :
+ * id: port name
+ * f : input pointer to the data format
+ * p : input pointer to the protocol description
+ *
+ * Operations :
+ * returns the port parameters from the HAL internal buffer.
+ *
+ * Return value :
+ * error code in case the Port_id is not compatible with the current OPP value
+ */
+void abe_read_port_descriptor(abe_port_id id, abe_data_format_t *f, abe_port_protocol_t *p);
+
+/*
+ * ABE_READ_APS_ENERGY
+ *
+ * Parameter :
+ * Port_ID : port ID supporting APS
+ * APS data struct pointer
+ *
+ * Operations :
+ * Returns the estimated amount of energy
+ *
+ * Return value :
+ * error code when the Port is not activated.
+ */
+void abe_read_aps_energy(abe_port_id *p, abe_gain_t *a);
+
+/*
+ * ABE_WRITE_PORT_GAIN
+ *
+ * Parameter :
+ * port : name of the port (VX_DL_PORT, MM_DL_PORT, MM_EXT_DL_PORT, TONES_DL_PORT, …);
+ * dig_gain_port pointer to returned port gain and time constant
+ *
+ * Operations :
+ * saves the gain data in the local HAL-L0 table of gains in native format.
+ * Translate the gain to the AE-FW format and load it in CMEM
+ *
+ * Return value :
+ * error code in case the gain_id is not compatible with the current OPP value.
+ */
+
+void abe_write_port_gain (abe_port_id port, abe_gain_t g, abe_ramp_t ramp);
+
+/*
+ * ABE_READ_GAIN
+ *
+ * Parameter :
+ * port : name of the port (VX_DL_PORT, MM_DL_PORT, MM_EXT_DL_PORT, TONES_DL_PORT, …);
+ * dig_gain_port pointer to returned port gain and time constant
+ *
+ * Operations :
+ * returns the real-time value of the gain from CMEM.
+ *
+ * Return value :
+ * error code in case the gain_id is not compatible with the current OPP value.
+ */
+void abe_read_port_gain(abe_port_id port, abe_gain_t *gain, abe_ramp_t *ramp);
+
+/*
+ * ABE_READ_GAIN_RANGES
+ *
+ * Parameter :
+ * Id : name of the AE port
+ * Gain data pointer to the minimum, maximum gain,
+ * gain steps for the overall digital and/or analog hardware.
+ *
+ * Operations :
+ * returns the gain steps accuracy and range. If the API abe_enable_dyn_extension
+ * was called, the ports connected to Phoenix McPDM will also incorporate the gains
+ * of the analog part, else only the digital part is taken into account.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_gain_range(abe_port_id id, abe_gain_t *min, abe_gain_t *max, abe_gain_t *step);
+
+/*
+ * ABE_WRITE_EQUALIZER
+ *
+ * Parameter :
+ * Id : name of the equalizer
+ * Param : equalizer coefficients
+ *
+ * Operations :
+ * Load the coefficients in CMEM. This API can be called when the corresponding equalizer
+ * is not activated. After reloading the firmware the default coefficients corresponds to
+ * "no equalizer feature". Loading all coefficients with zeroes disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_equalizer(abe_equ_id id, abe_equ_t *param);
+
+/*
+ * ABE_WRITE_ASRC
+ *
+ * Parameter :
+ * Id : name of the asrc
+ * param : drift value t compensate
+ *
+ * Operations :
+ * Load the drift coefficients in FW memory. This API can be called when the corresponding
+ * ASRC is not activated. After reloading the firmware the default coefficients corresponds
+ * to "no ASRC activated". Loading the drift value with zero disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_asrc(abe_asrc_id id, abe_drift_t *param);
+
+/*
+ * ABE_WRITE_APS
+ *
+ * Parameter :
+ * Id : name of the aps filter
+ * param : table of filter coefficients
+ *
+ * Operations :
+ * Load the filters and thresholds coefficients in FW memory. This API can be called when
+ * the corresponding APS is not activated. After reloading the firmware the default coefficients
+ * corresponds to "no APS activated". Loading all the coefficients value with zero disables
+ * the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_aps(abe_aps_id id, abe_aps_t *param);
+
+/*
+ * ABE_WRITE_MIXER
+ *
+ * Parameter :
+ * Id : name of the mixer
+ * param : list of input gains of the mixer
+ * p : list of ports corresponding to the above gains
+ *
+ * Operations :
+ * Load the gain coefficients in FW memory. This API can be called when the corresponding
+ * MIXER is not activated. After reloading the firmware the default coefficients corresponds
+ * to "all input and output mixer's gain in mute state". A mixer is disabled with a network
+ * reconfiguration corresponding to an OPP value.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_mixer(abe_mixer_id id, abe_gain_t g, abe_ramp_t ramp, abe_port_id p);
+
+/*
+ * ABE_WRITE_EANC
+ *
+ * Parameter :
+ * param : table of coefficients
+ *
+ * Operations :
+ * Load the EANC coefficients in FW memory. This API can be called when EANC is not
+ * activated. After reloading the firmware the default coefficients corresponds to
+ * "no EANC activated". Loading the coefficients value with zero disables the feature.
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_eanc(abe_eanc_t *param);
+
+/*
+ * ABE_ENABLE_ROUTER_CONFIGURATION
+ *
+ * Parameter :
+ * Id : name of the router
+ * param : list of output index of the route
+ *
+ * Operations : load a pre-computed router configuration
+ *
+ * Return value :
+ * None.
+ */
+void abe_enable_router_configuration(abe_router_id id, abe_uint32 configuration);
+
+/*
+ * ABE_SET_ROUTER_CONFIGURATION
+ *
+ * Parameter :
+ * Id : name of the router
+ * Conf : id of the configuration
+ * param : list of output index of the route
+ *
+ * Operations :
+ * The uplink router takes its input from DMIC (6 samples), AMIC (2 samples) and
+ * PORT1/2 (2 stereo ports). Each sample will be individually stored in an intermediate
+ * table of 10 elements. The intermediate table is used to route the samples to
+ * three directions : REC1 mixer, 2 EANC DMIC source of filtering and MM recording audio path.
+ * For example, a use case consisting in AMIC used for uplink voice communication, DMIC 0,1,2,3
+ * used for multimedia recording, , DMIC 5 used for EANC filter, DMIC 4 used for the feedback channel,
+ * will be implemented with the following routing table index list :
+ * [3, 2 , 1, 0, 0, 0 (two dummy indexes to data that will not be on MM_UL), 4, 5, 7, 6]
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_router_configuration(abe_router_id id, abe_uint32 configuration, abe_router_t *param);
+
+/*
+ * ABE_WRITE_ROUTER
+ *
+ * Parameter :
+ * Id : name of the router
+ * param : list of output index of the route
+ *
+ * Operations :
+ * The uplink router takes its input from DMIC (6 samples);, AMIC (2 samples); and
+ * PORT1/2 (2 stereo ports);. Each sample will be individually stored in an intermediate
+ * table of 10 elements. The intermediate table is used to route the samples to
+ * three directions : REC1 mixer, 2 EANC DMIC source of filtering and MM recording audio path.
+ * For example, a use case consisting in AMIC used for uplink voice communication, DMIC 0,1,2,3
+ * used for multimedia recording, , DMIC 5 used for EANC filter, DMIC 4 used for the feedback channel,
+ * will be implemented with the following routing table index list :
+ * [3, 2 , 1, 0, 0, 0 (two dummy indexes to data that will not be on MM_UL);, 4, 5, 7, 6]
+ *
+ * Return value :
+ * None.
+ */
+void abe_write_router(abe_router_id id, abe_router_t *param);
+
+/*
+ * ABE_READ_ASRC
+ *
+ * Parameter :
+ * Id : name of the asrc
+ * param : drift value to compensate
+ *
+ *
+ * Operations :
+ * read drift ppm value
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_asrc(abe_asrc_id id, abe_drift_t *param);
+
+/*
+ * ABE_READ_APS
+ *
+ * Parameter :
+ * Id : name of the aps filter
+ * param : table of filter coefficients
+ *
+ * Operations :
+ * Read APS coefficients
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_aps(abe_aps_id id, abe_aps_t *param);
+
+/*
+ * ABE_READ_MIXER
+ *
+ * Parameter :
+ * Id : name of the aps filter
+ * param : table of filter coefficients
+ *
+ * Operations :
+ * Id : name of the mixer
+ * param : list of input and output gains of the mixer
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_mixer(abe_mixer_id id, abe_gain_t *f_gain, abe_ramp_t *f_ramp, abe_port_id p);
+
+/*
+ * ABE_READ_EANC
+ *
+ * Parameter :
+ * param : table of coefficients
+ *
+ * Operations :
+ * read eanc coefficients
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_eanc(abe_eanc_t *param);
+
+/*
+ * ABE_READ_ROUTER
+ *
+ * Parameter :
+ * Id : name of the router
+ * param : list of output index of the route
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_router(abe_router_id id, abe_router_t *param);
+
+/*
+ * ABE_READ_DEBUG_TRACE
+ *
+ * Parameter :
+ * data destination pointer
+ * max number of data read
+ *
+ * Operations :
+ * reads the AE circular data pointer holding pairs of debug data+timestamps, and store
+ * the pairs in linear addressing to the parameter pointer. Stops the copy when the max
+ * parameter is reached or when the FIFO is empty.
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_debug_trace(abe_uint32 *data, abe_uint32 *n);
+
+/*
+ * ABE_SET_DEBUG_TRACE
+ *
+ * Parameter :
+ * debug ID from a list to be defined
+ *
+ * Operations :
+ * load a mask which filters the debug trace to dedicated types of data
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_debug_trace(abe_dbg_t debug);
+
+/*
+ * ABE_SET_DEBUG_PINS
+ *
+ * Parameter :
+ * debugger commands to the AESS register in charge of the debug pins
+ *
+ * Operations :
+ * interpret the debugger commands: activate the AESS debug pins and
+ * allocate those pins to the AE outputs.
+ *
+ * Return value :
+ * None.
+ */
+void abe_set_debug_pins(abe_uint32 debug_pins);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_API_H_ */
diff --git a/sound/soc/codecs/abe/abe_cm_addr.h b/sound/soc/codecs/abe/abe_cm_addr.h
new file mode 100644
index 000000000000..e9e95da4d787
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_cm_addr.h
@@ -0,0 +1,320 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_CM_ADDR_H_
+#define _ABE_CM_ADDR_H_
+
+/* Coefficients memory sizeof */
+#define abe_cm_sizeof(x) (C_##x##_ADDR_END - C_##x##_ADDR + 1)
+
+#define C_init_ADDR 0
+#define C_init_ADDR_END 249
+
+#define C_Coef1_ADDR 250
+#define C_Coef1_ADDR_END 250
+
+#define C_CoefM1_ADDR 251
+#define C_CoefM1_ADDR_END 251
+
+#define C_1_Alpha_ADDR 252
+#define C_1_Alpha_ADDR_END 260
+
+#define C_Alpha_ADDR 261
+#define C_Alpha_ADDR_END 269
+
+#define C_GainsWRamp_ADDR 270
+#define C_GainsWRamp_ADDR_END 287
+
+#define C_Gains_ADDR 288
+#define C_Gains_ADDR_END 299
+
+#define C_Gains_DL1M_ADDR 300
+#define C_Gains_DL1M_ADDR_END 303
+
+#define C_Gains_DL2M_ADDR 304
+#define C_Gains_DL2M_ADDR_END 307
+
+#define C_Gains_EchoM_ADDR 308
+#define C_Gains_EchoM_ADDR_END 309
+
+#define C_Gains_SDTM_ADDR 310
+#define C_Gains_SDTM_ADDR_END 311
+
+#define C_Gains_VxRecM_ADDR 312
+#define C_Gains_VxRecM_ADDR_END 315
+
+#define C_Gains_ULM_ADDR 316
+#define C_Gains_ULM_ADDR_END 319
+
+#define C_SDT_Coefs_ADDR 320
+#define C_SDT_Coefs_ADDR_END 336
+
+#define C_MM96_F_Coefs_ADDR 337
+#define C_MM96_F_Coefs_ADDR_END 353
+
+#define C_DMIC0_96F_Coefs_ADDR 354
+#define C_DMIC0_96F_Coefs_ADDR_END 370
+
+#define C_AMIC_EQ_Coefs_ADDR 371
+#define C_AMIC_EQ_Coefs_ADDR_END 387
+
+#define C_DMIC1_EQ_Coefs_ADDR 388
+#define C_DMIC1_EQ_Coefs_ADDR_END 404
+
+#define C_DMIC2_EQ_Coefs_ADDR 405
+#define C_DMIC2_EQ_Coefs_ADDR_END 421
+
+#define C_DMIC3_EQ_Coefs_ADDR 422
+#define C_DMIC3_EQ_Coefs_ADDR_END 438
+
+#define C_CoefASRC1_UL_VX_ADDR 439
+#define C_CoefASRC1_UL_VX_ADDR_END 457
+
+#define C_CoefASRC2_UL_VX_ADDR 458
+#define C_CoefASRC2_UL_VX_ADDR_END 476
+
+#define C_CoefASRC3_UL_VX_ADDR 477
+#define C_CoefASRC3_UL_VX_ADDR_END 495
+
+#define C_CoefASRC4_UL_VX_ADDR 496
+#define C_CoefASRC4_UL_VX_ADDR_END 514
+
+#define C_CoefASRC5_UL_VX_ADDR 515
+#define C_CoefASRC5_UL_VX_ADDR_END 533
+
+#define C_CoefASRC6_UL_VX_ADDR 534
+#define C_CoefASRC6_UL_VX_ADDR_END 552
+
+#define C_CoefASRC7_UL_VX_ADDR 553
+#define C_CoefASRC7_UL_VX_ADDR_END 571
+
+#define C_CoefASRC8_UL_VX_ADDR 572
+#define C_CoefASRC8_UL_VX_ADDR_END 590
+
+#define C_CoefASRC9_UL_VX_ADDR 591
+#define C_CoefASRC9_UL_VX_ADDR_END 609
+
+#define C_CoefASRC10_UL_VX_ADDR 610
+#define C_CoefASRC10_UL_VX_ADDR_END 628
+
+#define C_CoefASRC11_UL_VX_ADDR 629
+#define C_CoefASRC11_UL_VX_ADDR_END 647
+
+#define C_CoefASRC12_UL_VX_ADDR 648
+#define C_CoefASRC12_UL_VX_ADDR_END 666
+
+#define C_CoefASRC13_UL_VX_ADDR 667
+#define C_CoefASRC13_UL_VX_ADDR_END 685
+
+#define C_CoefASRC14_UL_VX_ADDR 686
+#define C_CoefASRC14_UL_VX_ADDR_END 704
+
+#define C_CoefASRC15_UL_VX_ADDR 705
+#define C_CoefASRC15_UL_VX_ADDR_END 723
+
+#define C_CoefASRC16_UL_VX_ADDR 724
+#define C_CoefASRC16_UL_VX_ADDR_END 742
+
+#define C_AlphaCurrent_UL_VX_ADDR 743
+#define C_AlphaCurrent_UL_VX_ADDR_END 743
+
+#define C_BetaCurrent_UL_VX_ADDR 744
+#define C_BetaCurrent_UL_VX_ADDR_END 744
+
+#define C_CoefASRC1_DL_VX_ADDR 745
+#define C_CoefASRC1_DL_VX_ADDR_END 763
+
+#define C_CoefASRC2_DL_VX_ADDR 764
+#define C_CoefASRC2_DL_VX_ADDR_END 782
+
+#define C_CoefASRC3_DL_VX_ADDR 783
+#define C_CoefASRC3_DL_VX_ADDR_END 801
+
+#define C_CoefASRC4_DL_VX_ADDR 802
+#define C_CoefASRC4_DL_VX_ADDR_END 820
+
+#define C_CoefASRC5_DL_VX_ADDR 821
+#define C_CoefASRC5_DL_VX_ADDR_END 839
+
+#define C_CoefASRC6_DL_VX_ADDR 840
+#define C_CoefASRC6_DL_VX_ADDR_END 858
+
+#define C_CoefASRC7_DL_VX_ADDR 859
+#define C_CoefASRC7_DL_VX_ADDR_END 877
+
+#define C_CoefASRC8_DL_VX_ADDR 878
+#define C_CoefASRC8_DL_VX_ADDR_END 896
+
+#define C_CoefASRC9_DL_VX_ADDR 897
+#define C_CoefASRC9_DL_VX_ADDR_END 915
+
+#define C_CoefASRC10_DL_VX_ADDR 916
+#define C_CoefASRC10_DL_VX_ADDR_END 934
+
+#define C_CoefASRC11_DL_VX_ADDR 935
+#define C_CoefASRC11_DL_VX_ADDR_END 953
+
+#define C_CoefASRC12_DL_VX_ADDR 954
+#define C_CoefASRC12_DL_VX_ADDR_END 972
+
+#define C_CoefASRC13_DL_VX_ADDR 973
+#define C_CoefASRC13_DL_VX_ADDR_END 991
+
+#define C_CoefASRC14_DL_VX_ADDR 992
+#define C_CoefASRC14_DL_VX_ADDR_END 1010
+
+#define C_CoefASRC15_DL_VX_ADDR 1011
+#define C_CoefASRC15_DL_VX_ADDR_END 1029
+
+#define C_CoefASRC16_DL_VX_ADDR 1030
+#define C_CoefASRC16_DL_VX_ADDR_END 1048
+
+#define C_AlphaCurrent_DL_VX_ADDR 1049
+#define C_AlphaCurrent_DL_VX_ADDR_END 1049
+
+#define C_BetaCurrent_DL_VX_ADDR 1050
+#define C_BetaCurrent_DL_VX_ADDR_END 1050
+
+#define C_CoefASRC1_DL_MM_ADDR 1051
+#define C_CoefASRC1_DL_MM_ADDR_END 1068
+
+#define C_CoefASRC2_DL_MM_ADDR 1069
+#define C_CoefASRC2_DL_MM_ADDR_END 1086
+
+#define C_CoefASRC3_DL_MM_ADDR 1087
+#define C_CoefASRC3_DL_MM_ADDR_END 1104
+
+#define C_CoefASRC4_DL_MM_ADDR 1105
+#define C_CoefASRC4_DL_MM_ADDR_END 1122
+
+#define C_CoefASRC5_DL_MM_ADDR 1123
+#define C_CoefASRC5_DL_MM_ADDR_END 1140
+
+#define C_CoefASRC6_DL_MM_ADDR 1141
+#define C_CoefASRC6_DL_MM_ADDR_END 1158
+
+#define C_CoefASRC7_DL_MM_ADDR 1159
+#define C_CoefASRC7_DL_MM_ADDR_END 1176
+
+#define C_CoefASRC8_DL_MM_ADDR 1177
+#define C_CoefASRC8_DL_MM_ADDR_END 1194
+
+#define C_CoefASRC9_DL_MM_ADDR 1195
+#define C_CoefASRC9_DL_MM_ADDR_END 1212
+
+#define C_CoefASRC10_DL_MM_ADDR 1213
+#define C_CoefASRC10_DL_MM_ADDR_END 1230
+
+#define C_CoefASRC11_DL_MM_ADDR 1231
+#define C_CoefASRC11_DL_MM_ADDR_END 1248
+
+#define C_CoefASRC12_DL_MM_ADDR 1249
+#define C_CoefASRC12_DL_MM_ADDR_END 1266
+
+#define C_CoefASRC13_DL_MM_ADDR 1267
+#define C_CoefASRC13_DL_MM_ADDR_END 1284
+
+#define C_CoefASRC14_DL_MM_ADDR 1285
+#define C_CoefASRC14_DL_MM_ADDR_END 1302
+
+#define C_CoefASRC15_DL_MM_ADDR 1303
+#define C_CoefASRC15_DL_MM_ADDR_END 1320
+
+#define C_CoefASRC16_DL_MM_ADDR 1321
+#define C_CoefASRC16_DL_MM_ADDR_END 1338
+
+#define C_AlphaCurrent_DL_MM_ADDR 1339
+#define C_AlphaCurrent_DL_MM_ADDR_END 1339
+
+#define C_BetaCurrent_DL_MM_ADDR 1340
+#define C_BetaCurrent_DL_MM_ADDR_END 1340
+
+#define C_DL2_L_Coefs_ADDR 1341
+#define C_DL2_L_Coefs_ADDR_END 1365
+
+#define C_DL2_R_Coefs_ADDR 1366
+#define C_DL2_R_Coefs_ADDR_END 1390
+
+#define C_DL1_Coefs_ADDR 1391
+#define C_DL1_Coefs_ADDR_END 1415
+
+#define C_VX_8_48_BP_Coefs_ADDR 1416
+#define C_VX_8_48_BP_Coefs_ADDR_END 1428
+
+#define C_VX_8_48_LP_Coefs_ADDR 1429
+#define C_VX_8_48_LP_Coefs_ADDR_END 1441
+
+#define C_VX_48_8_LP_Coefs_ADDR 1442
+#define C_VX_48_8_LP_Coefs_ADDR_END 1454
+
+#define C_VX_16_48_HP_Coefs_ADDR 1455
+#define C_VX_16_48_HP_Coefs_ADDR_END 1461
+
+#define C_VX_16_48_LP_Coefs_ADDR 1462
+#define C_VX_16_48_LP_Coefs_ADDR_END 1474
+
+#define C_VX_48_16_LP_Coefs_ADDR 1475
+#define C_VX_48_16_LP_Coefs_ADDR_END 1487
+
+#define C_EANC_WarpCoeffs_ADDR 1488
+#define C_EANC_WarpCoeffs_ADDR_END 1489
+
+#define C_EANC_FIRcoeffs_ADDR 1490
+#define C_EANC_FIRcoeffs_ADDR_END 1510
+
+#define C_EANC_IIRcoeffs_ADDR 1511
+#define C_EANC_IIRcoeffs_ADDR_END 1527
+
+#define C_APS_coeffs1_ADDR 1528
+#define C_APS_coeffs1_ADDR_END 1536
+
+#define C_APS_coeffs2_ADDR 1537
+#define C_APS_coeffs2_ADDR_END 1539
+
+#define C_APS_DL2_L_coeffs1_ADDR 1540
+#define C_APS_DL2_L_coeffs1_ADDR_END 1548
+
+#define C_APS_DL2_R_coeffs1_ADDR 1549
+#define C_APS_DL2_R_coeffs1_ADDR_END 1557
+
+#define C_APS_DL2_L_coeffs2_ADDR 1558
+#define C_APS_DL2_L_coeffs2_ADDR_END 1560
+
+#define C_APS_DL2_R_coeffs2_ADDR 1561
+#define C_APS_DL2_R_coeffs2_ADDR_END 1563
+
+#define C_AlphaCurrent_ECHO_REF_ADDR 1564
+#define C_AlphaCurrent_ECHO_REF_ADDR_END 1564
+
+#define C_BetaCurrent_ECHO_REF_ADDR 1565
+#define C_BetaCurrent_ECHO_REF_ADDR_END 1565
+
+#define C_APS_DL1_EQ_ADDR 1566
+#define C_APS_DL1_EQ_ADDR_END 1574
+
+#define C_APS_DL2_L_EQ_ADDR 1575
+#define C_APS_DL2_L_EQ_ADDR_END 1583
+
+#define C_APS_DL2_R_EQ_ADDR 1584
+#define C_APS_DL2_R_EQ_ADDR_END 1592
+
+#define C_Vibra2_consts_ADDR 1593
+#define C_Vibra2_consts_ADDR_END 1596
+
+#define C_Vibra1_coeffs_ADDR 1597
+#define C_Vibra1_coeffs_ADDR_END 1607
+
+#define C_48_96_LP_Coefs_ADDR 1608
+#define C_48_96_LP_Coefs_ADDR_END 1622
+
+#define C_98_48_LP_Coefs_ADDR 1623
+#define C_98_48_LP_Coefs_ADDR_END 1637
+
+#endif /* _ABECM_ADDR_H_ */
diff --git a/sound/soc/codecs/abe/abe_cof.h b/sound/soc/codecs/abe/abe_cof.h
new file mode 100644
index 000000000000..f4d50d2132ff
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_cof.h
@@ -0,0 +1,9 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
diff --git a/sound/soc/codecs/abe/abe_dat.h b/sound/soc/codecs/abe/abe_dat.h
new file mode 100644
index 000000000000..f5861a475b09
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_dat.h
@@ -0,0 +1,1212 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_DAT_H_
+#define _ABE_DAT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Callbacks
+ */
+abe_subroutine2 callbacks[MAXCALLBACK]; /* 2 parameters subroutine pointers */
+
+abe_port_t abe_port[MAXNBABEPORTS]; /* list of ABE ports */
+
+const abe_port_t abe_port_init[MAXNBABEPORTS] = {
+/* status, data format, drift, callback, io-task buffer 1, io-task buffer 2,
+ * protocol, dma offset, features, name
+ * - Features reseted at start
+ */
+
+ /* DMIC1 */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_dmic1,
+ 0,
+ {
+ SNK_P,
+ DMIC_PORT_PROT,
+ {{
+ dmem_dmic,
+ dmem_dmic_size,
+ DMIC_ITER
+ }},
+ },
+ {0, 0},
+ {EQDMIC1, 0},
+ "DMIC_UL",
+ },
+ /* DMIC2 */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_dmic2,
+ 0,
+ {
+ SNK_P,
+ DMIC_PORT_PROT,
+ {{
+ dmem_dmic,
+ dmem_dmic_size,
+ DMIC_ITER
+ }},
+ },
+ {0, 0},
+ {EQDMIC2, 0},
+ "DMIC_UL",
+ },
+ /* DMIC3 */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_dmic3,
+ 0,
+ {
+ SNK_P,
+ DMIC_PORT_PROT,
+ {{
+ dmem_dmic,
+ dmem_dmic_size,
+ DMIC_ITER
+ }},
+ },
+ {0, 0},
+ {EQDMIC3, 0},
+ "DMIC_UL",
+ },
+ /* PDM_UL */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_amic,
+ 0,
+ {
+ SNK_P,
+ MCPDMUL_PORT_PROT,
+ {{
+ dmem_amic,
+ dmem_amic_size,
+ MCPDM_UL_ITER,
+ }},
+ },
+ {0, 0},
+ {EQAMIC, 0},
+ "AMIC_UL",
+ },
+ /* BT_VX_UL */
+ {
+ IDLE_P,
+ {8000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_bt_vx_ul,
+ 0,
+ {
+ SNK_P,
+ SERIAL_PORT_PROT,
+ {{
+ MCBSP1_DMA_TX * ATC_SIZE,
+ dmem_bt_vx_ul,
+ dmem_bt_vx_ul_size,
+ 1 * SCHED_LOOP_8kHz,
+ DEFAULT_THR_WRITE,
+ }},
+ },
+ {0, 0},
+ {0},
+ "BT_VX_UL",
+ },
+ /* MM_UL */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_mm_ul,
+ 0,
+ {
+ SRC_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX3 * ATC_SIZE,
+ dmem_mm_ul,
+ dmem_mm_ul_size,
+ 10 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_WRITE,
+ ABE_DMASTATUS_RAW,
+ 1 << 3,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__3, 120},
+ {UPROUTE, 0},
+ "MM_UL",
+ },
+ /* MM_UL2 */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_mm_ul2,
+ 0,
+ {
+ SRC_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX4 * ATC_SIZE,
+ dmem_mm_ul2,
+ dmem_mm_ul2_size,
+ 2 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_WRITE,
+ ABE_DMASTATUS_RAW,
+ 1 << 4,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__4, 24},
+ {UPROUTE, 0},
+ "MM_UL2",
+ },
+ /* VX_UL */
+ {
+ IDLE_P,
+ {8000, MONO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_vx_ul,
+ 0,
+ {
+ SRC_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX2*ATC_SIZE,
+ dmem_vx_ul,
+ dmem_vx_ul_size / 2,
+ 1 * SCHED_LOOP_8kHz,
+ DEFAULT_THR_WRITE,
+ ABE_DMASTATUS_RAW,
+ 1 << 2,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__2, 2},
+ {ASRC2, 0},
+ "VX_UL",
+ },
+ /* MM_DL */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_mm_dl,
+ 0,
+ {
+ SNK_P,
+ PINGPONG_PORT_PROT,
+ {{
+ CBPr_DMA_RTX0 * ATC_SIZE,
+ dmem_mm_dl,
+ dmem_mm_dl_size,
+ 2 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_READ,
+ ABE_DMASTATUS_RAW,
+ 1 << 0,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__0, 24},
+ {ASRC3, 0},
+ "MM_DL",
+ },
+ /* VX_DL */
+ {
+ IDLE_P,
+ {8000, MONO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_vx_dl,
+ 0,
+ {
+ SNK_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX1 * ATC_SIZE,
+ dmem_vx_dl,
+ dmem_vx_dl_size,
+ 1 * SCHED_LOOP_8kHz,
+ DEFAULT_THR_READ,
+ ABE_DMASTATUS_RAW,
+ 1 << 1,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__1, 2},
+ {ASRC1, 0},
+ "VX_DL",
+ },
+ /* TONES_DL */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_tones_dl,
+ 0,
+ {
+ SNK_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX5 * ATC_SIZE,
+ dmem_tones_dl,
+ dmem_tones_dl_size,
+ 2 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_READ,
+ ABE_DMASTATUS_RAW,
+ 1 << 5,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__5, 24},
+ {0},
+ "TONES_DL",
+ },
+ /* VIB_DL */
+ {
+ IDLE_P,
+ {24000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_vib,
+ 0,
+ {
+ SNK_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX6 * ATC_SIZE,
+ dmem_vib_dl,
+ dmem_vib_dl_size,
+ 2 * SCHED_LOOP_24kHz,
+ DEFAULT_THR_READ,
+ ABE_DMASTATUS_RAW,
+ 1 << 6,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__6, 12},
+ {0},
+ "VIB_DL",
+ },
+ /* BT_VX_DL */
+ {
+ IDLE_P,
+ {8000, MONO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_bt_vx_dl,
+ 0,
+ {
+ SRC_P,
+ SERIAL_PORT_PROT,
+ {{
+ MCBSP1_DMA_RX * ATC_SIZE,
+ dmem_bt_vx_dl,
+ dmem_bt_vx_dl_size,
+ 1 * SCHED_LOOP_8kHz,
+ DEFAULT_THR_WRITE,
+ }},
+ },
+ {0, 0},
+ {0},
+ "BT_VX_DL",
+ },
+ /* PDM_DL1 */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ 0,
+ 0,
+ {
+ SRC_P,
+ MCPDMDL_PORT_PROT,
+ {{
+ dmem_mcpdm,
+ dmem_mcpdm_size,
+ }},
+ },
+ {0, 0},
+ {MIXDL1, EQ1, APS1, 0},
+ "PDM_DL1",
+ },
+ /* MM_EXT_OUT */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_mm_ext_out,
+ 0,
+ {
+ SRC_P,
+ SERIAL_PORT_PROT,
+ {{
+ MCBSP1_DMA_RX * ATC_SIZE,
+ dmem_mm_ext_out,
+ dmem_mm_ext_out_size,
+ 2 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_WRITE,
+ }},
+ },
+ {0, 0},
+ {0},
+ "MM_EXT_OUT",
+ },
+ /* PDM_DL2 */
+ {
+ IDLE_P,
+ {96000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ 0,
+ 0,
+ {
+ SRC_P,
+ MCPDMDL_PORT_PROT,
+ {{0, 0, 0, 0, 0, 0, 0}},
+ },
+ {0, 0},
+ {MIXDL2, EQ2L, APS2L, EQ2R, APS2R, 0},
+ "PDM_DL2",
+ },
+ /* PDM_VIB */
+ {
+ IDLE_P,
+ {24000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ 0,
+ 0,
+ {
+ SRC_P,
+ MCPDMDL_PORT_PROT,
+ {{0, 0, 0, 0, 0, 0, 0}},
+ },
+ {0, 0},
+ {0},
+ "PDM_VIB",
+ },
+ /* SCHD_DBG_PORT */
+ {
+ IDLE_P,
+ {48000, STEREO_MSB},
+ NODRIFT,
+ NOCALLBACK,
+ smem_mm_trace,
+ 0,
+ {
+ SRC_P,
+ DMAREQ_PORT_PROT,
+ {{
+ CBPr_DMA_RTX7 * ATC_SIZE,
+ dmem_mm_trace,
+ dmem_mm_trace_size,
+ 2 * SCHED_LOOP_48kHz,
+ DEFAULT_THR_WRITE,
+ ABE_DMASTATUS_RAW,
+ 1 << 4,
+ }},
+ },
+ {CIRCULAR_BUFFER_PERIPHERAL_R__7, 24},
+ {SEQUENCE, CONTROL, GAINS, 0},
+ "SCHD_DBG",
+ },
+};
+
+const abe_port_info_t abe_port_info[MAXNBABEPORTS] = {
+ /* DMIC1 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* DMIC2 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT2, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* DMIC3 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT3, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* PDM_UL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* BT_VX_UL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* MM_UL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* MM_UL2 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* VX_UL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* MM_DL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_MIXER, {MM_DL_PORT, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* VX_DL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* TONES_DL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* VIB_DL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* BT_VX_DL */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* PDM_DL1 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* MM_EXT_OUT */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* PDM_DL2 */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* PDM_VIB */
+ {
+ ABE_OPP50,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+ /* SCHD_DBG_PORT */
+ {
+ ABE_OPP25,
+ {SUB_WRITE_PORT_GAIN, {DMIC_PORT1, MUTE_GAIN, 0, 0}},
+ {0, {0, 0, 0, 0}},
+ },
+};
+
+/*
+ * Firmware features
+ */
+abe_feature_t all_feature[MAXNBFEATURE];
+
+const abe_feature_t all_feature_init[] = {
+/* on_reset, off, read, write, status, input, output, slots, opp, name */
+ /* EQ1: equalizer downlink path headset + earphone */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq1,
+ c_write_eq1,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " DLEQ1",
+ },
+ /* EQ2L: equalizer downlink path integrated handsfree left */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq2,
+ c_write_eq2,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " DLEQ2L",
+ },
+ /* EQ2R: equalizer downlink path integrated handsfree right */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " DLEQ2R",
+ },
+ /* EQSDT: equalizer downlink path side-tone */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " EQSDT",
+ },
+ /* EQDMIC1: SRC+equalizer uplink DMIC 1st pair */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " EQDMIC1",
+ },
+ /* EQDMIC2: SRC+equalizer uplink DMIC 2nd pair */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " EQDMIC2",
+ },
+ /* EQDMIC3: SRC+equalizer uplink DMIC 3rd pair */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " EQDMIC3",
+ },
+ /* EQAMIC: SRC+equalizer uplink AMIC */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " EQAMIC",
+ },
+ /* APS1: Acoustic protection for headset */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " APS1",
+ },
+ /* APS2: acoustic protection high-pass filter for handsfree left */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " APS2",
+ },
+ /* APS3: acoustic protection high-pass filter for handsfree right */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " APS3",
+ },
+ /* ASRC1: asynchronous sample-rate-converter for the downlink voice path */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " ASRC_VXDL"
+ },
+ /* ASRC2: asynchronous sample-rate-converter for the uplink voice path */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " ASRC_VXUL",
+ },
+ /* ASRC3: asynchronous sample-rate-converter for the multimedia player */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " ASRC_MMDL",
+ },
+ /* ASRC4: asynchronous sample-rate-converter for the echo reference */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " ASRC_ECHO",
+ },
+ /* MXDL1: mixer of the headset and earphone path */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " MIX_DL1",
+ },
+ /* MXDL2: mixer of the hands-free path */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " MIX_DL2",
+ },
+ /* MXAUDUL: mixer for uplink tone mixer */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " MXSAUDUL",
+ },
+ /* MXVXREC: mixer for voice recording */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " MXVXREC",
+ },
+ /* MXSDT: mixer for side-tone */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " MIX_SDT",
+ },
+ /* MXECHO: mixer for echo reference */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " MIX_ECHO",
+ },
+ /* UPROUTE: router of the uplink path */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP50,
+ " DLEQ3",
+ },
+ /* GAINS: all gains */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " DLEQ3",
+ },
+ /* EANC: active noise canceller */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP100,
+ " DLEQ3",
+ },
+ /* SEQ: sequencing queue of micro tasks */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " DLEQ3",
+ },
+ /* CTL: Phoenix control queue through McPDM */
+ {
+ c_feat_init_eq,
+ c_feat_init_eq,
+ c_feat_read_eq3,
+ c_write_eq3,
+ 0,
+ 0x1000,
+ 0x1010,
+ 2,
+ 0,
+ ABE_OPP25,
+ " DLEQ3",
+ },
+};
+
+/*
+ * Table indexed by the PORT_ID and returning the index
+ * to the D_IODescr table of structures
+ */
+const abe_uint32 sio_task_index[LAST_PORT_ID] =
+{
+ /* AE sink ports - Uplink */
+ 7, /* DMIC_PORT - specific protocol */
+ 7, /* DMIC_PORT - specific protocol */
+ 7, /* DMIC_PORT - specific protocol */
+ 8, /* PDM_UL_PORT - specific protocol */
+ 14, /* BT_VX_UL_PORT BT uplink */
+
+ /* AE source ports - Uplink */
+ 3, /* MM_UL_PORT up to 5 stereo channels */
+ 4, /* MM_UL2_PORT stereo FM record path */
+ 2, /* VX_UL_PORT stereo FM record path */
+
+ /* AE sink ports - Downlink */
+ 0, /* MM_DL_PORT multimedia player audio path */
+ 1, /* VX_DL_PORT */
+ 5, /* TONES_DL_PORT */
+ 6, /* VIB_DL_PORT */
+
+ /* AE source ports - Downlink */
+ 13, /* BT_VX_DL_PORT */
+ 9, /* PDM_DL1_PORT */
+ 12, /* MM_EXT_OUT_PORT */
+ 10, /* PDM_DL2_PORT */
+ 11, /* PDM_VIB_PORT */
+
+ /* dummy port used to declare the other tasks of the scheduler */
+ SCHD_DBG_PORT,
+};
+
+/*
+ * Memory mapping of DMEM FIFOs
+ */
+abe_uint32 abe_map_dmem[LAST_PORT_ID]; /* DMEM port map */
+abe_uint32 abe_map_dmem_secondary[LAST_PORT_ID];
+abe_uint32 abe_map_dmem_size[LAST_PORT_ID]; /* DMEM port buffer sizes */
+
+/*
+ * AESS/ATC destination and source address translation
+ * (except McASPs) from the original 64bits words address
+ */
+const abe_uint32 abe_atc_dstid[ABE_ATC_DESC_SIZE >> 3] = {
+ /* DMA_0 DMIC PDM_DL PDM_UL McB1TX McB1RX McB2TX McB2RX 0-7 */
+ 0, 0, 12, 0, 1, 0, 2, 0,
+ /* McB3TX McB3RX SLIMT0 SLIMT1 SLIMT2 SLIMT3 SLIMT4 SLIMT5 8-15 */
+ 3, 0, 4, 5, 6, 7, 8, 9,
+ /* SLIMT6 SLIMT7 SLIMR0 SLIMR1 SLIMR2 SLIMR3 SLIMR4 SLIMR5 16-23 */
+ 10, 11, 0, 0, 0, 0, 0, 0,
+ /* SLIMR6 SLIMR7 McASP1X ------ ------ McASP1R ----- ------ 24-31 */
+ 0, 0, 14, 0, 0, 0, 0, 0,
+ /* CBPrT0 CBPrT1 CBPrT2 CBPrT3 CBPrT4 CBPrT5 CBPrT6 CBPrT7 32-39 */
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ /* CBP_T0 CBP_T1 CBP_T2 CBP_T3 CBP_T4 CBP_T5 CBP_T6 CBP_T7 40-47 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* CBP_T8 CBP_T9 CBP_T10 CBP_T11 CBP_T12 CBP_T13 CBP_T14 CBP_T15 48-63 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+const abe_uint32 abe_atc_srcid[ABE_ATC_DESC_SIZE >> 3] = {
+ /* DMA_0 DMIC PDM_DL PDM_UL McB1TX McB1RX McB2TX McB2RX 0-7 */
+ 0, 12, 0, 13, 0, 1, 0, 2,
+ /* McB3TX McB3RX SLIMT0 SLIMT1 SLIMT2 SLIMT3 SLIMT4 SLIMT5 8-15 */
+ 0, 3, 0, 0, 0, 0, 0, 0,
+ /* SLIMT6 SLIMT7 SLIMR0 SLIMR1 SLIMR2 SLIMR3 SLIMR4 SLIMR5 16-23 */
+ 0, 0, 4, 5, 6, 7, 8, 9,
+ /* SLIMR6 SLIMR7 McASP1X ------ ------ McASP1R ------ ------ 24-31 */
+ 10, 11, 0, 0, 0, 14, 0, 0,
+ /* CBPrT0 CBPrT1 CBPrT2 CBPrT3 CBPrT4 CBPrT5 CBPrT6 CBPrT7 32-39 */
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ /* CBP_T0 CBP_T1 CBP_T2 CBP_T3 CBP_T4 CBP_T5 CBP_T6 CBP_T7 40-47 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* CBP_T8 CBP_T9 CBP_T10 CBP_T11 CBP_T12 CBP_T13 CBP_T14 CBP_T15 48-63 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/*
+ * Router tables
+ */
+/* preset routing configurations */
+const abe_router_t abe_router_ul_table_preset[NBROUTE_CONFIG][NBROUTE_UL] = {
+ /* Voice uplink with Phoenix microphones */
+ {
+ /* 0 .. 9 = MM_UL */
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 12 .. 13 = VX_UL */
+ AMIC_L_labelID,
+ AMIC_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID,
+ ZERO_labelID,
+ },
+ /* Voice uplink with the first DMIC pair */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC1_L_labelID,
+ DMIC1_R_labelID,
+ DMIC2_L_labelID,
+ DMIC2_R_labelID,
+ DMIC3_L_labelID,
+ DMIC3_R_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC1_L_labelID,
+ DMIC1_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID,
+ ZERO_labelID,
+ },
+ /* Voice uplink with the second DMIC pair */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC1_L_labelID,
+ DMIC1_R_labelID,
+ DMIC2_L_labelID,
+ DMIC2_R_labelID,
+ DMIC3_L_labelID,
+ DMIC3_R_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC2_L_labelID,
+ DMIC2_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID,
+ ZERO_labelID,
+ },
+ /* Voice uplink with the last DMIC pair */
+ {
+ /* 0 .. 9 = MM_UL */
+ DMIC1_L_labelID,
+ DMIC1_R_labelID,
+ DMIC2_L_labelID,
+ DMIC2_R_labelID,
+ DMIC3_L_labelID,
+ DMIC3_R_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 10 .. 11 = MM_UL2 */
+ ZERO_labelID,
+ ZERO_labelID,
+ /* 12 .. 13 = VX_UL */
+ DMIC3_L_labelID,
+ DMIC3_R_labelID,
+ /* 14 .. 15 = RESERVED */
+ ZERO_labelID,
+ ZERO_labelID,
+ },
+};
+
+/* all default routing configurations */
+abe_router_t abe_router_ul_table[NBROUTE_CONFIG_MAX][NBROUTE_UL];
+
+/*
+ * ABE_GLOBAL DATA
+ */
+/* flag, indicates the allowed control of Phoenix through McPDM slot 6 */
+abe_uint32 abe_global_mcpdm_control;
+abe_event_id abe_current_event_id;
+
+/*
+ * ABE SUBROUTINES AND SEQUENCES
+ */
+
+/*
+const abe_seq_t abe_seq_array [MAXNBSEQUENCE] [MAXSEQUENCESTEPS] =
+ {{0, 0, 0, 0}, {-1, 0, 0, 0}},
+ {{0, 0, 0, 0}, {-1, 0, 0, 0}},
+const seq_t setup_hw_sequence2 [ ] = { 0, C_AE_FUNC1, 0, 0, 0, 0,
+ -1, C_CALLBACK1, 0, 0, 0, 0 };
+
+const abe_subroutine2 abe_sub_array [MAXNBSUBROUTINE] =
+ abe_init_atc, 0, 0,
+ abe_init_atc, 0, 0,
+
+ typedef double (*PtrFun) (double);
+PtrFun pFun;
+pFun = sin;
+y = (* pFun) (x);
+*/
+
+const abe_sequence_t seq_null = {
+ NOMASK,
+ {
+ CL_M1,
+ 0,
+ {0, 0, 0, 0},
+ 0,
+ },
+ {
+ CL_M1,
+ 0,
+ {0, 0, 0, 0},
+ 0,
+ },
+};
+
+abe_subroutine2 abe_all_subsubroutine[MAXNBSUBROUTINE]; /* table of new subroutines called in the sequence */
+abe_uint32 abe_all_subsubroutine_nparam[MAXNBSUBROUTINE]; /* number of parameters per calls */
+abe_uint32 abe_subroutine_id[MAXNBSUBROUTINE]; /* index of the subroutine */
+abe_uint32 abe_subroutine_write_pointer;
+
+/* table of all sequences */
+abe_sequence_t abe_all_sequence[MAXNBSEQUENCE];
+
+abe_uint32 abe_sequence_write_pointer;
+
+/* current number of pending sequences (avoids to look in the table) */
+abe_uint32 abe_nb_pending_sequences;
+
+/* pending sequences due to ressource collision */
+abe_uint32 abe_pending_sequences[MAXNBSEQUENCE];
+
+/* mask of unsharable ressources among other sequences */
+abe_uint32 abe_global_sequence_mask;
+
+/* table of active sequences */
+abe_seq_t abe_active_sequence[MAXACTIVESEQUENCE][MAXSEQUENCESTEPS];
+
+/* index of the plugged subroutine doing ping-pong cache-flush DMEM accesses */
+abe_uint32 abe_irq_pingpong_player_id;
+
+/* base addresses of the ping pong buffers in bytes addresses */
+abe_uint32 abe_base_address_pingpong[MAX_PINGPONG_BUFFERS];
+
+/* size of each ping/pong buffers */
+abe_uint32 abe_size_pingpong;
+
+/* number of ping/pong buffer being used */
+abe_uint32 abe_nb_pingpong;
+
+/*
+ * ABE_DEBUG DATA
+ */
+
+/* General circular buffer used to trace APIs calls and AE activity */
+abe_uint32 abe_dbg_activity_log[DBG_LOG_SIZE];
+abe_uint32 abe_dbg_activity_log_write_pointer;
+abe_uint32 abe_dbg_mask;
+
+/* Global variable holding parameter errors */
+abe_uint32 abe_dbg_param;
+
+/* Output of messages selector */
+abe_uint32 abe_dbg_output;
+
+/* Last parameters */
+#define SIZE_PARAM 10
+
+abe_uint32 param1[SIZE_PARAM];
+abe_uint32 param2[SIZE_PARAM];
+abe_uint32 param3[SIZE_PARAM];
+abe_uint32 param4[SIZE_PARAM];
+abe_uint32 param5[SIZE_PARAM];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_DAT_H_ */
diff --git a/sound/soc/codecs/abe/abe_dbg.c b/sound/soc/codecs/abe/abe_dbg.c
new file mode 100644
index 000000000000..32a34b138879
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_dbg.c
@@ -0,0 +1,99 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+/*
+ * ABE_DBG_LOG
+ *
+ * Parameter :
+ * x : data to be logged
+ *
+ * abe_dbg_activity_log : global circular buffer holding the data
+ * abe_dbg_activity_log_write_pointer : circular write pointer
+ *
+ * Operations :
+ * saves data in the log file
+ *
+ * Return value :
+ * none
+ */
+void abe_dbg_log_copy(abe_uint32 x)
+{
+ abe_dbg_activity_log[abe_dbg_activity_log_write_pointer] = x;
+
+ if (abe_dbg_activity_log_write_pointer == (DBG_LOG_SIZE - 1))
+ abe_dbg_activity_log_write_pointer = 0;
+ else
+ abe_dbg_activity_log_write_pointer ++;
+}
+
+void abe_dbg_log(abe_uint32 x)
+{
+ abe_time_stamp_t t;
+ abe_millis_t m;
+ abe_micros_t time;
+
+ abe_read_global_counter(&t, &m);/* extract AE timer */
+ abe_read_sys_clock(&time); /* extract system timer */
+
+ abe_dbg_log_copy(x); /* dump data */
+ abe_dbg_log_copy(time);
+ abe_dbg_log_copy(t);
+ abe_dbg_log_copy(m);
+}
+
+/*
+ * ABE_DEBUG_OUTPUT_PINS
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ * set the debug output pins of AESS
+ *
+ * Return value :
+ *
+ */
+void abe_debug_output_pins(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_DBG_ERROR_LOG
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ * log the error codes
+ *
+ * Return value :
+ *
+ */
+void abe_dbg_error_log(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_DEBUGGER
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_debugger(abe_uint32 x)
+{
+}
diff --git a/sound/soc/codecs/abe/abe_dbg.h b/sound/soc/codecs/abe/abe_dbg.h
new file mode 100644
index 000000000000..daecd9a7c374
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_dbg.h
@@ -0,0 +1,167 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * DEFINE
+ */
+#define NO_OUTPUT 0
+#define TERMINAL_OUTPUT 1
+#define LINE_OUTPUT 2
+#define DEBUG_TRACE_OUTPUT 3
+
+#define DBG_LOG_SIZE 1000
+
+#define DBG_BITFIELD_OFFSET 8
+
+#define DBG_API_CALLS 0
+#define DBG_MAPI (1L << (DBG_API_CALLS + DBG_BITFIELD_OFFSET))
+
+#define DBG_EXT_DATA_ACCESS 1
+#define DBG_MDATA (1L << (DBG_EXT_DATA_ACCESS + DBG_BITFIELD_OFFSET))
+
+#define DBG_ERR_CODES 2
+#define DBG_MERR (1L << (DBG_API_CALLS + DBG_BITFIELD_OFFSET))
+
+/*
+ * IDs used for traces
+ */
+#define ID_RESET_HAL (1 + DBG_MAPI)
+#define ID_LOAD_FW (2 + DBG_MAPI)
+#define ID_DEFAULT_CONFIGURATION (3 + DBG_MAPI)
+#define ID_IRQ_PROCESSING (4 + DBG_MAPI)
+#define ID_EVENT_GENERATOR_SWITCH (5 + DBG_MAPI)
+#define ID_SET_MEMORY_CONFIG (6 + DBG_MAPI)
+#define ID_READ_LOWEST_OPP (7 + DBG_MAPI)
+#define ID_SET_OPP_PROCESSING (8 + DBG_MAPI)
+#define ID_SET_PING_PONG_BUFFER (9 + DBG_MAPI)
+#define ID_PLUG_SUBROUTINE (10 + DBG_MAPI)
+#define ID_UNPLUG_SUBROUTINE (11 + DBG_MAPI)
+#define ID_PLUG_SEQUENCE (12 + DBG_MAPI)
+#define ID_LAUNCH_SEQUENCE (13 + DBG_MAPI)
+#define ID_LAUNCH_SEQUENCE_PARAM (14 + DBG_MAPI)
+#define ID_SET_ANALOG_CONTROL (15 + DBG_MAPI)
+#define ID_READ_ANALOG_GAIN_DL (16 + DBG_MAPI)
+#define ID_READ_ANALOG_GAIN_UL (17 + DBG_MAPI)
+#define ID_ENABLE_DYN_UL_GAIN (18 + DBG_MAPI)
+#define ID_DISABLE_DYN_UL_GAIN (19 + DBG_MAPI)
+#define ID_ENABLE_DYN_EXTENSION (20 + DBG_MAPI)
+#define ID_DISABLE_DYN_EXTENSION (21 + DBG_MAPI)
+#define ID_NOTIFY_ANALOG_GAIN_CHANGED (22 + DBG_MAPI)
+#define ID_RESET_PORT (23 + DBG_MAPI)
+#define ID_READ_REMAINING_DATA (24 + DBG_MAPI)
+#define ID_DISABLE_DATA_TRANSFER (25 + DBG_MAPI)
+#define ID_ENABLE_DATA_TRANSFER (26 + DBG_MAPI)
+#define ID_READ_GLOBAL_COUNTER (27 + DBG_MAPI)
+#define ID_SET_DMIC_FILTER (28 + DBG_MAPI)
+#define ID_WRITE_PORT_DESCRIPTOR (29 + DBG_MAPI)
+#define ID_READ_PORT_DESCRIPTOR (30 + DBG_MAPI)
+#define ID_READ_PORT_ADDRESS (31 + DBG_MAPI)
+#define ID_WRITE_PORT_GAIN (32 + DBG_MAPI)
+#define ID_WRITE_HEADSET_OFFSET (33 + DBG_MAPI)
+#define ID_READ_GAIN_RANGES (34 + DBG_MAPI)
+#define ID_WRITE_EQUALIZER (35 + DBG_MAPI)
+#define ID_WRITE_ASRC (36 + DBG_MAPI)
+#define ID_WRITE_APS (37 + DBG_MAPI)
+#define ID_WRITE_MIXER (38 + DBG_MAPI)
+#define ID_WRITE_EANC (39 + DBG_MAPI)
+#define ID_WRITE_ROUTER (40 + DBG_MAPI)
+#define ID_READ_PORT_GAIN (41 + DBG_MAPI)
+#define ID_READ_ASRC (42 + DBG_MAPI)
+#define ID_READ_APS (43 + DBG_MAPI)
+#define ID_READ_APS_ENERGY (44 + DBG_MAPI)
+#define ID_READ_MIXER (45 + DBG_MAPI)
+#define ID_READ_EANC (46 + DBG_MAPI)
+#define ID_READ_ROUTER (47 + DBG_MAPI)
+#define ID_READ_DEBUG_TRACE (48 + DBG_MAPI)
+#define ID_SET_DEBUG_TRACE (49 + DBG_MAPI)
+#define ID_SET_DEBUG_PINS (50 + DBG_MAPI)
+#define ID_CALL_SUBROUTINE (51 + DBG_MAPI)
+
+/*
+ * IDs used for error codes
+ */
+#define NOERR 0
+#define ABE_SET_MEMORY_CONFIG_ERR (1 + DBG_MERR)
+#define ABE_BLOCK_COPY_ERR (2 + DBG_MERR)
+#define ABE_SEQTOOLONG (3 + DBG_MERR)
+#define ABE_BADSAMPFORMAT (4 + DBG_MERR)
+#define ABE_SET_ATC_MEMORY_CONFIG_ERR (5 + DBG_MERR)
+#define ABE_PROTOCOL_ERROR (6 + DBG_MERR)
+#define ABE_PARAMETER_ERROR (7 + DBG_MERR)
+#define ABE_PORT_REPROGRAMMING (8 + DBG_MERR) /* port programmed while still running */
+#define ABE_READ_USE_CASE_OPP_ERR (9 + DBG_MERR)
+#define ABE_PARAMETER_OVERFLOW (10 + DBG_MERR)
+
+/*
+ * IDs used for error codes
+ */
+#define ERR_LIB (1 << 1) /* error in the LIB.C file */
+#define ERR_API (1 << 2) /* error in the API.C file */
+#define ERR_INI (1 << 3) /* error in the INI.C file */
+#define ERR_SEQ (1 << 4) /* error in the SEQ.C file */
+#define ERR_DBG (1 << 5) /* error in the DBG.C file */
+#define ERR_EXT (1 << 6) /* error in the EXT.C file */
+
+/*
+ * MACROS
+ */
+#ifdef HAL_TIME_STAMP
+#define _log(x) ((x&abe_dbg_mask)?abe_dbg_log(x); \
+ abe_dbg_time_stamp(x); \
+ abe_dbg_printf(x); \
+ )
+#else
+#define _log(x) {if(x&abe_dbg_mask)abe_dbg_log(x);}
+#endif
+
+/*
+ * PROTOTYPES
+ */
+
+/*
+ * ABE_DBG_LOG
+ *
+ * Parameter :
+ * x : data to be logged
+ *
+ * abe_dbg_activity_log : global circular buffer holding the data
+ * abe_dbg_activity_log_write_pointer : circular write pointer
+ *
+ * Operations :
+ * saves data in the log file
+ *
+ * Return value :
+ * none
+ */
+void abe_dbg_log(abe_uint32 x);
+
+/*
+ * ABE_DBG_ERROR_LOG
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ * log the error codes
+ *
+ * Return value :
+ *
+ */
+void abe_dbg_error_log(abe_uint32 x);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sound/soc/codecs/abe/abe_def.h b/sound/soc/codecs/abe/abe_def.h
new file mode 100644
index 000000000000..4fc48a2b917b
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_def.h
@@ -0,0 +1,450 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_DEF_H_
+#define _ABE_DEF_H_
+
+/*
+ * HARDWARE AND PERIPHERAL DEFINITIONS
+ */
+
+/* PMEM size: 1024 words of 64 bits
+ * CMEM size: 2048 coefficients
+ * SMEM size: 3072 stereo samples
+ * DMEM size: 64 kB
+ */
+#define ABE_PMEM_SIZE 8192
+#define ABE_CMEM_SIZE 8192
+#define ABE_SMEM_SIZE 24576
+#define ABE_DMEM_SIZE 65536L
+#define ABE_ATC_DESC_SIZE 512
+
+#define ABE_ABE_REVISION 0x00 /* revision number */
+#define ABE_DUMMY_ADDRESS ABE_ABE_REVISION /* used as dummy register for generic IO tasks */
+
+#define ABE_MCU_IRQSTATUS_RAW 0x24 /* holds the MCU Irq signal */
+#define ABE_DSP_IRQSTATUS_RAW 0x4C /* holds the DSP Irq signal */
+#define ABE_DMASTATUS_RAW 0x84 /* holds the DMA req lines to the sDMA */
+
+#define EVENT_GENERATOR_COUNTER 0x68
+#define EVENT_GENERATOR_COUNTER_DEFAULT 2050 /* see computation in "abe_event_generator_switch" */
+
+#define EVENT_GENERATOR_START 0x6C /* start / stop the EVENT generator */
+#define EVENT_GENERATOR_ON 1
+#define EVENT_GENERATOR_OFF 0
+
+#define EVENT_SOURCE_SELECTION 0x70 /* selection of the EVENT generator source */
+#define EVENT_SOURCE_DMA 0
+#define EVENT_SOURCE_COUNTER 1
+
+#define AUDIO_ENGINE_SCHEDULER 0x74 /* selection of the ABE DMA req line from ATC */
+#define ABE_ATC_DMIC_DMA_REQ 1
+#define ABE_ATC_MCPDMDL_DMA_REQ 2
+#define ABE_ATC_MCPDMUL_DMA_REQ 3
+
+#define ABE_ATC_DIRECTION_IN 0 /* Direction=0 means input from ABE point of view */
+#define ABE_ATC_DIRECTION_OUT 1 /* Direction=1 means output from ABE point of view */
+
+#define ABE_DMAREQ_REGISTER(desc) (abe_uint32 *)((desc/8) + CIRCULAR_BUFFER_PERIPHERAL_R__0)
+
+//#define ABE_SEND_DMAREQ(dma) (*((abe_uint32 *)(ABE_ATC_BASE_ADDRESS_MPU+ABE_DMASTATUS_RAW)) = (dma))
+
+#define ABE_CBPR0_IDX 0 /* MM_DL */
+#define ABE_CBPR1_IDX 1 /* VX_DL */
+#define ABE_CBPR2_IDX 2 /* VX_UL */
+#define ABE_CBPR3_IDX 3 /* MM_UL */
+#define ABE_CBPR4_IDX 4 /* MM_UL2 */
+#define ABE_CBPR5_IDX 5 /* TONES */
+#define ABE_CBPR6_IDX 6 /* VIB */
+#define ABE_CBPR7_IDX 7 /* DEBUG/CTL */
+
+#define CIRCULAR_BUFFER_PERIPHERAL_R__0 (0x100 + ABE_CBPR0_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__1 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR1_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__2 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR2_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__3 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR3_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__4 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR4_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__5 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR5_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__6 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR6_IDX * 4)
+#define CIRCULAR_BUFFER_PERIPHERAL_R__7 (CIRCULAR_BUFFER_PERIPHERAL_R__0 + ABE_CBPR7_IDX * 4)
+
+/*
+ * DMA requests
+ */
+#define External_DMA_0 0 /* Internal connection doesn't connect at ABE boundary */
+#define DMIC_DMA_REQ 1 /* Transmit request digital microphone */
+#define McPDM_DMA_DL 2 /* Multichannel PDM downlink */
+#define McPDM_DMA_UP 3 /* Multichannel PDM uplink */
+#define MCBSP1_DMA_TX 4 /* MCBSP module 1 - transmit request */
+#define MCBSP1_DMA_RX 5 /* MCBSP module 1 - receive request */
+#define MCBSP2_DMA_TX 6 /* MCBSP module 2 - transmit request */
+#define MCBSP2_DMA_RX 7 /* MCBSP module 2 - receive request */
+#define MCBSP3_DMA_TX 8 /* MCBSP module 3 - transmit request */
+#define MCBSP3_DMA_RX 9 /* MCBSP module 3 - receive request */
+#define SLIMBUS1_DMA_TX0 10 /* SLIMBUS module 1 - transmit request channel 0 */
+#define SLIMBUS1_DMA_TX1 11 /* SLIMBUS module 1 - transmit request channel 1 */
+#define SLIMBUS1_DMA_TX2 12 /* SLIMBUS module 1 - transmit request channel 2 */
+#define SLIMBUS1_DMA_TX3 13 /* SLIMBUS module 1 - transmit request channel 3 */
+#define SLIMBUS1_DMA_TX4 14 /* SLIMBUS module 1 - transmit request channel 4 */
+#define SLIMBUS1_DMA_TX5 15 /* SLIMBUS module 1 - transmit request channel 5 */
+#define SLIMBUS1_DMA_TX6 16 /* SLIMBUS module 1 - transmit request channel 6 */
+#define SLIMBUS1_DMA_TX7 17 /* SLIMBUS module 1 - transmit request channel 7 */
+#define SLIMBUS1_DMA_RX0 18 /* SLIMBUS module 1 - receive request channel 0 */
+#define SLIMBUS1_DMA_RX1 19 /* SLIMBUS module 1 - receive request channel 1 */
+#define SLIMBUS1_DMA_RX2 20 /* SLIMBUS module 1 - receive request channel 2 */
+#define SLIMBUS1_DMA_RX3 21 /* SLIMBUS module 1 - receive request channel 3 */
+#define SLIMBUS1_DMA_RX4 22 /* SLIMBUS module 1 - receive request channel 4 */
+#define SLIMBUS1_DMA_RX5 23 /* SLIMBUS module 1 - receive request channel 5 */
+#define SLIMBUS1_DMA_RX6 24 /* SLIMBUS module 1 - receive request channel 6 */
+#define SLIMBUS1_DMA_RX7 25 /* SLIMBUS module 1 - receive request channel 7 */
+#define McASP1_AXEVT 26 /* McASP - Data transmit DMA request line */
+#define McASP1_AREVT 29 /* McASP - Data receive DMA request line */
+#define CBPr_DMA_RTX0 32 /* DMA of the Circular buffer peripheral 0 */
+#define CBPr_DMA_RTX1 33 /* DMA of the Circular buffer peripheral 1 */
+#define CBPr_DMA_RTX2 34 /* DMA of the Circular buffer peripheral 2 */
+#define CBPr_DMA_RTX3 35 /* DMA of the Circular buffer peripheral 3 */
+#define CBPr_DMA_RTX4 36 /* DMA of the Circular buffer peripheral 4 */
+#define CBPr_DMA_RTX5 37 /* DMA of the Circular buffer peripheral 5 */
+#define CBPr_DMA_RTX6 38 /* DMA of the Circular buffer peripheral 6 */
+#define CBPr_DMA_RTX7 39 /* DMA of the Circular buffer peripheral 7 */
+
+/*
+ * ATC DESCRIPTORS - DESTINATIONS
+ */
+#define DEST_DMEM access 0x00
+#define DEST_MCBSP1_ TX 0x01
+#define DEST_MCBSP2_ TX 0x02
+#define DEST_MCBSP3_TX 0x03
+#define DEST_SLIMBUS1_TX0 0x04
+#define DEST_SLIMBUS1_TX1 0x05
+#define DEST_SLIMBUS1_TX2 0x06
+#define DEST_SLIMBUS1_TX3 0x07
+#define DEST_SLIMBUS1_TX4 0x08
+#define DEST_SLIMBUS1_TX5 0x09
+#define DEST_SLIMBUS1_TX6 0x0A
+#define DEST_SLIMBUS1_TX7 0x0B
+#define DEST_MCPDM_DL 0x0C
+#define DEST_MCASP_TX0 0x0D
+#define DEST_MCASP_TX1 0x0E
+#define DEST_MCASP_TX2 0x0F
+#define DEST_MCASP_TX3 0x10
+#define DEST_EXTPORT0 0x11
+#define DEST_EXTPORT1 0x12
+#define DEST_EXTPORT2 0x13
+#define DEST_EXTPORT3 0x14
+#define DEST_MCPDM_ON 0x15
+#define DEST_CBP_CBPr 0x3F
+
+/*
+ * ATC DESCRIPTORS - SOURCES
+ */
+#define SRC_DMEM access 0x0
+#define SRC_MCBSP1_RX 0x01
+#define SRC_MCBSP2_RX 0x02
+#define SRC_MCBSP3_RX 0x03
+#define SRC_SLIMBUS1_RX0 0x04
+#define SRC_SLIMBUS1_RX1 0x05
+#define SRC_SLIMBUS1_RX2 0x06
+#define SRC_SLIMBUS1_RX3 0x07
+#define SRC_SLIMBUS1_RX4 0x08
+#define SRC_SLIMBUS1_RX5 0x09
+#define SRC_SLIMBUS1_RX6 0x0A
+#define SRC_SLIMBUS1_RX7 0x0B
+#define SRC_DMIC_UP 0x0C
+#define SRC_MCPDM_UP 0x0D
+#define SRC_MCASP_RX0 0x0E
+#define SRC_MCASP_RX1 0x0F
+#define SRC_MCASP_RX2 0x10
+#define SRC_MCASP_RX3 0x11
+#define SRC_CBP_CBPr 0x3F
+
+/*
+ * cache-flush mechanism
+ */
+#define NB_BYTES_CACHELINE_SHFT 4
+#define NB_BYTES_IN_CACHE_LINE (1<<NB_BYTES_CACHELINE_SHFT) /* there are 16 bytes in each cache lines */
+
+/*
+ * DEFINITIONS SHARED WITH VIRTAUDIO
+ */
+
+#define UC1_LP 1 /* MP3 low-power player use-case */
+#define UC2_VOICE_CALL_AND_IHF_MMDL 2 /* enables voice ul/dl on earpiece + MM_DL on IHF */
+#define UC3_VOICE_CALL 3 /* basic voice-call use-case */
+#define UC4_EANC 4 /* EANC test */
+#define UC5_PINGPONG_MMDL 5 /* Test MM_DL with Ping-Pong */
+#define UC6_PINGPONG_MMDL_WITH_IRQ 6 /* ping-pong with IRQ instead of sDMA */
+
+#define HAL_RESET_HAL 10 /* abe_reset_hal () */
+#define HAL_WRITE_MIXER 11 /* abe_write_mixer () */
+
+#if 0
+#define HAL_WRITE_MIXER 12 /* void abe_irq_processing (void) */
+#define HAL_WRITE_MIXER 13 /* void abe_event_generator_switch (abe_event_id e) */
+#define HAL_WRITE_MIXER 14 /* abe_read_use_case_opp (abe_use_case_id *u, abe_opp_t *o) */
+#define HAL_WRITE_MIXER 15 /* abe_write_mixer () */
+#define HAL_WRITE_MIXER 17 /* abe_read_sys_clock (abe_micros_t *time); */
+#define HAL_WRITE_MIXER 18 /* abe_fprintf (char *line); */
+#define HAL_WRITE_MIXER 11 /* abe_reset_hal (void); */
+#define HAL_WRITE_MIXER 11 /* abe_read_use_case_opp (abe_use_case_id *u, abe_opp_t *o); */
+#define HAL_WRITE_MIXER 11 /* abe_load_fw (void); */
+#define HAL_WRITE_MIXER 11 /* abe_read_port_address (abe_port_id port, abe_dma_t *dma); */
+#define HAL_WRITE_MIXER 11 /* abe_default_configuration (abe_uint32 use_case, abe_uint32 param1, abe_uint32 param2, abe_uint32 param3, abe_uint32 param4); */
+#define HAL_WRITE_MIXER 11 /* abe_irq_processing (void); */
+#define HAL_WRITE_MIXER 11 /* abe_event_generator_switch (abe_event_id e); */
+#define HAL_WRITE_MIXER 11 /* abe_read_lowest_opp (abe_opp_t *o); */
+#define HAL_WRITE_MIXER 11 /* abe_set_opp_processing (abe_opp_t opp); */
+#define HAL_WRITE_MIXER 11 /* abe_set_ping_pong_buffer (abe_port_id port, abe_uint32 n); */
+#define HAL_WRITE_MIXER 11 /* abe_connect_irq_ping_pong_port (MM_DL, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_uint32 *p); */
+#define HAL_WRITE_MIXER 11 /* abe_plug_subroutine (abe_uint32 *id, abe_subroutine2 f, abe_uint32 n); */
+#define HAL_WRITE_MIXER 11 /* abe_plug_sequence (abe_uint32 *id, abe_sequence_t *s); */
+#define HAL_WRITE_MIXER 11 /* abe_launch_sequence (abe_patch_rev patch, abe_uint32 n); */
+#define HAL_WRITE_MIXER 11 /* abe_launch_sequence_param (abe_patch_rev patch, abe_uint32 n, abe_int32 *param1, abe_int32 *param2, abe_int32 *param3, abe_int32 *param4); */; */
+#define HAL_WRITE_MIXER 11 /* abe_read_analog_gain_dl (abe_gain_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_read_analog_gain_ul (abe_gain_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_enable_dyn_ul_gain (void); */
+#define HAL_WRITE_MIXER 11 /* abe_disable_dyn_ul_gain (void); */
+#define HAL_WRITE_MIXER 11 /* abe_enable_dyn_extension (void); */
+#define HAL_WRITE_MIXER 11 /* abe_disable_dyn_extension (void); */
+#define HAL_WRITE_MIXER 11 /* abe_notify_analog_gain_changed (abe_ana_port_id Id, abe_gain_t *G); */
+#define HAL_WRITE_MIXER 11 /* abe_reset_port (abe_port_id id); */
+#define HAL_WRITE_MIXER 11 /* abe_read_remaining_data (abe_port_id port, abe_uint32 *n); */
+#define HAL_WRITE_MIXER 11 /* abe_disable_data_transfer (abe_port_id *p); */
+#define HAL_WRITE_MIXER 11 /* abe_enable_data_transfer (abe_port_id p); */
+#define HAL_WRITE_MIXER 11 /* abe_read_global_counter (abe_time_stamp_t *t, abe_millis_t *m); */
+#define HAL_WRITE_MIXER 11 /* abe_set_dmic_filter (abe_dmic_ratio_t d); */
+#define HAL_WRITE_MIXER 11 /* abe_connect_cbpr_dmareq_port (abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_connect_dmareq_port (abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_dma_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_connect_dmareq_ping_pong_port (abe_port_id id, abe_data_format_t *f, abe_uint32 d, abe_uint32 s, abe_dma_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_connect_serial_port (abe_port_id id, abe_data_format_t *f, abe_uint32 i); */
+#define HAL_WRITE_MIXER 11 /* abe_write_port_descriptor (abe_port_id id, abe_data_format_t *f, abe_port_protocol_t *p, abe_dma_t *dma); */
+#define HAL_WRITE_MIXER 11 /* abe_read_port_descriptor (abe_port_id id, abe_data_format_t *f, abe_port_protocol_t *p); */
+#define HAL_WRITE_MIXER 11 /* abe_read_aps_energy (abe_port_id *p, abe_gain_t *a); */
+#define HAL_WRITE_MIXER 11 /* abe_write_port_gain (abe_port_id port, abe_gain_t gain, abe_micros_t ramp); */
+#define HAL_WRITE_MIXER 11 /* abe_read_port_gain (abe_port_id port, abe_gain_t *gain, abe_micros_t *ramp); */
+#define HAL_WRITE_MIXER 11 /* abe_read_gain_range (abe_port_id id, abe_gain_t *min, abe_gain_t *max, abe_gain_t *step); */
+#define HAL_WRITE_MIXER 11 /* abe_write_equalizer (abe_equ_id id, abe_equ_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_write_asrc (abe_asrc_id id, abe_drift_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_write_aps (abe_aps_id id, abe_aps_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_write_mixer (abe_mixer_id id, abe_gain_t g, abe_micros_t ramp, abe_port_id p); */
+#define HAL_WRITE_MIXER 11 /* abe_write_eanc (abe_eanc_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_write_router (abe_router_id id, abe_router_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_read_asrc (abe_asrc_id id, abe_drift_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_read_aps (abe_aps_id id, abe_aps_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_read_mixer (abe_mixer_id id, abe_gain_t *gain, abe_micros_t *ramp, abe_port_id p); */
+#define HAL_WRITE_MIXER 11 /* abe_read_eanc (abe_eanc_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_read_router (abe_router_id id, abe_router_t *param); */
+#define HAL_WRITE_MIXER 11 /* abe_read_debug_trace (abe_uint32 *data, abe_uint32 *n); */
+#define HAL_WRITE_MIXER 11 /* abe_set_debug_trace (abe_dbg_t debug); */
+#define HAL_WRITE_MIXER 11 /* abe_set_debug_pins (abe_uint32 debug_pins); */
+#endif
+
+#define COPY_FROM_ABE_TO_HOST 1 /* ID used for LIB memory copy subroutines */
+#define COPY_FROM_HOST_TO_ABE 2
+
+/*
+ * INTERNAL DEFINITIONS
+ */
+
+#define CC_M1 0xFF /* unsigned version of (-1) */
+#define CS_M1 0xFFFF /* unsigned version of (-1) */
+#define CL_M1 0xFFFFFFFFL /* unsigned version of (-1) */
+
+#define NBEANC1 20 /* 20 Q6.26 coef for the FIR */
+#define NBEANC2 16 /* 16 Q6.26 coef for the IIR */
+
+#define NBEQ1 25 /* 24 Q6.26 coefficients */
+#define NBEQ2 13 /* 2x12 Q6.26 coefficients */
+
+#define NBAPS1 10 /* TBD APS first set of parameters */
+#define NBAPS2 10 /* TBD APS second set of parameters */
+
+#define NBMIX_AUDIO_UL 2 /* Mixer used for sending tones to the uplink voice path */
+#define NBMIX_DL1 4 /* Main downlink mixer */
+#define NBMIX_DL2 4 /* Handsfree downlink mixer */
+#define NBMIX_SDT 2 /* Side-tone mixer */
+#define NBMIX_ECHO 2 /* Echo reference mixer */
+#define NBMIX_VXREC 4 /* Voice record mixer */
+ /*
+ Mixer ID Input port ID Comments
+ DL1_MIXER 0 TONES_DL path
+ 1 VX_DL path
+ 2 MM_DL path
+ 3 MM_UL2 path
+
+ DL2_MIXER 0 TONES_DL path
+ 1 VX_DL path
+ 2 MM_DL path
+ 3 MM_UL2 path
+
+ SDT_MIXER 0 Uplink path
+ 1 Downlink path
+
+ ECHO_MIXER 0 DL1_MIXER path
+ 1 DL2_MIXER path
+
+ AUDUL_MIXER 0 TONES_DL path
+ 1 Uplink path
+ 2 MM_DL path
+
+ VXREC_MIXER 0 TONES_DL path
+ 1 VX_DL path
+ 2 MM_DL path
+ 3 VX_UL path
+ */
+#define MIX_DL1_INPUT_TONES 0
+#define MIX_DL1_INPUT_VX_DL 1
+#define MIX_DL1_INPUT_MM_DL 2
+#define MIX_DL1_INPUT_MM_UL2 3
+
+#define MIX_DL2_INPUT_TONES 0
+#define MIX_DL2_INPUT_VX_DL 1
+#define MIX_DL2_INPUT_MM_DL 2
+#define MIX_DL2_INPUT_MM_UL2 3
+
+#define MIX_SDT_INPUT_DL1_MIXER 0
+#define MIX_SDT_INPUT_DL2_MIXER 1
+
+#define MIX_AUDUL_INPUT_TONES 0
+#define MIX_AUDUL_INPUT_UPLINK 1
+#define MIX_AUDUL_INPUT_MM_DL 2
+
+#define MIX_VXREC_INPUT_TONES 0
+#define MIX_VXREC_INPUT_VX_DL 1
+#define MIX_VXREC_INPUT_MM_DL 2
+#define MIX_VXREC_INPUT_VX_UL 3
+
+#define NBROUTE_UL 16 /* nb of samples to route */
+#define NBROUTE_CONFIG_MAX 10 /* 10 routing tables max */
+
+#define NBROUTE_CONFIG 4 /* 4 pre-computed routing tables */
+#define UPROUTE_CONFIG_AMIC 0 /* AMIC on VX_UL */
+#define UPROUTE_CONFIG_DMIC1 1 /* DMIC first pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC2 2 /* DMIC second pair on VX_UL */
+#define UPROUTE_CONFIG_DMIC3 3 /* DMIC last pair on VX_UL */
+
+#define ABE_PMEM 1
+#define ABE_CMEM 2
+#define ABE_SMEM 3
+#define ABE_DMEM 4
+#define ABE_ATC 5
+
+#define MAXCALLBACK 100 /* call-back indexes */
+#define MAXNBSUBROUTINE 100 /* subroutines */
+
+#define MAXNBSEQUENCE 20 /* time controlled sequenced */
+#define MAXACTIVESEQUENCE 20 /* maximum simultaneous active sequences */
+#define MAXSEQUENCESTEPS 2 /* max number of steps in the sequences */
+#define MAXFEATUREPORT 8 /* max number of feature associated to a port */
+#define SUB_0_PARAM 0
+#define SUB_1_PARAM 1 /* number of parameters per sequence calls */
+#define SUB_2_PARAM 2
+#define SUB_3_PARAM 3
+#define SUB_4_PARAM 4
+
+#define FREE_LINE 0 /* active sequence mask = 0 means the line is free */
+#define NOMASK (1 << 0) /* no ask for collision protection */
+#define MASK_PDM_OFF (1 << 1) /* do not allow a PDM OFF during the execution of this sequence */
+#define MASK_PDM_ON (1 << 2) /* do not allow a PDM ON during the execution of this sequence */
+
+#define NBCHARFEATURENAME 16 /* explicit name of the feature */
+#define NBCHARPORTNAME 16 /* explicit name of the port */
+#define MAXNBABEPORTS LAST_PORT_ID /* number of sink+source ports of the ABE */
+#define MAX_MAP_DMEM LAST_PORT_ID
+
+#define SNK_P ABE_ATC_DIRECTION_IN /* sink / input port */
+#define SRC_P ABE_ATC_DIRECTION_OUT /* source / ouptut port */
+
+#define NODRIFT 0 /* no ASRC applied */
+#define GAIN_MAXIMUM 30L
+#define GAIN_24dB 24L
+#define GAIN_18dB 18L
+#define GAIN_12dB 12L
+#define GAIN_6dB 6L
+#define GAIN_0dB 0 /* default gain = 1 */
+#define GAIN_M6dB -6L
+#define GAIN_M12dB -12L
+#define GAIN_M18dB -18L
+#define GAIN_M24dB -24L
+#define GAIN_M30dB -30L
+#define GAIN_M40dB -40L
+#define GAIN_M50dB -50L
+#define MUTE_GAIN -140L /* muted gain = -140 decibels */
+
+#define RAMP_0MS 0 /* ramp_t is in milli- seconds */
+#define RAMP_1MS 1L
+#define RAMP_2MS 2L
+#define RAMP_5MS 5L
+#define RAMP_10MS 10L
+#define RAMP_20MS 20L
+#define RAMP_50MS 50L
+#define RAMP_100MS 100L
+#define RAMP_200MS 200L
+#define RAMP_500MS 500L
+#define RAMP_1000MS 1000L
+#define RAMP_MAXLENGTH 10000L
+
+#define LINABE_TO_DECIBELS 1 /* for abe_translate_gain_format */
+#define DECIBELS_TO_LINABE 2
+#define IIRABE_TO_MICROS 1 /* for abe_translate_ramp_format */
+#define MICROS_TO_IIABE 2
+
+#define IDLE_P 1 /* port idled */
+#define RUN_P 2 /* port running */
+#define NOCALLBACK 0
+#define NOPARAMETER 0
+
+#define MCPDM_UL_ITER 2 /* number of ATC access upon AMIC DMArequests, all the FIFOs are enabled */
+#define MCPDM_DL_ITER 6 /* All the McPDM FIFOs are enabled simultaneously */
+#define DMIC_ITER 6 /* All the DMIC FIFOs are enabled simultaneously */
+
+#define DEFAULT_THR_READ 1 /* port / flow management */
+#define DEFAULT_THR_WRITE 1 /* port / flow management */
+
+#define DEFAULT_CONTROL_MCPDMDL 1 /* allows control on the PDM line */
+
+#define MAX_PINGPONG_BUFFERS 2 /* TBD later if needed */
+
+/*
+ * Indexes to the subroutines
+ */
+#define SUB_WRITE_MIXER 1
+#define SUB_WRITE_PORT_GAIN 2
+
+/* OLD WAY */
+#define c_feat_init_eq 1
+#define c_feat_read_eq1 2
+#define c_write_eq1 3
+#define c_feat_read_eq2 4
+#define c_write_eq2 5
+#define c_feat_read_eq3 6
+#define c_write_eq3 7
+
+/*
+ * MACROS
+ */
+
+#define LOAD_ABEREG(reg,data) {abe_uint32 *ocp_addr = (abe_uint32 *)((reg)+ABE_ATC_BASE_ADDRESS_MPU); *ocp_addr= (data);}
+
+#define maximum(a,b) (((a)<(b))?(b):(a))
+#define absolute(a) ( ((a)>0) ? (a):((-1)*(a)) )
+
+// Gives 1% errors
+//#define abe_power_of_two(x) (abe_float)(1 + x*(0.69315 + x*(0.24022 + x*(0.056614 + x*(0.00975 ))))) /* for x = [-1..+1] */
+//#define abe_log_of_two(i) (abe_float)(-2.4983 + i*(4.0321 + i*(-2.0843 + i*(0.63 + i*(-0.0793))))) /* for i = [+1..+2[ */
+// Gives 0.1% errors
+//#define abe_power_of_two(xx) (abe_float)(1 + xx*(0.69314718055995 + xx*(0.24022650695909 + xx*(0.05661419083812 + xx*(0.0096258236109 ))))) /* for x = [-1..+1] */
+//#define abe_log_of_two(i) (abe_float)(-3.02985297173966 + i*(6.07170945221999 + i*(-5.27332161514862 + i*(3.22638187067771 + i*(-1.23767101624897 + i*(0.26766043958616 + i*(-0.02490211314987))))))) /* for i = [+1..+2[ */
+
+#define abe_power_of_two(xx) (abe_float)(0.9999999924494 + xx*(0.69314847688495 + xx*(0.24022677604481 + xx*(0.05549256818679 + xx*(0.00961666477618 + xx*(0.0013584351075 + xx*(0.00015654359307))))))) /* for x = [-1..+1] */
+#define abe_log_of_two(xx) (abe_float)(-3.02985297175803 + xx*(6.07170945229365 + xx*(-5.27332161527062 + xx*(3.22638187078450 + xx*(-1.23767101630110 + xx*(0.26766043959961 + xx*(-0.02490211315130))))))) /* for x = [+1..+2] */
+#define abe_sine(xx) (abe_float)(-0.000000389441 + xx*(6.283360925789 + xx*(-0.011140658372 + xx*(-41.073653348384 + xx*(-3.121196875959 + xx*(100.619954580736 + xx*( -59.133359355846))))))) /* for x = [0 .. pi/2] */
+#define abe_sqrt(xx) (abe_float)(0.32298238417665 + xx*(0.93621865220393 + xx*(-0.36276443369703 + xx*(0.13008602653101+ xx*(-0.03017833169073 + xx*(0.00393731964847 + xx*-0.00021858629159 )))))) /* for x = [1 .. 4] */
+
+#endif /* _ABE_DEF_H_ */
diff --git a/sound/soc/codecs/abe/abe_define.h b/sound/soc/codecs/abe/abe_define.h
new file mode 100644
index 000000000000..030c11a580e4
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_define.h
@@ -0,0 +1,54 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_DEFINE_H_
+#define _ABE_DEFINE_H_
+
+#define ATC_DESCRIPTOR_NUMBER 64
+#define PROCESSING_SLOTS 24
+#define TASKS_IN_SLOT 4
+#define TASK_POOL_LENGTH 128
+#define MCU_IRQ 0x44
+#define DSP_IRQ 0x5c
+#define DMA_REQ 0x84
+#define DCMD_FIFO_NUMBER 2
+#define DCMD_FIFO_LENGTH 8
+#define DEBUG_FIFO_LENGTH 16
+#define IRQ_FIFO_LENGTH 6
+#define SIGNAL_L_MF_COPIED 0x0010
+#define SIGNAL_L_MMDL_PP 0x0020
+#define IO_DESCR_NUMBER 19
+#define IO_DESCR_LIST_NELEM 4
+#define IO_DESCR_LIST_SIZE 6
+#define PING_PONG_NUMBER 8
+#define MAX_MM_BUFFERS 2
+#define DEBUG_BUF_LENGTH 32
+#define PHOENIX_FIFO_LENGTH 8
+#define EQUALIZATION_F_ORDER 8
+#define DEFAULT_FILTER_ORDER 8
+#define GAINS_WITH_RAMP 18
+#define GAINS_NO_RAMP 12
+#define McPDM_OUT_FIFO_LENGTH 18
+#define McPDM_IN_FIFO_LENGTH 127
+#define TASK_CLUSTER_NUMBER 4
+#define TASK_CLUSTER_LENGTH 8
+#define MASK_NB_PHASES 15
+#define EANC_IIR_MEMSIZE 17
+#define ASRC_UL_VX_FIR_L 19
+#define ASRC_DL_VX_FIR_L 19
+#define ASRC_DL_MM_FIR_L 18
+#define ASRC_N_8k 2
+#define ASRC_N_16k 4
+#define ASRC_N_48k 12
+#define EANC_IIR_MEMSIZE 17
+#define VIBRA_N 5
+#define VIBRA1_IIR_MEMSIZE 11
+
+#endif /* _ABE_DEFINE_H_ */
diff --git a/sound/soc/codecs/abe/abe_dm_addr.h b/sound/soc/codecs/abe/abe_dm_addr.h
new file mode 100644
index 000000000000..5a3f27f0cac3
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_dm_addr.h
@@ -0,0 +1,234 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_DM_ADDR_H_
+#define _ABE_DM_ADDR_H_
+
+/* Data memory sizeof */
+#define abe_dm_sizeof(x) (D_##x##_ADDR_END - D_##x##_ADDR + 1)
+
+#define D_atcDescriptors_ADDR 0
+#define D_atcDescriptors_ADDR_END 511
+
+#define D_McPDM_UL_Fifo_ADDR 512
+#define D_McPDM_UL_Fifo_ADDR_END 1019
+
+#define D_McPDM_DL_Fifo_ADDR 1024
+#define D_McPDM_DL_Fifo_ADDR_END 1531
+
+#define D_DMIC_UL_Fifo_ADDR 1536
+#define D_DMIC_UL_Fifo_ADDR_END 2043
+
+#define D_MM_UL_FIFO_ADDR 2048
+#define D_MM_UL_FIFO_ADDR_END 2535
+
+#define D_MM_DL_ADDR 2560
+#define D_MM_DL_ADDR_END 2847
+
+#define stack_ADDR 2848
+#define stack_ADDR_END 2975
+
+#define D_version_ADDR 2976
+#define D_version_ADDR_END 2979
+
+#define D_tasksList_ADDR 2980
+#define D_tasksList_ADDR_END 4003
+
+#define D_multiFrame_ADDR 4004
+#define D_multiFrame_ADDR_END 4195
+
+#define D_nextMultiFrame_ADDR 4196
+#define D_nextMultiFrame_ADDR_END 4387
+
+#define D_taskClusters_ADDR 4388
+#define D_taskClusters_ADDR_END 4451
+
+#define D_idleTask_ADDR 4452
+#define D_idleTask_ADDR_END 4453
+
+#define D_typeLengthCheck_ADDR 4454
+#define D_typeLengthCheck_ADDR_END 4455
+
+#define D_taskStep_ADDR 4456
+#define D_taskStep_ADDR_END 4459
+
+#define D_pCurrentTask_ADDR 4460
+#define D_pCurrentTask_ADDR_END 4461
+
+#define D_pFastLoopBack_ADDR 4462
+#define D_pFastLoopBack_ADDR_END 4463
+
+#define D_pNextFastLoopBack_ADDR 4464
+#define D_pNextFastLoopBack_ADDR_END 4467
+
+#define D_ppCurrentTask_ADDR 4468
+#define D_ppCurrentTask_ADDR_END 4469
+
+#define D_loopCounter_ADDR 4470
+#define D_loopCounter_ADDR_END 4471
+
+#define D_idleSlotsReq_ADDR 4472
+#define D_idleSlotsReq_ADDR_END 4473
+
+#define D_PostMcuIrq_ADDR 4476
+#define D_PostMcuIrq_ADDR_END 4479
+
+#define D_PostDspIrq_ADDR 4480
+#define D_PostDspIrq_ADDR_END 4483
+
+#define D_McuIrqFifo_ADDR 4484
+#define D_McuIrqFifo_ADDR_END 4507
+
+#define D_DspIrqFifo_ADDR 4508
+#define D_DspIrqFifo_ADDR_END 4531
+
+#define D_McuIrqFifoDesc_ADDR 4532
+#define D_McuIrqFifoDesc_ADDR_END 4543
+
+#define D_DspIrqFifoDesc_ADDR 4544
+#define D_DspIrqFifoDesc_ADDR_END 4555
+
+#define D_debugFifo_ADDR 4556
+#define D_debugFifo_ADDR_END 4619
+
+#define D_debugFifoDesc_ADDR 4620
+#define D_debugFifoDesc_ADDR_END 4631
+
+#define D_DCFifoDesc_ADDR 4632
+#define D_DCFifoDesc_ADDR_END 4655
+
+#define D_DCFifo_ADDR 4656
+#define D_DCFifo_ADDR_END 4847
+
+#define D_IODescr_ADDR 4848
+#define D_IODescr_ADDR_END 5227
+
+#define D_IODescrList_ADDR 5228
+#define D_IODescrList_ADDR_END 5275
+
+#define D_PingPongDesc_ADDR 5276
+#define D_PingPongDesc_ADDR_END 5323
+
+#define D_IRQMask_ADDR 5324
+#define D_IRQMask_ADDR_END 5355
+
+#define D_DebugAbe2hal_ADDR 5356
+#define D_DebugAbe2hal_ADDR_END 5483
+
+#define D_Debug_hal2abe_ADDR 5484
+#define D_Debug_hal2abe_ADDR_END 5611
+
+#define D_Cmd2PhenixFifoDesc_ADDR 5612
+#define D_Cmd2PhenixFifoDesc_ADDR_END 5623
+
+#define D_ctrlPortFifo_ADDR 5632
+#define D_ctrlPortFifo_ADDR_END 5647
+
+#define D_StatusFromPhoenixFifoDesc_ADDR 5648
+#define D_StatusFromPhoenixFifoDesc_ADDR_END 5659
+
+#define D_Cmd2PhoenixFifo_ADDR 5660
+#define D_Cmd2PhoenixFifo_ADDR_END 5691
+
+#define D_StatusFromPhoenixFifo_ADDR 5692
+#define D_StatusFromPhoenixFifo_ADDR_END 5723
+
+#define D_Data_LSB_2_ADDR 5724
+#define D_Data_LSB_2_ADDR_END 5727
+
+#define D_Ref0_ADDR 5728
+#define D_Ref0_ADDR_END 5737
+
+#define D_VIB_DL_ADDR 5740
+#define D_VIB_DL_ADDR_END 5931
+
+#define D_DebugRegister_ADDR 5932
+#define D_DebugRegister_ADDR_END 6071
+
+#define D_Gcount_ADDR 6072
+#define D_Gcount_ADDR_END 6073
+
+#define D_VX_UL_ADDR 6144
+#define D_VX_UL_ADDR_END 6239
+
+#define D_VX_DL_ADDR 6272
+#define D_VX_DL_ADDR_END 6367
+
+#define D_DCcounter_ADDR 6368
+#define D_DCcounter_ADDR_END 6371
+
+#define D_DCsum_ADDR 6372
+#define D_DCsum_ADDR_END 6379
+
+#define D_MM_UL2_FIFO_ADDR 6400
+#define D_MM_UL2_FIFO_ADDR_END 6503
+
+#define D_TONES_DL_ADDR 6528
+#define D_TONES_DL_ADDR_END 6631
+
+#define D_aUplinkRouting_ADDR 6632
+#define D_aUplinkRouting_ADDR_END 6647
+
+#define D_VirtAudioLoop_ADDR 6648
+#define D_VirtAudioLoop_ADDR_END 6651
+
+#define D_VIBRA_DL_ADDR 6656
+#define D_VIBRA_DL_ADDR_END 6711
+
+#define D_AsrcVars_DL_VX_ADDR 6712
+#define D_AsrcVars_DL_VX_ADDR_END 6743
+
+#define D_CoefAddresses_DL_VX_ADDR 6744
+#define D_CoefAddresses_DL_VX_ADDR_END 6775
+
+#define D_AsrcVars_UL_VX_ADDR 6776
+#define D_AsrcVars_UL_VX_ADDR_END 6807
+
+#define D_CoefAddresses_UL_VX_ADDR 6808
+#define D_CoefAddresses_UL_VX_ADDR_END 6839
+
+#define D_AsrcVars_DL_MM_ADDR 6840
+#define D_AsrcVars_DL_MM_ADDR_END 6871
+#define D_AsrcVars_DL_MM_sizeof 32
+
+#define D_CoefAddresses_DL_MM_ADDR 6872
+#define D_CoefAddresses_DL_MM_ADDR_END 6903
+
+#define D_APS_thresholds_ADDR 6904
+#define D_APS_thresholds_ADDR_END 6911
+
+#define D_APS_IRQ_ADDR 6912
+#define D_APS_IRQ_ADDR_END 6919
+
+#define D_TraceBufAdr_ADDR 6920
+#define D_TraceBufAdr_ADDR_END 6921
+
+#define D_TraceBufOffset_ADDR 6922
+#define D_TraceBufOffset_ADDR_END 6923
+
+#define D_TraceBufLength_ADDR 6924
+#define D_TraceBufLength_ADDR_END 6925
+
+#define D_AsrcVars_ECHO_REF_ADDR 6928
+#define D_AsrcVars_ECHO_REF_ADDR_END 6959
+
+#define D_Pempty_ADDR 6960
+#define D_Pempty_ADDR_END 6963
+
+#define D_Trace_buffer_ADDR 8192
+#define D_Trace_buffer_ADDR_END 10239
+
+#define D_PING_ADDR 16384
+#define D_PING_ADDR_END 40959
+
+#define D_PONG_ADDR 40960
+#define D_PONG_ADDR_END 65535
+
+#endif /* _ABE_DM_ADDR_H_ */
diff --git a/sound/soc/codecs/abe/abe_ext.c b/sound/soc/codecs/abe/abe_ext.c
new file mode 100644
index 000000000000..531a50c1758c
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_ext.c
@@ -0,0 +1,118 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+/*
+ * ABE_DEFAULT_IRQ_PINGPONG_PLAYER
+ *
+ *
+ * Operations :
+ * generates data for the cache-flush buffer
+ *
+ * Return value :
+ * None.
+ */
+void abe_default_irq_pingpong_player(void)
+{
+ /* ping-pong access to MM_DL at 48kHz Mono with 20ms packet sizes */
+ #define N_SAMPLES_MAX ((int)(1024))
+
+ static abe_int32 idx;
+ abe_uint32 i, dst, n_samples;
+ abe_int32 temp [N_SAMPLES_MAX], audio_sample;
+ const abe_int32 audio_pattern [8] = {0, 11585, 16384, 11585, 0, -11586, -16384, -11586 };
+
+ /* read the address of the Pong buffer */
+ abe_read_next_ping_pong_buffer (MM_DL_PORT, &dst, &n_samples);
+
+ /* generate a test pattern */
+ for (i = 0; i < n_samples; i++) {
+ idx = (idx +1) & 7; /* circular addressing */
+ audio_sample = audio_pattern [idx];
+ temp [i] = ((audio_sample << 16) + audio_sample);
+ }
+
+ /* copy the pattern (flush it) to DMEM pointer update
+ * not necessary here because the buffer size do not
+ * change from one ping to the other pong
+ */
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, dst, &(temp[0]), n_samples * 4);
+ /* @ see comment above , abe_set_ping_pong_buffer (MM_DL_PORT, n_samples * 4); */
+}
+
+/*
+ * initialize the default values for call-backs to subroutines
+ * - FIFO IRQ call-backs for sequenced tasks
+ * - FIFO IRQ call-backs for audio player/recorders (ping-pong protocols)
+ * - Remote debugger interface
+ * - Error monitoring
+ * - Activity Tracing
+ */
+
+/*
+ * ABE_READ_SYS_CLOCK
+ *
+ * Parameter :
+ * pointer to the system clock
+ *
+ * Operations :
+ * returns the current time indication for the LOG
+ *
+ * Return value :
+ * None.
+ */
+void abe_read_sys_clock(abe_micros_t *time)
+{
+ static abe_micros_t clock;
+
+ *time = clock;
+ clock ++;
+}
+
+/*
+ * ABE_APS_TUNING
+ *
+ * Parameter :
+ *
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_aps_tuning(void)
+{
+}
+
+/**
+* @fn abe_lock_executione()
+*
+* Operations : set a spin-lock and wait in case of collision
+*
+*
+* @see ABE_API.h
+*/
+void abe_lock_execution(void)
+{
+}
+
+/**
+* @fn abe_unlock_executione()
+*
+* Operations : reset a spin-lock (end of subroutine)
+*
+*
+* @see ABE_API.h
+*/
+void abe_unlock_execution(void)
+{
+}
diff --git a/sound/soc/codecs/abe/abe_ext.h b/sound/soc/codecs/abe/abe_ext.h
new file mode 100644
index 000000000000..40e83deb6805
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_ext.h
@@ -0,0 +1,34 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_EXT_H_
+#define _ABE_EXT_H_
+
+#include <linux/io.h>
+#define PC_SIMULATION 0 /* Tuning is done on PC ? */
+
+/*
+ * OS DEPENDENT MMU CONFIGURATION
+ */
+#define ABE_ATC_BASE_ADDRESS_L3 L3_ABE_44XX_PHYS + 0xf1000
+ /* base address used for L3/DMA access */
+#define ABE_DMEM_BASE_ADDRESS_L3 L3_ABE_44XX_PHYS + 0x80000
+ /* 64kB as seen from DMA access */
+#define ABE_PMEM_BASE_ADDRESS_MPU IO_ADDRESS(L3_ABE_44XX_PHYS) + 0xe0000
+ /* 8kB as seen from MPU access */
+#define ABE_CMEM_BASE_ADDRESS_MPU IO_ADDRESS(L3_ABE_44XX_PHYS) + 0xa0000
+ /* 8kB */
+#define ABE_SMEM_BASE_ADDRESS_MPU IO_ADDRESS(L3_ABE_44XX_PHYS) + 0xc0000
+ /* 24kB */
+#define ABE_DMEM_BASE_ADDRESS_MPU IO_ADDRESS(L3_ABE_44XX_PHYS) + 0x80000
+ /* 64kB */
+#define ABE_ATC_BASE_ADDRESS_MPU IO_ADDRESS(L3_ABE_44XX_PHYS) + 0xf1000
+
+#endif /* _ABE_EXT_H_ */
diff --git a/sound/soc/codecs/abe/abe_functionsId.h b/sound/soc/codecs/abe/abe_functionsId.h
new file mode 100644
index 000000000000..bfc51a2c69d2
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_functionsId.h
@@ -0,0 +1,75 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_FUNCTIONSID_H_
+#define _ABE_FUNCTIONSID_H_
+
+/*
+ * TASK function ID definitions
+ */
+#define C_ABE_FW_FUNCTION_nullCall 0
+#define C_ABE_FW_FUNCTION_test 1
+#define C_ABE_FW_FUNCTION_IIR 2
+#define C_ABE_FW_FUNCTION_monoToStereoPack 3
+#define C_ABE_FW_FUNCTION_stereoToMonoSplit 4
+#define C_ABE_FW_FUNCTION_decimator 5
+#define C_ABE_FW_FUNCTION_OS0Fill 6
+#define C_ABE_FW_FUNCTION_mixer2 7
+#define C_ABE_FW_FUNCTION_mixer4 8
+#define C_ABE_FW_FUNCTION_taskCluster 9
+#define C_ABE_FW_FUNCTION_treatDelayedTasksFifo 10
+#define C_ABE_FW_FUNCTION_treatPostedIrq 11
+#define C_ABE_FW_FUNCTION_inplaceGain 12
+#define C_ABE_FW_FUNCTION_EANC 13
+#define C_ABE_FW_FUNCTION_IO_MM_UL_old 14
+#define C_ABE_FW_FUNCTION_fillMcPDMOutFifo 15
+#define C_ABE_FW_FUNCTION_IO_generic 16
+#define C_ABE_FW_FUNCTION_IO_DMIC_UL 17
+#define C_ABE_FW_FUNCTION_IO_AMIC_UL 18
+#define C_ABE_FW_FUNCTION_StreamRouting 19
+#define C_ABE_FW_FUNCTION_StreamRoutingLoop 20
+#define C_ABE_FW_FUNCTION_VIBRA2 21
+#define C_ABE_FW_FUNCTION_VIBRA1 22
+#define C_ABE_FW_FUNCTION_APS_core 23
+#define C_ABE_FW_FUNCTION_ASRC_DL_wrapper 24
+#define C_ABE_FW_FUNCTION_ASRC_UL_wrapper 25
+#define C_ABE_FW_FUNCTION_IO_MM_UL 26
+#define C_ABE_FW_FUNCTION_gainConverge 27
+#define C_ABE_FW_FUNCTION_dualIir 28
+#define C_ABE_FW_FUNCTION_EANC_wrapper 29
+#define C_ABE_FW_FUNCTION_DCoffset 30
+#define C_ABE_FW_FUNCTION_IO_DL_pp 31
+
+/*
+ * COMMAND function ID definitions
+ */
+#define nullCommand_CMDID 0
+#define cmdMemcpyDM2SM_CMDID 1
+#define cmdMemcpyDM2CM_CMDID 2
+#define cmdMemcpySM2SM_CMDID 3
+#define cmdMemcpyCM2CM_CMDID 4
+#define cmdMemcpySM2DM_CMDID 5
+#define cmdMemcpyCM2DM_CMDID 6
+#define cmdClearCM_CMDID 7
+#define cmdClearSM_CMDID 8
+#define cmdSendIRQ_CMDID 9
+#define cmdMemcpyDM2DM_CMDID 10
+
+/*
+ * COPY function ID definitions
+ */
+#define COPY_D2S_LR_CFPID 0
+#define COPY_D2S_2_CFPID 1
+#define COPY_D2S_MONO_CFPID 2
+#define COPY_S1D_MONO_CFPID 3
+#define COPY_S2D_MONO_CFPID 4
+#define COPY_S2D_2_CFPID 5
+
+#endif /* _ABE_FUNCTIONSID_H_ */
diff --git a/sound/soc/codecs/abe/abe_fw.h b/sound/soc/codecs/abe/abe_fw.h
new file mode 100644
index 000000000000..1bcf6c2b3f24
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_fw.h
@@ -0,0 +1,479 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+//#include "ABE_CM_ADDR.h"
+//#include "ABE_SM_ADDR.h"
+//#include "ABE_DM_ADDR.h"
+//#include "ABE_typedef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * GLOBAL DEFINITION
+ */
+#define FW_SCHED_LOOP_FREQ 4000 /* one scheduler loop = 4kHz = 12 samples at 48kHz */
+
+#define SCHED_LOOP_8kHz ( 8000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_16kHz (16000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_24kHz (24000/FW_SCHED_LOOP_FREQ)
+#define SCHED_LOOP_48kHz (48000/FW_SCHED_LOOP_FREQ)
+
+#define TASKS_IN_SLOT 4
+#define TASKS_IN_SLOT_OPP_25 4 /* Step = 4 <> 1 task per slot */
+#define TASKS_IN_SLOT_OPP_50 2
+#define TASKS_IN_SLOT_OPP_100 1
+
+/*
+ * DMEM AREA - SCHEDULER
+ */
+#define smem_mm_trace 0
+#define dmem_mm_trace 0
+#define dmem_mm_trace_size 0
+
+/* ATC descriptors not using the AESS naming convention
+typedef struct abeatcdescTag {
+ unsigned readPointer:7; // Desc0
+ unsigned reserved0:1;
+ unsigned bufSize:7;
+ unsigned IRQdest:1;
+ unsigned error:1;
+ unsigned reserved1:5;
+ unsigned direction:1;
+ unsigned empty:1;
+ unsigned writePointer:7;
+ unsigned reserved2:1;
+ unsigned baseAddr:12; // Desc1
+ unsigned iteration_lower4:4; // iteration field overlaps the 16 bits boundary
+ unsigned iteration_upper3:3;
+ unsigned source:6;
+ unsigned dest:6;
+ unsigned DescrAct:1;
+} ABE_SAtcDescriptor;
+*/
+
+#define ATC_SIZE 8 /* 8 bytes per descriptors */
+
+typedef struct {
+ unsigned rdpt:7; /* first 32bits word of the descriptor */
+ unsigned reserved0:1;
+ unsigned cbsize:7;
+ unsigned irqdest:1;
+ unsigned cberr:1;
+ unsigned reserved1:5;
+ unsigned cbdir:1;
+ unsigned nw:1;
+ unsigned wrpt:7;
+ unsigned reserved2:1;
+ unsigned badd:12; /* second 32bits word of the descriptor */
+ unsigned iter:7; /* iteration field overlaps the 16 bits boundary */
+ unsigned srcid:6;
+ unsigned destid:6;
+ unsigned desen:1;
+} abe_satcdescriptor_aess;
+
+/*
+ * table of scheduler tasks :
+ * char scheduler_table[24 x 4] : four bytes used at OPP100%
+ */
+#define dmem_scheduler_table D_multiFrame_ADDR
+
+#define dmem_eanc_task_pointer D_pFastLoopBack_ADDR
+
+/*
+ * OPP value :
+ * pointer increment steps in the scheduler table
+ */
+#define dmem_scheduler_table_step D_taskStep_ADDR
+
+/*
+ * table of scheduler tasks (max 64) :
+ * char task_descriptors[64 x 8] : eight bytes per task
+ * TASK INDEX, INITPTR 1,2,3, INITREG, Loop Counter, Reserved 1,2
+ */
+#define dmem_task_descriptor D_tasksList_ADDR
+
+/*
+ * table of task function addresses:
+ * short task_function_descriptors[32 x 1] : 16bits addresses to PMEM using TASK_INDEX above
+ */
+
+/*
+ * IDs of the micro tasks
+ */
+
+// from ABE_FunctionsId.h
+/*#define id_ copyMultiFrame_TFID
+#define id_ inplaceGain_TFID
+#define id_ mixer_TFID
+#define id_ IIR_TFID
+#define id_ gainConverge_TFID
+#define id_ sinGen_TFID
+#define id_ OSR0Fill_TFID
+#define id_ IOtask_TFID
+
+#define id_mixer
+#define id_eq
+#define id_upsample_src
+#define id_downsample_src
+#define id_asrc
+#define id_gain_update
+#define id_aps_hs
+#define id_aps_ihf
+#define id_dither
+#define id_eanc
+#define id_io
+#define id_router
+#define id_dynamic_dl
+#define id_dynamic_ul
+#define id_sequence_reader
+#define id_ ..
+*/
+
+/*
+ * I/O DESCRIPTORS
+ */
+#define dmem_port_descriptors D_IODescr_ADDR
+
+/* ping_pong_t descriptors table
+ * structure of 8 bytes:
+ * uint16 base_address1
+ * uint16 size1 (16bits address format)
+ * uint16 base_address2
+ * uint16 size2
+ * } ping_pong_t
+ * ping_pong_t dmem_ping_pong_t [8]
+ */
+#define dmem_ping_pong_buffer D_PING_ADDR /* U8 address */
+
+/*
+ * IRQ mask used with ports with IRQ (DMA or host)
+ * uint32 dmem_irq_masks [8]
+ */
+#define dmem_irq_masks D_IRQMask_ADDR
+
+/*
+ * tables of to the 8 FIFO sequences (delayed commands) holding 12bytes tasks in the format
+ * structure {
+ * 1) Down counter delay on 16bits, decremented on each scheduler period
+ * 2) Code on 8 bits for the type of operation to execute : call or data move.
+ * 3) Three 16bits parameters (for data move example example : source/destination/counter)
+ * 4) Three bytes reserved
+ * } seq_fw_task_t
+ *
+ * structure {
+ * uint32 : base address(MSB) + read pointer(LSB)
+ * uint32 : max address (MSB) + write pointer (LSB)
+ * } FIFO_generic;
+ * seq_fw_task_t FIFO_CONTENT [8]; 96 bytes
+ *
+ * FIFO_SEQ dmem_fifo_sequences [8]; all FIFO sequences
+ */
+#define dmem_fifo_sequences D_DCFifo_ADDR
+#define dmem_fifo_sequences_descriptors D_DCFifoDesc_ADDR
+
+/*
+ * IRQ FIFOs
+ *
+ * structure {
+ * uint32 : base address(MSB) + read pointer(LSB)
+ * uint32 : max address (MSB) + write pointer (LSB)
+ * uint32 IRQ_CODES [6];
+ * } dmem_fifo_irq_mcu; 32 bytes
+ * } dmem_fifo_irq_dsp; 32 bytes
+ */
+#define dmem_fifo_irq_mcu_descriptor D_McuIrqFifoDesc_ADDR
+#define dmem_fifo_irq_dsp_descriptor D_DspIrqFifoDesc_ADDR
+#define dmem_fifo_irq_mcu D_McuIrqFifo_ADDR
+#define dmem_fifo_irq_dsp D_DspIrqFifo_ADDR
+
+/*
+ * remote debugger exchange buffer
+ * uint32 dmem_debug_ae2hal [32]
+ * uint32 dmem_debug_hal2ae [32]
+ */
+#define dmem_debug_ae2hal D_DebugAbe2hal_ADDR
+#define dmem_debug_hal2ae D_Debug_hal2abe_ADDR
+
+/*
+ * DMEM address of the ASRC ppm drift parameter for ASRCs (voice and multimedia paths)
+ * uint32 smem_asrc(x)_drift
+ */
+#define dmem_asrc1_drift D_ASRC1drift_ADDR
+#define dmem_asrc2_drift D_ASRC2drift_ADDR
+
+/*
+ * DMEM indexes of the router uplink paths
+ * uint8 dmem_router_index [8]
+ */
+// OC: TBD ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//#define dmem_router_index
+
+/*
+ * analog control circular buffer commands to Phoenix
+ * structure {
+ * uint32 : base address(MSB) + read pointer(LSB)
+ * uint32 : max address (MSB) + write pointer (LSB)
+ * uint32 FIFO_CONTENT [6];
+ * } dmem_commands_to_phoenix; 32 bytes
+ */
+#define dmem_commands_to_phoenix D_Cmd2PhenixFifo_ADDR
+#define dmem_commands_to_phoenix_descriptor D_Cmd2PhenixFifoDesc_ADDR
+
+/*
+ * analog control circular buffer commands from Phoenix (status line)
+ * structure {
+ * uint32 : base address(MSB) + read pointer(LSB)
+ * uint32 : max address (MSB) + write pointer (LSB)
+ * uint32 FIFO_CONTENT [6];
+ * } dmem_commands_to_phoenix; 32 bytes
+ */
+#define dmem_commands_from_phoenix D_StatusFromPhenixFifo_ADDR
+#define dmem_commands_from_phoenix_descriptor D_StatusFromPhenixFifoDesc_ADDR
+
+/*
+ * DEBUG mask
+ * uint16 dmem_debug_trace_mask
+ * each bit of this word enables a type a trace in the debug circular buffer
+ */
+
+// OC: TBD ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//#define dmem_debug_trace_mask
+
+/*
+ * DEBUG circular buffer
+ * structure {
+ * uint32 : base address(MSB) + read pointer(LSB)
+ * uint32 : max address (MSB) + write pointer (LSB)
+ * uint32 FIFO_CONTENT [14]; = TIMESTAMP + CODE
+ * } dmem_debug_trace_buffer; 64 bytes
+ * should be much larger (depends on the DMEM mapping...)
+ */
+#define dmem_debug_trace_buffer
+#define dmem_debug_trace_fifo D_debugFifo_ADDR
+#define dmem_debug_trace_descriptor D_debugFifoDesc_ADDR
+
+/*
+ * Infinite counter incremented on each sheduler periods (~250 us)
+ * uint16 dmem_debug_time_stamp
+ */
+#define dmem_debug_time_stamp D_loopCounter_ADDR
+
+/*
+ * ATC BUFFERS + IO TASKS SMEM buffers
+ */
+#define dmem_dmic D_DMIC_UL_Fifo_ADDR
+#define dmem_dmic_size ((D_DMIC_UL_Fifo_ADDR_END-D_DMIC_UL_Fifo_ADDR+1)/4)
+#define smem_dmic1 DMIC0_96_labelID
+#define smem_dmic2 DMIC1_96_labelID
+#define smem_dmic3 DMIC2_96_labelID
+
+#define dmem_amic D_McPDM_UL_Fifo_ADDR
+#define dmem_amic_size ((D_McPDM_UL_Fifo_ADDR_END-D_McPDM_UL_Fifo_ADDR+1)/4)
+#define smem_amic AMIC_96_labelID
+
+#define dmem_mcpdm D_McPDM_DL_Fifo_ADDR
+#define dmem_mcpdm_size ((D_McPDM_DL_Fifo_ADDR_END-D_McPDM_DL_Fifo_ADDR+1)/4)
+
+#define dmem_bt_vx_dl 0
+#define dmem_bt_vx_dl_size 0
+#define smem_bt_vx_ul 0
+
+#define dmem_bt_vx_ul 0
+#define dmem_bt_vx_ul_size 0
+#define smem_bt_vx_dl 0 /* @@@ TBD IN FIRMWARE */
+
+#define dmem_mm_ul D_MM_UL_FIFO_ADDR
+#define dmem_mm_ul_size ((D_MM_UL_FIFO_ADDR_END-D_MM_UL_FIFO_ADDR+1)/4)
+#define smem_mm_ul 0 /* managed directly by the router */
+
+#define dmem_mm_ul2 D_MM_UL2_FIFO_ADDR
+#define dmem_mm_ul2_size ((D_MM_UL2_FIFO_ADDR_END-D_MM_UL2_FIFO_ADDR+1)/4)
+#define smem_mm_ul2 0 /* managed directly by the router */
+
+#define dmem_mm_dl D_MM_DL_ADDR
+#define dmem_mm_dl_size ((D_MM_DL_ADDR_END-D_MM_DL_ADDR+1)/4)
+//#define smem_mm_dl IO_MM_DL_ASRC_labelID /* ASRC input buffer, size 40 */
+#define smem_mm_dl MM_DL_labelID /* @@@ at OPP 25/50 or without ASRC */
+
+#define dmem_vx_dl D_VX_DL_ADDR
+#define dmem_vx_dl_size ((D_VX_DL_ADDR_END-D_VX_DL_ADDR+1)/4)
+#define smem_vx_dl IO_VX_DL_ASRC_labelID /* ASRC input buffer, size 40 */
+
+#define dmem_vx_ul D_VX_UL_ADDR
+#define dmem_vx_ul_size ((D_VX_UL_ADDR_END-D_VX_UL_ADDR+1)/4)
+#define smem_vx_ul IO_VX_UL_8k_ASRC_labelID
+
+#define dmem_tones_dl D_TONES_DL_ADDR
+#define dmem_tones_dl_size ((D_TONES_DL_ADDR_END-D_TONES_DL_ADDR+1)/4)
+#define smem_tones_dl Tones_labelID
+
+#define dmem_vib_dl D_VIBRA_DL_ADDR
+#define dmem_vib_dl_size ((D_VIBRA_DL_ADDR_END-D_VIBRA_DL_ADDR+1)/4)
+#define smem_vib IO_VIBRA_DL_labelID
+
+#define dmem_mm_ext_out 0
+#define dmem_mm_ext_out_size 0
+#define smem_mm_ext_out 0
+
+/*
+ * INITPTR / INITREG AREA
+ */
+
+/*
+ * POINTER - used for the port descriptor programming
+ * corresponds to 8bits addresses to the INITPTR area
+ *
+ * List from ABE_INITxxx_labels.h
+ */
+#define ptr_ul_rec
+#define ptr_vx_dl
+#define ptr_mm_dl
+#define ptr_mm_ext
+#define ptr_tones
+#define ptr_vibra2
+
+/*
+ * SMEM AREA
+ */
+
+/*
+ * PHOENIX OFFSET in SMEM
+ * used to subtract a DC offset on the headset path (power consumption optimization)
+ */
+
+/* OC: exact usage to be detailled */
+#define smem_phoenix_offset S_PhoenixOffset_ADDR
+
+/*
+ * EQUALIZERS Z AREA
+ * used to reset the filter memory - IIR-8 (max)
+ * int24 stereo smem_equ(x) [8x2 + 1]
+ */
+#define smem_equ1 S_EQU1_data_ADDR
+#define smem_equ2 S_EQU2_data_ADDR
+#define smem_equ3 S_EQU3_data_ADDR
+#define smem_equ4 S_EQU4_data_ADDR
+#define smem_sdt S_SDT_data_ADDR
+
+/*
+ * GAIN SMEM on PORT
+ * int32 smem_G0 [18] : desired gain on the ports
+ * format of G0 = 6 bits left shifted desired gain in linear 24bits format
+ * int24 stereo G0 [18] = G0
+ * int24 stereo GI [18] current value of the gain in the same format of G0
+ * List of smoothed gains :
+ * 6 DMIC 0 1 2 3 4 5
+ * 2 AMIC L R
+ * 4 PORT1/2_RX L R
+ * 2 MM_EXT L R
+ * 2 MM_VX_DL L R
+ * 2 IHF L R
+ * ---------------
+ * 18 = TOTAL
+ */
+#define smem_g0 S_GTarget_ADDR /* [9] 2 gains in 1 SM address */
+#define smem_g1 S_GCurrent_ADDR /* [9] 2 gains in 1 SM address */
+
+/*
+ * COEFFICIENTS AREA
+ */
+
+/*
+ * delay coefficients used in the IIR-1 filters
+ * int24 cmem_gain_delay_iir1[9 x 2] (a, (1-a))
+ *
+ * 3 for 6 DMIC 0 1 2 3 4 5
+ * 1 for 2 AMIC L R
+ * 2 for 4 PORT1/2_RX L R
+ * 1 for 2 MM_EXT L R
+ * 1 for 2 MM_VX_DL L R
+ * 1 for 2 IHF L R
+ */
+
+#define cmem_gain_alpha C_Alpha_ADDR /* [9] */
+#define cmem_gain_1_alpha C_1_Alpha_ADDR
+
+/*
+ * true gain values in the multiplier format (shift +6), left and right
+ * int24 cmem_gains [18]
+ */
+#define cmem_gain_ramp C_GainsWRamp_ADDR /* [18] */
+#define cmem_ramp_1_M_alpha C_1_Alpha_ADDR
+#define cmem_ramp_alpha C_Alpha_ADDR
+
+#define cmem_mixers_offset 30
+#define cmem_mixer_dl1 (cmem_gain_ramp + cmem_mixers_offset + 0)
+#define cmem_mixer_dl2 (cmem_gain_ramp + cmem_mixers_offset + 4)
+#define cmem_mixer_echo (cmem_gain_ramp + cmem_mixers_offset + 8)
+#define cmem_mixer_sdt (cmem_gain_ramp + cmem_mixers_offset + 10)
+#define cmem_mixer_vxrec (cmem_gain_ramp + cmem_mixers_offset + 12)
+#define cmem_mixer_audul (cmem_gain_ramp + cmem_mixers_offset + 16)
+
+/*
+ * DMIC SRC 96->48
+ * the filter is changed depending on the decimatio ratio used (16/25/32/40)
+ * int32 cmem_src2_dmic [6] IIR with 2 coefs in the recursive part and 4 coefs in the direct part
+ */
+#define cmem_src2_dmic
+
+/*
+ * EANC coefficients
+ * structure of :
+ * 20 Q6.26 coef for the FIR
+ * 16 Q6.26 coef for the IIR
+ * 1 Q6.26 coef for Lambda
+ */
+#define cmem_eanc_coef_fir
+#define cmem_eanc_coef_iir
+#define cmem_eanc_coef_lambda
+
+/*
+ * EQUALIZERS - SDT - COEF AREA
+ * int24 cmem_equ(x) [8x2+1]
+ */
+#define cmem_equ1 C_EQU1_data_ADDR
+#define cmem_equ2 C_EQU2_data_ADDR
+#define cmem_equ3 C_EQU3_data_ADDR
+#define cmem_equ4 C_EQU4_data_ADDR
+#define cmem_sdt C_SDT_data_ADDR
+
+/*
+ * APS - COEF AREA
+ * int24 cmem_aps(x) [16]
+ */
+#define cmem_aps1
+#define cmem_aps2
+#define cmem_aps3
+
+/*
+ * DITHER - COEF AREA
+ * int24 cmem_dither(x) [4]
+ */
+#define cmem_dither
+
+/*
+ * PMEM AREA
+ */
+
+#define sub_copy_d2s_1616 COPY_D2S_LR_CFPID /* data move in IO tasks */
+#define sub_copy_d2s COPY_D2S_2_CFPID
+#define sub_copy_d2s_mono COPY_D2S_MONO_CFPID
+#define sub_copy_s2d_left COPY_S1D_MONO_CFPID
+#define sub_copy_s2d_mono COPY_S2D_MONO_CFPID
+#define sub_copy_s2d COPY_S2D_2_CFPID
+
+#define ERR_DEFAULT_DATA_READ sub_copy_d2s
+#define ERR_DEFAULT_DATA_WRITE sub_copy_s2d
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sound/soc/codecs/abe/abe_ini.c b/sound/soc/codecs/abe/abe_ini.c
new file mode 100644
index 000000000000..082b98ca5816
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_ini.c
@@ -0,0 +1,674 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+#include "abe_dat.h" /* data declaration */
+
+/*
+ * initialize the default values for call-backs to subroutines
+ * - FIFO IRQ call-backs for sequenced tasks
+ * - FIFO IRQ call-backs for audio player/recorders (ping-pong protocols)
+ * - Remote debugger interface
+ * - Error monitoring
+ * - Activity Tracing
+ */
+
+/*
+ * ABE_HW_CONFIGURATION
+ *
+ * Parameter :
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_hw_configuration()
+{
+ abe_uint32 atc_reg;
+ abe_port_protocol_t *protocol;
+ abe_data_format_t format;
+
+ /* initializes the ABE ATC descriptors in DMEM - MCPDM_UL */
+ protocol = &(abe_port[PDM_UL_PORT].protocol); format = abe_port[PDM_UL_PORT].format;
+ abe_init_atc(PDM_UL_PORT);
+ abe_init_io_tasks(PDM_UL_PORT, &format, protocol);
+
+ /* initializes the ABE ATC descriptors in DMEM - MCPDM_DL */
+ protocol = &(abe_port[PDM_DL1_PORT].protocol); format = abe_port[PDM_DL1_PORT].format;
+ abe_init_atc(PDM_DL1_PORT);
+ abe_init_io_tasks(PDM_DL1_PORT, &format, protocol);
+
+ /* one DMIC port enabled = all DMICs enabled, since there is a single DMIC path for all DMICs */
+ protocol = &(abe_port[DMIC_PORT1].protocol); format = abe_port[DMIC_PORT1].format;
+ abe_init_atc(DMIC_PORT1);
+ abe_init_io_tasks(DMIC_PORT1, &format, protocol);
+
+ /* enables the DMAreq from AESS AESS_DMAENABLE_SET = 255 */
+ atc_reg = 0xFF;
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x60, &atc_reg, 4);
+
+#if 0
+ /* let the EVENT be configured once the ports are already programmed */
+ /* enables EVENT_GENERATOR_START=6C from McPDM */
+ atc_reg = 0x01;
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x6C, &atc_reg, 4);
+
+ // set McPDM_DL as EVENT_SOURCE_SELECTION
+ event = 0L; // source = DMAreq
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x70, &event, 4);
+
+ event = 2L; // source = MCPDM_DL to AUDIO_ENGINE_SCHEDULER
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x74, &event, 4);
+#endif
+}
+
+/*
+ * ABE_BUILD_SCHEDULER_TABLE
+ *
+ * Parameter :
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_build_scheduler_table()
+{
+ short VirtAudio_aMultiFrame[PROCESSING_SLOTS][TASKS_IN_SLOT];
+ abe_uint16 i, n;
+ abe_uint8 *ptr;
+ char aUplinkMuxing[16];
+ abe_uint32 dFastLoopback;
+
+ for (ptr = (abe_uint8 *)&(VirtAudio_aMultiFrame[0][0]), i=0; i < sizeof(VirtAudio_aMultiFrame); i++)
+ *ptr++ = 0;
+
+ VirtAudio_aMultiFrame[0][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_AMIC;
+ VirtAudio_aMultiFrame[0][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_VX_DL;
+ VirtAudio_aMultiFrame[0][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_VX_DL_8;
+
+ VirtAudio_aMultiFrame[1][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_BP;
+ VirtAudio_aMultiFrame[1][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_0SR;
+ VirtAudio_aMultiFrame[1][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_LP;
+ VirtAudio_aMultiFrame[1][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_DL;
+
+ // VirtAudio_aMultiFrame[2][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_MM_DL;
+ VirtAudio_aMultiFrame[2][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_MM_UL_ROUTING;
+ VirtAudio_aMultiFrame[2][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_MM_UL2_ROUTING;
+ VirtAudio_aMultiFrame[2][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_UL;
+#if 0
+ VirtAudio_aMultiFrame[3][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_TONES_DL;
+#endif
+ VirtAudio_aMultiFrame[3][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VXRECMixer;
+ VirtAudio_aMultiFrame[3][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VXREC_SPLIT;
+ VirtAudio_aMultiFrame[3][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_SideTone;
+
+ VirtAudio_aMultiFrame[4][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1Mixer;
+ VirtAudio_aMultiFrame[4][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2Mixer;
+ VirtAudio_aMultiFrame[4][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_SDTMixer;
+ VirtAudio_aMultiFrame[4][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_UL2;
+
+ VirtAudio_aMultiFrame[5][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EchoMixer;
+ VirtAudio_aMultiFrame[5][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_EQ;
+ VirtAudio_aMultiFrame[5][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_EQ;
+ VirtAudio_aMultiFrame[5][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_GAIN;
+
+ VirtAudio_aMultiFrame[6][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_EQ;
+ VirtAudio_aMultiFrame[6][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_EQ;
+ VirtAudio_aMultiFrame[6][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_GAIN;
+
+ VirtAudio_aMultiFrame[8][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EchoMixer;
+
+ VirtAudio_aMultiFrame[9][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_0SR;
+ VirtAudio_aMultiFrame[9][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_LP;
+ VirtAudio_aMultiFrame[9][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_LP;
+
+ VirtAudio_aMultiFrame[10][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_0SR;
+ VirtAudio_aMultiFrame[10][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_LP;
+ VirtAudio_aMultiFrame[10][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_LP;
+
+ VirtAudio_aMultiFrame[11][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_McPDM_DL;
+
+ VirtAudio_aMultiFrame[12][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_AMIC;
+ VirtAudio_aMultiFrame[12][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_96_48_LP;
+ VirtAudio_aMultiFrame[12][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_96_48_DEC;
+ VirtAudio_aMultiFrame[12][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_EQ;
+
+ VirtAudio_aMultiFrame[13][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_96_48_LP;
+ VirtAudio_aMultiFrame[13][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_96_48_DEC;
+ VirtAudio_aMultiFrame[13][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_EQ;
+ VirtAudio_aMultiFrame[13][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_SPLIT;
+
+ VirtAudio_aMultiFrame[14][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_96_48_LP;
+ VirtAudio_aMultiFrame[14][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_96_48_DEC;
+ VirtAudio_aMultiFrame[14][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_EQ;
+ VirtAudio_aMultiFrame[14][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_SPLIT;
+
+ VirtAudio_aMultiFrame[15][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_96_48_LP;
+ VirtAudio_aMultiFrame[15][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_96_48_DEC;
+ VirtAudio_aMultiFrame[15][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_EQ;
+ VirtAudio_aMultiFrame[15][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_SPLIT;
+
+ VirtAudio_aMultiFrame[16][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_SPLIT;
+ VirtAudio_aMultiFrame[16][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_IIR;
+ VirtAudio_aMultiFrame[16][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_CORE;
+
+ VirtAudio_aMultiFrame[17][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_IIR;
+ VirtAudio_aMultiFrame[17][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_SPLIT;
+ VirtAudio_aMultiFrame[17][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_L_APS_CORE;
+ VirtAudio_aMultiFrame[17][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_R_APS_CORE;
+
+ VirtAudio_aMultiFrame[21][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_ROUTING;
+ VirtAudio_aMultiFrame[21][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ULMixer;
+
+ VirtAudio_aMultiFrame[22][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_LP;
+ VirtAudio_aMultiFrame[22][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_DEC1;
+ VirtAudio_aMultiFrame[22][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_BP;
+
+ VirtAudio_aMultiFrame[23][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_McPDM_DL;
+ VirtAudio_aMultiFrame[23][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_VX_UL_8;
+ VirtAudio_aMultiFrame[23][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_VX_UL;
+ VirtAudio_aMultiFrame[23][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_GAIN_UPDATE;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_multiFrame_ADDR, (abe_uint32*)VirtAudio_aMultiFrame, sizeof(VirtAudio_aMultiFrame));
+
+ /* DMIC Fast Loopback */
+ dFastLoopback = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_DMIC;
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_pNextFastLoopBack_ADDR, (abe_uint32*)&dFastLoopback, sizeof (dFastLoopback));
+
+ /* reset the uplink router */
+ n = D_aUplinkRouting_ADDR_END - D_aUplinkRouting_ADDR + 1;
+ for(i = 0; i < n; i++)
+ aUplinkMuxing[i] = ZERO_labelID;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_aUplinkRouting_ADDR, (abe_uint32 *)aUplinkMuxing, sizeof(aUplinkMuxing));
+}
+
+/*
+ * ABE_INIT_ATC
+ *
+ * Parameter :
+ * prot : protocol being used
+ *
+ * Operations :
+ * load the DMEM ATC/AESS descriptors
+ *
+ * Return value :
+ *
+ */
+void abe_init_atc(abe_port_id id)
+{
+ abe_satcdescriptor_aess desc;
+ abe_uint8 thr, thr1, thr2, iter, data_shift, iter_samples;
+ abe_int32 iterfactor;
+
+ // load default values of the descriptor
+ desc.rdpt = desc.wrpt = desc.irqdest = desc.cberr = desc.desen =0;
+ desc.reserved0 = desc.reserved1 = desc.reserved2 = 0;
+ desc.srcid = desc.destid = desc.badd = desc.iter = desc.cbsize = 0;
+
+
+ switch ((abe_port[id]).protocol.protocol_switch) {
+ case SLIMBUS_PORT_PROT:
+ desc.cbdir = (abe_port[id]).protocol.direction;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_slimbus.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_slimbus.buf_addr1) >> 4;
+ desc.iter = (abe_port[id]).protocol.p.prot_slimbus.iter;
+ desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_slimbus.desc_addr1 >> 3];
+ desc.nw = 1;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_slimbus.desc_addr1, (abe_uint32*)&desc, sizeof(desc));
+
+ desc.badd = (abe_port[id]).protocol.p.prot_slimbus.buf_addr2;
+ desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_slimbus.desc_addr2 >> 3];
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_slimbus.desc_addr2, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ case SERIAL_PORT_PROT:
+ desc.cbdir = (abe_port[id]).protocol.direction;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_serial.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_serial.buf_addr) >> 4;
+ desc.iter = (abe_port[id]).protocol.p.prot_serial.iter;
+ desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_serial.desc_addr >> 3];
+ desc.nw = 1;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_serial.desc_addr, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ case DMIC_PORT_PROT:
+ desc.cbdir = ABE_ATC_DIRECTION_IN;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_dmic.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_dmic.buf_addr) >> 4;
+ desc.iter = DMIC_ITER;
+ desc.srcid = abe_atc_srcid [ABE_ATC_DMIC_DMA_REQ];
+ desc.nw = 1;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_DMIC_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ case MCPDMDL_PORT_PROT:
+ abe_global_mcpdm_control = abe_port[id].protocol.p.prot_mcpdmdl.control; /* Control allowed on McPDM DL */
+ desc.cbdir = ABE_ATC_DIRECTION_OUT;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_mcpdmdl.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_mcpdmdl.buf_addr) >> 4;
+ desc.iter = MCPDM_DL_ITER;
+ desc.destid = abe_atc_dstid [ABE_ATC_MCPDMDL_DMA_REQ];
+ desc.nw = 0;
+ desc.wrpt = desc.iter; /* @@@ pre-load the ATC buffer (?) */
+ desc.desen = 1;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_MCPDMDL_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ case MCPDMUL_PORT_PROT:
+ desc.cbdir = ABE_ATC_DIRECTION_IN;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_mcpdmul.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_mcpdmul.buf_addr) >> 4;
+ desc.iter = MCPDM_UL_ITER;
+ desc.srcid = abe_atc_srcid [ABE_ATC_MCPDMUL_DMA_REQ];
+ desc.wrpt = MCPDM_UL_ITER; /* @@@ pre-load the ATC buffer (Virtio bug) */
+ desc.nw = 1;
+ desc.desen = 1;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_MCPDMUL_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ case PINGPONG_PORT_PROT:
+ /* software protocol, nothing to do on ATC */
+ break;
+ case DMAREQ_PORT_PROT:
+ desc.cbdir = (abe_port[id]).protocol.direction;
+ desc.cbsize = (abe_port[id]).protocol.p.prot_dmareq.buf_size;
+ desc.badd = ((abe_port[id]).protocol.p.prot_dmareq.buf_addr) >> 4;
+ desc.iter = 1; /* CBPr needs ITER=1. this is the eDMA job to do the iterations */
+ desc.nw = 0; /* data is sent on DMAreq, and never before data is prepared */
+
+ thr = (abe_int8) abe_port[id].protocol.p.prot_dmareq.thr_flow;
+ iterfactor = abe_dma_port_iter_factor (&((abe_port[id]).format));
+ data_shift = (abe_uint8)((iterfactor > 1)? 1:0); /* shift = 0 for mono, shift = 1 for stereo - see update of ATC pointers in IOtasks */
+ thr = (abe_uint8)(thr * iterfactor); /* scales the data threshold to the number of words in DMEM per sample */
+ iter = (abe_uint8) abe_dma_port_iteration(&((abe_port[id]).format));
+ iter_samples = (abe_uint8)(iter / iterfactor); /* number of "samples" either mono or stereo */
+
+ /* check is input from ABE point of view */
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN) {
+ /* Firmware compares X+Drift to Thresholds */
+ thr2 = (abe_uint8)(iter - thr);
+ thr1 = (abe_uint8)(iter + thr);
+ desc.wrpt = ((thr1 + thr2) >> 1) + 2;
+ } else {
+ /* thresholds for write access to DMEM */
+ thr2 = 0;
+ thr1 = (abe_uint8)(thr * 2);
+ desc.wrpt = ((thr1 + thr2) >> 1);
+ }
+
+ if (desc.cbdir == ABE_ATC_DIRECTION_OUT)
+ desc.destid = abe_atc_dstid[(abe_port[id]).protocol.p.prot_dmareq.desc_addr >> 3];
+ else
+ desc.srcid = abe_atc_srcid[(abe_port[id]).protocol.p.prot_dmareq.desc_addr >> 3];
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_dmareq.desc_addr, (abe_uint32*)&desc, sizeof(desc));
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ *
+ *ABE_INIT_DMA_T
+ * Parameter :
+ * prot : protocol being used
+ *
+ * Operations :
+ * load the dma_t with physical information from AE memory mapping
+ *
+ * Return value :
+ *
+ */
+void abe_init_dma_t(abe_port_id id, abe_port_protocol_t *prot)
+{
+ abe_dma_t_offset dma;
+ abe_uint32 idx;
+
+ dma.data = 0; /* default dma_t points to address 0000... */
+ dma.iter = 0;
+
+ switch (prot->protocol_switch) {
+ case PINGPONG_PORT_PROT:
+ dma.data = (prot->p).prot_pingpong.buf_addr;
+ dma.iter = (prot->p).prot_pingpong.buf_size;
+ break;
+ case DMAREQ_PORT_PROT:
+ for (idx = 0; idx < 32; idx++) {
+ if (((prot->p).prot_dmareq.dma_data) == (abe_uint32)(1 << idx))
+ break;
+ }
+ dma.data = (CIRCULAR_BUFFER_PERIPHERAL_R__0 + idx*4);
+ dma.iter = (prot->p).prot_dmareq.iter;
+ break;
+ case CIRCULAR_PORT_PROT:
+ dma.data = (prot->p).prot_dmareq.buf_addr;
+ dma.iter = (prot->p).prot_dmareq.iter;
+ break;
+ case SLIMBUS_PORT_PROT:
+ case SERIAL_PORT_PROT:
+ case DMIC_PORT_PROT:
+ case MCPDMDL_PORT_PROT:
+ case MCPDMUL_PORT_PROT:
+ default:
+ break;
+ }
+
+ /* upload the dma type */
+ abe_port [id].dma = dma;
+}
+
+/*
+ * ABE_INIT_IO_TASKS
+ *
+ * Parameter :
+ * prot : protocol being used
+ *
+ * Operations :
+ * load the micro-task parameters doing to DMEM <==> SMEM data moves
+ *
+ * I/O descriptors input parameters :
+ * For Read from DMEM usually THR1/THR2 = X+1/X-1
+ * For Write to DMEM usually THR1/THR2 = 2/0
+ * UP_1/2 =X+1/X-1
+ *
+ * Return value :
+ *
+ */
+void abe_init_io_tasks(abe_port_id id, abe_data_format_t *format, abe_port_protocol_t *prot)
+{
+ ABE_SIODescriptor desc;
+ ABE_SPingPongDescriptor desc_pp;
+ abe_uint32 thr, thr1, thr2, iter, direction, data_shift, iter_samples, up1, up2, smem, copy_func_index;
+ abe_uint32 iterfactor, dmareq_addr, dmareq_field;
+ abe_uint32 atc_desc_address, sio_desc_address, sio_id;
+ short VirtAudio_aMultiFrame[PROCESSING_SLOTS][TASKS_IN_SLOT];
+
+ dmareq_addr = ABE_DUMMY_ADDRESS;
+ dmareq_field = 0;
+ thr = DEFAULT_THR_READ; /* default threshold */
+ atc_desc_address = 0; /* dummy assignment */
+
+ iter = abe_dma_port_iteration(format);
+ iterfactor = abe_dma_port_iter_factor(format);
+ iter_samples = (iter / iterfactor); /* number of "samples" either mono or stereo */
+
+ switch (prot->protocol_switch) {
+ case DMIC_PORT_PROT:
+ atc_desc_address = ABE_ATC_DMIC_DMA_REQ;
+ break;
+ case MCPDMDL_PORT_PROT:
+ atc_desc_address = ABE_ATC_MCPDMDL_DMA_REQ;
+ break;
+ case MCPDMUL_PORT_PROT:
+ atc_desc_address = ABE_ATC_MCPDMUL_DMA_REQ;
+ break;
+ case PINGPONG_PORT_PROT:
+ dmareq_addr = abe_port[id].protocol.p.prot_pingpong.irq_addr;
+ dmareq_field = abe_port[id].protocol.p.prot_pingpong.irq_data;
+ break;
+ case SLIMBUS_PORT_PROT:
+ thr = (abe_int8) abe_port[id].protocol.p.prot_dmareq.thr_flow;
+ atc_desc_address = abe_port[id].protocol.p.prot_dmareq.desc_addr;
+ break;
+ case SERIAL_PORT_PROT: /* McBSP/McASP */
+ thr = (abe_int8) abe_port[id].protocol.p.prot_serial.thr_flow;
+ atc_desc_address = (abe_int16) abe_port[id].protocol.p.prot_serial.desc_addr;
+ break;
+ case DMAREQ_PORT_PROT: /* DMA w/wo CBPr */
+ thr = (abe_int8) abe_port[id].protocol.p.prot_dmareq.thr_flow;
+ dmareq_addr = abe_port[id].protocol.p.prot_dmareq.dma_addr;
+ dmareq_field = abe_port[id].protocol.p.prot_dmareq.dma_data;
+ atc_desc_address = abe_port[id].protocol.p.prot_dmareq.desc_addr;
+ break;
+ default:
+ break;
+ }
+
+ smem = (abe_uint8) abe_port[id].smem_buffer1;
+ copy_func_index = (abe_uint8) abe_dma_port_copy_subroutine_id(format, abe_port[id].protocol.direction);
+
+ /* special situation of the PING_PONG protocol which has its own SIO descriptor format */
+ /*
+ Sequence of operations on ping-pong buffers B0/B1
+
+ ----------------------------------------------------------------- time --------------------------------------------->>>>
+ Host Application is ready to send data from DDR to B0
+ SDMA is initialized from "abe_connect_irq_ping_pong_port" to B0
+
+ ABE HAL init FW to B0
+ send DMAreq to fill B0
+
+ FIRMWARE starts sending B1 data, sends DMAreq v continue with B0, sends DMAreq v continue with B1
+ DMAreq v (direct access from HAL to AESS regs) v (from ABE_FW) v (from ABE_FW)
+ SDMA | fills B0 | fills B1 ... | fills B0 ...
+ */
+
+ if (prot->protocol_switch == PINGPONG_PORT_PROT) {
+ /* clear pong memory
+ * dmem_addr = abe_base_address_pingpong [0];
+ * abe_clear_memory(ABE_DMEM, (dmem_addr << 2), abe_size_pingpong);
+ */
+
+ /* load the IO descriptor */
+ desc_pp.drift_ASRC = 0; /* no drift */
+ desc_pp.drift_io = 0; /* no drift */
+ desc_pp.hw_ctrl_addr = (abe_uint16)dmareq_addr;
+ desc_pp.copy_func_index = (abe_uint8)copy_func_index;
+ desc_pp.smem_addr = (abe_uint8)smem;
+ desc_pp.atc_irq_data = (abe_uint8)dmareq_field; /* DMA req 0 is used for CBPr0 */
+ desc_pp.x_io = (abe_uint8)iter_samples; /* size of block transfer */
+ desc_pp.data_size = (abe_uint8)iterfactor;
+ desc_pp.workbuff_BaseAddr = (abe_uint16)(abe_base_address_pingpong [0]); /* address comunicated in Bytes */
+ desc_pp.workbuff_Samples = (abe_uint16)((abe_size_pingpong/iterfactor) >> 2); /* size comunicated in XIO sample */
+ desc_pp.nextbuff0_BaseAddr = (abe_uint16)(abe_base_address_pingpong [0]);
+ desc_pp.nextbuff0_Samples = (abe_uint16)((abe_size_pingpong/iterfactor) >> 2);
+ desc_pp.nextbuff1_BaseAddr = (abe_uint16)(abe_base_address_pingpong [1]);
+ desc_pp.nextbuff1_Samples = (abe_uint16)((abe_size_pingpong/iterfactor) >> 2);
+ desc_pp.counter = 1;
+
+ /* send a DMA req to fill B0 with N samples
+ * abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, ABE_DMASTATUS_RAW, &(abe_port[id].protocol.p.prot_pingpong.irq_data), 4);
+ */
+ } else {
+ /* shift = 0 for mono, shift = 1 for stereo - see update of ATC pointers in IOtasks */
+ data_shift = (abe_uint8)((iterfactor > 1) ? 1 : 0);
+
+ /* scales the data threshold to the number of words in DMEM per sample */
+ thr = (abe_uint8)(thr * iterfactor);
+
+ /* check is input from ABE point of view */
+ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN) {
+ /* Firmware compares X+Drift to Thresholds */
+ thr2 = (abe_uint8)(iter - thr);
+ thr1 = (abe_uint8)(iter + thr);
+ direction = 0;
+ } else {
+ /* thresholds for write access to DMEM */
+ thr2 = 0;
+ thr1 = (abe_uint8)(thr * 2);
+ direction = 3; /* offset of the write pointer in the ATC descriptor */
+ }
+
+ up1 = (abe_uint8)(iter + thr);
+ up2 = (abe_uint8)(maximum(0, (abe_int8)iter - (abe_int8)thr));
+
+ desc.drift_ASRC = 0; /* no drift */
+ desc.drift_io = 0; /* no drift */
+ desc.hw_ctrl_addr = (abe_uint16)dmareq_addr;
+ desc.copy_func_index = (abe_uint8)copy_func_index;
+ desc.x_io = (abe_uint8)iter_samples; /* size of block transfer */
+ desc.threshold_1 = (abe_uint8)thr1; /* Read DMEM : X+1 Write DMEM : 0 */
+ desc.threshold_2 = (abe_uint8)thr2; /* Read DMEM : X-1 Write DMEM : 2 */
+ desc.update_1 = (abe_uint8)up1; /* X+1 */
+ desc.update_2 = (abe_uint8)up2; /* X-1 */
+ desc.data_size = (abe_uint8)data_shift; /* shift one bit XIO+DRIFT for ATC updates */
+ desc.smem_addr = (abe_uint8)smem;
+ desc.flow_counter = 0;
+ desc.atc_irq_data = (abe_uint8)dmareq_field; /* DMA req 0 is used for CBPr0 */
+ desc.atc_address = (abe_uint8)(atc_desc_address >> 2); /* Address of ABE/ATC descriptor in WORD32 addresses */
+ desc.direction_rw = (abe_uint8)direction; /* 0 for read_ptr 3 for write_ptr */
+ desc.padding16[0] = 0; /* To keep 32bits alignment */
+ desc.padding16[1] = 0;
+ }
+
+ /* @@@ to be corrected in FW 06.xx
+ @@@ Only one IO task will be implemented in the single task list
+ @@@ Or two tasks will be implemented with one being disabled from the IO descriptor's related indication
+ */
+ if (id == MM_DL_PORT) {
+ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, D_multiFrame_ADDR, (abe_uint32*)VirtAudio_aMultiFrame, sizeof(VirtAudio_aMultiFrame));
+
+ if (prot->protocol_switch == PINGPONG_PORT_PROT)
+ VirtAudio_aMultiFrame[1][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_PING_PONG;
+ else
+ VirtAudio_aMultiFrame[1][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_DL;
+
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_multiFrame_ADDR, (abe_uint32*)VirtAudio_aMultiFrame, sizeof(VirtAudio_aMultiFrame));
+ }
+
+ /* @@@ to be corrected in FW 06.xx
+ @@@ PP descriptor for MM_DL will be overlaid with the SIO descriptor for other transfer protocol
+ */
+ if (prot->protocol_switch == PINGPONG_PORT_PROT) {
+ sio_desc_address = D_PingPongDesc_ADDR;
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, sio_desc_address, (abe_uint32*)&desc_pp, sizeof(desc_pp));
+ } else {
+ sio_id = sio_task_index [id];
+ sio_desc_address = dmem_port_descriptors + (sio_id * sizeof(ABE_SIODescriptor));
+ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, sio_desc_address, (abe_uint32*)&desc, sizeof(desc));
+ }
+}
+
+/*
+ * ABE_INIT_DMIC
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_init_dmic(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_INIT_MCPDM
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_init_mcpdm(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_RESET_FEATURE
+ *
+ * Parameter :
+ * x : index of the feature to be initialized
+ *
+ * Operations :
+ * reload the configuration
+ *
+ * Return value :
+ *
+ */
+void abe_reset_one_feature(abe_uint32 x)
+{
+ all_feature[x] = all_feature_init[x]; /* load default fields */
+ /* @@@@ abe_call_subroutine((all_feature[x]).disable_feature, NOPARAMETER, NOPARAMETER, NOPARAMETER, NOPARAMETER); */
+}
+
+/*
+ * ABE_RESET_ALL_FEATURE
+ *
+ * Parameter :
+ * none
+ *
+ * Operations :
+ * load default configuration for all features
+ * struct {
+ * uint16 load_default_data;
+ * uint16 read_parameter;
+ * uint16 write_parameter;
+ * uint16 running_status;
+ * uint16 fw_input_buffer_address;
+ * uint16 fw_output_buffer_address;
+ * uint16 fw_scheduler_slot_position;
+ * uint16 fw_scheduler_subslot_position;
+ * uint16 min_opp;
+ * char name[NBCHARFEATURENAME];
+ * } abe_feature_t;
+ *
+ * Return value :
+ *
+ */
+void abe_reset_all_features(void)
+{
+ abe_uint16 i;
+
+ for (i = 0; i < MAXNBFEATURE; i++)
+ abe_reset_one_feature(i);
+}
+
+/* ABE_RESET_ONE_PORT
+ *
+ * Parameter :
+ * none
+ *
+ * Operations :
+ * load default configuration for one port
+ *
+ * Return value :
+ *
+ */
+void abe_reset_one_port(abe_uint32 x)
+{
+ abe_port[x] = abe_port_init[x];
+
+ /* @@@ stop ATC activity .. */
+}
+
+/*
+ * ABE_RESET_ALL_PORTS
+ *
+ * Parameter :
+ * none
+ *
+ * Operations :
+ * load default configuration for all features
+ *
+ * Return value :
+ *
+ */
+void abe_reset_all_ports(void)
+{
+ abe_uint16 i;
+
+ for (i = 0; i < MAXNBABEPORTS; i++)
+ abe_reset_one_port(i);
+}
diff --git a/sound/soc/codecs/abe/abe_initxxx_labels.h b/sound/soc/codecs/abe/abe_initxxx_labels.h
new file mode 100644
index 000000000000..c378496c085e
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_initxxx_labels.h
@@ -0,0 +1,258 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_INITXXX_LABELS_H_
+#define _ABE_INITXXX_LABELS_H_
+
+#define Voice_8k_UL_labelID 0
+#define Voice_8k_DL_labelID 1
+#define ECHO_REF_8K_labelID 2
+#define Voice_16k_UL_labelID 3
+#define Voice_16k_DL_labelID 4
+#define ECHO_REF_16K_labelID 5
+#define MM_DL_labelID 6
+#define IO_VX_DL_ASRC_labelID 7
+#define IO_VX_UL_8k_ASRC_labelID 8
+#define IO_VX_UL_16k_ASRC_labelID 9
+#define IO_MM_DL_ASRC_labelID 10
+#define IO_VIBRA_DL_labelID 11
+#define ZERO_labelID 12
+#define Z_1_labelID 13
+#define Dummy_AM_labelID 14
+#define Dummy_Regs_labelID 15
+#define Gr_1_labelID 16
+#define Gr_2_labelID 17
+#define Gr_Regs_labelID 18
+#define OSR96_2_labelID 19
+#define UP_DOWN_48_96_labelID 20
+#define EQ_96K_labelID 21
+#define McPDMout_3_labelID 22
+#define DL1_M_labelID 23
+#define DL2_M_labelID 24
+#define MM_UL2_labelID 25
+#define VX_DL_labelID 26
+#define Tones_labelID 27
+#define DL1_M_G_Tones_labelID 28
+#define DL2_M_G_Tones_labelID 29
+#define DL_M_MM_UL2_VX_DL_labelID 30
+#define TC_Regs_labelID 31
+#define Echo_M_labelID 32
+#define Echo_M_G_labelID 33
+#define VX_UL_labelID 34
+#define SDT_F_labelID 35
+#define SDT_F_data_labelID 36
+#define SDT_Coef_labelID 37
+#define SDT_Regs_labelID 38
+#define SDT_M_labelID 39
+#define DL1_labelID 40
+#define SDT_M_G_labelID 41
+#define DMIC1_labelID 42
+#define DMIC1_L_labelID 43
+#define DMIC1_R_labelID 44
+#define DMIC2_labelID 45
+#define DMIC2_L_labelID 46
+#define DMIC2_R_labelID 47
+#define DMIC3_labelID 48
+#define DMIC3_L_labelID 49
+#define DMIC3_R_labelID 50
+#define BT_UL_labelID 51
+#define BT_L_labelID 52
+#define BT_R_labelID 53
+#define AMIC_labelID 54
+#define AMIC_L_labelID 55
+#define AMIC_R_labelID 56
+#define EANC_FBK_labelID 57
+#define EANC_FBK_L_labelID 58
+#define EANC_FBK_R_labelID 59
+#define EchoRef_L_labelID 60
+#define EchoRef_R_labelID 61
+#define MM_DL_L_labelID 62
+#define MM_DL_R_labelID 63
+#define MM_UL_labelID 64
+#define AMIC_96_labelID 65
+#define DMIC0_96_labelID 66
+#define DMIC1_96_labelID 67
+#define DMIC2_96_labelID 68
+#define DMIC_desc_labelID 69
+#define DMIC_eanc_labelID 70
+#define DMIC_Regs_labelID 71
+#define DMIC_Regs2_labelID 72
+#define AMIC_96_F_labelID 73
+#define DMIC0_96_F_labelID 74
+#define DMIC1_96_F_labelID 75
+#define DMIC2_96_F_labelID 76
+#define UL_MIC_48K_labelID 77
+#define DMIC0_dec_labelID 78
+#define AMIC_EQ_data_labelID 79
+#define AMIC_EQ_Coefs_labelID 80
+#define DMIC1_EQ_data_labelID 81
+#define DMIC1_EQ_Coefs_labelID 82
+#define DMIC2_EQ_data_labelID 83
+#define DMIC2_EQ_Coefs_labelID 84
+#define DMIC3_EQ_data_labelID 85
+#define DMIC3_EQ_Coefs_labelID 86
+#define EQ_DL_48K_labelID 87
+#define EQ_48K_labelID 88
+#define SIO_VX_UL_labelID 89
+#define SIO_VX_DL_labelID 90
+#define SIO_TONES_DL_labelID 91
+#define VX_DL_data_labelID 92
+#define UP_DOWN_8_48_labelID 93
+#define SIO_MM_DL_labelID 94
+#define AMIC_desc_labelID 95
+#define AMIC_Regs_labelID 96
+#define McPDM_Out1_labelID 97
+#define McPDM_Out2_labelID 98
+#define McPDM_Out3_labelID 99
+#define McPDM_DL_Out1_labelID 100
+#define McPDM_DL_Regs_labelID 101
+#define VX_UL_MUX_labelID 102
+#define MM_UL2_MUX_labelID 103
+#define MM_UL_MUX_labelID 104
+#define IO_MM_UL_Regs_labelID 105
+#define MM_UL_desc_labelID 106
+#define MM_UL_FIFO_labelID 107
+#define IO_MM_UL2_Regs_labelID 108
+#define MM_UL2_desc_labelID 109
+#define MM_UL2_FIFO_labelID 110
+#define XinASRC_DL_VX_labelID 111
+#define ASRC_DL_VX_Coefs_labelID 112
+#define ASRC_DL_VX_Alpha_labelID 113
+#define ASRC_DL_VX_VarsBeta_labelID 114
+#define ASRC_DL_VX_8k_Regs_labelID 115
+#define XinASRC_UL_VX_labelID 116
+#define ASRC_UL_VX_Coefs_labelID 117
+#define ASRC_UL_VX_Alpha_labelID 118
+#define ASRC_UL_VX_VarsBeta_labelID 119
+#define ASRC_UL_VX_8k_Regs_labelID 120
+#define UL_48_8_DEC_labelID 121
+#define UP_DOWN_16_48_labelID 122
+#define ASRC_DL_VX_16k_Regs_labelID 123
+#define ASRC_UL_VX_16k_Regs_labelID 124
+#define UL_48_16_DEC_labelID 125
+#define XinASRC_DL_MM_labelID 126
+#define ASRC_DL_MM_Coefs_labelID 127
+#define ASRC_DL_MM_Alpha_labelID 128
+#define ASRC_DL_MM_VarsBeta_labelID 129
+#define ASRC_DL_MM_Regs_labelID 130
+#define VX_REC_labelID 131
+#define VXREC_M_G_VX_DL_labelID 132
+#define VXREC_UL_M_Tones_VX_UL_labelID 133
+#define VX_REC_L_labelID 134
+#define VX_REC_R_labelID 135
+#define UL_M_G_VX_DL_labelID 136
+#define DL2_M_L_labelID 137
+#define DL2_M_R_labelID 138
+#define DL1_M_data_labelID 139
+#define DL1_M_Coefs_labelID 140
+#define DL2_M_LR_data_labelID 141
+#define DL2_M_LR_Coefs_labelID 142
+#define VX_DL_8_48_LP_COEFS_labelID 143
+#define VX_DL_8_48_BP_COEFS_labelID 144
+#define VX_DL_8_48_BP_DATA_labelID 145
+#define VX_DL_8_48_LP_DATA_labelID 146
+#define EQ_VX_DL_8K_labelID 147
+#define EQ_VX_DL_48K_labelID 148
+#define EARP_48_96_LP_DATA_labelID 149
+#define EQ_48_96_LP_labelID 150
+#define IHF_48_96_LP_DATA_labelID 151
+#define VX_DL_16_48_HP_COEFS_labelID 152
+#define VX_DL_16_48_LP_COEFS_labelID 153
+#define VX_DL_16_48_HP_DATA_labelID 154
+#define VX_DL_16_48_LP_DATA_labelID 155
+#define EQ_VX_DL_16K_labelID 156
+#define VX_UL_48_8_LP_COEFS_labelID 157
+#define VX_UL_48_8_BP_DATA_labelID 158
+#define VX_UL_48_8_LP_DATA_labelID 159
+#define EQ_VX_UL_8K_labelID 160
+#define EQ_VX_UL_48K_labelID 161
+#define VX_UL_8_TEMP_labelID 162
+#define VX_UL_48_16_LP_COEFS_labelID 163
+#define VX_UL_48_16_HP_DATA_labelID 164
+#define VX_UL_48_16_LP_DATA_labelID 165
+#define EQ_VX_UL_16K_labelID 166
+#define VX_UL_16_TEMP_labelID 167
+#define GTarget_labelID 168
+#define GCurrent_labelID 169
+#define pAPS_iir1_p23_labelID 170
+#define pAPS_iir1_p45_labelID 171
+#define APS_IIR_Regs_labelID 172
+#define pAPS_core_p1_labelID 173
+#define pAPS_core_p23_labelID 174
+#define pAPS_core_p45_labelID 175
+#define pAPS_core_r_labelID 176
+#define XinASRC_ECHO_REF_labelID 177
+#define ASRC_ECHO_REF_Coefs_labelID 178
+#define ASRC_ECHO_REF_Alpha_labelID 179
+#define ASRC_ECHO_REF_VarsBeta_labelID 180
+#define ASRC_ECHO_REF_8k_Regs_labelID 181
+#define ASRC_ECHO_REF_16k_Regs_labelID 182
+#define DL2_APS_IIR_p23_labelID 183
+#define DL2_APS_IIR_p45_labelID 184
+#define DL2_L_APS_CORE_p23_labelID 185
+#define DL2_L_APS_CORE_p45_labelID 186
+#define DL2_R_APS_CORE_p23_labelID 187
+#define DL2_R_APS_CORE_p45_labelID 188
+#define DMIC1_Gain_labelID 189
+#define DMIC2_Gain_labelID 190
+#define DMIC3_Gain_labelID 191
+#define AMIC_Gain_labelID 192
+#define DL1_Gain_labelID 193
+#define DL2_Gain_labelID 194
+#define DEFAULT_Gain_labelID 195
+#define DL1_APS_labelID 196
+#define DL2_L_APS_labelID 197
+#define DL2_R_APS_labelID 198
+#define ECHO_REF_48_16_HP_DATA_labelID 199
+#define ECHO_REF_48_16_LP_DATA_labelID 200
+#define ECHO_REF_48_8_BP_DATA_labelID 201
+#define ECHO_REF_48_8_LP_DATA_labelID 202
+#define ECHO_REF_DEC_labelID 203
+#define pEANC_p0_labelID 204
+#define pEANC_p1_labelID 205
+#define pEANC_p23_labelID 206
+#define pEANC_p45_labelID 207
+#define pEANC_reg1_labelID 208
+#define pEANC_reg2_labelID 209
+#define pEANC_reg3_labelID 210
+#define pEANC_r_labelID 211
+#define DL1_APS_EQ_p23_labelID 212
+#define DL1_APS_EQ_p45_labelID 213
+#define DL2_APS_EQ_p23_labelID 214
+#define DL2_APS_EQ_p45_labelID 215
+#define pDC_EANC_p23_labelID 216
+#define pDC_EANC_r_labelID 217
+#define SIO_VIBRA_DL_labelID 218
+#define pVIBRA1_p0_labelID 219
+#define pVIBRA1_p1_labelID 220
+#define pVIBRA1_p23_labelID 221
+#define pVIBRA1_p45_labelID 222
+#define pVibra1_pR1_labelID 223
+#define pVibra1_pR2_labelID 224
+#define pVibra1_pR3_labelID 225
+#define pVIBRA1_r_labelID 226
+#define pVIBRA2_p0_labelID 227
+#define pVIBRA2_p1_labelID 228
+#define pVIBRA2_p23_labelID 229
+#define pVIBRA2_p45_labelID 230
+#define pCtrl_p67_labelID 231
+#define pVIBRA2_r_labelID 232
+#define VIBRA_labelID 233
+#define PING_labelID 234
+#define PING_Regs_labelID 235
+#define UP_48_96_LP_COEFS_labelID 236
+#define AMIC_96_48_data_labelID 237
+#define DOWN_96_48_Coefs_labelID 238
+#define DOWN_96_48_Regs_labelID 239
+#define DMIC0_96_48_data_labelID 240
+#define DMIC1_96_48_data_labelID 241
+#define DMIC2_96_48_data_labelID 242
+
+#endif /* _ABE_INITXXXX_LABELS_H_ */
diff --git a/sound/soc/codecs/abe/abe_irq.c b/sound/soc/codecs/abe/abe_irq.c
new file mode 100644
index 000000000000..5701401b2923
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_irq.c
@@ -0,0 +1,53 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+/*
+ * initialize the default values for call-backs to subroutines
+ * - FIFO IRQ call-backs for sequenced tasks
+ * - FIFO IRQ call-backs for audio player/recorders (ping-pong protocols)
+ * - Remote debugger interface
+ * - Error monitoring
+ * - Activity Tracing
+ */
+
+/*
+ * ABE_IRQ_PING_PONG
+ *
+ * Parameter :
+ * No parameter
+ *
+ * Operations :
+ * Check for ping-pong subroutines (low-power players)
+ *
+ * Return value :
+ * None.
+ */
+void abe_irq_ping_pong(void)
+{
+ abe_call_subroutine(abe_irq_pingpong_player_id, NOPARAMETER, NOPARAMETER, NOPARAMETER, NOPARAMETER);
+}
+
+/*
+ * ABE_IRQ_CHECK_FOR_SEQUENCES
+ *
+ * Parameter :
+ * No parameter
+ *
+ * Operations :
+ * check the active sequence list
+ *
+ * Return value :
+ * None.
+ */
+void abe_irq_check_for_sequences(void)
+{
+}
diff --git a/sound/soc/codecs/abe/abe_lib.c b/sound/soc/codecs/abe/abe_lib.c
new file mode 100644
index 000000000000..7cf874abf472
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_lib.c
@@ -0,0 +1,703 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+/*
+ * ABE_TRANSLATE_TO_XMEM_FORMAT
+ *
+ * Parameter :
+ * Operations :
+ * translates a floating point data to the cmem/smem/dmem data format
+ * Return value :
+ * None.
+ */
+void abe_translate_to_xmem_format(abe_int32 memory_bank, float fc, abe_uint32 *c)
+{
+#if 0
+ abe_int32 l;
+ abe_float afc;
+
+ l = 0;
+ afc = absolute(fc);
+
+ switch (memory_bank) {
+ case ABE_CMEM:
+ if (afc >= 1.0 && afc < 32.0) {
+ /* ALU post shifter +6 */
+ l = (abe_int32)(fc * (1 << 16));
+ l = (l << 2) + 2;
+ } else if (afc >= 0.5 && afc < 1.0) {
+ /* ALU post shifter +1 */
+ l = (abe_int32)(fc * (1 << 21));
+ l = (l << 2) + 1;
+ } else if (afc >= 0.25 && afc < 0.5) {
+ /* ALU post shifter 0 */
+ l = (abe_int32)(fc * (1 << 22));
+ l = (l << 2) + 0;
+ } else if (afc < 0.25) {
+ /* ALU post shifter -6 */
+ l = (abe_int32)(fc * (1 << 28));
+ l = (l << 2) + 3;
+ }
+ break;
+ case ABE_SMEM:
+ /* Q23 data format */
+ l = (abe_int32)(fc * (1 << 23));
+ break;
+ case ABE_DMEM:
+ /* Q31 data format (1<<31)=0 */
+ l = (abe_int32)(fc * 2* (1 << 30));
+ break;
+ default: /* ABE_PMEM */
+ /* Q31 data format */
+ l = (abe_int32)(2 * fc * 2* (1 << 30));
+ break;
+ }
+
+ *c = l;
+#endif
+}
+
+/*
+ * ABE_TRANSLATE_GAIN_FORMAT
+ *
+ * Parameter :
+ * Operations :
+ * f: original format name for gain or frequency.
+ * 1=linear ABE => decibels
+ * 2=decibels => linear ABE firmware format
+ *
+ * lin = power(2, decibel/602); lin = [0.0001 .. 30.0]
+ * decibel = 6.02 * log2(lin), decibel = [-70 .. +30]
+ *
+ * g1: pointer to the original data
+ * g2: pointer to the translated gain data
+ *
+ * Return value :
+ * None.
+ */
+void abe_translate_gain_format(abe_uint32 f, abe_float g1, abe_float *g2)
+{
+#if 0
+ abe_float g, frac_part, gg1, gg2;
+ abe_int32 int_part, i;
+
+ #define C_20LOG2 ((abe_float)6.020599913)
+
+ gg1 = (g1);
+ int_part = 0;
+ frac_part = gg2 = 0;
+
+ switch (f) {
+ case DECIBELS_TO_LINABE:
+ g = gg1 / C_20LOG2;
+ int_part = (abe_int32) g;
+ frac_part = g - int_part;
+
+ gg2 = abe_power_of_two(frac_part);
+
+ if (int_part > 0)
+ gg2 = gg2 * (1 << int_part);
+ else
+ gg2 = gg2 / (1 << (-int_part));
+
+ break;
+ case LINABE_TO_DECIBELS:
+ if (gg1 == 1.0) {
+ gg2 = 0.0;
+ return;
+ }
+
+ /* find the power of 2 by iteration */
+ if (gg1 > 1.0) {
+ for (i = 0; i < 63; i++) {
+ if ((1 << i) > gg1) {
+ int_part = (i-1);
+ frac_part = gg1 / (1 << int_part);
+ break;
+ }
+ }
+ gg2 = C_20LOG2 * (int_part + abe_log_of_two(frac_part));
+ } else {
+ for (i = 0; i < 63; i++) {
+ if (((1 << i) * gg1) > 1) {
+ int_part = i;
+ frac_part = gg1 * (1 << int_part);
+ break;
+ }
+ }
+ /* compute the dB using polynomial
+ * interpolation in the [1..2] range
+ */
+ gg2 = C_20LOG2 * (((-1)*int_part) + abe_log_of_two(frac_part));}
+ break;
+ }
+
+ *g2 = gg2;
+#endif
+ }
+
+/*
+ * ABE_TRANSLATE_RAMP_FORMAT
+ *
+ * Parameter :
+ * Operations :
+ * f: original format name for gain or frequency.
+ * 1=ABE IIR coef => microseconds
+ * 2=microseconds => ABE IIR coef
+ *
+ * g1: pointer to the original data
+ * g2: pointer to the translated gain data
+ *
+ * Return value :
+ * None.
+ */
+void abe_translate_ramp_format(abe_float ramp, abe_float *ramp_iir1)
+{
+ *ramp_iir1 = 0.125;
+}
+
+/*
+ * ABE_TRANSLATE_EQU_FORMAT
+ *
+ * Parameter :
+ * Operations :
+ * Translate
+ *
+ * Return value :
+ * None.
+ */
+void abe_translate_equ_format(abe_equ_t *p, abe_float *iir, abe_uint32 n)
+{
+#if 0
+ switch (p->type
+typedef struct {
+ abe_iir_t equ_param1; /* type of filter */
+ abe_uint32 equ_param2; /* filter length */
+ union { /* parameters are the direct and recursive coefficients in */
+ abe_int32 type1 [NBEQ1]; /* Q6.26 integer fixed-point format. */
+ struct {
+ abe_int32 freq [NBEQ2]; /* parameters are the frequency (type "freq") and Q factors */
+ abe_int32 gain [NBEQ2]; /* (type "gain") of each band. */
+ } type2;
+ } coef;
+ abe_int32 equ_param3;
+ } abe_equ_t;
+
+ Fs = 48000;
+ f0 = 19000;
+ Q = sqrt(0.5)
+ dBgain = -40
+
+
+ A = sqrt (power (10, dBgain/20));
+ w0 = 2*pi*f0/Fs
+ alpha = sin(w0) / (2*Q);
+
+ %PeakingEQ ==========================================
+ b_peak = print_ABE_data ([1+alpha*A -2*cos(w0) 1-alpha*A],3);
+ a_peak = print_ABE_data ([1+alpha/A -2*cos(w0) 1-alpha/A],3);
+
+#endif
+}
+
+/*
+ * ABE_FPRINTF
+ *
+ * Parameter :
+ * character line to be printed
+ *
+ * Operations :
+ *
+ * Return value :
+ * None.
+ */
+void abe_fprintf(char *line)
+{
+ switch (abe_dbg_output) {
+ case NO_OUTPUT:
+ break;
+ case TERMINAL_OUTPUT:
+ break;
+ case LINE_OUTPUT:
+ break;
+ case DEBUG_TRACE_OUTPUT:
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * ABE_READ_FEATURE_FROM_PORT
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_read_feature_from_port(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_WRITE_FEATURE_TO_PORT
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_write_feature_to_port(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_READ_FIFO
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_read_fifo(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_WRITE_FIFO
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_write_fifo(abe_uint32 x)
+{
+}
+
+/*
+ * ABE_CLEAR_MEMORY
+ *
+ * Parameter :
+ * memory bank among PMEM, DMEM, CMEM, SMEM, ATC/IO
+ * address of the memory copy (byte addressing)
+ * number of data to move
+ *
+ * Operations :
+ * memory area clear
+ *
+ * Return value :
+ * none
+ */
+void abe_clear_memory(abe_int32 memory_bank, abe_int32 address, abe_uint32 nb_bytes)
+{
+ abe_uint32 i, data = 0;
+
+#if PC_SIMULATION
+ nb_bytes = (nb_bytes + 3) & (-4L); /* copy is done on 32bits boundaries */
+ if (address & (3L)) /* error ifstart address is not 32bits aligned */
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+
+ for (i = 0; i < (nb_bytes >> 2); i++, address += 4) {
+ switch (memory_bank) {
+ case ABE_PMEM:
+ target_server_write_pmem(address, &data, nb_bytes);
+ break;
+ case ABE_CMEM:
+ target_server_write_cmem(address, &data, nb_bytes);
+ break;
+ case ABE_SMEM:
+ target_server_write_smem(address, &data, nb_bytes);
+ break;
+ case ABE_DMEM:
+ target_server_write_dmem(address, &data, nb_bytes);
+ break;
+ case ABE_ATC:
+ target_server_write_atc(address/4, &data, nb_bytes);
+ break;
+ }
+ }
+#else
+ abe_uint32 base_address = 0, *dst_ptr, *src_ptr;
+
+ nb_bytes = (nb_bytes + 3) & (-4L); /* copy is done on 32bits boundaries */
+ if (address & (3L)) /* error ifstart address is not 32bits aligned */
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+
+ switch (memory_bank) {
+ case ABE_PMEM:
+ base_address = (abe_uint32) ABE_PMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_CMEM:
+ base_address = (abe_uint32) ABE_CMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_SMEM:
+ base_address = (abe_uint32) ABE_SMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_DMEM:
+ base_address = (abe_uint32) ABE_DMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_ATC:
+ base_address = (abe_uint32) ABE_ATC_BASE_ADDRESS_MPU;
+ break;
+ default:
+ base_address = (abe_uint32) ABE_SMEM_BASE_ADDRESS_MPU;
+ abe_dbg_param |= ERR_LIB;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ break;
+ }
+
+ dst_ptr = (abe_uint32 *)(base_address + address);
+ src_ptr = (abe_uint32 *)data;
+
+ for (i = 0; i < (nb_bytes >> 2); i++)
+ *dst_ptr++ = data;
+#endif
+}
+
+/*
+ * ABE_BLOCK_COPY
+ *
+ * Parameter :
+ * direction of the data move (Read/Write)
+ * memory bank among PMEM, DMEM, CMEM, SMEM, ATC/IO
+ * address of the memory copy (byte addressing)
+ * long pointer to the data
+ * number of data to move
+ *
+ * Operations :
+ * block data move
+ *
+ * Return value :
+ * none
+ */
+void abe_block_copy(abe_int32 direction, abe_int32 memory_bank, abe_int32 address, abe_uint32 *data, abe_uint32 nb_bytes)
+{
+#if PC_SIMULATION
+ nb_bytes = (nb_bytes + 3) & (-4L); /* copy is done on 32bits boundaries */
+ if (address & (3L)) /* error ifstart address is not 32bits aligned */
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+
+ if (direction == COPY_FROM_HOST_TO_ABE) {
+ switch (memory_bank) {
+ case ABE_PMEM:
+ target_server_write_pmem(address, data, nb_bytes);
+ break;
+ case ABE_CMEM:
+ target_server_write_cmem(address, data, nb_bytes);
+ break;
+ case ABE_SMEM:
+ target_server_write_smem(address, data, nb_bytes);
+ break;
+ case ABE_DMEM:
+ target_server_write_dmem(address, data, nb_bytes);
+ break;
+ case ABE_ATC:
+ target_server_write_atc(address / 4, data, nb_bytes);
+ break;
+ default:
+ abe_dbg_param |= ERR_LIB;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ break;
+ }
+ } else {
+ switch (memory_bank) {
+ case ABE_PMEM:
+ target_server_read_pmem(address, data, nb_bytes);
+ break;
+ case ABE_CMEM:
+ target_server_read_cmem(address, data, nb_bytes);
+ break;
+ case ABE_SMEM:
+ target_server_read_smem(address, data, nb_bytes);
+ break;
+ case ABE_DMEM:
+ target_server_read_dmem(address, data, nb_bytes);
+ break;
+ case ABE_ATC:
+ target_server_read_atc(address/4, data, nb_bytes);
+ break;
+ default:
+ abe_dbg_param |= ERR_LIB;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ break;
+ }
+ }
+#else
+ abe_uint32 i;
+ abe_uint32 base_address = 0, *src_ptr, *dst_ptr, n;
+
+ nb_bytes = (nb_bytes + 3) & (-4L); /* copy is done on 32bits boundaries */
+ if (address & (3L)) /* error ifstart address is not 32bits aligned */
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+
+ switch (memory_bank) {
+ case ABE_PMEM:
+ base_address = (abe_uint32) ABE_PMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_CMEM:
+ base_address = (abe_uint32) ABE_CMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_SMEM:
+ base_address = (abe_uint32) ABE_SMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_DMEM:
+ base_address = (abe_uint32) ABE_DMEM_BASE_ADDRESS_MPU;
+ break;
+ case ABE_ATC:
+ base_address = (abe_uint32) ABE_ATC_BASE_ADDRESS_MPU;
+ break;
+ default:
+ base_address = (abe_uint32) ABE_SMEM_BASE_ADDRESS_MPU;
+ abe_dbg_param |= ERR_LIB;
+ abe_dbg_error_log(ABE_BLOCK_COPY_ERR);
+ break;
+ }
+
+ if (direction == COPY_FROM_HOST_TO_ABE) {
+ dst_ptr = (abe_uint32 *)(base_address + address);
+ src_ptr = (abe_uint32 *)data;
+ } else {
+ dst_ptr = (abe_uint32 *)data;
+ src_ptr = (abe_uint32 *)(base_address + address);
+ }
+
+ n = (nb_bytes/4);
+
+ for (i = 0; i < n; i++)
+ *dst_ptr++ = *src_ptr++;
+
+#endif
+}
+
+/*
+ * ABE_MONITORING
+ *
+ * Parameter :
+ *
+ * Operations :
+ * checks the internal status of ABE and HAL
+ *
+ * Return value :
+ * Call Backs on Errors
+ */
+void abe_monitoring(void)
+{
+ abe_dbg_param = 0;
+}
+
+/*
+ * ABE_FORMAT_SWITCH
+ *
+ * Parameter :
+ *
+ * Operations :
+ * translates the sampling and data length to ITER number for the DMA
+ * and the multiplier factor to apply during data move with DMEM
+ *
+ * Return value :
+ * Call Backs on Errors
+ */
+void abe_format_switch(abe_data_format_t *f, abe_uint32 *iter, abe_uint32 *mulfac)
+{
+ abe_uint32 n_freq, n_samp;
+
+ /* scheduler loop ratio : 12 samples at 48kHz */
+ n_freq = (f->f) / FW_SCHED_LOOP_FREQ;
+
+ switch (f->samp_format) {
+ case MONO_16_LSB:
+ *mulfac = 1;
+ n_samp = 2;
+ break;
+ case MONO_MSB:
+ *mulfac = 1;
+ n_samp = 2;
+ break;
+ case TWO_MONO_MSB:
+ *mulfac = 1;
+ n_samp = 1;
+ break;
+ case STEREO_16_16:
+ *mulfac = 1;
+ n_samp = 2;
+ break;
+ case STEREO_MSB:
+ *mulfac = 2;
+ n_samp = 4;
+ break;
+ case THREE_MSB:
+ *mulfac = 3;
+ n_samp = 6;
+ break;
+ case FOUR_MSB:
+ *mulfac = 4;
+ n_samp = 8;
+ break;
+ case FIVE_MSB:
+ *mulfac = 5;
+ n_samp = 10;
+ break;
+ case SIX_MSB:
+ *mulfac = 6;
+ n_samp = 12;
+ break;
+ case SEVEN_MSB:
+ *mulfac = 7;
+ n_samp = 14;
+ break;
+ case EIGHT_MSB:
+ *mulfac = 8;
+ n_samp = 16;
+ break;
+ case NINE_MSB:
+ *mulfac = 9;
+ n_samp = 16;
+ break;
+ case TEN_MSB:
+ *mulfac = 10;
+ n_samp = 16;
+ break;
+ default:
+ *mulfac = 1;
+ n_samp = 2;
+ break;
+ }
+
+ *iter = (n_freq * n_samp) / 2;
+}
+
+/*
+ * ABE_DMA_PORT_ITERATION
+ *
+ * Parameter :
+ *
+ * Operations :
+ * translates the sampling and data length to ITER number for the DMA
+ *
+ * Return value :
+ * Call Backs on Errors
+ */
+abe_uint32 abe_dma_port_iteration(abe_data_format_t *f)
+{
+ abe_uint32 iter, mulfac;
+
+ abe_format_switch(f, &iter, &mulfac);
+
+ return iter;
+}
+
+/*
+ * ABE_DMA_PORT_ITER_FACTOR
+ *
+ * Parameter :
+ *
+ * Operations :
+ * returns the multiplier factor to apply during data move with DMEM
+ *
+ * Return value :
+ * Call Backs on Errors
+ */
+abe_uint32 abe_dma_port_iter_factor(abe_data_format_t *f)
+{
+ abe_uint32 iter, mulfac;
+
+ abe_format_switch(f, &iter, &mulfac);
+
+ return mulfac;
+}
+
+/*
+ * ABE_DMA_PORT_COPY_SUBROUTINE_ID
+ *
+ * Parameter :
+ *
+ * Operations :
+ * returns the index of the function doing the copy in I/O tasks
+ *
+ * Return value :
+ * Call Backs on Errors
+ */
+abe_uint32 abe_dma_port_copy_subroutine_id(abe_data_format_t *f, abe_uint32 direction)
+{
+ abe_uint32 id;
+
+ if (direction == ABE_ATC_DIRECTION_IN) {
+ switch (f->samp_format) {
+ case THREE_MSB:
+ case FOUR_MSB:
+ case FIVE_MSB:
+ case SIX_MSB:
+ case SEVEN_MSB:
+ case EIGHT_MSB:
+ case NINE_MSB:
+ case TEN_MSB:
+ case TWO_MONO_MSB: /* non-supported data format */
+ case MONO_16_LSB:
+ id = ERR_DEFAULT_DATA_READ;
+ break;
+ case MONO_MSB:
+ id = sub_copy_d2s_mono;
+ break;
+ case STEREO_16_16:
+ id = sub_copy_d2s_1616;
+ break;
+ case STEREO_MSB:
+ default:
+ id = sub_copy_d2s;
+ break;
+ }
+ } else {
+ switch (f->samp_format) {
+ case THREE_MSB: /* formats directly managed in MM_UL2 router */
+ case FOUR_MSB:
+ case FIVE_MSB:
+ case SIX_MSB:
+ case SEVEN_MSB:
+ case EIGHT_MSB:
+ case NINE_MSB:
+ case TEN_MSB:
+ case TWO_MONO_MSB: /* non-supported data format */
+ case STEREO_16_16:
+ case MONO_16_LSB:
+ id = ERR_DEFAULT_DATA_WRITE;
+ break;
+ case MONO_MSB:
+ id = sub_copy_s2d_mono;
+ break;
+ id = ERR_DEFAULT_DATA_WRITE;
+ break;
+ case STEREO_MSB:
+ default:
+ id = sub_copy_s2d;
+ break;
+ }
+ }
+
+ return id;
+}
diff --git a/sound/soc/codecs/abe/abe_lib.h b/sound/soc/codecs/abe/abe_lib.h
new file mode 100644
index 000000000000..cc867aa0d1d5
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_lib.h
@@ -0,0 +1,108 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void abe_translate_gain_format(abe_uint32 f, abe_float g1, abe_float *g2);
+void abe_translate_ramp_format(abe_float g1, abe_float *g2);
+void abe_clear_memory(abe_int32 memory_bank, abe_int32 address, abe_uint32 nb_bytes);
+
+/*
+ * ABE_FPRINTF
+ *
+ * Parameter :
+ * character line to be printed
+ *
+ * Operations :
+ *
+ * Return value :
+ * None.
+ */
+void abe_fprintf(char *line);
+
+/*
+ * ABE_READ_FEATURE_FROM_PORT
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_read_feature_from_port(abe_uint32 x);
+
+/*
+ * ABE_WRITE_FEATURE_TO_PORT
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_write_feature_to_port(abe_uint32 x);
+
+/*
+ * ABE_READ_FIFO
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_read_fifo(abe_uint32 x);
+
+/*
+ * ABE_WRITE_FIFO
+ *
+ * Parameter :
+ * x : d
+ *
+ * Operations :
+ *
+ *
+ * Return value :
+ *
+ */
+void abe_write_fifo(abe_uint32 x);
+
+/*
+ * ABE_BLOCK_COPY
+ *
+ * Parameter :
+ * direction of the data move (Read/Write)
+ * memory bank among PMEM, DMEM, CMEM, SMEM, ATC/IO
+ * address of the memory copy (byte addressing)
+ * long pointer to the data
+ * number of data to move
+ *
+ * Operations :
+ * block data move
+ *
+ * Return value :
+ * none
+ */
+void abe_block_copy(abe_int32 direction, abe_int32 memory_bank, abe_int32 address, abe_uint32 *data, abe_uint32 nb);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/sound/soc/codecs/abe/abe_main.c b/sound/soc/codecs/abe/abe_main.c
new file mode 100644
index 000000000000..d4b5e4e39cdc
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_main.c
@@ -0,0 +1,95 @@
+/* =============================================================================
+* Texas Instruments OMAP(TM) Platform Software
+* (c) Copyright 2009 Texas Instruments Incorporated. All Rights Reserved.
+*
+* Use of this software is controlled by the terms and conditions found
+* in the license agreement under which this software has been supplied.
+* =========================================================================== */
+/**
+ * @file ABE_MAIN.C
+ *
+ * 'ABEMAIN.C' dummy main of the HAL
+ *
+ * @path
+ * @rev 01.00
+ */
+/* ----------------------------------------------------------------------------
+*!
+*! Revision History
+*! ===================================
+*! 27-Nov-2008 Original (LLF)
+*! 05-Jun-2009 V05 release
+* =========================================================================== */
+
+
+#if !PC_SIMULATION
+
+
+#include "abe_main.h"
+#include "abe_test.h"
+
+void main (void)
+{
+
+ abe_dma_t dma_sink, dma_source;
+ abe_data_format_t format;
+ abe_uint32 base_address;
+
+ abe_reset_hal ();
+ abe_auto_check_data_format_translation ();
+ abe_check_opp ();
+ abe_check_dma ();
+
+ /*
+ To be added here :
+ Device driver initialization:
+ McPDM_DL : threshold=1, 6 slots activated
+ DMIC : threshold=1, 6 microphones activated
+ McPDM_UL : threshold=1, two microphones activated
+ */
+
+
+ /* MM_DL INIT
+ connect a DMA channel to MM_DL port (ATC FIFO)
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ abe_connect_cbpr_dmareq_port (MM_DL_PORT, &format, ABE_CBPR0_IDX, &dma_sink);
+
+
+ connect a Ping-Pong SDMA protocol to MM_DL port with Ping-Pong 576 stereo samples
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ abe_connect_dmareq_ping_pong_port (MM_DL_PORT, &format, ABE_CBPR0_IDX, (576 * 4), &dma_sink);
+
+
+ connect a Ping-Pong cache-flush protocol to MM_DL port with 50Hz (20ms) rate
+ */
+ abe_add_subroutine (&abe_irq_pingpong_player_id, (abe_subroutine2) abe_default_irq_pingpong_player, SUB_0_PARAM);
+ format.f = 48000; format.samp_format = STEREO_MSB;
+ #define N_SAMPLES ((int)(48000 * 0.020)) /* ping-pong access to MM_DL at 48kHz Mono with 20ms packet sizes */
+ abe_connect_irq_ping_pong_port (MM_DL_PORT, &format, abe_irq_pingpong_player_id, N_SAMPLES, &base_address);
+
+
+
+ /* VX_DL INIT
+ connect a DMA channel to VX_DL port (ATC FIFO)
+ */
+ format.f = 8000; format.samp_format = MONO_MSB;
+ abe_connect_cbpr_dmareq_port (VX_DL_PORT, &format, ABE_CBPR1_IDX, &dma_sink);
+
+ /* VX_UL INIT
+ connect a DMA channel to VX_UL port (ATC FIFO)
+ */
+ format.f = 8000; format.samp_format = MONO_MSB;
+ abe_connect_cbpr_dmareq_port (VX_UL_PORT, &format, ABE_CBPR2_IDX, &dma_source);
+
+ /* make the AE waking event to be the McPDM DMA requests */
+ abe_write_event_generator (EVENT_MCPDM);
+
+ abe_enable_data_transfer (MM_DL_PORT );
+ abe_enable_data_transfer (VX_DL_PORT );
+ abe_enable_data_transfer (VX_UL_PORT );
+ abe_enable_data_transfer (PDM_UL_PORT);
+ abe_enable_data_transfer (PDM_DL1_PORT);
+
+}
+
+#endif
diff --git a/sound/soc/codecs/abe/abe_main.h b/sound/soc/codecs/abe/abe_main.h
new file mode 100644
index 000000000000..b9f5dcabf137
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_main.h
@@ -0,0 +1,53 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_MAIN_H_
+#define _ABE_MAIN_H_
+
+#include "abe_def.h"
+#include "abe_typ.h"
+#include "abe_dbg.h"
+#include "abe_ext.h"
+#include "abe_lib.h"
+#include "abe_ref.h"
+#include "abe_api.h"
+//#include "ABE_DAT.h"
+
+#include "abe_typedef.h"
+#include "abe_functionsId.h"
+#include "abe_taskId.h"
+#include "abe_dm_addr.h"
+#include "abe_sm_addr.h"
+#include "abe_cm_addr.h"
+#include "abe_initxxx_labels.h"
+
+#include "abe_fw.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ABE_HAL_VERSION 0x00000002L
+#define ABE_FW_VERSION 0x00000000L
+#define ABE_HW_VERSION 0x00000000L
+
+#define HAL_TIME_STAMP 0 /* generates the time-stamps used for the AESS verification */
+
+#define ABE_DEBUG_CHECKERS 0 /* pipe connection to the TARGET simulator */
+#define ABE_DEBUG_HWFILE 0 /* simulator data extracted from a text-file */
+#define ABE_DEBUG_LL_LOG 0 /* low-level log files */
+
+#define ABE_DEBUG (ABE_DEBUG_CHECKERS | ABE_DEBUG_HWFILE | ABE_DEBUG_LL_LOG)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_MAIN_H_ */
diff --git a/sound/soc/codecs/abe/abe_ref.h b/sound/soc/codecs/abe/abe_ref.h
new file mode 100644
index 000000000000..73bff4dc23a1
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_ref.h
@@ -0,0 +1,108 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_REF_H_
+#define _ABE_REF_H_
+
+/*
+ * 'ABE_PRO.H' all non-API prototypes for INI, IRQ, SEQ ...
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * HAL EXTERNAL API
+ */
+
+/*
+ * HAL INTERNAL API
+ */
+
+void abe_build_scheduler_table(void);
+void abe_reset_one_feature(abe_uint32 x);
+void abe_reset_all_features(void);
+void abe_reset_one_port(abe_uint32 x);
+void abe_reset_all_ports(void);
+void abe_reset_all_fifo(void);
+void abe_reset_all_sequence(void);
+abe_uint32 abe_dma_port_iteration(abe_data_format_t *format);
+void abe_read_global_counter(abe_time_stamp_t *t, abe_millis_t *m);
+void abe_read_sys_clock(abe_micros_t *time);
+void abe_init_atc(abe_port_id id);
+void abe_init_io_tasks(abe_port_id id, abe_data_format_t *format, abe_port_protocol_t *prot);
+void abe_init_dma_t(abe_port_id id, abe_port_protocol_t *prot);
+abe_uint32 abe_dma_port_iter_factor(abe_data_format_t *f);
+abe_uint32 abe_dma_port_copy_subroutine_id(abe_data_format_t *format, abe_uint32 direction);
+void abe_call_subroutine(abe_uint32 idx, abe_uint32 p1, abe_uint32 p2, abe_uint32 p3, abe_uint32 p4);
+void abe_monitoring(void);
+void abe_lock_execution(void);
+void abe_unlock_execution(void);
+void abe_hw_configuration(void);
+void abe_add_subroutine(abe_uint32 *id, abe_subroutine2 f, abe_uint32 n);
+void abe_read_next_ping_pong_buffer(abe_port_id port, abe_uint32 *p, abe_uint32 *n);
+void abe_irq_ping_pong(void);
+void abe_irq_check_for_sequences(void);
+void abe_default_irq_pingpong_player(void);
+void abe_translate_to_xmem_format(abe_int32 memory_bank, float fc, abe_uint32 *c);
+void abe_read_hardware_configuration(abe_use_case_id *u, abe_opp_t *o, abe_hw_config_init_t *hw);
+
+/*
+ * HAL INTERNAL DATA
+ */
+
+extern abe_port_t abe_port[];
+extern abe_feature_t feature[];
+extern abe_subroutine2 callbacks[];
+
+extern abe_port_t abe_port[];
+extern const abe_port_t abe_port_init[];
+
+extern abe_feature_t all_feature[];
+extern const abe_feature_t all_feature_init[];
+
+extern abe_seq_t all_sequence[];
+extern const abe_seq_t all_sequence_init[];
+
+extern const abe_router_t abe_router_ul_table_preset[NBROUTE_CONFIG][NBROUTE_UL];
+extern abe_router_t abe_router_ul_table[NBROUTE_CONFIG_MAX][NBROUTE_UL];
+
+extern abe_uint32 abe_dbg_output;
+extern abe_uint32 abe_dbg_mask;
+extern abe_uint32 abe_dbg_activity_log[DBG_LOG_SIZE];
+extern abe_uint32 abe_dbg_activity_log_write_pointer;
+extern abe_uint32 abe_dbg_param;
+
+extern abe_uint32 abe_global_mcpdm_control;
+extern abe_event_id abe_current_event_id;
+
+extern const abe_sequence_t seq_null;
+extern abe_subroutine2 abe_all_subsubroutine[MAXNBSUBROUTINE]; /* table of new subroutines called in the sequence */
+extern abe_uint32 abe_all_subsubroutine_nparam[MAXNBSUBROUTINE]; /* number of parameters per calls */
+extern abe_uint32 abe_subroutine_id[MAXNBSUBROUTINE];
+extern abe_uint32 abe_subroutine_write_pointer;
+extern abe_sequence_t abe_all_sequence[MAXNBSEQUENCE]; /* table of all sequences */
+extern abe_uint32 abe_sequence_write_pointer;
+extern abe_uint32 abe_nb_pending_sequences; /* current number of pending sequences (avoids to look in the table) */
+extern abe_uint32 abe_pending_sequences[MAXNBSEQUENCE]; /* pending sequences due to ressource collision */
+extern abe_uint32 abe_global_sequence_mask; /* mask of unsharable ressources among other sequences */
+extern abe_seq_t abe_active_sequence[MAXACTIVESEQUENCE][MAXSEQUENCESTEPS]; /* table of active sequences */
+extern abe_uint32 abe_irq_pingpong_player_id; /* index of the plugged subroutine doing ping-pong cache-flush DMEM accesses */
+extern abe_uint32 abe_base_address_pingpong[MAX_PINGPONG_BUFFERS]; /* base addresses of the ping pong buffers */
+extern abe_uint32 abe_size_pingpong; /* size of each ping/pong buffers */
+extern abe_uint32 abe_nb_pingpong; /* number of ping/pong buffer being used */
+
+extern const abe_uint32 sio_task_index[LAST_PORT_ID];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_REF_H_ */
diff --git a/sound/soc/codecs/abe/abe_seq.c b/sound/soc/codecs/abe/abe_seq.c
new file mode 100644
index 000000000000..ec2a57d501e1
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_seq.c
@@ -0,0 +1,248 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#include "abe_main.h"
+
+/*
+ * SEQUENCES
+ * struct {
+ * micros_t time; Waiting time before executing next line
+ * seq_code_t code Subroutine index interpreted in the HAL and translated to
+ * FW subroutine codes in case of ABE tasks
+ * int32 param[2] Two parameters
+ * char param_tag[2] Flags used for parameters when launching the sequences
+ * } seq_t
+ *
+ */
+
+/*
+ * ABE_NULL_SUBROUTINE
+ *
+ * Operations : nothing
+ */
+void abe_null_subroutine_0(void) { }
+void abe_null_subroutine_2(abe_uint32 a, abe_uint32 b) { }
+void abe_null_subroutine_4(abe_uint32 a, abe_uint32 b, abe_uint32 c, abe_uint32 d) { }
+
+/*
+ * ABE_INIT_SUBROUTINE_TABLE
+ *
+ * Parameter :
+ * none
+ *
+ * Operations :
+ * initializes the default table of pointers to subroutines
+ *
+ * Return value :
+ *
+ */
+void abe_init_subroutine_table(void)
+{
+ abe_uint32 id;
+
+ /* reset the table's pointers */
+ abe_subroutine_write_pointer = 0;
+
+ abe_add_subroutine(&id, (abe_subroutine2) abe_null_subroutine_2, SUB_0_PARAM); /* the first index is the NULL task */
+ abe_add_subroutine(&(abe_subroutine_id[SUB_WRITE_MIXER]), (abe_subroutine2)abe_write_mixer, SUB_3_PARAM); /* write mixer has 3 parameters @@@ TBD*/
+ abe_add_subroutine(&abe_irq_pingpong_player_id, (abe_subroutine2)abe_null_subroutine_0, SUB_0_PARAM); /* ping-pong player IRQ */
+}
+
+/*
+ * ABE_ADD_SUBROUTINE
+ *
+ * Parameter :
+ * port id
+ * pointer to the subroutines
+ * number of parameters to push on the stack before call
+ *
+ * Operations :
+ * add one function pointer more and returns the index to it
+ *
+ * Return value :
+ *
+ */
+void abe_add_subroutine(abe_uint32 *id, abe_subroutine2 f, abe_uint32 nparam)
+{
+ abe_uint32 i, i_found;
+
+ if ((abe_subroutine_write_pointer >= MAXNBSUBROUTINE) || ((abe_uint32)f == 0)) {
+ abe_dbg_param |= ERR_SEQ;
+ abe_dbg_error_log(ABE_PARAMETER_OVERFLOW);
+ } else {
+ /* search if this subroutine address was not already
+ * declared, then return the previous index
+ */
+ for (i_found = abe_subroutine_write_pointer, i = 0; i < abe_subroutine_write_pointer; i++) {
+ if (f == abe_all_subsubroutine[i])
+ i_found = i;
+ }
+
+ if (i_found == abe_subroutine_write_pointer) {
+ *id = abe_subroutine_write_pointer;
+ abe_all_subsubroutine[abe_subroutine_write_pointer] = (f);
+ abe_all_subsubroutine_nparam[abe_subroutine_write_pointer] = nparam;
+ abe_subroutine_write_pointer++;
+ } else {
+ *id = i_found;
+ }
+ }
+}
+
+/*
+ * ABE_ADD_SEQUENCE
+ *
+ * Parameter :
+ * Id: returned sequence index after pluging a new sequence (index in the tables)
+ * s : sequence to be inserted
+ *
+ * Operations :
+ * Load a time-sequenced operations.
+ *
+ * Return value :
+ * None.
+ */
+
+void abe_add_sequence(abe_uint32 *id, abe_sequence_t *s)
+{
+ abe_seq_t *seq_src, *seq_dst;
+ abe_uint32 i, no_end_of_sequence_found;
+
+ seq_src = &(s->seq1);
+ seq_dst = &((abe_all_sequence[abe_sequence_write_pointer]).seq1);
+
+ if ((abe_sequence_write_pointer >= MAXNBSEQUENCE) || ((abe_uint32)s == 0)) {
+ abe_dbg_param |= ERR_SEQ;
+ abe_dbg_error_log(ABE_PARAMETER_OVERFLOW);
+ } else {
+ *id = abe_subroutine_write_pointer;
+ (abe_all_sequence[abe_sequence_write_pointer]).mask = s->mask; /* copy the mask */
+
+ for (no_end_of_sequence_found = 1, i = 0; i < MAXSEQUENCESTEPS; i++, seq_src++, seq_dst++) {
+ (*seq_dst) = (*seq_src); /* sequence copied line by line */
+
+ if ((*(abe_int32 *)seq_src) == -1) {
+ /* stop when the line start with time=(-1) */
+ no_end_of_sequence_found = 1;
+ break;
+ }
+ }
+ abe_subroutine_write_pointer++;
+
+ if (no_end_of_sequence_found)
+ abe_dbg_error_log(ABE_SEQTOOLONG);
+ }
+}
+
+/*
+ * ABE_RESET_ONE_SEQUENCE
+ *
+ * Parameter :
+ * sequence ID
+ *
+ * Operations :
+ * load default configuration for that sequence
+ * kill running activities
+ *
+ * Return value :
+ *
+ */
+void abe_reset_one_sequence(abe_uint32 id)
+{
+ /* @@@@@@@@@@@@@@@@ */
+}
+
+/*
+ * ABE_RESET_ALL_SEQUENCE
+ *
+ * Parameter :
+ * none
+ *
+ * Operations :
+ * load default configuration for all sequences
+ * kill any running activities
+ *
+ * Return value :
+ *
+ */
+void abe_reset_all_sequence(void)
+{
+ abe_uint32 i;
+
+ abe_init_subroutine_table();
+
+ /* arrange to have the first sequence index=0 to the NULL operation sequence */
+ abe_add_sequence(&i, (abe_sequence_t *)&seq_null);
+
+ /* reset the the collision protection mask */
+ abe_global_sequence_mask = 0;
+
+ /* reset the pending sequences list */
+ for (abe_nb_pending_sequences = i = 0; i < MAXNBSEQUENCE; i++)
+ abe_pending_sequences[i] = 0;
+}
+
+/*
+ * ABE_CALL_SUBROUTINE
+ *
+ * Parameter :
+ * index to the table of all registered Call-backs and subroutines
+ *
+ * Operations :
+ * run and log a subroutine
+ *
+ * Return value :
+ * None.
+ */
+void abe_call_subroutine(abe_uint32 idx, abe_uint32 p1, abe_uint32 p2, abe_uint32 p3, abe_uint32 p4)
+{
+ abe_subroutine0 f0;
+ abe_subroutine1 f1;
+ abe_subroutine2 f2;
+ abe_subroutine3 f3;
+ abe_subroutine4 f4;
+
+ if (idx > MAXNBSUBROUTINE)
+ return;
+
+ switch (idx) {
+#if 0
+ /* call the subroutines defined at compilation time (const .. sequences) */
+ case SUB_WRITE_MIXER_DL1 :
+ /@@@@ abe_write_mixer_dl1 (p1, p2, p3)
+ abe_fprintf ("write_mixer");
+ break;
+#endif
+ /* call the subroutines defined at execution time (dynamic sequences) */
+ default :
+ switch (abe_all_subsubroutine_nparam [abe_subroutine_id[idx]]) {
+ case SUB_0_PARAM:
+ f0 = (abe_subroutine0)abe_all_subsubroutine[idx];
+ (*f0)();
+ break;
+ case SUB_1_PARAM:
+ f1 = (abe_subroutine1)abe_all_subsubroutine [idx];
+ (*f1)(p1);
+ break;
+ case SUB_2_PARAM:
+ f2 = abe_all_subsubroutine[idx];
+ (*f2)(p1, p2);
+ break;
+ case SUB_3_PARAM:
+ f3 = (abe_subroutine3)abe_all_subsubroutine[idx];
+ (*f3)(p1, p2, p3);
+ break;
+ case SUB_4_PARAM:
+ f4 = (abe_subroutine4)abe_all_subsubroutine[idx];
+ (*f4)(p1, p2, p3, p4);
+ break;
+ }
+ }
+}
diff --git a/sound/soc/codecs/abe/abe_seq.h b/sound/soc/codecs/abe/abe_seq.h
new file mode 100644
index 000000000000..6e15531e920e
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_seq.h
@@ -0,0 +1,127 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+void abe_init_subroutine_table(void);
+
+/*
+ * Register Programming Examples
+ *
+ * 1. Power on sequence
+ *
+ * The modules HSLDO, NCP, LSLDO, LPPLL are enabled/disabled automatically by the TWL6040 power state machine after pin AUDPWRON transitions from 0 ' 1. No register writes are necessary.
+ *
+ * For the purposes of test it is possible to bypass the power state machine and manually enable these modules in the same order as described in Fig 2-XX. This can be done after VIO comes up and I2C register writes are possible.
+ *
+ * The manual sequence could be as follows
+ * LDOCTL = 0x04 (Enable HSLDO)
+ * NCPCTL = 0x03 (Enable NCP in auto mode)
+ * LDOCTL = 0x05 (Enable LSLDO)
+ * LPPLLCTL = 0x09 (Enable LPPLL with output frequency = 19.2MHz)
+ *
+ * Please see Fig 2-64 for details on details to be maintained between successive I2C register writes.
+ *
+ * Further if the system MCLK is active the HPPLL could be enabled instead of the LPPLL.
+ * (a) For a square wave where slicer is not required
+ * HPPLLCTL = 0x11 (Select HPPLL output, Enable HPPLL)
+ * (a) For a sine wave where slicer is required
+ * HPPLLCTL = 0x19 (Select HPPLL output, Enable Slicer, Enable HPPLL)
+ *
+ */
+
+/*
+ * 2. Setting up a stereo UPLINK path through MICAMPL, MICAMPR input amplifiers
+ * AMICBCTL = 0x10
+ * MICGAIN = 0x0F (Gain to 24 dB for L and R)
+ * HPPLLCTL = 0x19 (Select HPPLL output, Enable Slicer, Enable HPPLL)
+ * MICLCTL = 0x0D (Select MMIC input, Enable ADC)
+ * MICRCTL = 0x0D (Select SMIC input, Enable ADC)
+ *
+ */
+
+/*
+ * 3. Setting up a stereo headset MP3 playback DNLINK path
+ * Please see section 2.3.1.1 for details
+ *
+ * (b) HP
+ * HSGAIN = 0x22 (-4 dB gain on L and R amplifiers)
+ * HSLCTL = 0x01 (Enable HSDAC L, HP mode)
+ * HSRCTL = 0x01 (Enable HSDAC R, HP mode)
+ * Wait 80us
+ * HSLCTL = 0x05 (Enable HSLDRV, HP mode)
+ * HSRCTL = 0x05 (Enable HSRDRV, HP mode)
+ * Wait 2ms
+ * HSLCTL = 0x25 (Close HSDACL switch)
+ * HSRCTL = 0x25 (Close HSDACR switch)
+ *
+ */
+
+/*
+ * (a) LP
+ * HSGAIN = 0x22 (-4 dB gain on L and R amplifiers)
+ * HSLCTL = 0x03 (Enable HSDAC L, LP mode)
+ * HSRCTL = 0x03 (Enable HSDAC R, LP mode)
+ * Wait 80us
+ * HSLCTL = 0x0F (Enable HSLDRV, LP mode)
+ * HSRCTL = 0x0F (Enable HSRDRV, LP mode)
+ * Wait 2ms
+ * HSLCTL = 0x2F (Close HSDACL switch)
+ * HSRCTL = 0x2F (Close HSDACR switch)
+ *
+ */
+
+/*
+ * 4. Setting up a stereo FM playback path on headset
+ * (a) HP
+ * LINEGAIN = 0x1B (0dB gain on L and R inputs)
+ * MICLCTL = 0x02 (Enable Left LINEAMP)
+ * MICRCTL = 0x02 (Enable Right LINEAMP)
+ * HSGAIN = 0x22 (-4 dB gain on L and R amplifiers)
+ * HSLCTL = 0x04 (Enable HSLDRV in HP mode)
+ * HSRCTL = 0x04 (Enable HSRDRV in HP mode)
+ * Wait 2ms
+ * HSLCTL = 0x44 (Close FMLOOP switch)
+ * HSRCTL = 0x44 (Close FMLOOP switch)
+ *
+ *
+ */
+
+/*
+ * (b) LP
+ * LINEGAIN = 0x1B (0dB gain on L and R inputs)
+ * MICLCTL = 0x02 (Enable Left LINEAMP)
+ * MICRCTL = 0x02 (Enable Right LINEAMP)
+ * HSGAIN = 0x22 (-4 dB gain on L and R amplifiers)
+ * HSLCTL = 0x0C (Enable HSLDRV in LP mode)
+ * HSRCTL = 0x0C (Enable HSRDRV in LP mode)
+ * Wait 2ms
+ * HSLCTL = 0x4C (Close FMLOOP switch)
+ * HSRCTL = 0x4C (Close FMLOOP switch)
+ *
+ */
+
+
+/*
+ * 5. Setting up a handset call
+ *
+ * UPLINK
+ *
+ * AMICBCTL = 0x10
+ * MICGAIN = 0x0F (Gain to 24 dB for L and R)
+ * HPPLLCTL = 0x19 (Select HPPLL output, Enable Slicer, Enable HPPLL)
+ * MICLCTL = 0x0D (Select MMIC input, Enable ADC)
+ * MICRCTL = 0x0D (Select SMIC input, Enable ADC)
+ *
+ * DNLINK
+ *
+ * HSLCTL = 0x01 (Enable HSDACL, HP mode)
+ * Wait 80us
+ * EARCTL = 0x03 (Enable EAR, Gain = min, by default enabling EAR connects HSDACL output to EAR)
+ *
+ */
diff --git a/sound/soc/codecs/abe/abe_sm_addr.h b/sound/soc/codecs/abe/abe_sm_addr.h
new file mode 100644
index 000000000000..0b7730e53a8a
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_sm_addr.h
@@ -0,0 +1,398 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_SM_ADDR_H_
+#define _ABE_SM_ADDR_H_
+
+/* Samples memory sizeof */
+#define abe_sm_sizeof(x) (S_##x##_ADDR_END - S_##x##_ADDR + 1)
+
+#define S_init_ADDR 0
+#define S_init_ADDR_END 249
+
+#define S_Data0_ADDR 250
+#define S_Data0_ADDR_END 250
+
+#define S_Temp_ADDR 251
+#define S_Temp_ADDR_END 251
+
+#define S_PhoenixOffset_ADDR 252
+#define S_PhoenixOffset_ADDR_END 252
+
+#define S_GTarget_ADDR 253
+#define S_GTarget_ADDR_END 261
+
+#define S_GCurrent_ADDR 262
+#define S_GCurrent_ADDR_END 270
+
+#define S_Tones_ADDR 271
+#define S_Tones_ADDR_END 282
+
+#define S_VX_DL_ADDR 283
+#define S_VX_DL_ADDR_END 294
+
+#define S_MM_UL2_ADDR 295
+#define S_MM_UL2_ADDR_END 306
+
+#define S_MM_DL_ADDR 307
+#define S_MM_DL_ADDR_END 318
+
+#define S_DL1_M_Out_ADDR 319
+#define S_DL1_M_Out_ADDR_END 330
+
+#define S_DL2_M_Out_ADDR 331
+#define S_DL2_M_Out_ADDR_END 342
+
+#define S_Echo_M_Out_ADDR 343
+#define S_Echo_M_Out_ADDR_END 354
+
+#define S_SDT_M_Out_ADDR 355
+#define S_SDT_M_Out_ADDR_END 366
+
+#define S_VX_UL_ADDR 367
+#define S_VX_UL_ADDR_END 378
+
+#define S_SDT_F_ADDR 379
+#define S_SDT_F_ADDR_END 390
+
+#define S_SDT_F_data_ADDR 391
+#define S_SDT_F_data_ADDR_END 407
+
+#define S_MM_DL_OSR_ADDR 408
+#define S_MM_DL_OSR_ADDR_END 431
+
+#define S_MM_96_F_ADDR 432
+#define S_MM_96_F_ADDR_END 455
+
+#define S_MM96_F_data_ADDR 456
+#define S_MM96_F_data_ADDR_END 472
+
+#define S_24_zeros_ADDR 473
+#define S_24_zeros_ADDR_END 496
+
+#define S_DMIC1_ADDR 497
+#define S_DMIC1_ADDR_END 508
+
+#define S_DMIC2_ADDR 509
+#define S_DMIC2_ADDR_END 520
+
+#define S_DMIC3_ADDR 521
+#define S_DMIC3_ADDR_END 532
+
+#define S_BT_UL_ADDR 533
+#define S_BT_UL_ADDR_END 544
+
+#define S_AMIC_ADDR 545
+#define S_AMIC_ADDR_END 556
+
+#define S_EANC_FBK_ADDR 557
+#define S_EANC_FBK_ADDR_END 568
+
+#define S_DMIC1_L_ADDR 569
+#define S_DMIC1_L_ADDR_END 580
+
+#define S_DMIC1_R_ADDR 581
+#define S_DMIC1_R_ADDR_END 592
+
+#define S_DMIC2_L_ADDR 593
+#define S_DMIC2_L_ADDR_END 604
+
+#define S_DMIC2_R_ADDR 605
+#define S_DMIC2_R_ADDR_END 616
+
+#define S_DMIC3_L_ADDR 617
+#define S_DMIC3_L_ADDR_END 628
+
+#define S_DMIC3_R_ADDR 629
+#define S_DMIC3_R_ADDR_END 640
+
+#define S_BT_L_ADDR 641
+#define S_BT_L_ADDR_END 652
+
+#define S_BT_R_ADDR 653
+#define S_BT_R_ADDR_END 664
+
+#define S_AMIC_L_ADDR 665
+#define S_AMIC_L_ADDR_END 676
+
+#define S_AMIC_R_ADDR 677
+#define S_AMIC_R_ADDR_END 688
+
+#define S_EANC_FBK_L_ADDR 689
+#define S_EANC_FBK_L_ADDR_END 700
+
+#define S_EANC_FBK_R_ADDR 701
+#define S_EANC_FBK_R_ADDR_END 712
+
+#define S_EchoRef_L_ADDR 713
+#define S_EchoRef_L_ADDR_END 724
+
+#define S_EchoRef_R_ADDR 725
+#define S_EchoRef_R_ADDR_END 736
+
+#define S_MM_DL_L_ADDR 737
+#define S_MM_DL_L_ADDR_END 748
+
+#define S_MM_DL_R_ADDR 749
+#define S_MM_DL_R_ADDR_END 760
+
+#define S_MM_UL_ADDR 761
+#define S_MM_UL_ADDR_END 820
+
+#define S_AMIC_96k_ADDR 821
+#define S_AMIC_96k_ADDR_END 844
+
+#define S_DMIC0_96k_ADDR 845
+#define S_DMIC0_96k_ADDR_END 868
+
+#define S_DMIC1_96k_ADDR 869
+#define S_DMIC1_96k_ADDR_END 892
+
+#define S_DMIC2_96k_ADDR 893
+#define S_DMIC2_96k_ADDR_END 916
+
+#define S_DMIC4EANC_ADDR 917
+#define S_DMIC4EANC_ADDR_END 922
+
+#define S_AMIC_96_F_ADDR 923
+#define S_AMIC_96_F_ADDR_END 946
+
+#define S_DMIC0_96_F_ADDR 947
+#define S_DMIC0_96_F_ADDR_END 970
+
+#define S_DMIC1_96_F_ADDR 971
+#define S_DMIC1_96_F_ADDR_END 994
+
+#define S_DMIC2_96_F_ADDR 995
+#define S_DMIC2_96_F_ADDR_END 1018
+
+#define S_UL_MIC_48K_ADDR 1019
+#define S_UL_MIC_48K_ADDR_END 1030
+
+#define S_AMIC_EQ_data_ADDR 1031
+#define S_AMIC_EQ_data_ADDR_END 1047
+
+#define S_DMIC1_EQ_data_ADDR 1048
+#define S_DMIC1_EQ_data_ADDR_END 1064
+
+#define S_DMIC2_EQ_data_ADDR 1065
+#define S_DMIC2_EQ_data_ADDR_END 1081
+
+#define S_DMIC3_EQ_data_ADDR 1082
+#define S_DMIC3_EQ_data_ADDR_END 1098
+
+#define S_Voice_8k_UL_ADDR 1099
+#define S_Voice_8k_UL_ADDR_END 1101
+
+#define S_Voice_8k_DL_ADDR 1102
+#define S_Voice_8k_DL_ADDR_END 1103
+
+#define S_VX_DL_data_ADDR 1104
+#define S_VX_DL_data_ADDR_END 1120
+
+#define S_McPDM_Out1_ADDR 1121
+#define S_McPDM_Out1_ADDR_END 1144
+
+#define S_McPDM_Out2_ADDR 1145
+#define S_McPDM_Out2_ADDR_END 1168
+
+#define S_McPDM_Out3_ADDR 1169
+#define S_McPDM_Out3_ADDR_END 1192
+
+#define S_Voice_16k_UL_ADDR 1193
+#define S_Voice_16k_UL_ADDR_END 1197
+
+#define S_Voice_16k_DL_ADDR 1198
+#define S_Voice_16k_DL_ADDR_END 1201
+
+#define S_XinASRC_DL_VX_ADDR 1202
+#define S_XinASRC_DL_VX_ADDR_END 1241
+
+#define S_XinASRC_UL_VX_ADDR 1242
+#define S_XinASRC_UL_VX_ADDR_END 1281
+
+#define S_XinASRC_DL_MM_ADDR 1282
+#define S_XinASRC_DL_MM_ADDR_END 1321
+
+#define S_VX_REC_ADDR 1322
+#define S_VX_REC_ADDR_END 1333
+
+#define S_VX_REC_L_ADDR 1334
+#define S_VX_REC_L_ADDR_END 1345
+
+#define S_VX_REC_R_ADDR 1346
+#define S_VX_REC_R_ADDR_END 1357
+
+#define S_DL2_M_L_ADDR 1358
+#define S_DL2_M_L_ADDR_END 1369
+
+#define S_DL2_M_R_ADDR 1370
+#define S_DL2_M_R_ADDR_END 1381
+
+#define S_DL2_M_LR_EQ_data_ADDR 1382
+#define S_DL2_M_LR_EQ_data_ADDR_END 1406
+
+#define S_DL1_M_EQ_data_ADDR 1407
+#define S_DL1_M_EQ_data_ADDR_END 1431
+
+#define S_VX_DL_8_48_BP_data_ADDR 1432
+#define S_VX_DL_8_48_BP_data_ADDR_END 1444
+
+#define S_VX_DL_8_48_LP_data_ADDR 1445
+#define S_VX_DL_8_48_LP_data_ADDR_END 1457
+
+#define S_EARP_48_96_LP_data_ADDR 1458
+#define S_EARP_48_96_LP_data_ADDR_END 1472
+
+#define S_IHF_48_96_LP_data_ADDR 1473
+#define S_IHF_48_96_LP_data_ADDR_END 1487
+
+#define S_VX_DL_16_48_HP_data_ADDR 1488
+#define S_VX_DL_16_48_HP_data_ADDR_END 1494
+
+#define S_VX_DL_16_48_LP_data_ADDR 1495
+#define S_VX_DL_16_48_LP_data_ADDR_END 1507
+
+#define S_VX_UL_48_8_BP_data_ADDR 1508
+#define S_VX_UL_48_8_BP_data_ADDR_END 1520
+
+#define S_VX_UL_48_8_LP_data_ADDR 1521
+#define S_VX_UL_48_8_LP_data_ADDR_END 1533
+
+#define S_VX_UL_8_TEMP_ADDR 1534
+#define S_VX_UL_8_TEMP_ADDR_END 1535
+
+#define S_VX_UL_48_16_HP_data_ADDR 1536
+#define S_VX_UL_48_16_HP_data_ADDR_END 1542
+
+#define S_VX_UL_48_16_LP_data_ADDR 1543
+#define S_VX_UL_48_16_LP_data_ADDR_END 1555
+
+#define S_VX_UL_16_TEMP_ADDR 1556
+#define S_VX_UL_16_TEMP_ADDR_END 1559
+
+#define S_EANC_IIR_data_ADDR 1560
+#define S_EANC_IIR_data_ADDR_END 1576
+
+#define S_EANC_SignalTemp_ADDR 1577
+#define S_EANC_SignalTemp_ADDR_END 1597
+
+#define S_EANC_Input_ADDR 1598
+#define S_EANC_Input_ADDR_END 1598
+
+#define S_EANC_Output_ADDR 1599
+#define S_EANC_Output_ADDR_END 1599
+
+#define S_APS_IIRmem1_ADDR 1600
+#define S_APS_IIRmem1_ADDR_END 1608
+
+#define S_APS_IIRmem2_ADDR 1609
+#define S_APS_IIRmem2_ADDR_END 1611
+
+#define S_APS_OutSamples_ADDR 1612
+#define S_APS_OutSamples_ADDR_END 1623
+
+#define S_XinASRC_ECHO_REF_ADDR 1624
+#define S_XinASRC_ECHO_REF_ADDR_END 1663
+
+#define S_ECHO_REF_16K_ADDR 1664
+#define S_ECHO_REF_16K_ADDR_END 1668
+
+#define S_ECHO_REF_8K_ADDR 1669
+#define S_ECHO_REF_8K_ADDR_END 1671
+
+#define S_DL1_ADDR 1672
+#define S_DL1_ADDR_END 1683
+
+#define S_APS_DL2_IIRmem1_ADDR 1684
+#define S_APS_DL2_IIRmem1_ADDR_END 1692
+
+#define S_APS_DL2_L_IIRmem2_ADDR 1693
+#define S_APS_DL2_L_IIRmem2_ADDR_END 1695
+
+#define S_APS_DL2_R_IIRmem2_ADDR 1696
+#define S_APS_DL2_R_IIRmem2_ADDR_END 1698
+
+#define S_DL1_APS_ADDR 1699
+#define S_DL1_APS_ADDR_END 1710
+
+#define S_DL2_L_APS_ADDR 1711
+#define S_DL2_L_APS_ADDR_END 1722
+
+#define S_DL2_R_APS_ADDR 1723
+#define S_DL2_R_APS_ADDR_END 1734
+
+#define S_ECHO_REF_48_8_BP_data_ADDR 1735
+#define S_ECHO_REF_48_8_BP_data_ADDR_END 1747
+
+#define S_ECHO_REF_48_8_LP_data_ADDR 1748
+#define S_ECHO_REF_48_8_LP_data_ADDR_END 1760
+
+#define S_ECHO_REF_48_16_HP_data_ADDR 1761
+#define S_ECHO_REF_48_16_HP_data_ADDR_END 1767
+
+#define S_ECHO_REF_48_16_LP_data_ADDR 1768
+#define S_ECHO_REF_48_16_LP_data_ADDR_END 1780
+
+#define S_APS_DL1_EQ_data_ADDR 1781
+#define S_APS_DL1_EQ_data_ADDR_END 1789
+
+#define S_APS_DL2_EQ_data_ADDR 1790
+#define S_APS_DL2_EQ_data_ADDR_END 1798
+
+#define S_DC_DCvalue_ADDR 1799
+#define S_DC_DCvalue_ADDR_END 1799
+
+#define S_VIBRA_ADDR 1800
+#define S_VIBRA_ADDR_END 1805
+
+#define S_Vibra2_in_ADDR 1806
+#define S_Vibra2_in_ADDR_END 1811
+
+#define S_Vibra2_addr_ADDR 1812
+#define S_Vibra2_addr_ADDR_END 1812
+
+#define S_VibraCtrl_forRightSM_ADDR 1813
+#define S_VibraCtrl_forRightSM_ADDR_END 1836
+
+#define S_Rnoise_mem_ADDR 1837
+#define S_Rnoise_mem_ADDR_END 1837
+
+#define S_Ctrl_ADDR 1838
+#define S_Ctrl_ADDR_END 1855
+
+#define S_Vibra1_in_ADDR 1856
+#define S_Vibra1_in_ADDR_END 1861
+
+#define S_Vibra1_temp_ADDR 1862
+#define S_Vibra1_temp_ADDR_END 1885
+
+#define S_VibraCtrl_forLeftSM_ADDR 1886
+#define S_VibraCtrl_forLeftSM_ADDR_END 1909
+
+#define S_Vibra1_mem_ADDR 1910
+#define S_Vibra1_mem_ADDR_END 1920
+
+#define S_VibraCtrl_Stereo_ADDR 1921
+#define S_VibraCtrl_Stereo_ADDR_END 1944
+
+#define S_AMIC_96_48_data_ADDR 1945
+#define S_AMIC_96_48_data_ADDR_END 1959
+
+#define S_DMIC0_96_48_data_ADDR 1960
+#define S_DMIC0_96_48_data_ADDR_END 1974
+
+#define S_DMIC1_96_48_data_ADDR 1975
+#define S_DMIC1_96_48_data_ADDR_END 1989
+
+#define S_DMIC2_96_48_data_ADDR 1990
+#define S_DMIC2_96_48_data_ADDR_END 2004
+
+#endif /* _ABESM_ADDR_H_ */
diff --git a/sound/soc/codecs/abe/abe_sys.h b/sound/soc/codecs/abe/abe_sys.h
new file mode 100644
index 000000000000..f4d50d2132ff
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_sys.h
@@ -0,0 +1,9 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
diff --git a/sound/soc/codecs/abe/abe_taskId.h b/sound/soc/codecs/abe/abe_taskId.h
new file mode 100644
index 000000000000..851923dbf983
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_taskId.h
@@ -0,0 +1,111 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_TASKID_H_
+#define _ABE_TASKID_H_
+
+#define C_ABE_FW_TASK_test 0
+#define C_ABE_FW_TASK_void 1
+#define C_ABE_FW_TASK_cluster 2
+#define C_ABE_FW_TASK_DL1Mixer 3
+#define C_ABE_FW_TASK_DL2Mixer 4
+#define C_ABE_FW_TASK_EchoMixer 5
+#define C_ABE_FW_TASK_SideTone 6
+#define C_ABE_FW_TASK_SDTMixer 7
+#define C_ABE_FW_TASK_IO_DMIC 8
+#define C_ABE_FW_TASK_IO_DMIC2 9
+#define C_ABE_FW_TASK_AMIC_96_48_LP 10
+#define C_ABE_FW_TASK_AMIC_96_48_DEC 11
+#define C_ABE_FW_TASK_AMIC_EQ 12
+#define C_ABE_FW_TASK_DMIC1_96_48_LP 13
+#define C_ABE_FW_TASK_DMIC1_96_48_DEC 14
+#define C_ABE_FW_TASK_DMIC1_EQ 15
+#define C_ABE_FW_TASK_DMIC2_96_48_LP 16
+#define C_ABE_FW_TASK_DMIC2_96_48_DEC 17
+#define C_ABE_FW_TASK_DMIC2_EQ 18
+#define C_ABE_FW_TASK_DMIC3_96_48_LP 19
+#define C_ABE_FW_TASK_DMIC3_96_48_DEC 20
+#define C_ABE_FW_TASK_DMIC3_EQ 21
+#define C_ABE_FW_TASK_DMIC1_SPLIT 22
+#define C_ABE_FW_TASK_DMIC2_SPLIT 23
+#define C_ABE_FW_TASK_DMIC3_SPLIT 24
+#define C_ABE_FW_TASK_AMIC_SPLIT 25
+#define C_ABE_FW_TASK_IO_MM_UL_test 26
+#define C_ABE_FW_TASK_IO_MM_UL2_test 27
+#define C_ABE_FW_TASK_IO_VX_UL 28
+#define C_ABE_FW_TASK_IO_VX_DL 29
+#define C_ABE_FW_TASK_IO_TONES_DL 30
+#define C_ABE_FW_TASK_IO_MM_DL 31
+#define C_ABE_FW_TASK_IO_VIB_DL_test 32
+#define C_ABE_FW_TASK_IO_AMIC 33
+#define C_ABE_FW_TASK_McPDM_DL 34
+#define C_ABE_FW_TASK_VX_UL_ROUTING 35
+#define C_ABE_FW_TASK_MM_UL2_ROUTING 36
+#define C_ABE_FW_TASK_MM_UL_ROUTING 37
+#define C_ABE_FW_TASK_IO_MM_UL 38
+#define C_ABE_FW_TASK_IO_MM_UL2 39
+#define C_ABE_FW_TASK_ASRC_VX_DL_8 40
+#define C_ABE_FW_TASK_ASRC_VX_UL_8 41
+#define C_ABE_FW_TASK_ASRC_VX_DL_16 42
+#define C_ABE_FW_TASK_ASRC_VX_UL_16 43
+#define C_ABE_FW_TASK_ASRC_MM_DL 44
+#define C_ABE_FW_TASK_VXRECMixer 45
+#define C_ABE_FW_TASK_VXREC_SPLIT 46
+#define C_ABE_FW_TASK_ULMixer 47
+#define C_ABE_FW_TASK_MM_SPLIT 48
+#define C_ABE_FW_TASK_VX_DL_8_48_BP 49
+#define C_ABE_FW_TASK_VX_DL_8_48_0SR 50
+#define C_ABE_FW_TASK_VX_DL_8_48_LP 51
+#define C_ABE_FW_TASK_VX_DL_16_48_HP 52
+#define C_ABE_FW_TASK_VX_DL_16_48_0SR 53
+#define C_ABE_FW_TASK_VX_DL_16_48_LP 54
+#define C_ABE_FW_TASK_DL1_EQ 55
+#define C_ABE_FW_TASK_DL1_GAIN 56
+#define C_ABE_FW_TASK_EARP_48_96_0SR 57
+#define C_ABE_FW_TASK_EARP_48_96_LP 58
+#define C_ABE_FW_TASK_DL2_EQ 59
+#define C_ABE_FW_TASK_DL2_GAIN 60
+#define C_ABE_FW_TASK_IHF_48_96_0SR 61
+#define C_ABE_FW_TASK_IHF_48_96_LP 62
+#define C_ABE_FW_TASK_VX_UL_48_8_LP 63
+#define C_ABE_FW_TASK_VX_UL_48_8_DEC1 64
+#define C_ABE_FW_TASK_VX_UL_48_8_BP 65
+#define C_ABE_FW_TASK_VX_UL_48_16_LP 66
+#define C_ABE_FW_TASK_VX_UL_48_16_DEC1 67
+#define C_ABE_FW_TASK_VX_UL_48_16_HP 68
+#define C_ABE_FW_TASK_GAIN_UPDATE 69
+#define C_ABE_FW_TASK_DELAY_CMD 70
+#define C_ABE_FW_TASK_ASRC_ECHO_REF_8 71
+#define C_ABE_FW_TASK_ASRC_ECHO_REF_16 72
+#define C_ABE_FW_TASK_DL1_APS_IIR 73
+#define C_ABE_FW_TASK_DL1_APS_CORE 74
+#define C_ABE_FW_TASK_DL2_APS_IIR 75
+#define C_ABE_FW_TASK_DL2_APS_SPLIT 76
+#define C_ABE_FW_TASK_DL2_L_APS_CORE 77
+#define C_ABE_FW_TASK_DL2_R_APS_CORE 78
+#define C_ABE_FW_TASK_ECHO_REF_48_8_LP 79
+#define C_ABE_FW_TASK_ECHO_REF_48_8_DEC1 80
+#define C_ABE_FW_TASK_ECHO_REF_48_8_BP 81
+#define C_ABE_FW_TASK_ECHO_REF_48_16_LP 82
+#define C_ABE_FW_TASK_ECHO_REF_48_16_DEC1 83
+#define C_ABE_FW_TASK_ECHO_REF_48_16_HP 84
+#define C_ABE_FW_TASK_EANC 85
+#define C_ABE_FW_TASK_EANC_WRAP 86
+#define C_ABE_FW_TASK_DL1_APS_EQ 87
+#define C_ABE_FW_TASK_DL2_APS_EQ 88
+#define C_ABE_FW_TASK_DC_REMOVAL 89
+#define C_ABE_FW_TASK_IO_VIBRA_DL 90
+#define C_ABE_FW_TASK_VIBRA1 91
+#define C_ABE_FW_TASK_VIBRA2 92
+#define C_ABE_FW_TASK_VIBRA_SPLIT 93
+#define C_ABE_FW_TASK_VIBRA_PACK 94
+#define C_ABE_FW_TASK_IO_PING_PONG 95
+
+#endif /* _ABE_TASKID_H_ */
diff --git a/sound/soc/codecs/abe/abe_test.c b/sound/soc/codecs/abe/abe_test.c
new file mode 100644
index 000000000000..ab8ede60c7b8
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_test.c
@@ -0,0 +1,104 @@
+/* =============================================================================
+* Texas Instruments OMAP(TM) Platform Software
+* (c) Copyright 2009 Texas Instruments Incorporated. All Rights Reserved.
+*
+* Use of this software is controlled by the terms and conditions found
+* in the license agreement under which this software has been supplied.
+* =========================================================================== */
+/**
+ * @file ABE_API.C
+ *
+ * All the visible API for the audio drivers
+ *
+ * @path
+ * @rev 01.00
+ */
+/* ----------------------------------------------------------------------------
+*!
+*! Revision History
+*! ===================================
+*! 27-Nov-2008 Original
+*! 05-Jun-2009 V05 release
+* =========================================================================== */
+
+#if !PC_SIMULATION
+
+#include "abe_main.h"
+
+#include <math.h>
+
+/* ========================================================================== */
+/**
+* @fn ABE_AUTO_CHECK_DATA_FORMAT_TRANSLATION()
+*/
+/* ========================================================================= */
+
+void abe_auto_check_data_format_translation (void)
+{
+ abe_float test, f_decibel, f_linear, max_error;
+ abe_uint32 data_mem;
+#define C_20LOG2 ((abe_float)6.020599913)
+
+ for (max_error = 0, f_decibel = -70; f_decibel < 30; f_decibel += 0.1)
+ {
+ f_linear = 0;
+ abe_translate_gain_format (DECIBELS_TO_LINABE, f_decibel, &f_linear);
+ abe_translate_to_xmem_format (ABE_CMEM, f_linear, &data_mem);
+ abe_translate_to_xmem_format (ABE_SMEM, f_linear, &data_mem);
+ abe_translate_to_xmem_format (ABE_DMEM, f_linear, &data_mem);
+
+ test = (abe_float) pow (2, f_decibel/C_20LOG2);
+ if ( (absolute(f_linear - test) / 1) > max_error)
+ max_error = (absolute(f_linear - test) / 1);
+
+ abe_translate_gain_format (LINABE_TO_DECIBELS, f_linear, &f_decibel);
+ test = (abe_float) (C_20LOG2 * log(f_linear) / log(2));
+
+ if ( (absolute(f_decibel - test) / 1) > max_error)
+ max_error = (absolute(f_decibel - test) / 1);
+
+ /* the observed max gain error is 0.0001 decibel (0.002%) */
+ }
+
+}
+/* ========================================================================== */
+/**
+* @fn ABE_AUTO_CHECK_DATA_FORMAT_TRANSLATION()
+*/
+/* ========================================================================= */
+
+void abe_check_opp (void)
+{
+ abe_use_case_id UC[] = {ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE, ABE_RINGER_TONES, 0};
+ abe_opp_t OPP;
+ abe_hw_config_init_t CONFIG;
+
+ abe_read_hardware_configuration (UC, &OPP, &CONFIG); /* check HW config and OPP config */
+}
+
+/* ========================================================================== */
+/**
+* @fn ABE_AUTO_CHECK_DATA_FORMAT_TRANSLATION()
+*/
+/* ========================================================================= */
+
+void abe_check_dma (void)
+{
+ abe_port_id id;
+ abe_data_format_t format;
+ abe_uint32 d;
+ abe_dma_t dma_sink;
+
+ /* check abe_read_port_address () */
+ id = VX_UL_PORT;
+ abe_read_port_address (id, &dma_sink);
+
+ format.f = 8000; format.samp_format = STEREO_MSB;
+ d = abe_dma_port_iter_factor (&format);
+ d = abe_dma_port_iteration (&format);
+ abe_connect_cbpr_dmareq_port (VX_DL_PORT, &format, ABE_CBPR1_IDX, &dma_sink);
+ abe_read_port_address (id, &dma_sink);
+
+}
+
+#endif /* #if !PC_SIMULATION */
diff --git a/sound/soc/codecs/abe/abe_test.h b/sound/soc/codecs/abe/abe_test.h
new file mode 100644
index 000000000000..c3407f514bc8
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_test.h
@@ -0,0 +1,25 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_TEST_H_
+#define _ABE_TEST_H_
+
+/*
+ * HAL test API
+ */
+void abe_auto_check_data_format_translation(void);
+void abe_check_opp(void);
+void abe_check_dma (void);
+
+/*
+ * HAL test DATA
+ */
+
+#endif /* _ABE_TEST_H_ */
diff --git a/sound/soc/codecs/abe/abe_typ.h b/sound/soc/codecs/abe/abe_typ.h
new file mode 100644
index 000000000000..81396df11728
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_typ.h
@@ -0,0 +1,630 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_TYP_H_
+#define _ABE_TYP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * BASIC TYPES
+ */
+
+typedef char abe_flag;
+typedef unsigned char abe_uint8;
+typedef char abe_int8;
+typedef unsigned short abe_uint16;
+typedef short abe_int16;
+typedef unsigned long abe_uint32;
+typedef long abe_int32;
+typedef float abe_float;
+typedef double abe_double;
+
+typedef abe_uint32 abe_errc_t;
+
+typedef abe_float abe_decibel;
+//typedef abe_uint32 abe_millisecond;
+//typedef abe_uint32 abe_milliHertz;
+//typedef abe_uint32 abe_millimeter;
+//typedef abe_uint32 abe_millidegree;
+//typedef abe_uint32 abe_permille;
+//typedef abe_uint32 abe_microsecond;
+
+typedef abe_uint32 abe_result;
+typedef abe_decibel abe_gain_t; /* smoothed gain amplitude and ramp */
+typedef abe_float abe_ramp_t;
+
+typedef abe_uint32 abe_freq_t; /* 4 bytes millihertz */
+typedef abe_uint32 abe_millis_t; /* 4 bytes milliseconds */
+typedef abe_uint32 abe_micros_t; /* 4 bytes microseconds */
+
+typedef abe_uint32 abe_dbg_mask_t; /* 4 bytes Bit field indicating the type of informations to be traced */
+typedef abe_uint32 abe_time_stamp_t; /* 4 bytes infinite loop 32bits counter incremented on each firmware loop */
+ /* scheduling task loops (250us / 272us with respectively 48kHz / 44.1kHz on Phoenix). */
+typedef abe_uint32 abe_dbg_t; /* debug filter */
+
+typedef abe_uint32 abe_seq_code_t; /* Index to the table of sequences */
+typedef abe_uint32 abe_sub_code_t; /* Index to the table of subroutines called in the sequence */
+
+typedef void (* abe_subroutine0)(void); /* subroutine with no parameter */
+typedef void (* abe_subroutine1)(abe_uint32); /* subroutine with one parameter */
+typedef void (* abe_subroutine2)(abe_uint32, abe_uint32); /* subroutine with two parameters */
+typedef void (* abe_subroutine3)(abe_uint32, abe_uint32, abe_uint32); /* subroutine with three parameters */
+typedef void (* abe_subroutine4)(abe_uint32, abe_uint32, abe_uint32, abe_uint32); /* subroutine with four parameters */
+
+/*
+ * CODE PORTABILITY - FUTURE PATCHES
+ *
+ * 32bits field for having the code compatible with future revisions of the hardware (audio integration)
+ * or evolution of the software partitionning. Used for the highest level APIs (launch_sequences)
+ */
+typedef abe_uint32 abe_patch_rev;
+
+/*
+ * ENUMS
+ */
+
+/*
+ * MEMORY CONFIG TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (EANC, multimedia complex use-cases)
+ */
+typedef enum {
+ ABE_AUDIO_PLAYER_ON_HEADSET_OR_EARPHONE = 1,
+ ABE_DRIFT_MANAGEMENT_FOR_AUDIO_PLAYER,
+ ABE_VOICE_CALL_ON_HEADSET_OR_EARPHONE_OR_BT,
+ ABE_MULTIMEDIA_AUDIO_RECORDER,
+ ABE_VIBRATOR_OR_HAPTICS,
+ ABE_VOICE_CALL_ON_HANDS_FREE_SPEAKER,
+ ABE_RINGER_TONES,
+ ABE_VOICE_CALL_WITH_EARPHONE_ACTIVE_NOISE_CANCELLER,
+
+ ABE_LAST_USE_CASE
+} abe_use_case_id;
+
+/*
+ * OPP TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ * 2: OPP 50% (multimedia and voice calls)
+ * 3: OPP100% (EANC, multimedia complex use-cases)
+ */
+typedef enum {
+ ABE_OPP0 = 0,
+ ABE_OPP25, ABE_OPP50, ABE_OPP100
+} abe_opp_t;
+
+/*
+ * IIR TYPE
+ *
+ * 0: Ultra Lowest power consumption audio player
+ * 1: OPP 25% (simple multimedia features)
+ */
+typedef enum {
+ ABE_IIR_TYPE_1 = 0,
+ ABE_IIR_TYPE_2
+} abe_iir_t;
+
+/*
+ * DMIC DECIMATION RATIO
+ *
+ */
+typedef enum {
+ ABE_DEC16 = 16,
+ ABE_DEC25 = 25,
+ ABE_DEC32 = 32,
+ ABE_DEC40 = 40
+} abe_dmic_ratio_t;
+
+/*
+ * SAMPLES TYPE
+ *
+ * mono 16bits sample LSB aligned, 16 MSB bits are unused
+ * mono sample MSB aligned (16/24/32bits)
+ * two successive mono samples in one 32bits container
+ * Two L/R 16bits samples in a 32bits container,
+ * Two channels defined with two MSB aligned samples
+ * Three channels defined with three MSB aligned samples (MIC)
+ * Four channels defined with four MSB aligned samples (MIC)
+ * . . .
+ * Eight channels defined with six MSB aligned samples (MIC)
+ */
+typedef enum {
+ MONO_16_LSB = 1,
+ MONO_MSB,
+ TWO_MONO_MSB,
+ STEREO_16_16,
+ STEREO_MSB, THREE_MSB, FOUR_MSB, FIVE_MSB, SIX_MSB, SEVEN_MSB, EIGHT_MSB, NINE_MSB, TEN_MSB,
+} abe_samp_t;
+
+/*
+ * PORT PROTOCOL TYPE
+ */
+typedef enum {
+ SLIMBUS_PORT_PROT = 1,
+ SERIAL_PORT_PROT,
+ DMIC_PORT_PROT,
+ MCPDMDL_PORT_PROT,
+ MCPDMUL_PORT_PROT,
+ PINGPONG_PORT_PROT,
+ DMAREQ_PORT_PROT,
+ FIFO_PORT_PROT,
+ CIRCULAR_PORT_PROT,
+} abe_port_protocol_switch_id;
+
+/*
+ * PORT IDs
+ */
+typedef enum {
+ /* AE sink ports - Uplink */
+ DMIC_PORT1, /* digital microphones pairs */
+ DMIC_PORT2,
+ DMIC_PORT3,
+ PDM_UL_PORT, /* analog MICs */
+ BT_VX_UL_PORT, /* BT uplink */
+
+ /* AE source ports - Uplink */
+ MM_UL_PORT, /* up to 5 stereo channels */
+ MM_UL2_PORT, /* stereo FM record path */
+ VX_UL_PORT, /* stereo FM record path */
+
+ /* AE sink ports - Downlink */
+ MM_DL_PORT, /* multimedia player audio path */
+ VX_DL_PORT,
+ TONES_DL_PORT,
+ VIB_DL_PORT,
+
+ /* AE source ports - Downlink */
+ BT_VX_DL_PORT,
+ PDM_DL1_PORT,
+ MM_EXT_OUT_PORT,
+ PDM_DL2_PORT,
+ PDM_VIB_PORT,
+
+ SCHD_DBG_PORT, /* dummy port used to declare the other tasks of the scheduler */
+
+ LAST_PORT_ID
+} abe_port_id;
+
+/*
+ * GAIN IDs
+ */
+typedef enum {
+ VX_DL_IN_GAIN = 1, // mixer's gain
+ MM_DL_IN_GAIN,
+ TONES_DL_IN_GAIN,
+ MM_VX_DL_IN_GAIN,
+ MM_IHF_DL_IN_GAIN, // mixer's gain
+ MM_HS_DL_OUT_GAIN, // Output Left gain
+ MM_IHF_L_DL_OUT_GAIN, // Output Left gain
+ MM_IHF_R_DL_OUT_GAIN, // Output Right gain
+ MM_VIB1_DL_GAIN, MM_VIB2_DL_GAIN, // no gain in fact ...
+ DMIC_UL_IN_GAIN_0, DMIC_UL_IN_GAIN_1, // today = same GAIN on DMIC pairs
+ DMIC_UL_IN_GAIN_2, DMIC_UL_IN_GAIN_3,
+ DMIC_UL_IN_GAIN_4, DMIC_UL_IN_GAIN_5,
+ AMIC_UL_IN_GAIN_L, AMIC_UL_IN_GAIN_R, // today = same gain on AMIC pair
+ ECHO_REF_GAIN,
+ BT_VX_DL_OUT_GAIN,
+ BT_VX_UL_IN_GAIN,
+} abe_gain_id;
+
+/*
+ * ANA_PORT_ID Analog companion audio port
+ */
+typedef enum {
+ EAR_PHOENIX = 1,
+ HS_L, HS_R,
+ IHF_L, IHF_R,
+ VIBRA1, VIBRA2
+} abe_ana_port_id ;
+
+typedef abe_int32 headset_offset_t; /* Calibration data from the analog companion */
+
+/*
+ * Signal processing module names - EQ APS MIX ROUT
+ */
+#define FEAT_EQ1 1 /* equalizer downlink path headset + earphone */
+#define FEAT_EQ2L FEAT_EQ1+1 /* equalizer downlink path integrated handsfree LEFT */
+#define FEAT_EQ2R FEAT_EQ2L+1 /* equalizer downlink path integrated handsfree RIGHT */
+#define FEAT_EQVIB1 FEAT_EQ2R+1 /* equalizer downlink path vibra 1 */
+#define FEAT_EQVIB2 FEAT_EQVIB1+1 /* equalizer downlink path vibra 2 */
+#define FEAT_EQSDT FEAT_EQVIB2+1 /* equalizer downlink path side-tone */
+#define FEAT_EQDMIC1 FEAT_EQSDT+1 /* equalizer uplink path first DMIC pair */
+#define FEAT_EQDMIC2 FEAT_EQDMIC1+1 /* equalizer uplink path second DMIC pair */
+#define FEAT_EQDMIC3 FEAT_EQDMIC2+1 /* equalizer uplink path third DMIC pair */
+#define FEAT_EQAMIC FEAT_EQDMIC3+1 /* equalizer uplink path AMIC pair */
+#define FEAT_APS1 FEAT_EQAMIC+1 /* Acoustic protection for headset */
+#define FEAT_APS2 FEAT_APS1+1 /* acoustic protection high-pass filter for handsfree "Left" */
+#define FEAT_APS3 FEAT_APS2+1 /* acoustic protection high-pass filter for handsfree "Right" */
+#define FEAT_ASRC1 FEAT_APS3+1 /* asynchronous sample-rate-converter for the downlink voice path */
+#define FEAT_ASRC2 FEAT_ASRC1+1 /* asynchronous sample-rate-converter for the uplink voice path */
+#define FEAT_ASRC3 FEAT_ASRC2+1 /* asynchronous sample-rate-converter for the multimedia player */
+#define FEAT_ASRC4 FEAT_ASRC3+1 /* asynchronous sample-rate-converter for the echo reference */
+#define FEAT_MIXDL1 FEAT_ASRC4+1 /* mixer of the headset and earphone path */
+#define FEAT_MIXDL2 FEAT_MIXDL1+1 /* mixer of the hands-free path */
+#define FEAT_MIXAUDUL FEAT_MIXDL2+1 /* mixer for audio being sent on the voice_ul path */
+#define FEAT_MIXVXREC FEAT_MIXAUDUL+1 /* mixer for voice communication recording */
+#define FEAT_MIXSDT FEAT_MIXVXREC+1 /* mixer for side-tone */
+#define FEAT_MIXECHO FEAT_MIXSDT+1 /* mixer for echo reference */
+#define FEAT_UPROUTE FEAT_MIXECHO+1 /* router of the uplink path */
+#define FEAT_GAINS FEAT_UPROUTE+1 /* all gains */
+#define FEAT_EANC FEAT_GAINS+1 /* active noise canceller */
+#define FEAT_SEQ FEAT_EANC+1 /* sequencing queue of micro tasks */
+#define FEAT_CTL FEAT_SEQ+1 /* Phoenix control queue through McPDM */
+
+#define MAXNBFEATURE FEAT_CTL /* list of features of the firmware */
+
+typedef enum {
+ EQ1 = FEAT_EQ1, /* equalizer downlink path headset + earphone */
+ EQ2L = FEAT_EQ2L, /* equalizer downlink path integrated handsfree LEFT */
+ EQ2R = FEAT_EQ2R,
+ EQSDT = FEAT_EQSDT, /* equalizer downlink path side-tone */
+ EQDMIC1 = FEAT_EQDMIC1,
+ EQDMIC2 = FEAT_EQDMIC2,
+ EQDMIC3 = FEAT_EQDMIC3,
+ EQAMIC = FEAT_EQAMIC, /* equalizer uplink path AMIC pair */
+} abe_equ_id;
+
+typedef enum {
+ APS1 = FEAT_APS1, /* Acoustic protection for headset */
+ APS2L = FEAT_APS2,
+ APS2R = FEAT_APS3
+} abe_aps_id;
+
+typedef enum {
+ ASRC1 = FEAT_ASRC1, /* asynchronous sample-rate-converter for the downlink voice path */
+ ASRC2 = FEAT_ASRC2, /* asynchronous sample-rate-converter for the uplink voice path */
+ ASRC3 = FEAT_ASRC3, /* asynchronous sample-rate-converter for the multimedia player */
+ ASRC4 = FEAT_ASRC4, /* asynchronous sample-rate-converter for the voice uplink echo_reference */
+} abe_asrc_id;
+
+typedef enum {
+ MIXDL1 = FEAT_MIXDL1,
+ MIXDL2 = FEAT_MIXDL2,
+ MIXSDT = FEAT_MIXSDT,
+ MIXECHO = FEAT_MIXECHO,
+ MIXEANC = FEAT_EANC,
+ MIXAUDUL = FEAT_MIXAUDUL,
+ MIXVXREC = FEAT_MIXVXREC,
+} abe_mixer_id;
+
+typedef enum {
+ UPROUTE = FEAT_UPROUTE, /* there is only one router up to now */
+} abe_router_id;
+
+typedef enum {
+ GAINS = FEAT_GAINS, /* Misc tasks of the scheduler */
+ SEQUENCE = FEAT_SEQ,
+ CONTROL = FEAT_CTL
+} abe_schd_id;
+
+/*
+ * EVENT GENERATORS
+ */
+typedef enum {
+ EVENT_MCPDM = 1,
+ EVENT_DMIC, EVENT_TIMER,
+ EVENT_McBSP, EVENT_McASP, EVENT_SLIMBUS, EVENT_DEFAULT,
+} abe_event_id;
+
+/*
+ * TYPES USED FOR APIS
+ */
+
+/*
+ * HARDWARE CONFIG TYPE
+ */
+typedef struct {
+ abe_uint32 AESS_EVENT_GENERATOR_COUNTER__COUNTER_VALUE; /* EVENT_GENERATOR_COUNTER_DEFAULT gives about 96kHz */
+ abe_uint32 AESS_EVENT_SOURCE_SELECTION__SELECTION; /* 0: DMAreq, 1:Counter */
+ abe_uint32 AESS_AUDIO_ENGINE_SCHEDULER__DMA_REQ_SELECTION; /* 5bits DMAreq selection */
+ abe_event_id HAL_EVENT_SELECTION;
+
+ abe_uint32 MCPDM_CTRL__DIV_SEL; /* 0: 96kHz 1:192kHz */
+ abe_uint32 MCPDM_CTRL__CMD_INT; /* 0: no command in the FIFO, 1: 6 data on each lines (with commands) */
+ abe_uint32 MCPDM_CTRL__PDMOUTFORMAT; /* 0:MSB aligned 1:LSB aligned */
+ abe_uint32 MCPDM_CTRL__PDM_DN5_EN;
+ abe_uint32 MCPDM_CTRL__PDM_DN4_EN;
+ abe_uint32 MCPDM_CTRL__PDM_DN3_EN;
+ abe_uint32 MCPDM_CTRL__PDM_DN2_EN;
+ abe_uint32 MCPDM_CTRL__PDM_DN1_EN;
+ abe_uint32 MCPDM_CTRL__PDM_UP3_EN;
+ abe_uint32 MCPDM_CTRL__PDM_UP2_EN;
+ abe_uint32 MCPDM_CTRL__PDM_UP1_EN;
+ abe_uint32 MCPDM_FIFO_CTRL_DN__DN_TRESH;
+ abe_uint32 MCPDM_FIFO_CTRL_UP__UP_TRESH;
+
+ abe_uint32 DMIC_CTRL__DMIC_CLK_DIV; /* 0:2.4MHz 1:3.84MHz */
+ abe_uint32 DMIC_CTRL__DMICOUTFORMAT; /* 0:MSB aligned 1:LSB aligned */
+ abe_uint32 DMIC_CTRL__DMIC_UP3_EN;
+ abe_uint32 DMIC_CTRL__DMIC_UP2_EN;
+ abe_uint32 DMIC_CTRL__DMIC_UP1_EN;
+ abe_uint32 DMIC_FIFO_CTRL__DMIC_TRESH; /* 1*(DMIC_UP1_EN+ 2+ 3)*2 OCP read access every 96/88.1 KHz. */
+
+ abe_uint32 MCBSP_SPCR1_REG__RJUST; /* 1:MSB 2:LSB aligned */
+ abe_uint32 MCBSP_THRSH2_REG_REG__XTHRESHOLD;
+ abe_uint32 MCBSP_THRSH1_REG_REG__RTHRESHOLD;
+
+} abe_hw_config_init_t;
+
+/*
+ * EANC_T
+ *
+ * TBD : coefficients of the EANC
+ */
+typedef struct {
+ abe_int32 dmic_index;
+ abe_int32 fir_coef[NBEANC1];
+ abe_int32 lambda;
+ abe_int32 iir_filter[NBEANC2];
+ abe_int32 loop_gain;
+} abe_eanc_t;
+
+/*
+ * EQU_T
+ *
+ * coefficients of the equalizer
+ */
+typedef struct {
+ abe_iir_t equ_type; /* type of filter */
+ abe_uint32 equ_length; /* filter length */
+ union { /* parameters are the direct and recursive coefficients in */
+ abe_int32 type1[NBEQ1]; /* Q6.26 integer fixed-point format. */
+ struct {
+ abe_float freq[NBEQ2]; /* center frequency of the band [Hz] */
+ abe_float gain[NBEQ2]; /* gain of each band. [dB]*/
+ abe_float q[NBEQ2]; /* Q factor of this band [dB] */
+ } type2;
+ } coef;
+ abe_int32 equ_param3;
+} abe_equ_t;
+
+/*
+ * APS_T
+ *
+ * coefficients of the Acoustics Protection and Safety
+ */
+typedef struct {
+ abe_int32 coef1[NBAPS1];
+ abe_int32 coef2[NBAPS2];
+} abe_aps_t;
+
+typedef struct {
+ abe_decibel e1; /* structure of two energy_t estimation for coil and membrane */
+ abe_decibel e2;
+} abe_aps_energy_t;
+
+/*
+ * ROUTER_T
+ *
+ * table of indexes in unsigned bytes
+ */
+typedef abe_uint32 abe_router_t;
+
+/*
+ * DATA_FORMAT_T
+ *
+ * used in port declaration
+ */
+typedef struct {
+ abe_freq_t f; /* Sampling frequency of the stream */
+ abe_samp_t samp_format; /* Sample format type */
+} abe_data_format_t;
+
+/*
+ * PORT_PROTOCOL_T
+ *
+ * port declaration
+ */
+typedef struct {
+ abe_uint32 direction; /* Direction=0 means input from AESS point of view */
+ abe_port_protocol_switch_id protocol_switch; /* Protocol type (switch) during the data transfers */
+ union {
+ struct { /* Slimbus peripheral connected to ATC */
+ abe_uint32 desc_addr1; /* Address of ATC Slimbus descriptor's index */
+ abe_uint32 desc_addr2; /* Second ATC index for SlimBus reception (or NULL) */
+ abe_uint32 buf_addr1; /* DMEM address 1 in bytes */
+ abe_uint32 buf_addr2; /* DMEM address 2 in bytes */
+ abe_uint32 buf_size; /* DMEM buffer size size in bytes */
+ abe_uint32 iter; /* ITERation on each DMAreq signals */
+ abe_uint32 thr_flow; /* Data threshold for flow management */
+ } prot_slimbus;
+
+ struct {
+ abe_uint32 desc_addr; /* McBSP/McASP peripheral connected to ATC */
+ abe_uint32 buf_addr; /* Address of ATC McBSP/McASP descriptor's in bytes */
+ abe_uint32 buf_size; /* DMEM address in bytes */
+ abe_uint32 iter; /* ITERation on each DMAreq signals */
+ abe_uint32 thr_flow; /* Data threshold for flow management */
+ } prot_serial;
+
+ struct { /* DMIC peripheral connected to ATC */
+ abe_uint32 buf_addr; /* DMEM address in bytes */
+ abe_uint32 buf_size; /* DMEM buffer size in bytes */
+ abe_uint32 nbchan; /* Number of activated DMIC */
+ } prot_dmic;
+
+ struct { /* McPDMDL peripheral connected to ATC */
+ abe_uint32 buf_addr; /* DMEM address in bytes */
+ abe_uint32 buf_size; /* DMEM size in bytes */
+ abe_uint32 control; /* Control allowed on McPDM DL */
+ } prot_mcpdmdl;
+
+ struct { /* McPDMUL peripheral connected to ATC */
+ abe_uint32 buf_addr; /* DMEM address size in bytes */
+ abe_uint32 buf_size; /* DMEM buffer size size in bytes */
+ } prot_mcpdmul;
+
+ struct { /* Ping-Pong interface to the Host using cache-flush */
+ abe_uint32 buf_addr; /* DMEM buffer base address in bytes */
+ abe_uint32 buf_size; /* DMEM size in bytes for each ping and pong buffers */
+ abe_uint32 irq_addr; /* IRQ address (either DMA (0) MCU (1) or DSP(2)) */
+ abe_uint32 irq_data; /* IRQ data content loaded in the AESS IRQ register */
+ abe_uint32 callback; /* Call-back function upon IRQ reception */
+ } prot_pingpong;
+
+ struct { /* DMAreq line to CBPr */
+ abe_uint32 desc_addr; /* Address of ATC descriptor's */
+ abe_uint32 buf_addr; /* DMEM buffer address in bytes */
+ abe_uint32 buf_size; /* DMEM buffer size size in bytes */
+ abe_uint32 iter; /* ITERation on each DMAreq signals */
+ abe_uint32 thr_flow; /* Data threshold for flow management */
+ abe_uint32 dma_addr; /* DMAreq address */
+ abe_uint32 dma_data; /* DMA/AESS = 1 << #DMA */
+ } prot_dmareq;
+
+ struct { /* Circular buffer - direct addressing to DMEM */
+ abe_uint32 buf_addr; /* DMEM buffer base address in bytes */
+ abe_uint32 buf_size; /* DMEM buffer size in bytes */
+ abe_uint32 dma_addr; /* DMAreq address */
+ abe_uint32 dma_data; /* DMA/AESS = 1 << #DMA */
+ } prot_circular_buffer;
+ }p;
+} abe_port_protocol_t;
+
+/*
+ * IO_task_descriptor
+ *
+ */
+typedef struct {
+ char type; /* (0 = disabled, R/W, ATC,PingPong,DMAreq,Slimbus) */
+ char format; /* data formats */
+ char smem_buffer;
+ char cmem_gain;
+ char atc1;
+ char atc2;
+ char n;
+ char IRQ;
+ char thr1;
+ char thr2;
+ char dma_address;
+ char dma_data;
+ char irq_route;
+ char asrc;
+} abe_io_task_descriptor_t;
+
+/*
+ * DMA_T
+ *
+ * dma structure for easing programming
+ */
+typedef struct {
+ void *data; /* Pointer to the first address of the */
+ /* destination buffer (either DMA or Ping-Pong read/write pointers). */
+ abe_uint32 iter; /* number of iterations for the DMA data moves. */
+} abe_dma_t;
+
+typedef struct {
+ abe_uint32 data; /* Offset to the first address of the */
+ abe_uint32 iter; /* number of iterations for the DMA data moves. */
+} abe_dma_t_offset;
+
+/*
+ * SEQ_T
+ *
+ * struct {
+ * micros_t time; Waiting time before executing next line
+ * seq_code_t code Subroutine index interpreted in the HAL and translated to
+ * FW subroutine codes in case of ABE tasks
+ * int32 param[2] Two parameters
+ * } seq_t
+ *
+ */
+typedef struct {
+ abe_micros_t delta_time;
+ abe_sub_code_t code;
+ abe_uint32 param[4];
+ abe_uint8 tag;
+} abe_seq_t;
+
+typedef struct {
+ abe_uint32 mask;
+ abe_seq_t seq1;
+ abe_seq_t seq2;
+} abe_sequence_t;
+
+/*
+ * DRIFT_T
+ *
+ * ASRC drift parameter in [ppm] value
+ */
+typedef abe_int32 abe_drift_t;
+
+/*
+ * INTERNAL DATA TYPES
+ */
+
+/*
+ * ABE_PORT_T status / format / sampling / protocol(call_back) / features / gain / name ..
+ *
+ */
+typedef struct {
+ abe_uint16 status; /* running / idled */
+ abe_data_format_t format; /* Sample format type */
+ abe_drift_t drift; /* API : for ASRC */
+ abe_uint16 callback; /* optionnal call-back index for errors and ack */
+ abe_uint16 smem_buffer1; /* IO tasks buffers */
+ abe_uint16 smem_buffer2;
+ abe_port_protocol_t protocol;
+ abe_dma_t_offset dma; /* pointer and iteration counter of the xDMA */
+ abe_uint16 feature_index [MAXFEATUREPORT]; /* list of features associated to a port (EQ, APS, ... , ends with 0) */
+ // abe_millibel gain_calibration; /* gain tuning, default=0dB */
+ char name[NBCHARPORTNAME];
+} abe_port_t;
+
+/*
+ * ABE_SUBROUTINE_T
+ *
+ */
+typedef struct {
+ abe_uint32 sub_id;
+ abe_int32 param[4];
+} abe_subroutine_t;
+
+/*
+ * ABE_PORT_INFO_T
+ *
+ * OPP, subroutines to call on reset
+ */
+typedef struct {
+ abe_opp_t min_opp;
+ abe_subroutine_t sub1;
+ abe_subroutine_t sub2;
+} abe_port_info_t;
+
+/*
+ * ABE_FEATURE_T
+ *
+ */
+typedef struct {
+ abe_uint16 enable_with_default_data;
+ abe_uint16 disable_feature;
+ abe_uint16 read_parameter;
+ abe_uint16 write_parameter;
+ abe_uint16 running_status;
+ abe_uint16 fw_input_buffer_address;
+ abe_uint16 fw_output_buffer_address;
+ abe_uint16 fw_scheduler_slot_position;
+ abe_uint16 fw_scheduler_subslot_position;
+ abe_opp_t min_opp;
+ char name[NBCHARFEATURENAME];
+} abe_feature_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_TYP_H_ */
diff --git a/sound/soc/codecs/abe/abe_typedef.h b/sound/soc/codecs/abe/abe_typedef.h
new file mode 100644
index 000000000000..6255651e42e8
--- /dev/null
+++ b/sound/soc/codecs/abe/abe_typedef.h
@@ -0,0 +1,354 @@
+/*
+ * ==========================================================================
+ * Texas Instruments OMAP(TM) Platform Firmware
+ * (c) Copyright 2009, Texas Instruments Incorporated. All Rights Reserved.
+ *
+ * Use of this firmware is controlled by the terms and conditions found
+ * in the license agreement under which this firmware has been supplied.
+ * ==========================================================================
+ */
+
+#ifndef _ABE_TYPEDEF_H_
+#define _ABE_TYPEDEF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "abe_define.h"
+
+//-------------------------------------------------------------
+// Basic types definition
+//-------------------------------------------------------------
+#ifdef __chess__
+typedef unsigned char ABE_uchar;
+typedef signed char ABE_char;
+typedef unsigned ABE_uint16;
+typedef int ABE_int16;
+typedef long ABE_int32;
+typedef unsigned long ABE_uint32;
+#else
+typedef unsigned char ABE_uchar;
+typedef char ABE_char;
+typedef unsigned short ABE_uint16;
+typedef short ABE_int16;
+typedef long ABE_int32;
+typedef unsigned long ABE_uint32;
+#endif
+
+typedef ABE_uchar* pABE_uchar;
+typedef ABE_char* pABE_char;
+typedef ABE_uint16* pABE_uint16;
+typedef ABE_int16* pABE_int16;
+typedef ABE_int32* pABE_int32;
+typedef ABE_uint32* pABE_uint32;
+
+//-------------------------------------------------------------
+// Commonly used structures
+//-------------------------------------------------------------
+
+#ifdef __chess__
+/* ========================================================================== */
+/**
+* This is a structure description for ABE_SAtcDescriptor. This structuce contains
+* descriptor for ATC regristers
+*
+* @param readPointer 7 bits for read pointer index
+* @param bufSize 7 bits for circular buffer size
+* @param IRQdest IRQ destination 0:DSP 1:MCU
+* @param error report buffer access errors
+* @param direction Circular buffer direction 0:IN 1:OUT
+* @param empty Set to 1 is circular buffer empty
+* @param writePointer 7 bits for write pointer index
+* @param baseAddr 12 bits for circular buffer base address
+* @param iteration_lower4 4 lower bits of iteration flied
+* @param iteration_upper3 3 upper bits of iteration flied
+* @param source Source ID
+* @param dest Destination ID
+* @param DescrAct 0: descriptor is not active 1:descriptor is active
+*/
+/* ========================================================================== */
+typedef struct abeatcdescTag {
+ unsigned readPointer : 7; // Desc0
+ unsigned reserved0 : 1;
+ unsigned bufSize : 7;
+ unsigned IRQdest : 1;
+ unsigned error : 1;
+ unsigned reserved1 : 5;
+ unsigned direction : 1;
+ unsigned empty : 1;
+ unsigned writePointer : 7;
+ unsigned reserved2 : 1;
+ unsigned baseAddr : 12; // Desc1
+ unsigned iteration_lower4 : 4; // iteration field overlaps the 16 bits boundary
+ unsigned iteration_upper3 : 3;
+ unsigned source : 6;
+ unsigned dest : 6;
+ unsigned DescrAct : 1;
+} ABE_SAtcDescriptor;
+#else
+/* ========================================================================== */
+/**
+* This is a structure description for ABE_SAtcDescriptor. This structuce contains
+* descriptor for ATC regristers
+*
+* @param readPointer 7 bits for read pointer index
+* @param bufSize 7 bits for circular buffer size
+* @param IRQdest IRQ destination 0:DSP 1:MCU
+* @param error report buffer access errors
+* @param direction Circular buffer direction 0:IN 1:OUT
+* @param empty Set to 1 is circular buffer empty
+* @param writePointer 7 bits for write pointer index
+* @param baseAddr 12 bits for circular buffer base address
+* @param iteration 7 bits of iteration flied
+* @param source Source ID
+* @param dest Destination ID
+* @param DescrAct 0: descriptor is not active 1:descriptor is active
+*/
+/* ========================================================================== */
+typedef struct abeatcdescTag{
+ unsigned readPointer : 7; // Desc0
+ unsigned reserved0 : 1;
+ unsigned bufSize : 7;
+ unsigned IRQdest : 1;
+ unsigned error : 1;
+ unsigned reserved1 : 5;
+ unsigned direction : 1;
+ unsigned empty : 1;
+ unsigned writePointer : 7;
+ unsigned reserved2 : 1;
+ unsigned baseAddr : 12; // Desc1
+ unsigned iteration : 7; // iteration field overlaps the 16 bits boundary
+ unsigned source : 6;
+ unsigned dest : 6;
+ unsigned DescrAct : 1;
+} ABE_SAtcDescriptor;
+#endif
+
+typedef ABE_SAtcDescriptor* pABE_SAtcDescriptor;
+
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+typedef struct abetaskTag{
+ ABE_uchar iF; // Index of called function
+ ABE_uchar A0;
+ ABE_uchar A1;
+ ABE_uchar A2_3;
+ ABE_uchar A4_5; // Pointers for initprt
+ ABE_uchar R; // Pointer for initreg
+ ABE_uchar misc0;
+ ABE_uchar misc1; // Filling data to 32 bits alignment
+} ABE_STask;
+typedef ABE_STask* pABE_STask;
+typedef ABE_STask** ppABE_STask;
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+
+/* ========================================================================== */
+/**
+* This is a structure description for ABE_SFiFoDescr. This structuce contains
+* descriptor for general purpose FIFO for ABe module
+*
+* @param Wp Write part (Write Pointer and FIFO start address)
+* @param Rp Read part (read Pointer and FIFO end address)
+* @param fifoSize FIFO size
+* @param elementSize Element size of FIFO content
+*/
+/* ========================================================================== */
+typedef struct abefifodescrTag{
+ /* Write part of the FIFO (must be multiple of 32 bits) */
+ union{
+ struct{
+ ABE_uint16 writePtr;
+ ABE_uint16 fifoStartAddr;
+ } s16;
+ ABE_uint32 writePtr_fifoStartAddr;
+ } Wp;
+ /* Read part of the FIFO (must be multiple of 32 bits) */
+ union{
+ struct{
+ ABE_uint16 readPtr;
+ ABE_uint16 fifoEndAddr;
+ } s16;
+ ABE_uint32 readPtr_fifoEndAddr;
+ } Rp;
+ /* generic part (only set at the init of the FIFO by ABE FW) */
+ ABE_uint16 fifoSize;
+ ABE_uint16 elementSize;
+} ABE_SFiFoDescr;
+typedef ABE_SFiFoDescr* pABE_SFiFoDescr;
+
+/* ========================================================================== */
+/**
+* This is a structure description for ABE_SDelayedCmd. This structuce contains
+* descriptor for delay command processing
+*
+* @param delay Delay for the execution of the command (0: immediate)
+* @param p0 Parameter 0
+* @param p1 Parameter 1
+* @param p2 Parameter 2
+* @param p3 Parameter 3
+* @param code Action ID
+* @param misc0 Padding on 32 bits
+* @param misc1 Padding on 32 bits
+*/
+/* ========================================================================== */
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+// most of the times: p0 = dest addr, p1 = src addr, p2 = count
+typedef struct abedelayedcommandTag{
+ ABE_uint16 delay;
+ ABE_uint16 p0;
+ ABE_uint16 p1;
+ ABE_uint16 p2;
+ ABE_uchar p3;
+ ABE_uchar code;
+ ABE_uchar misc0;
+ ABE_uchar misc1;
+} ABE_SDelayedCmd;
+typedef ABE_SDelayedCmd* pABE_SDelayedCmd;
+
+typedef ABE_SDelayedCmd ABE_TDelayedCmdFifo[DCMD_FIFO_LENGTH];
+typedef ABE_TDelayedCmdFifo* pABE_TDelayedCmdFifo;
+//-------------------------------------------------------------
+#ifdef __chess__
+typedef void (*pABE_voidFunction)()clobbers(R0, R1, R2, R3, R4, R5, R6, R7, R13);
+typedef void (*pABE_voidFunctionsList[])()clobbers(R0, R1, R2, R3, R4, R5, R6, R7, R13);
+typedef void (*pABE_cmdFunction)(pABE_SDelayedCmd) clobbers(R0, R1, R2, R3, R4, R5, R6, R7, R13);
+typedef void (*pABE_cmdFunctionsList[])(pABE_SDelayedCmd) clobbers(R0, R1, R2, R3, R4, R5, R6, R7, R13);
+typedef void (*pABE_copyFunction)(ABE_uint16 chess_storage(R13))clobbers(R13);
+typedef void (*pABE_copyFunctionsList[])(ABE_uint16 chess_storage(R13))clobbers(R13);
+
+#endif
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+// ABE Enum IO defines
+enum ABE_EIOAction {ABE_IOAction_disabled, ABE_IOAction_read, ABE_IOAction_write};
+enum ABE_EIOType {ABE_EIOType_ATC, ABE_EIOType_pingPong, ABE_EIOType_DMAreq, ABE_EIOType_slimbus};
+enum ABE_EIOFormat {ABE_EIOFormat_32_lsb, ABE_EIOFormat_32_msb, ABE_EIOFormat_32_2x16, ABE_EIOFormat_32_2xMono};
+
+
+typedef struct abeiodescriptorTag{
+ ABE_uint16 drift_ASRC; //0 /* [W] asrc output used for the next ASRC call (+/- 1 / 0)*/
+ ABE_uint16 drift_io; //2 /* [W] asrc output used for controlling the number of samples to be exchanged (+/- 1 / 0) */
+ ABE_uint16 hw_ctrl_addr; //4 /* DMAReq address or HOST IRQ buffer address (ATC ADDRESS) */
+ ABE_uchar copy_func_index; //6 /* index of the copy subroutine */
+ ABE_uchar x_io; //7 /* X number of SMEM samples to move */
+ ABE_uchar data_size; //8 /* 0 for mono data, 1 for stereo data */
+ ABE_uchar smem_addr; //9 /* internal SMEM buffer INITPTR pointer index */
+ ABE_uchar atc_irq_data; //10 /* data content to be loaded to "hw_ctrl_addr" */
+ ABE_uchar atc_address; //11 /* ATC descriptor address */
+ ABE_uchar threshold_1; //12 /* THR1; For stereo data, THR1 is provided by HAL as THR1<<1 */
+ ABE_uchar threshold_2; //13 /* THR2; For stereo data, THR2 is provided by HAL as THR2<<1 */
+ ABE_uchar update_1; //14 /* UP_1; For stereo data, UP_1 is provided by HAL as UP_1<<1 */
+ ABE_uchar update_2; //15 /* UP_2; For stereo data, UP_2 is provided by HAL as UP_2<<1 */
+ ABE_uchar flow_counter; //16 /* Flow error counter */
+ ABE_uchar direction_rw; //17 /* Read DMEM =0, Write DMEM =3 (ATC offset of the access pointer) */
+ ABE_uchar padding16[2]; // To keep 32bits alignment,
+ } ABE_SIODescriptor;
+
+typedef ABE_SIODescriptor* pABE_SIODescriptor;
+typedef ABE_SIODescriptor** ppABE_SIODescriptor;
+
+typedef struct abepingpongdescriptorTag{
+ ABE_uint16 drift_ASRC; //0 /* [W] asrc output used for the next ASRC call (+/- 1 / 0)*/
+ ABE_uint16 drift_io; //2 /* [W] asrc output used for controlling the number of samples to be exchanged (+/- 1 / 0) */
+ ABE_uint16 hw_ctrl_addr; //4 /* DMAReq address or HOST IRQ buffer address (ATC ADDRESS) */
+ ABE_uchar copy_func_index; //6 /* index of the copy subroutine */
+ ABE_uchar x_io; //7 /* X number of SMEM samples to move */
+ ABE_uchar data_size; //8 /* 0 for mono data, 1 for stereo data */
+ ABE_uchar smem_addr; //9 /* internal SMEM buffer INITPTR pointer index */
+ ABE_uchar atc_irq_data; //10 /* data content to be loaded to "hw_ctrl_addr" */
+ ABE_uchar counter; //11 /* ping/pong buffer flag */
+ ABE_uint16 workbuff_BaseAddr; //12 /* current Base address of the working buffer */
+ ABE_uint16 workbuff_Samples; //14 /* samples left in the working buffer */
+ ABE_uint16 nextbuff0_BaseAddr; //16 /* Base address of the ping/pong buffer 0 */
+ ABE_uint16 nextbuff0_Samples; //18 /* samples available in the ping/pong buffer 0 */
+ ABE_uint16 nextbuff1_BaseAddr; //20 /* Base address of the ping/pong buffer 1 */
+ ABE_uint16 nextbuff1_Samples; //22 /* samples available in the ping/pong buffer 1 */
+ } ABE_SPingPongDescriptor;
+
+typedef ABE_SPingPongDescriptor* pABE_SPingPongDescriptor;
+
+#ifdef __chess__
+#define drift_ASRC 0 /* [W] asrc output used for the next ASRC call (+/- 1 / 0)*/
+#define drift_io 2 /* [W] asrc output used for controlling the number of samples to be exchanged (+/- 1 / 0) */
+#define hw_ctrl_addr 4 /* DMAReq address or HOST IRQ buffer address (ATC ADDRESS) */
+#define copy_func_index 6 /* index of the copy subroutine */
+#define x_io 7 /* X number of SMEM samples to move */
+#define data_size 8 /* 0 for mono data, 1 for stereo data */
+#define smem_addr 9 /* internal SMEM buffer INITPTR pointer index */
+#define atc_irq_data 10 /* data content to be loaded to "hw_ctrl_addr" */
+#define atc_address 11 /* ATC descriptor address */
+#define threshold_1 12 /* THR1; For stereo data, THR1 is provided by HAL as THR1<<1 */
+#define threshold_2 13 /* THR2; For stereo data, THR2 is provided by HAL as THR2<<1 */
+#define update_1 14 /* UP_1; For stereo data, UP_1 is provided by HAL as UP_1<<1 */
+#define update_2 15 /* UP_2; For stereo data, UP_2 is provided by HAL as UP_2<<1 */
+#define flow_counter 16 /* Flow error counter */
+#define direction_rw 17 /* Read DMEM =0, Write DMEM =3 (ATC offset of the access pointer) */
+#define counter 11 /* ping/pong buffer flag */
+#define workbuff_BaseAddr 12 /* current Base address of the working buffer */
+#define workbuff_Samples 14 /* samples left in the working buffer */
+#define nextbuff0_BaseAddr 16 /* Base address of the ping/pong buffer 0 */
+#define nextbuff0_Samples 18 /* samples available in the ping/pong buffer 0 */
+#define nextbuff1_BaseAddr 20 /* Base address of the ping/pong buffer 1 */
+#define nextbuff1_Samples 22 /* samples available in the ping/pong buffer 1 */
+#endif
+
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+/*
+typedef struct abedatafifodescrTag{
+ ABE_int32* writePtr;
+ ABE_int32* readPtr;
+ ABE_int32* fifoStartAddr;
+ ABE_int32* fifoEndAddr;
+} ABE_SDataFiFoDescr;
+typedef ABE_SDataFiFoDescr* pABE_SDataFiFoDescr;
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+typedef struct abedebugitemTag{
+ ABE_uint16 time;
+ ABE_uint16 data;
+} ABE_SDebugItem;
+typedef ABE_SDebugItem* pABE_SDebugItem;
+
+typedef ABE_SDebugItem ABE_TDebugFifo[DEBUG_FIFO_LENGTH];
+typedef ABE_TDebugFifo* pABE_TDebugFifo;
+
+typedef struct abedebugfifo{
+ pABE_SDebugItem readPtr;
+ ABE_uint16 fill; // Filling data to 32 bits alignment
+ pABE_SDebugItem writePtr;
+ pABE_SDebugItem fifoEndAddr;
+} ABE_SDebugFifoDescr;
+typedef ABE_SDebugFifoDescr* pABE_SDebugFifoDescr;
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+typedef struct abesettaskTag{ // Used for multiFrame update
+ ABE_uint16 index; // index in multiFrame table
+ pABE_STask taskPtr; // task pointer to be set at multiFrame[0][index]
+} ABE_SSetTask;
+typedef ABE_SSetTask* pABE_SSetTask;
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+typedef struct abebigcircbufTag{ //
+ ABE_int16 tableAddr; // Byte address
+ ABE_int16 tableLength; // In samples
+ ABE_int16 writeIndex; //
+ ABE_uint16 fill; // Filling data to 32 bits alignment
+ ABE_int16 readIndex; //
+ ABE_int16 threshold; //
+ ABE_int16 IRQ; //
+ ABE_int16 IRQValue; //
+} ABE_SBigCircularBufferDescr;
+typedef ABE_SBigCircularBufferDescr* pABE_SBigCircularBufferDescr;
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ABE_TYPEDEF_H_ */
diff --git a/sound/soc/codecs/abe/abehal.dsp b/sound/soc/codecs/abe/abehal.dsp
new file mode 100644
index 000000000000..c58029ec73e0
--- /dev/null
+++ b/sound/soc/codecs/abe/abehal.dsp
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Project File - Name="ABEHAL" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ABEHAL - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ABEHAL.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ABEHAL.mak" CFG="ABEHAL - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ABEHAL - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ABEHAL - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "ABEHAL"
+# PROP Scc_LocalPath "m:\a0918484_L1doc\ABE_Firmware\HAL\src"
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ABEHAL - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x3009 /d "NDEBUG"
+# ADD RSC /l 0x3009 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "ABEHAL - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x3009 /d "_DEBUG"
+# ADD RSC /l 0x3009 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "ABEHAL - Win32 Release"
+# Name "ABEHAL - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ABE_API.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_DBG.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_EXT.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_INI.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_IRQ.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_LIB.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_MAIN.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_SEQ.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_TEST.C
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ABE_API.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_CM_ADDR.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_COF.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_DAT.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_DBG.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_DEF.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_define.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_DM_ADDR.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_EXT.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_functionsId.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_FW.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_INITxxx_labels.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_LIB.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_MAIN.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_REF.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_SEQ.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_SM_ADDR.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_SYS.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_taskId.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_TEST.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_TYP.H
+# End Source File
+# Begin Source File
+
+SOURCE=.\ABE_typedef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\C_ABE_FW.CM
+# End Source File
+# Begin Source File
+
+SOURCE=.\C_ABE_FW.lDM
+# End Source File
+# Begin Source File
+
+SOURCE=.\C_ABE_FW.PM
+# End Source File
+# Begin Source File
+
+SOURCE=.\C_ABE_FW.SM32
+# End Source File
+# Begin Source File
+
+SOURCE=.\C_ABE_FW_SIZE.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CodingStyle.txt
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/sound/soc/codecs/abe/abehal.dsw b/sound/soc/codecs/abe/abehal.dsw
new file mode 100644
index 000000000000..f28cce8c49d5
--- /dev/null
+++ b/sound/soc/codecs/abe/abehal.dsw
@@ -0,0 +1,33 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ABEHAL"=.\ABEHAL.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ ABEHAL
+ m:\a0918484_L1doc\ABE_Firmware\HAL\src
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 4dbb853eef5a..efe38a404b96 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -26,7 +26,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -174,7 +174,7 @@ static int twl4030_write(struct snd_soc_codec *codec,
{
twl4030_write_reg_cache(codec, reg, value);
if (likely(reg < TWL4030_REG_SW_SHADOW))
- return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value,
+ return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value,
reg);
else
return 0;
@@ -230,25 +230,25 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
* Things to mute: Earpiece, PreDrivL/R, CarkitL/R
*/
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
reg_val & (~TWL4030_EAR_GAIN),
TWL4030_REG_EAR_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
reg_val & (~TWL4030_PREDL_GAIN),
TWL4030_REG_PREDL_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
reg_val & (~TWL4030_PREDR_GAIN),
TWL4030_REG_PREDL_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
reg_val & (~TWL4030_PRECKL_GAIN),
TWL4030_REG_PRECKL_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
reg_val & (~TWL4030_PRECKR_GAIN),
TWL4030_REG_PRECKR_CTL);
@@ -304,7 +304,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec)
do {
/* this takes a little while, so don't slam i2c */
udelay(2000);
- twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
+ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
TWL4030_REG_ANAMICL);
} while ((i++ < 100) &&
((byte & TWL4030_CNCL_OFFSET_START) ==
@@ -645,7 +645,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
twl4030->sysclk) + 1);
/* Bypass the reg_cache to mute the headset */
- twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
hs_gain & (~0x0f),
TWL4030_REG_HS_GAIN_SET);
diff --git a/sound/soc/codecs/twl6030.h b/sound/soc/codecs/twl6030.h
new file mode 100644
index 000000000000..713330e963d3
--- /dev/null
+++ b/sound/soc/codecs/twl6030.h
@@ -0,0 +1,138 @@
+/*
+ * ALSA SoC TWL6030 codec driver
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TWL6030_H__
+#define __TWL6030_H__
+
+#define TWL6030_REG_ASICID 0x01
+#define TWL6030_REG_ASICREV 0x02
+#define TWL6030_REG_INTID 0x03
+#define TWL6030_REG_INTMR 0x04
+#define TWL6030_REG_NCPCTL 0x05
+#define TWL6030_REG_LDOCTL 0x06
+#define TWL6030_REG_HPPLLCTL 0x07
+#define TWL6030_REG_LPPLLCTL 0x08
+#define TWL6030_REG_LPPLLDIV 0x09
+#define TWL6030_REG_AMICBCTL 0x0A
+#define TWL6030_REG_DMICBCTL 0x0B
+#define TWL6030_REG_MICLCTL 0x0C
+#define TWL6030_REG_MICRCTL 0x0D
+#define TWL6030_REG_MICGAIN 0x0E
+#define TWL6030_REG_LINEGAIN 0x0F
+#define TWL6030_REG_HSLCTL 0x10
+#define TWL6030_REG_HSRCTL 0x11
+#define TWL6030_REG_HSGAIN 0x12
+#define TWL6030_REG_EARCTL 0x13
+#define TWL6030_REG_HFLCTL 0x14
+#define TWL6030_REG_HFLGAIN 0x15
+#define TWL6030_REG_HFRCTL 0x16
+#define TWL6030_REG_HFRGAIN 0x17
+#define TWL6030_REG_VIBCTLL 0x18
+#define TWL6030_REG_VIBDATL 0x19
+#define TWL6030_REG_VIBCTLR 0x1A
+#define TWL6030_REG_VIBDATR 0x1B
+#define TWL6030_REG_HKCTL1 0x1C
+#define TWL6030_REG_HKCTL2 0x1D
+#define TWL6030_REG_GPOCTL 0x1E
+#define TWL6030_REG_ALB 0x1F
+#define TWL6030_REG_DLB 0x20
+#define TWL6030_REG_TRIM1 0x28
+#define TWL6030_REG_TRIM2 0x29
+#define TWL6030_REG_TRIM3 0x2A
+#define TWL6030_REG_HSOTRIM 0x2B
+#define TWL6030_REG_HFOTRIM 0x2C
+#define TWL6030_REG_ACCCTL 0x2D
+#define TWL6030_REG_STATUS 0x2E
+
+#define TWL6030_CACHEREGNUM (TWL6030_REG_STATUS + 1)
+
+#define TWL6030_VIOREGNUM 18
+#define TWL6030_VDDREGNUM 21
+
+/* INTID (0x03) fields */
+
+#define TWL6030_THINT 0x01
+#define TWL6030_PLUGINT 0x02
+#define TWL6030_UNPLUGINT 0x04
+#define TWL6030_HOOKINT 0x08
+#define TWL6030_HFINT 0x10
+#define TWL6030_VIBINT 0x20
+#define TWL6030_READYINT 0x40
+
+/* INTMR (0x04) fields */
+
+#define TWL6030_READYMSK 0x40
+#define TWL6030_ALLINT_MSK 0x7B
+
+/* NCPCTL (0x05) fields */
+
+#define TWL6030_NCPENA 0x01
+#define TWL6030_NCPOPEN 0x40
+
+/* LDOCTL (0x06) fields */
+
+#define TWL6030_LSLDOENA 0x01
+#define TWL6030_HSLDOENA 0x04
+#define TWL6030_REFENA 0x40
+#define TWL6030_OSCENA 0x80
+
+/* HPPLLCTL (0x07) fields */
+
+#define TWL6030_HPLLENA 0x01
+#define TWL6030_HPLLRST 0x02
+#define TWL6030_HPLLBP 0x04
+#define TWL6030_HPLLSQRENA 0x08
+#define TWL6030_HPLLSQRBP 0x10
+#define TWL6030_MCLK_12000KHZ (0 << 5)
+#define TWL6030_MCLK_19200KHZ (1 << 5)
+#define TWL6030_MCLK_26000KHZ (2 << 5)
+#define TWL6030_MCLK_38400KHZ (3 << 5)
+#define TWL6030_MCLK_MSK 0x60
+
+/* LPPLLCTL (0x08) fields */
+
+#define TWL6030_LPLLENA 0x01
+#define TWL6030_LPLLRST 0x02
+#define TWL6030_LPLLSEL 0x04
+#define TWL6030_LPLLFIN 0x08
+#define TWL6030_HPLLSEL 0x10
+
+/* HSLCTL (0x10) fields */
+
+#define TWL6030_HSDACMODEL 0x02
+#define TWL6030_HSDRVMODEL 0x08
+
+/* HSRCTL (0x11) fields */
+
+#define TWL6030_HSDACMODER 0x02
+#define TWL6030_HSDRVMODER 0x08
+
+/* ACCCTL (0x2D) fields */
+
+#define TWL6030_RESETSPLIT 0x04
+
+#define TWL6030_SYSCLK_SEL_LPPLL 1
+#define TWL6030_SYSCLK_SEL_HPPLL 2
+
+#define TWL6030_HPPLL_ID 1
+#define TWL6030_LPPLL_ID 2
+
+#endif /* End of __TWL6030_H__ */
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index b771238662b6..1d49dac409a8 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -6,6 +6,9 @@ config SND_OMAP_SOC_MCBSP
tristate
select OMAP_MCBSP
+config SND_OMAP_SOC_ABE
+ tristate
+
config SND_OMAP_SOC_N810
tristate "SoC Audio support for Nokia N810"
depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
@@ -56,6 +59,21 @@ config SND_OMAP_SOC_SDP3430
Say Y if you want to add support for SoC audio on Texas Instruments
SDP3430.
+config SND_OMAP_SOC_SDP4430
+ tristate "SoC Audio support for Texas Instruments SDP4430"
+ depends on TWL6030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+ select SND_OMAP_SOC_ABE
+ select SND_SOC_ABE_TWL6030
+ help
+ Say Y if you want to add support for SoC audio on Texas Instruments
+ SDP4430.
+
+config SND_OMAP_SOC_HDMI
+ tristate "SoC Audio support for HDMI interface on SDP4430"
+ depends on SND_OMAP_SOC_SDP4430
+ help
+ Say Y if you want to add support for HDMI interface on SDP4430
+
config SND_OMAP_SOC_OMAP3_PANDORA
tristate "SoC Audio support for OMAP3 Pandora"
depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index a37f49862389..e918f631ecc5 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,9 +1,13 @@
# OMAP Platform Support
snd-soc-omap-objs := omap-pcm.o
snd-soc-omap-mcbsp-objs := omap-mcbsp.o
+snd-soc-omap-abe-objs := mcpdm.o omap-abe.o
+snd-soc-omap-hdmi-objs:= omap-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
+obj-$(CONFIG_SND_OMAP_SOC_ABE) += snd-soc-omap-abe.o
+obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
@@ -12,6 +16,7 @@ snd-soc-overo-objs := overo.o
snd-soc-omap2evm-objs := omap2evm.o
snd-soc-omap3evm-objs := omap3evm.o
snd-soc-sdp3430-objs := sdp3430.o
+snd-soc-sdp4430-objs := sdp4430.o
snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
@@ -21,5 +26,6 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+obj-$(CONFIG_SND_OMAP_SOC_SDP4430) += snd-soc-sdp4430.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
new file mode 100644
index 000000000000..ccfe9af5faa2
--- /dev/null
+++ b/sound/soc/omap/mcpdm.c
@@ -0,0 +1,491 @@
+/*
+ * mcpdm.c -- McPDM interface driver
+ *
+ * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, 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/device.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include "mcpdm.h"
+
+static struct omap_mcpdm *mcpdm;
+
+static void omap_mcpdm_write(u16 reg, u32 val)
+{
+ __raw_writel(val, mcpdm->io_base + reg);
+}
+
+static int omap_mcpdm_read(u16 reg)
+{
+ return __raw_readl(mcpdm->io_base + reg);
+}
+
+void omap_mcpdm_reg_dump(void)
+{
+ dev_dbg(mcpdm->dev, "***********************\n");
+ dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
+ dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_IRQSTATUS));
+ dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_IRQENABLE_SET));
+ dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
+ dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_IRQWAKE_EN));
+ dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_DMAENABLE_SET));
+ dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
+ dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_DMAWAKEEN));
+ dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_CTRL));
+ dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_DN_DATA));
+ dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_UP_DATA));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
+ dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
+ omap_mcpdm_read(MCPDM_DN_OFFSET));
+ dev_dbg(mcpdm->dev, "***********************\n");
+}
+EXPORT_SYMBOL(omap_mcpdm_reg_dump);
+
+void omap_mcpdm_reset(int links, int reset)
+{
+ int ctrl = omap_mcpdm_read(MCPDM_CTRL);
+
+ if (links & MCPDM_UPLINK) {
+ if (reset)
+ ctrl |= SW_UP_RST;
+ else
+ ctrl &= ~SW_UP_RST;
+ }
+
+ if (links & MCPDM_DOWNLINK) {
+ if (reset)
+ ctrl |= SW_DN_RST;
+ else
+ ctrl &= ~SW_DN_RST;
+ }
+
+ omap_mcpdm_write(MCPDM_CTRL, ctrl);
+}
+EXPORT_SYMBOL(omap_mcpdm_reset);
+
+void omap_mcpdm_start(int stream)
+{
+ int ctrl = omap_mcpdm_read(MCPDM_CTRL);
+
+ if (stream)
+ ctrl |= mcpdm->up_channels;
+ else
+ ctrl |= mcpdm->dn_channels;
+
+ omap_mcpdm_write(MCPDM_CTRL, ctrl);
+}
+EXPORT_SYMBOL(omap_mcpdm_start);
+
+void omap_mcpdm_stop(int stream)
+{
+ int ctrl = omap_mcpdm_read(MCPDM_CTRL);
+
+ if (stream)
+ ctrl &= ~mcpdm->up_channels;
+ else
+ ctrl &= ~mcpdm->dn_channels;
+
+ omap_mcpdm_write(MCPDM_CTRL, ctrl);
+}
+EXPORT_SYMBOL(omap_mcpdm_stop);
+
+static int omap_mcpdm_get_channels(int links, int channels)
+{
+ int count;
+
+ if (links & MCPDM_UPLINK)
+ channels &= PDM_UP_MASK | PDM_STATUS_MASK;
+
+ if (links & MCPDM_DOWNLINK)
+ channels &= PDM_DN_MASK | PDM_CMD_MASK;
+
+ /* Brian Kernighan's method for counting set bits */
+ for (count = 0; channels; count++)
+ channels &= channels - 1;
+
+ return count;
+}
+
+int omap_mcpdm_set_uplink(struct omap_mcpdm_link *uplink)
+{
+ int irq_mask = 0;
+ int ctrl;
+
+ if (!uplink)
+ return -EINVAL;
+
+ mcpdm->uplink = uplink;
+
+ /* Enable irq request generation */
+ irq_mask |= uplink->irq_mask & UPLINK_IRQ_MASK;
+ omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
+
+ /* Configure uplink threshold */
+ if (uplink->threshold > UP_THRES_MAX)
+ uplink->threshold = UP_THRES_MAX;
+
+ omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
+
+ /* Configure DMA controller */
+ omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
+
+ /* Set pdm out format */
+ ctrl = omap_mcpdm_read(MCPDM_CTRL);
+ ctrl &= ~PDMOUTFORMAT;
+ ctrl |= uplink->format & PDMOUTFORMAT;
+
+ /* Uplink channels */
+ mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
+
+ omap_mcpdm_write(MCPDM_CTRL, ctrl);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_set_uplink);
+
+int omap_mcpdm_set_downlink(struct omap_mcpdm_link *downlink)
+{
+ int irq_mask = 0;
+ int ctrl;
+
+ if (!downlink)
+ return -EINVAL;
+
+ mcpdm->downlink = downlink;
+
+ /* Enable irq request generation */
+ irq_mask |= downlink->irq_mask & DOWNLINK_IRQ_MASK;
+ omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
+
+ /* Configure uplink threshold */
+ if (downlink->threshold > DN_THRES_MAX)
+ downlink->threshold = DN_THRES_MAX;
+
+ omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
+
+ /* Enable DMA request generation */
+ omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
+
+ /* Set pdm out format */
+ ctrl = omap_mcpdm_read(MCPDM_CTRL);
+ ctrl &= ~PDMOUTFORMAT;
+ ctrl |= downlink->format & PDMOUTFORMAT;
+
+ /* Downlink channels */
+ mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
+
+ omap_mcpdm_write(MCPDM_CTRL, ctrl);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_set_downlink);
+
+int omap_mcpdm_clr_uplink(struct omap_mcpdm_link *uplink)
+{
+ int irq_mask = 0;
+
+ if (!uplink)
+ return -EINVAL;
+
+ /* Disable irq request generation */
+ irq_mask |= uplink->irq_mask & UPLINK_IRQ_MASK;
+ omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
+
+ /* Disable DMA request generation */
+ omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
+
+ /* Clear Downlink channels */
+ mcpdm->up_channels = 0;
+
+ mcpdm->uplink = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_clr_uplink);
+
+int omap_mcpdm_clr_downlink(struct omap_mcpdm_link *downlink)
+{
+ int irq_mask = 0;
+
+ if (!downlink)
+ return -EINVAL;
+
+ /* Disable irq request generation */
+ irq_mask |= downlink->irq_mask & DOWNLINK_IRQ_MASK;
+ omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
+
+ /* Disable DMA request generation */
+ omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
+
+ /* clear Downlink channels */
+ mcpdm->dn_channels = 0;
+
+ mcpdm->downlink = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_clr_downlink);
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+ struct omap_mcpdm *mcpdm_irq = dev_id;
+ int irq_status;
+
+ irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
+
+ /* Acknowledge irq event */
+ omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
+
+ switch (irq_status) {
+ case DN_IRQ_FULL:
+ case DN_IRQ_EMTPY:
+ dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
+ omap_mcpdm_reset(MCPDM_DOWNLINK, 1);
+ omap_mcpdm_set_downlink(mcpdm_irq->downlink);
+ omap_mcpdm_reset(MCPDM_DOWNLINK, 0);
+ break;
+ case DN_IRQ:
+ dev_dbg(mcpdm_irq->dev, "DN write request\n");
+ break;
+ case UP_IRQ_FULL:
+ case UP_IRQ_EMPTY:
+ dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
+ omap_mcpdm_reset(MCPDM_UPLINK, 1);
+ omap_mcpdm_set_uplink(mcpdm_irq->uplink);
+ omap_mcpdm_reset(MCPDM_UPLINK, 0);
+ break;
+ case UP_IRQ:
+ dev_dbg(mcpdm_irq->dev, "UP write request\n");
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+int omap_mcpdm_request(void)
+{
+ int ret;
+
+ clk_enable(mcpdm->clk);
+
+ spin_lock(&mcpdm->lock);
+
+ if (!mcpdm->free) {
+ dev_err(mcpdm->dev, "McPDM interface is in use\n");
+ spin_unlock(&mcpdm->lock);
+ return -EBUSY;
+ }
+ mcpdm->free = 0;
+
+ spin_unlock(&mcpdm->lock);
+
+ /* Disable lines while request is ongoing */
+ omap_mcpdm_write(MCPDM_CTRL, 0x00);
+
+ ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+ 0, "McPDM", (void *)mcpdm);
+ if (ret) {
+ dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_request);
+
+void omap_mcpdm_free(void)
+{
+ clk_disable(mcpdm->clk);
+
+ spin_lock(&mcpdm->lock);
+ if (mcpdm->free) {
+ dev_err(mcpdm->dev, "McPDM interface is already free\n");
+ spin_unlock(&mcpdm->lock);
+ return;
+ }
+ mcpdm->free = 1;
+ spin_unlock(&mcpdm->lock);
+
+ free_irq(mcpdm->irq, (void *)mcpdm);
+}
+EXPORT_SYMBOL(omap_mcpdm_free);
+
+int omap_mcpdm_set_offset(int offset1, int offset2)
+{
+ int offset;
+
+ if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
+ return -EINVAL;
+
+ offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
+
+ /* Enable/disable offset cancellation for downlink channel 1 */
+ if (offset1)
+ offset |= DN_OFST_RX1_EN;
+ else
+ offset &= ~DN_OFST_RX1_EN;
+
+ /* Enable/disable offset cancellation for downlink channel 2 */
+ if (offset2)
+ offset |= DN_OFST_RX2_EN;
+ else
+ offset &= ~DN_OFST_RX2_EN;
+
+ omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcpdm_set_offset);
+
+static int __devinit omap_mcpdm_probe(struct platform_device *pdev)
+{
+ struct omap_mcpdm_platform_data *pdata = pdev->dev.platform_data;
+ int ret = 0;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "McPDM device initialized without "
+ "platform data\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ dev_dbg(&pdev->dev, "Initializing OMAP McPDM driver \n");
+
+ mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+ if (!mcpdm) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ spin_lock_init(&mcpdm->lock);
+ mcpdm->free = 1;
+ mcpdm->phys_base = pdata->phys_base;
+ mcpdm->io_base = ioremap(mcpdm->phys_base, SZ_4K);
+ if (!mcpdm->io_base) {
+ ret = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ mcpdm->irq = pdata->irq;
+
+ /* FIXME: Enable this ones correct clk nodes available */
+ if (!cpu_is_omap44xx()) {
+ mcpdm->clk = clk_get(&pdev->dev, "fclk");
+ if (IS_ERR(mcpdm->clk)) {
+ ret = PTR_ERR(mcpdm->clk);
+ dev_err(&pdev->dev, "unable to get fclk: %d\n", ret);
+ goto err_clk;
+ }
+ }
+
+ mcpdm->pdata = pdata;
+ mcpdm->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mcpdm);
+
+
+ return 0;
+
+err_clk:
+ iounmap(mcpdm->io_base);
+err_ioremap:
+ kfree(mcpdm);
+exit:
+ return ret;
+}
+
+static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
+{
+ struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (mcpdm_ptr) {
+ clk_disable(mcpdm_ptr->clk);
+ clk_put(mcpdm_ptr->clk);
+
+ iounmap(mcpdm_ptr->io_base);
+
+ mcpdm_ptr->clk = NULL;
+ mcpdm_ptr->free = 0;
+ mcpdm_ptr->dev = NULL;
+ }
+
+ printk(KERN_INFO "McPDM driver removed \n");
+
+ return 0;
+}
+
+static struct platform_driver omap_mcpdm_driver = {
+ .probe = omap_mcpdm_probe,
+ .remove = omap_mcpdm_remove,
+ .driver = {
+ .name = "omap-mcpdm",
+ },
+};
+
+static struct platform_device *omap_mcpdm_device;
+
+static struct omap_mcpdm_platform_data mcpdm_pdata = {
+ .phys_base = OMAP44XX_MCPDM_BASE,
+ .irq = INT_44XX_MCPDM_IRQ,
+};
+
+static int __init omap_mcpdm_init(void)
+{
+ int ret;
+ struct platform_device *device;
+
+ device = platform_device_alloc("omap-mcpdm", -1);
+ device->dev.platform_data = &mcpdm_pdata;
+
+ omap_mcpdm_device = device;
+ (void) platform_device_add(omap_mcpdm_device);
+
+ ret = platform_driver_register(&omap_mcpdm_driver);
+ if (ret)
+ goto error;
+ return 0;
+
+error:
+ printk(KERN_ERR "OMAP McPDM initialization error\n");
+ return ret;
+}
+arch_initcall(omap_mcpdm_init);
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
new file mode 100644
index 000000000000..c953e9519a29
--- /dev/null
+++ b/sound/soc/omap/mcpdm.h
@@ -0,0 +1,156 @@
+/*
+ * mcpdm.h -- Defines for McPDM driver
+ *
+ * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#define OMAP44XX_MCPDM_BASE 0x40132000
+#define OMAP44XX_MCPDM_L3_BASE 0x49032000
+
+/* McPDM registers */
+
+#define MCPDM_REVISION 0x00
+#define MCPDM_SYSCONFIG 0x10
+#define MCPDM_IRQSTATUS_RAW 0x24
+#define MCPDM_IRQSTATUS 0x28
+#define MCPDM_IRQENABLE_SET 0x2C
+#define MCPDM_IRQENABLE_CLR 0x30
+#define MCPDM_IRQWAKE_EN 0x34
+#define MCPDM_DMAENABLE_SET 0x38
+#define MCPDM_DMAENABLE_CLR 0x3C
+#define MCPDM_DMAWAKEEN 0x40
+#define MCPDM_CTRL 0x44
+#define MCPDM_DN_DATA 0x48
+#define MCPDM_UP_DATA 0x4C
+#define MCPDM_FIFO_CTRL_DN 0x50
+#define MCPDM_FIFO_CTRL_UP 0x54
+#define MCPDM_DN_OFFSET 0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define DN_IRQ (1 << 0)
+#define DN_IRQ_EMTPY (1 << 1)
+#define DN_IRQ_ALMST_EMPTY (1 << 2)
+#define DN_IRQ_FULL (1 << 3)
+
+#define UP_IRQ (1 << 8)
+#define UP_IRQ_EMPTY (1 << 9)
+#define UP_IRQ_ALMST_FULL (1 << 10)
+#define UP_IRQ_FULL (1 << 11)
+
+#define DOWNLINK_IRQ_MASK 0x00F
+#define UPLINK_IRQ_MASK 0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define DMA_DN_ENABLE 0x1
+#define DMA_UP_ENABLE 0x2
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define PDM_UP1_EN 0x0001
+#define PDM_UP2_EN 0x0002
+#define PDM_UP3_EN 0x0004
+#define PDM_DN1_EN 0x0008
+#define PDM_DN2_EN 0x0010
+#define PDM_DN3_EN 0x0020
+#define PDM_DN4_EN 0x0040
+#define PDM_DN5_EN 0x0080
+#define PDMOUTFORMAT 0x0100
+#define CMD_INT 0x0200
+#define STATUS_INT 0x0400
+#define SW_UP_RST 0x0800
+#define SW_DN_RST 0x1000
+#define PDM_UP_MASK 0x007
+#define PDM_DN_MASK 0x0F8
+#define PDM_CMD_MASK 0x200
+#define PDM_STATUS_MASK 0x400
+
+
+#define PDMOUTFORMAT_LJUST (0 << 8)
+#define PDMOUTFORMAT_RJUST (1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define UP_THRES_MAX 0xF
+#define DN_THRES_MAX 0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define DN_OFST_RX1_EN 0x0001
+#define DN_OFST_RX2_EN 0x0100
+
+#define DN_OFST_RX1 1
+#define DN_OFST_RX2 9
+#define DN_OFST_MAX 0x1F
+
+#define MCPDM_UPLINK 1
+#define MCPDM_DOWNLINK 2
+
+struct omap_mcpdm_link {
+ int irq_mask;
+ int threshold;
+ int format;
+ int channels;
+};
+
+struct omap_mcpdm_platform_data {
+ unsigned long phys_base;
+ u16 irq;
+};
+
+struct omap_mcpdm {
+ struct device *dev;
+ unsigned long phys_base;
+ void __iomem *io_base;
+ u8 free;
+ int irq;
+
+ spinlock_t lock;
+ struct omap_mcpdm_platform_data *pdata;
+ struct clk *clk;
+ struct omap_mcpdm_link *downlink;
+ struct omap_mcpdm_link *uplink;
+ struct completion irq_completion;
+
+ int dn_channels;
+ int up_channels;
+};
+
+void omap_mcpdm_reg_dump(void);
+void omap_mcpdm_reset(int links, int reset);
+void omap_mcpdm_start(int stream);
+void omap_mcpdm_stop(int stream);
+int omap_mcpdm_set_uplink(struct omap_mcpdm_link *uplink);
+int omap_mcpdm_set_downlink(struct omap_mcpdm_link *downlink);
+int omap_mcpdm_clr_uplink(struct omap_mcpdm_link *uplink);
+int omap_mcpdm_clr_downlink(struct omap_mcpdm_link *downlink);
+int omap_mcpdm_request(void);
+void omap_mcpdm_free(void);
+int omap_mcpdm_set_offset(int offset1, int offset2);
diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c
new file mode 100644
index 000000000000..b75b405ddfce
--- /dev/null
+++ b/sound/soc/omap/omap-abe.c
@@ -0,0 +1,330 @@
+/*
+ * omap-abe.c -- OMAP ALSA SoC DAI driver using Audio Backend
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, 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/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/control.h>
+#include <mach/dma.h>
+#include "mcpdm.h"
+#include "omap-pcm.h"
+#include "omap-abe.h"
+#include "../codecs/abe/abe_main.h"
+
+#define OMAP_ABE_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+struct omap_mcpdm_data {
+ struct omap_mcpdm_link *links;
+ int active[2];
+ int requested;
+};
+
+static struct omap_mcpdm_link omap_mcpdm_links[] = {
+ /* downlink */
+ {
+ .irq_mask = DN_IRQ_EMTPY | DN_IRQ_FULL,
+ .threshold = 1,
+ .format = PDMOUTFORMAT_LJUST,
+ .channels = PDM_DN_MASK | PDM_CMD_MASK,
+ },
+ /* uplink */
+ {
+ .irq_mask = UP_IRQ_EMPTY | UP_IRQ_FULL,
+ .threshold = 1,
+ .format = PDMOUTFORMAT_LJUST,
+ .channels = PDM_UP_MASK | PDM_STATUS_MASK |
+ PDM_DN_MASK | PDM_CMD_MASK,
+ },
+};
+
+static struct omap_mcpdm_data mcpdm_data = {
+ .links = omap_mcpdm_links,
+ .active = {0},
+ .requested = 0,
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_abe_dai_dma_params[] = {
+ {
+ .name = "Audio downlink",
+ .data_type = OMAP_DMA_DATA_TYPE_S32,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+ {
+ .name = "Audio uplink",
+ .data_type = OMAP_DMA_DATA_TYPE_S32,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+ },
+};
+
+static int omap_abe_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ int err = 0;
+
+ if (!mcpdm_priv->requested++)
+ err = omap_mcpdm_request();
+
+ return err;
+}
+
+static void omap_abe_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+
+ if (!--mcpdm_priv->requested)
+ omap_mcpdm_free();
+}
+
+static int omap_abe_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ int stream = substream->stream;
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!mcpdm_priv->active[stream]++)
+ omap_mcpdm_start(stream);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (!--mcpdm_priv->active[stream])
+ omap_mcpdm_stop(stream);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int omap_abe_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ int err, stream = substream->stream, dma_req;
+ abe_dma_t dma_params;
+
+ /* get abe dma data */
+ switch (cpu_dai->id) {
+ case OMAP_ABE_MM_DAI:
+ if (stream) {
+ abe_read_port_address(MM_UL2_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ4;
+ } else {
+ abe_read_port_address(MM_DL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ0;
+ }
+ break;
+ case OMAP_ABE_TONES_DL_DAI:
+ if (stream)
+ return -EINVAL;
+ else {
+ abe_read_port_address(TONES_DL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ5;
+ }
+ break;
+ case OMAP_ABE_VOICE_DAI:
+ if (stream) {
+ abe_read_port_address(VX_UL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ2;
+ } else {
+ abe_read_port_address(VX_DL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ1;
+ }
+ break;
+ case OMAP_ABE_DIG_UPLINK_DAI:
+ if (stream) {
+ abe_read_port_address(MM_UL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ3;
+
+ } else
+ return -EINVAL;
+ break;
+ case OMAP_ABE_VIB_DAI:
+ if (stream)
+ return -EINVAL;
+ else {
+ abe_read_port_address(VIB_DL_PORT, &dma_params);
+ dma_req = OMAP44XX_DMM_ABE_DMAREQ6;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ omap_abe_dai_dma_params[stream].dma_req = dma_req;
+ omap_abe_dai_dma_params[stream].port_addr =
+ (unsigned long)dma_params.data;
+ omap_abe_dai_dma_params[stream].packet_size = dma_params.iter;
+ cpu_dai->dma_data = &omap_abe_dai_dma_params[stream];
+
+ if (stream)
+ err = omap_mcpdm_set_uplink(&mcpdm_links[stream]);
+ else
+ err = omap_mcpdm_set_downlink(&mcpdm_links[stream]);
+
+ return err;
+}
+
+static int omap_abe_dai_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ int err;
+
+ if (substream->stream)
+ err = omap_mcpdm_clr_uplink(&mcpdm_links[substream->stream]);
+ else
+ err = omap_mcpdm_clr_downlink(&mcpdm_links[substream->stream]);
+
+ return err;
+}
+
+static struct snd_soc_dai_ops omap_abe_dai_ops = {
+ .startup = omap_abe_dai_startup,
+ .shutdown = omap_abe_dai_shutdown,
+ .trigger = omap_abe_dai_trigger,
+ .hw_params = omap_abe_dai_hw_params,
+ .hw_free = omap_abe_dai_hw_free,
+};
+
+struct snd_soc_dai omap_abe_dai[] = {
+ {
+ .name = "omap-abe-mm",
+ .id = OMAP_ABE_MM_DAI,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ .private_data = &mcpdm_data,
+ },
+ {
+ .name = "omap-abe-tone-dl",
+ .id = OMAP_ABE_TONES_DL_DAI,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ .private_data = &mcpdm_data,
+ },
+ {
+ .name = "omap-abe-voice",
+ .id = OMAP_ABE_VOICE_DAI,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ .private_data = &mcpdm_data,
+ },
+ {
+ .name = "omap-abe-dig-ul",
+ .id = OMAP_ABE_DIG_UPLINK_DAI,
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ .private_data = &mcpdm_data,
+ },
+ {
+ .name = "omap-abe-vib",
+ .id = OMAP_ABE_VIB_DAI,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = OMAP_ABE_FORMATS,
+ },
+ .ops = &omap_abe_dai_ops,
+ .private_data = &mcpdm_data,
+ },
+};
+EXPORT_SYMBOL_GPL(omap_abe_dai);
+
+static int __init snd_omap_abe_init(void)
+{
+ return snd_soc_register_dais(omap_abe_dai, ARRAY_SIZE(omap_abe_dai));
+}
+module_init(snd_omap_abe_init);
+
+static void __exit snd_omap_abe_exit(void)
+{
+ snd_soc_unregister_dais(omap_abe_dai, ARRAY_SIZE(omap_abe_dai));
+}
+module_exit(snd_omap_abe_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("OMAP ABE SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-abe.h b/sound/soc/omap/omap-abe.h
new file mode 100644
index 000000000000..44f23940601f
--- /dev/null
+++ b/sound/soc/omap/omap-abe.h
@@ -0,0 +1,35 @@
+/*
+ * omap-abe.h
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define OMAP_ABE_MM_DAI 0
+#define OMAP_ABE_TONES_DL_DAI 1
+#define OMAP_ABE_VOICE_DAI 2
+#define OMAP_ABE_DIG_UPLINK_DAI 3
+#define OMAP_ABE_VIB_DAI 4
+
+extern struct snd_soc_dai omap_abe_dai[];
+
+#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
new file mode 100644
index 000000000000..bfbe5bf95bab
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.c
@@ -0,0 +1,159 @@
+/*
+ * omap-hdmi.c -- OMAP ALSA SoC DAI driver for HDMI audio
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Jorge Candelaria <x0107209@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, 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/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/control.h>
+#include <mach/dma.h>
+#include "omap-pcm.h"
+#include "omap-hdmi.h"
+#include <mach/hdmi_lib.h>
+
+#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_48000)
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+HDMI_AudioFormat_t audio_format_param;
+HDMI_AudioDma_t audio_dma_param;
+HDMI_Core_AudioConfig_t audio_core_config;
+
+static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
+ .name = "HDMI playback",
+ .dma_req = OMAP44XX_DSS_HDMI_DMA_REQ,
+ .port_addr = HDMI_WP + HDMI_WP_AUDIO_DATA,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int err = 0;
+
+ err = HDMI_W1_WrapperEnable(HDMI_WP);
+
+ return err;
+}
+
+static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int err = 0;
+
+ err = HDMI_W1_WrapperDisable(HDMI_WP);
+
+ return err;
+}
+
+static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ err = HDMI_W1_StartAudioTransfer(HDMI_WP);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ err = HDMI_W1_StopAudioTransfer(HDMI_WP);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int stereo_channels, channel_location, format;
+ int err;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
+ break;
+
+ case SNDRV_PCM_FORMAT_S32_LE:
+ omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+ omap_hdmi_dai_dma_params.packet_size = 0x20;
+
+ cpu_dai->dma_data = &omap_hdmi_dai_dma_params;
+
+ return err;
+}
+
+static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+ .startup = omap_hdmi_dai_startup,
+ .shutdown = omap_hdmi_dai_shutdown,
+ .trigger = omap_hdmi_dai_trigger,
+ .hw_params = omap_hdmi_dai_hw_params,
+};
+
+struct snd_soc_dai omap_hdmi_dai = {
+ .name = "omap-hdmi-dai",
+ .id = -1,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = OMAP_HDMI_RATES,
+ .formats = OMAP_HDMI_FORMATS,
+ },
+ .ops = &omap_hdmi_dai_ops,
+};
+EXPORT_SYMBOL_GPL(omap_hdmi_dai);
+
+static int __init snd_omap_hdmi_init(void)
+{
+ return snd_soc_register_dai(&omap_hdmi_dai);
+}
+module_init(snd_omap_hdmi_init);
+
+static void __exit snd_omap_hdmi_exit(void)
+{
+ snd_soc_unregister_dai(&omap_hdmi_dai);
+}
+module_exit(snd_omap_hdmi_exit);
+
+MODULE_AUTHOR("Jorge Candelaria <x0107209@ti.com");
+MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
new file mode 100644
index 000000000000..7f9c6509a177
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.h
@@ -0,0 +1,29 @@
+/*
+ * omap-hdmi.h
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Jorge Candelaria <x0107209@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_HDMI_H__
+#define __OMAP_HDMI_H__
+
+extern struct snd_soc_dai omap_hdmi_dai;
+
+#endif /* End of __OMAP_HDMI_H__ */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index a5d46a7b196a..72de1eb47ed0 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -238,6 +238,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
substream->stream ? "Audio Capture" : "Audio Playback";
omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
+ omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
+ OMAP_DMA_DATA_TYPE_S16;
+ omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode =
+ OMAP_DMA_SYNC_ELEMENT;
cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
if (mcbsp_data->configured) {
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
new file mode 100644
index 000000000000..5e4867241166
--- /dev/null
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -0,0 +1,246 @@
+/*
+ * omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, 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/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/control.h>
+#include <mach/dma.h>
+#include <mach/mcbsp.h>
+#include "mcpdm.h"
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+
+struct omap_mcpdm_data {
+ struct omap_mcpdm_link *links;
+ int active;
+};
+
+static struct omap_mcpdm_link omap_mcpdm_links[] = {
+ /* downlink */
+ {
+ .irq_mask = DN_IRQ_EMTPY | DN_IRQ_FULL,
+ .threshold = 1,
+ .format = PDMOUTFORMAT_LJUST,
+ },
+ /* uplink */
+ {
+ .irq_mask = UP_IRQ_EMPTY | UP_IRQ_FULL,
+ .threshold = 1,
+ .format = PDMOUTFORMAT_LJUST,
+ },
+};
+
+static struct omap_mcpdm_data mcpdm_data = {
+ .links = omap_mcpdm_links,
+ .active = 0,
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
+ {
+ .name = "Audio downlink",
+ .dma_req = OMAP44XX_DMA_MCPDM_DL,
+ .data_type = OMAP_DMA_DATA_TYPE_S32,
+ .sync_mode = OMAP_DMA_SYNC_ELEMENT,
+ .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
+ },
+ {
+ .name = "Audio uplink",
+ .dma_req = OMAP44XX_DMA_MCPDM_UP,
+ .data_type = OMAP_DMA_DATA_TYPE_S32,
+ .sync_mode = OMAP_DMA_SYNC_ELEMENT,
+ .port_addr = OMAP44XX_MCPDM_BASE + MCPDM_UP_DATA,
+ },
+};
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int err = 0;
+
+ if (!cpu_dai->active)
+ err = omap_mcpdm_request();
+
+ return err;
+}
+
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ if (!cpu_dai->active)
+ omap_mcpdm_free();
+}
+
+static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ int stream = substream->stream;
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!mcpdm_priv->active++)
+ omap_mcpdm_start(stream);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (!--mcpdm_priv->active)
+ omap_mcpdm_stop(stream);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ int stream = substream->stream;
+ int channels, err, link_mask = 0;
+
+ cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+ channels = params_channels(params);
+ switch (channels) {
+ case 4:
+ if (stream)
+ /* up to 2 channels for uplink */
+ return -EINVAL;
+ link_mask |= 1 << 3;
+ case 3:
+ if (stream)
+ /* up to 2 channels for uplink */
+ return -EINVAL;
+ link_mask |= 1 << 2;
+ case 2:
+ link_mask |= 1 << 1;
+ case 1:
+ link_mask |= 1 << 0;
+ break;
+ default:
+ /* unsupported number of channels */
+ return -EINVAL;
+ }
+
+ if (stream) {
+ mcpdm_links[stream].channels = link_mask << 0;
+ err = omap_mcpdm_set_uplink(&mcpdm_links[stream]);
+ } else {
+ mcpdm_links[stream].channels = link_mask << 3;
+ err = omap_mcpdm_set_downlink(&mcpdm_links[stream]);
+ }
+
+ return err;
+}
+
+static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+ struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ int err;
+
+ if (substream->stream)
+ err = omap_mcpdm_clr_uplink(&mcpdm_links[substream->stream]);
+ else
+ err = omap_mcpdm_clr_downlink(&mcpdm_links[substream->stream]);
+
+ return err;
+}
+
+static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
+ .startup = omap_mcpdm_dai_startup,
+ .shutdown = omap_mcpdm_dai_shutdown,
+ .trigger = omap_mcpdm_dai_trigger,
+ .hw_params = omap_mcpdm_dai_hw_params,
+ .hw_free = omap_mcpdm_dai_hw_free,
+};
+
+#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai omap_mcpdm_dai = {
+ .name = "omap-mcpdm",
+ .id = -1,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = OMAP_MCPDM_RATES,
+ .formats = OMAP_MCPDM_FORMATS,
+ },
+ .ops = &omap_mcpdm_dai_ops,
+ .private_data = &mcpdm_data,
+};
+EXPORT_SYMBOL_GPL(omap_mcpdm_dai);
+
+static int __init snd_omap_mcpdm_init(void)
+{
+ return snd_soc_register_dai(&omap_mcpdm_dai);
+}
+module_init(snd_omap_mcpdm_init);
+
+static void __exit snd_omap_mcpdm_exit(void)
+{
+ snd_soc_unregister_dai(&omap_mcpdm_dai);
+}
+module_exit(snd_omap_mcpdm_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("OMAP PDM SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644
index 000000000000..73b80d559345
--- /dev/null
+++ b/sound/soc/omap/omap-mcpdm.h
@@ -0,0 +1,29 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+extern struct snd_soc_dai omap_mcpdm_dai;
+
+#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 84a1950880eb..fd8e6f2d6af5 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -37,7 +37,8 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
.period_bytes_min = 32,
.period_bytes_max = 64 * 1024,
.periods_min = 2,
@@ -135,6 +136,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
struct omap_runtime_data *prtd = runtime->private_data;
struct omap_pcm_dma_data *dma_data = prtd->dma_data;
struct omap_dma_channel_params dma_params;
+ int bytes;
/* return if this is a bufferless transfer e.g.
* codec <--> BT codec or GSM modem -- lg FIXME */
@@ -146,9 +148,9 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
* Note: Regardless of interface data formats supported by OMAP McBSP
* or EAC blocks, internal representation is always fixed 16-bit/sample
*/
- dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
+ dma_params.data_type = dma_data->data_type;
dma_params.trigger = dma_data->dma_req;
- dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
+ dma_params.sync_mode = dma_data->sync_mode;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
@@ -156,6 +158,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
dma_params.src_start = runtime->dma_addr;
dma_params.dst_start = dma_data->port_addr;
dma_params.dst_port = OMAP_DMA_PORT_MPUI;
+ dma_params.dst_fi = dma_data->packet_size;
} else {
dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
@@ -163,6 +166,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
dma_params.src_start = dma_data->port_addr;
dma_params.dst_start = runtime->dma_addr;
dma_params.src_port = OMAP_DMA_PORT_MPUI;
+ dma_params.src_fi = dma_data->packet_size;
}
/*
* Set DMA transfer frame size equal to ALSA period size and frame
@@ -170,7 +174,8 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
* we can transfer the whole ALSA buffer with single DMA transfer but
* still can get an interrupt at each period bounary
*/
- dma_params.elem_count = snd_pcm_lib_period_bytes(substream) / 2;
+ bytes = snd_pcm_lib_period_bytes(substream);
+ dma_params.elem_count = bytes >> dma_data->data_type;
dma_params.frame_count = runtime->periods;
omap_set_dma_params(prtd->dma_ch, &dma_params);
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index 8d9d26916b05..d58082d568a8 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -29,6 +29,9 @@ struct omap_pcm_dma_data {
char *name; /* stream identifier */
int dma_req; /* DMA request line */
unsigned long port_addr; /* transmit/receive register */
+ int data_type; /* data type 8,16,32 */
+ int sync_mode; /* sync mode: element, packet */
+ int packet_size; /* packet size only in PACKET mode */
};
extern struct snd_soc_platform omap_soc_platform;
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
new file mode 100644
index 000000000000..729b9216d91c
--- /dev/null
+++ b/sound/soc/omap/sdp4430.c
@@ -0,0 +1,278 @@
+/*
+ * sdp4430.c -- SoC audio for TI OMAP4430 SDP
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, 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 <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/mux.h>
+
+#include "mcpdm.h"
+#include "omap-abe.h"
+#include "omap-pcm.h"
+#include "../codecs/abe-twl6030.h"
+#include "../codecs/twl6030.h"
+
+static struct snd_soc_dai_link sdp4430_dai[];
+static struct snd_soc_card snd_soc_sdp4430;
+static int twl6030_power_mode;
+
+static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = twl6030_power_mode;
+ return 0;
+}
+
+static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int clk_id, freq;
+ int ret;
+
+ if (twl6030_power_mode == ucontrol->value.integer.value[0])
+ return 0;
+
+ if (ucontrol->value.integer.value[0]) {
+ clk_id = TWL6030_SYSCLK_SEL_HPPLL;
+ freq = 12000000;
+ } else {
+ clk_id = TWL6030_SYSCLK_SEL_LPPLL;
+ freq = 32768;
+ }
+
+ /* set the codec mclk */
+ ret = snd_soc_dai_set_sysclk(sdp4430_dai[0].codec_dai, clk_id, freq,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ twl6030_power_mode = ucontrol->value.integer.value[0];
+
+ return 1;
+}
+
+static const char *power_texts[] = {"Low-Power", "High-Performance"};
+
+static const struct soc_enum sdp4430_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, power_texts),
+};
+
+static const struct snd_kcontrol_new sdp4430_controls[] = {
+ SOC_ENUM_EXT("TWL6030 Power Mode", sdp4430_enum[0],
+ sdp4430_get_power_mode, sdp4430_set_power_mode),
+};
+
+/* SDP4430 machine DAPM */
+static const struct snd_soc_dapm_widget sdp4430_twl6030_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Ext Mic", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* External Mics: MAINMIC, SUBMIC with bias*/
+ {"MAINMIC", NULL, "Main Mic Bias"},
+ {"SUBMIC", NULL, "Main Mic Bias"},
+ {"Main Mic Bias", NULL, "Ext Mic"},
+
+ /* External Speakers: HFL, HFR */
+ {"Ext Spk", NULL, "HFL"},
+ {"Ext Spk", NULL, "HFR"},
+
+ /* Headset Mic: HSMIC with bias */
+ {"HSMIC", NULL, "Headset Mic Bias"},
+ {"Headset Mic Bias", NULL, "Headset Mic"},
+
+ /* Headset Stereophone (Headphone): HSOL, HSOR */
+ {"Headset Stereophone", NULL, "HSOL"},
+ {"Headset Stereophone", NULL, "HSOR"},
+};
+
+static int sdp4430_twl6030_init(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ /* Add SDP4430 specific controls */
+ ret = snd_soc_add_controls(codec, sdp4430_controls,
+ ARRAY_SIZE(sdp4430_controls));
+ if (ret)
+ return ret;
+
+ /* Add SDP4430 specific widgets */
+ ret = snd_soc_dapm_new_controls(codec, sdp4430_twl6030_dapm_widgets,
+ ARRAY_SIZE(sdp4430_twl6030_dapm_widgets));
+ if (ret)
+ return ret;
+
+ /* Set up SDP4430 specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ /* SDP4430 connected pins */
+ snd_soc_dapm_enable_pin(codec, "Ext Mic");
+ snd_soc_dapm_enable_pin(codec, "Ext Spk");
+ snd_soc_dapm_enable_pin(codec, "Headset Mic");
+ snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
+
+ /* TWL6030 not connected pins */
+ snd_soc_dapm_nc_pin(codec, "AFML");
+ snd_soc_dapm_nc_pin(codec, "AFMR");
+
+ ret = snd_soc_dapm_sync(codec);
+
+ return ret;
+}
+
+#ifdef SND_OMAP_SOC_HDMI
+struct snd_so_dai null_dai = {
+ .name = "null",
+ .playback
+ {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .format = SNDRV_PCM_FORMAT_S32_LE,
+ },
+}
+#endif
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sdp4430_dai[] = {
+ {
+ .name = "abe-twl6030",
+ .stream_name = "Multimedia",
+ .cpu_dai = &omap_abe_dai[OMAP_ABE_MM_DAI],
+ .codec_dai = &abe_dai[0],
+ .init = sdp4430_twl6030_init,
+ },
+ {
+ .name = "abe-twl6030",
+ .stream_name = "Tones DL",
+ .cpu_dai = &omap_abe_dai[OMAP_ABE_TONES_DL_DAI],
+ .codec_dai = &abe_dai[1],
+ },
+ {
+ .name = "abe-twl6030",
+ .stream_name = "Voice",
+ .cpu_dai = &omap_abe_dai[OMAP_ABE_VOICE_DAI],
+ .codec_dai = &abe_dai[2],
+ },
+ {
+ .name = "abe-twl6030",
+ .stream_name = "Digital Uplink",
+ .cpu_dai = &omap_abe_dai[OMAP_ABE_DIG_UPLINK_DAI],
+ .codec_dai = &abe_dai[3],
+ },
+ {
+ .name = "abe-twl6030",
+ .stream_name = "Vibrator",
+ .cpu_dai = &omap_abe_dai[OMAP_ABE_VIB_DAI],
+ .codec_dai = &abe_dai[4],
+ },
+#ifdef SND_OMAP_SOC_HDMI
+ {
+ .name = "hdmi",
+ .stream_name = "HDMI",
+ .cpu_dai = &omap_hdmi_dai,
+ .codec_dai = &null_dai,
+ },
+#endif
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_sdp4430 = {
+ .name = "SDP4430",
+ .platform = &omap_soc_platform,
+ .dai_link = sdp4430_dai,
+ .num_links = ARRAY_SIZE(sdp4430_dai),
+};
+
+/* Audio subsystem */
+static struct snd_soc_device sdp4430_snd_devdata = {
+ .card = &snd_soc_sdp4430,
+ .codec_dev = &soc_codec_dev_abe_twl6030,
+};
+
+static struct platform_device *sdp4430_snd_device;
+
+static int __init sdp4430_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap_4430sdp()) {
+ pr_debug("Not SDP4430!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "SDP4430 SoC init\n");
+
+#ifdef SND_OMAP_SOC_HDMI
+ snd_soc_register_dais(&null_dai, 1);
+#endif
+
+ sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!sdp4430_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata);
+ sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev;
+
+ ret = platform_device_add(sdp4430_snd_device);
+ if (ret)
+ goto err;
+
+ ret = snd_soc_dai_set_sysclk(sdp4430_dai[0].codec_dai,
+ TWL6030_SYSCLK_SEL_HPPLL, 12000000,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(sdp4430_snd_device);
+ return ret;
+}
+module_init(sdp4430_soc_init);
+
+static void __exit sdp4430_soc_exit(void)
+{
+ platform_device_unregister(sdp4430_snd_device);
+}
+module_exit(sdp4430_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC SDP4430");
+MODULE_LICENSE("GPL");
+